diff --git a/chalk-engine/src/slg.rs b/chalk-engine/src/slg.rs index 028ef8492ea..6ab528e481d 100644 --- a/chalk-engine/src/slg.rs +++ b/chalk-engine/src/slg.rs @@ -293,6 +293,8 @@ impl MayInvalidate<'_, I> { // Only variants left are placeholder = concrete, which always fails (ConstValue::Placeholder(_), _) | (ConstValue::Concrete(_), _) => true, + + (ConstValue::ConstProjection(_), _) => todo!(), } } diff --git a/chalk-engine/src/slg/aggregate.rs b/chalk-engine/src/slg/aggregate.rs index ffb79ec0477..bc77fb87ef6 100644 --- a/chalk-engine/src/slg/aggregate.rs +++ b/chalk-engine/src/slg/aggregate.rs @@ -551,6 +551,8 @@ impl AntiUnifier<'_, '_, I> { (ConstValue::Placeholder(_), _) | (_, ConstValue::Placeholder(_)) => { self.new_const_variable(ty) } + + (ConstValue::ConstProjection(_), _) | (_, ConstValue::ConstProjection(_)) => todo!(), } } diff --git a/chalk-engine/src/slg/resolvent.rs b/chalk-engine/src/slg/resolvent.rs index 906f8879a95..513d19672b7 100644 --- a/chalk-engine/src/slg/resolvent.rs +++ b/chalk-engine/src/slg/resolvent.rs @@ -698,6 +698,8 @@ impl<'i, I: Interner> Zipper<'i, I> for AnswerSubstitutor<'i, I> { "structural mismatch between answer `{:?}` and pending goal `{:?}`", answer, pending, ), + + (ConstValue::ConstProjection(_), _) => todo!(), } } diff --git a/chalk-integration/src/db.rs b/chalk-integration/src/db.rs index 262975b5654..ed99d5a361b 100644 --- a/chalk-integration/src/db.rs +++ b/chalk-integration/src/db.rs @@ -7,15 +7,16 @@ use crate::{ tls, SolverChoice, }; use chalk_ir::{ - AdtId, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId, ConstrainedSubst, - Environment, FnDefId, GeneratorId, GenericArg, Goal, ImplId, InEnvironment, OpaqueTyId, - ProgramClause, ProgramClauses, Substitution, TraitId, Ty, TyKind, UCanonical, + AdtId, AssocConstId, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId, + ConstrainedSubst, Environment, FnDefId, GeneratorId, GenericArg, Goal, ImplId, InEnvironment, + OpaqueTyId, ProgramClause, ProgramClauses, Substitution, TraitId, Ty, TyKind, UCanonical, UnificationDatabase, Variances, }; use chalk_solve::rust_ir::{ - AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, - FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum, - OpaqueTyDatum, TraitDatum, WellKnownTrait, + AdtDatum, AdtRepr, AssociatedConstDatum, AssociatedConstValue, AssociatedConstValueId, + AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, FnDefDatum, + FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum, OpaqueTyDatum, + TraitDatum, WellKnownTrait, }; use chalk_solve::{RustIrDatabase, Solution, SubstitutionResult}; use salsa::Database; @@ -91,6 +92,13 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().associated_ty_data(ty) } + fn associated_const_data( + &self, + ty: AssocConstId, + ) -> Arc> { + self.program_ir().unwrap().associated_const_data(ty) + } + fn trait_datum(&self, id: TraitId) -> Arc> { self.program_ir().unwrap().trait_datum(id) } @@ -106,6 +114,13 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().associated_ty_values[&id].clone() } + fn associated_const_value( + &self, + id: AssociatedConstValueId, + ) -> Arc> { + self.program_ir().unwrap().associated_const_values[&id].clone() + } + fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { self.program_ir().unwrap().opaque_ty_data(id) } @@ -235,6 +250,10 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().assoc_type_name(assoc_ty_id) } + fn assoc_const_name(&self, assoc_const_id: AssocConstId) -> String { + self.program_ir().unwrap().assoc_const_name(assoc_const_id) + } + fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId) -> String { self.program_ir().unwrap().opaque_type_name(opaque_ty_id) } diff --git a/chalk-integration/src/error.rs b/chalk-integration/src/error.rs index ba223d2d249..ae320eb82ae 100644 --- a/chalk-integration/src/error.rs +++ b/chalk-integration/src/error.rs @@ -66,6 +66,7 @@ pub enum RustIrError { InvalidFundamentalTypesParameters(Identifier), NegativeImplAssociatedValues(Identifier), MissingAssociatedType(Identifier), + MissingAssociatedConst(Identifier), IncorrectNumberOfVarianceParameters { identifier: Identifier, expected: usize, @@ -142,6 +143,9 @@ impl std::fmt::Display for RustIrError { RustIrError::MissingAssociatedType(name) => { write!(f, "no associated type `{}` defined in trait", name) } + RustIrError::MissingAssociatedConst(name) => { + write!(f, "no associated constant `{}` defined in trait", name) + } RustIrError::IncorrectNumberOfVarianceParameters { identifier, expected, diff --git a/chalk-integration/src/interner.rs b/chalk-integration/src/interner.rs index 41d485a8bf0..4b3d6dc9787 100644 --- a/chalk-integration/src/interner.rs +++ b/chalk-integration/src/interner.rs @@ -4,8 +4,8 @@ use chalk_ir::{ TyKind, }; use chalk_ir::{ - AdtId, AliasTy, AssocTypeId, CanonicalVarKind, CanonicalVarKinds, ConstData, Constraint, - Constraints, FnDefId, Goals, InEnvironment, Lifetime, OpaqueTy, OpaqueTyId, + AdtId, AliasTy, AssocConstId, AssocTypeId, CanonicalVarKind, CanonicalVarKinds, ConstData, + Constraint, Constraints, FnDefId, Goals, InEnvironment, Lifetime, OpaqueTy, OpaqueTyId, ProgramClauseImplication, ProgramClauses, ProjectionTy, QuantifiedWhereClauses, SeparatorTraitRef, Substitution, TraitId, Ty, TyData, VariableKind, VariableKinds, Variances, }; @@ -97,6 +97,13 @@ impl Interner for ChalkIr { tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) } + fn debug_assoc_const_id( + id: AssocConstId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_assoc_const_id(id, fmt))) + } + fn debug_opaque_ty_id( id: OpaqueTyId, fmt: &mut fmt::Formatter<'_>, diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index 58d9a392227..f3d1f0dee77 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -884,18 +884,30 @@ impl LowerWithEnv for Lifetime { } } -impl LowerWithEnv for (&Impl, ImplId, &AssociatedTyValueIds) { +impl LowerWithEnv + for ( + &Impl, + ImplId, + &AssociatedTyValueIds, + &AssociatedConstValueIds, + ) +{ type Lowered = rust_ir::ImplDatum; fn lower(&self, env: &Env) -> LowerResult { - let (impl_, impl_id, associated_ty_value_ids) = self; + let (impl_, impl_id, associated_ty_value_ids, associated_const_value_ids) = self; let polarity = impl_.polarity.lower(); let binders = env.in_binders(impl_.all_parameters(), |env| { let trait_ref = impl_.trait_ref.lower(env)?; debug!(?trait_ref); - if !polarity.is_positive() && !impl_.assoc_ty_values.is_empty() { + if !polarity.is_positive() + && impl_ + .assoc_item_values + .iter() + .any(|item| item.ty().is_some()) + { Err(RustIrError::NegativeImplAssociatedValues( impl_.trait_ref.trait_name.clone(), ))?; @@ -913,18 +925,29 @@ impl LowerWithEnv for (&Impl, ImplId, &AssociatedTyValueIds) { // within the impl, which should have already assigned and // stored in the map let associated_ty_value_ids = impl_ - .assoc_ty_values + .assoc_item_values .iter() + .filter_map(|item| item.ty()) .map(|atv| associated_ty_value_ids[&(*impl_id, atv.name.str.clone())]) .collect(); debug!(?associated_ty_value_ids); + let associated_const_value_ids = impl_ + .assoc_item_values + .iter() + .filter_map(|item| item.const_()) + .map(|acv| associated_const_value_ids[&(*impl_id, acv.name.str.clone())]) + .collect(); + + debug!(?associated_const_value_ids); + Ok(rust_ir::ImplDatum { polarity, binders, impl_type: impl_.impl_type.lower(), associated_ty_value_ids, + associated_const_value_ids, }) } } @@ -993,16 +1016,29 @@ impl LowerWithEnv for (&TraitDefn, chalk_ir::TraitId) { })?; let associated_ty_ids: Vec<_> = trait_defn - .assoc_ty_defns + .assoc_item_defns .iter() + .filter_map(|item| item.ty()) .map(|defn| env.lookup_associated_ty(*trait_id, &defn.name).unwrap().id) .collect(); + let associated_const_ids: Vec<_> = trait_defn + .assoc_item_defns + .iter() + .filter_map(|item| item.const_()) + .map(|defn| { + env.lookup_associated_const(*trait_id, &defn.name) + .unwrap() + .id + }) + .collect(); + let trait_datum = rust_ir::TraitDatum { id: *trait_id, binders, flags: trait_defn.flags.lower(), associated_ty_ids, + associated_const_ids, well_known: trait_defn.well_known.map(|def| def.lower()), }; @@ -1030,6 +1066,16 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult = program + .associated_const_data + .iter() + .map(|(&associated_const_id, datum)| { + let lookup = AssociatedConstLookup { + id: associated_const_id, + }; + ((datum.trait_id, datum.name.clone()), lookup) + }) + .collect(); let auto_traits = program .trait_data @@ -1051,6 +1097,7 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult, bool>; pub type OpaqueTyVariableKinds = BTreeMap, TypeKind>; pub type GeneratorKinds = BTreeMap, TypeKind>; pub type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId, Ident), AssociatedTyLookup>; +pub type AssociatedConstLookups = + BTreeMap<(chalk_ir::TraitId, Ident), AssociatedConstLookup>; pub type AssociatedTyValueIds = BTreeMap<(chalk_ir::ImplId, Ident), AssociatedTyValueId>; +pub type AssociatedConstValueIds = + BTreeMap<(chalk_ir::ImplId, Ident), AssociatedConstValueId>; pub type ForeignIds = BTreeMap>; pub type ParameterMap = BTreeMap>; @@ -47,6 +51,7 @@ pub struct Env<'k> { pub opaque_ty_ids: &'k OpaqueTyIds, pub opaque_ty_kinds: &'k OpaqueTyVariableKinds, pub associated_ty_lookups: &'k AssociatedTyLookups, + pub associated_const_lookups: &'k AssociatedConstLookups, pub auto_traits: &'k AutoTraits, pub foreign_ty_ids: &'k ForeignIds, pub generator_ids: &'k GeneratorIds, @@ -75,6 +80,11 @@ pub struct AssociatedTyLookup { pub addl_variable_kinds: Vec>, } +#[derive(Debug, PartialEq, Eq)] +pub struct AssociatedConstLookup { + pub id: chalk_ir::AssocConstId, +} + pub enum TypeLookup<'k> { Parameter(&'k WithKind), Adt(AdtId), @@ -222,6 +232,16 @@ impl Env<'_> { .ok_or(RustIrError::MissingAssociatedType(ident.clone())) } + pub fn lookup_associated_const( + &self, + trait_id: TraitId, + ident: &Identifier, + ) -> LowerResult<&AssociatedConstLookup> { + self.associated_const_lookups + .get(&(trait_id, ident.str.clone())) + .ok_or(RustIrError::MissingAssociatedConst(ident.clone())) + } + /// Introduces new parameters, shifting the indices of existing /// parameters to accommodate them. The indices of the new binders /// will be assigned in order as they are iterated. diff --git a/chalk-integration/src/lowering/program_lowerer.rs b/chalk-integration/src/lowering/program_lowerer.rs index 1f39cd9bf27..22a39db869d 100644 --- a/chalk-integration/src/lowering/program_lowerer.rs +++ b/chalk-integration/src/lowering/program_lowerer.rs @@ -1,12 +1,13 @@ -use chalk_ir::cast::Cast; use chalk_ir::{ self, AdtId, AssocTypeId, BoundVar, ClosureId, DebruijnIndex, FnDefId, ForeignDefId, GeneratorId, ImplId, OpaqueTyId, TraitId, TyVariableKind, VariableKinds, }; +use chalk_ir::{cast::Cast, AssocConstId}; use chalk_parse::ast::*; use chalk_solve::rust_ir::{ - self, Anonymize, AssociatedTyValueId, GeneratorDatum, GeneratorInputOutputDatum, - GeneratorWitnessDatum, GeneratorWitnessExistential, OpaqueTyDatum, OpaqueTyDatumBound, + self, Anonymize, AssociatedConstValueId, AssociatedTyValueId, GeneratorDatum, + GeneratorInputOutputDatum, GeneratorWitnessDatum, GeneratorWitnessExistential, OpaqueTyDatum, + OpaqueTyDatumBound, }; use rust_ir::IntoWhereClauses; use std::collections::{BTreeMap, HashSet}; @@ -25,6 +26,8 @@ pub(super) struct ProgramLowerer { associated_ty_lookups: AssociatedTyLookups, associated_ty_value_ids: AssociatedTyValueIds, + associated_const_lookups: AssociatedConstLookups, + associated_const_value_ids: AssociatedConstValueIds, adt_ids: AdtIds, fn_def_ids: FnDefIds, closure_ids: ClosureIds, @@ -58,25 +61,45 @@ impl ProgramLowerer { for (item, &raw_id) in program.items.iter().zip(raw_ids) { match item { Item::TraitDefn(d) => { - if d.flags.auto && !d.assoc_ty_defns.is_empty() { + if d.flags.auto && !d.assoc_item_defns.is_empty() { Err(RustIrError::AutoTraitAssociatedTypes(d.name.clone()))?; } - for defn in &d.assoc_ty_defns { - let addl_variable_kinds = defn.all_parameters(); - let lookup = AssociatedTyLookup { - id: AssocTypeId(self.next_item_id()), - addl_variable_kinds: addl_variable_kinds.anonymize(), - }; - self.associated_ty_lookups - .insert((TraitId(raw_id), defn.name.str.clone()), lookup); + for defn in &d.assoc_item_defns { + match defn { + AssocItemDefn::Ty(defn) => { + let addl_variable_kinds = defn.all_parameters(); + let lookup = AssociatedTyLookup { + id: AssocTypeId(self.next_item_id()), + addl_variable_kinds: addl_variable_kinds.anonymize(), + }; + self.associated_ty_lookups + .insert((TraitId(raw_id), defn.name.str.clone()), lookup); + } + AssocItemDefn::Const(defn) => { + let lookup = AssociatedConstLookup { + id: AssocConstId(self.next_item_id()), + }; + self.associated_const_lookups + .insert((TraitId(raw_id), defn.name.str.clone()), lookup); + } + } } } Item::Impl(d) => { - for atv in &d.assoc_ty_values { - let atv_id = AssociatedTyValueId(self.next_item_id()); - self.associated_ty_value_ids - .insert((ImplId(raw_id), atv.name.str.clone()), atv_id); + for aiv in &d.assoc_item_values { + match aiv { + AssocItemValue::Ty(atv) => { + let atv_id = AssociatedTyValueId(self.next_item_id()); + self.associated_ty_value_ids + .insert((ImplId(raw_id), atv.name.str.clone()), atv_id); + } + AssocItemValue::Const(acv) => { + let acv_id = AssociatedConstValueId(self.next_item_id()); + self.associated_const_value_ids + .insert((ImplId(raw_id), acv.name.str.clone()), acv_id); + } + } } } @@ -154,6 +177,8 @@ impl ProgramLowerer { let mut impl_data = BTreeMap::new(); let mut associated_ty_data = BTreeMap::new(); let mut associated_ty_values = BTreeMap::new(); + let mut associated_const_data = BTreeMap::new(); + let mut associated_const_values = BTreeMap::new(); let mut opaque_ty_data = BTreeMap::new(); let mut generator_data = BTreeMap::new(); let mut generator_witness_data = BTreeMap::new(); @@ -175,6 +200,7 @@ impl ProgramLowerer { generator_ids: &self.generator_ids, generator_kinds: &self.generator_kinds, associated_ty_lookups: &self.associated_ty_lookups, + associated_const_lookups: &self.associated_const_lookups, parameter_map: BTreeMap::new(), auto_traits: &self.auto_traits, foreign_ty_ids: &self.foreign_ty_ids, @@ -265,85 +291,143 @@ impl ProgramLowerer { trait_data.insert(trait_id, Arc::new(trait_datum)); - for assoc_ty_defn in &trait_defn.assoc_ty_defns { - let lookup = &self.associated_ty_lookups - [&(trait_id, assoc_ty_defn.name.str.clone())]; - - // The parameters in scope for the associated - // type definitions are *both* those from the - // trait *and* those from the associated type - // itself. - // - // Insert the associated type parameters first - // into the list so that they are given the - // indices starting from 0. This corresponds - // to the "de bruijn" convention where "more - // inner" sets of parameters get the lower - // indices: - // - // e.g., in this example, the indices would be - // assigned `[A0, A1, T0, T1]`: - // - // ``` - // trait Foo { - // type Bar; - // } - // ``` - let mut variable_kinds = assoc_ty_defn.all_parameters(); - variable_kinds.extend(trait_defn.all_parameters()); - - let binders = empty_env.in_binders(variable_kinds, |env| { - Ok(rust_ir::AssociatedTyDatumBound { - bounds: assoc_ty_defn.bounds.lower(&env)?, - where_clauses: assoc_ty_defn.where_clauses.lower(&env)?, - }) - })?; - - associated_ty_data.insert( - lookup.id, - Arc::new(rust_ir::AssociatedTyDatum { - trait_id: TraitId(raw_id), - id: lookup.id, - name: assoc_ty_defn.name.str.clone(), - binders, - }), - ); + for assoc_item_defn in &trait_defn.assoc_item_defns { + match assoc_item_defn { + AssocItemDefn::Ty(assoc_ty_defn) => { + let lookup = &self.associated_ty_lookups + [&(trait_id, assoc_ty_defn.name.str.clone())]; + + // The parameters in scope for the associated + // type definitions are *both* those from the + // trait *and* those from the associated type + // itself. + // + // Insert the associated type parameters first + // into the list so that they are given the + // indices starting from 0. This corresponds + // to the "de bruijn" convention where "more + // inner" sets of parameters get the lower + // indices: + // + // e.g., in this example, the indices would be + // assigned `[A0, A1, T0, T1]`: + // + // ``` + // trait Foo { + // type Bar; + // } + // ``` + let mut variable_kinds = assoc_ty_defn.all_parameters(); + variable_kinds.extend(trait_defn.all_parameters()); + + let binders = empty_env.in_binders(variable_kinds, |env| { + Ok(rust_ir::AssociatedTyDatumBound { + bounds: assoc_ty_defn.bounds.lower(&env)?, + where_clauses: assoc_ty_defn.where_clauses.lower(&env)?, + }) + })?; + + associated_ty_data.insert( + lookup.id, + Arc::new(rust_ir::AssociatedTyDatum { + trait_id: TraitId(raw_id), + id: lookup.id, + name: assoc_ty_defn.name.str.clone(), + binders, + }), + ); + } + AssocItemDefn::Const(assoc_const_defn) => { + let lookup = &self.associated_const_lookups + [&(trait_id, assoc_const_defn.name.str.clone())]; + + let variable_kinds = trait_defn.all_parameters(); + let binders = assoc_const_defn + .value + .as_ref() + .map(|value| { + empty_env + .in_binders(variable_kinds, |env| value.lower(&env)) + }) + .transpose()?; + associated_const_data.insert( + lookup.id, + Arc::new(rust_ir::AssociatedConstDatum { + trait_id: TraitId(raw_id), + id: lookup.id, + name: assoc_const_defn.name.str.clone(), + ty: assoc_const_defn.ty.lower(&empty_env)?, + binders, + }), + ); + } + } } } Item::Impl(ref impl_defn) => { let impl_id = ImplId(raw_id); let impl_datum = Arc::new( - (impl_defn, impl_id, &self.associated_ty_value_ids).lower(&empty_env)?, + ( + impl_defn, + impl_id, + &self.associated_ty_value_ids, + &self.associated_const_value_ids, + ) + .lower(&empty_env)?, ); impl_data.insert(impl_id, impl_datum.clone()); let trait_id = impl_datum.trait_id(); - for atv in &impl_defn.assoc_ty_values { - let atv_id = self.associated_ty_value_ids[&(impl_id, atv.name.str.clone())]; - let lookup = &self.associated_ty_lookups[&(trait_id, atv.name.str.clone())]; - - // The parameters in scope for the associated - // type definitions are *both* those from the - // impl *and* those from the associated type - // itself. As in the "trait" case above, we begin - // with the parameters from the impl. - let mut variable_kinds = atv.all_parameters(); - variable_kinds.extend(impl_defn.all_parameters()); - - let value = empty_env.in_binders(variable_kinds, |env| { - Ok(rust_ir::AssociatedTyValueBound { - ty: atv.value.lower(env)?, - }) - })?; - - associated_ty_values.insert( - atv_id, - Arc::new(rust_ir::AssociatedTyValue { - impl_id, - associated_ty_id: lookup.id, - value, - }), - ); + for aiv in &impl_defn.assoc_item_values { + match aiv { + AssocItemValue::Ty(atv) => { + let atv_id = + self.associated_ty_value_ids[&(impl_id, atv.name.str.clone())]; + let lookup = + &self.associated_ty_lookups[&(trait_id, atv.name.str.clone())]; + + // The parameters in scope for the associated + // type definitions are *both* those from the + // impl *and* those from the associated type + // itself. As in the "trait" case above, we begin + // with the parameters from the impl. + let mut variable_kinds = atv.all_parameters(); + variable_kinds.extend(impl_defn.all_parameters()); + + let value = empty_env.in_binders(variable_kinds, |env| { + Ok(rust_ir::AssociatedTyValueBound { + ty: atv.value.lower(env)?, + }) + })?; + + associated_ty_values.insert( + atv_id, + Arc::new(rust_ir::AssociatedTyValue { + impl_id, + associated_ty_id: lookup.id, + value, + }), + ); + } + AssocItemValue::Const(acv) => { + let acv_id = self.associated_const_value_ids + [&(impl_id, acv.name.str.clone())]; + let lookup = &self.associated_const_lookups + [&(trait_id, acv.name.str.clone())]; + + let variable_kinds = impl_defn.all_parameters(); + let value = empty_env + .in_binders(variable_kinds, |env| acv.value.lower(env))?; + associated_const_values.insert( + acv_id, + Arc::new(rust_ir::AssociatedConstValue { + impl_id, + associated_const_id: lookup.id, + value, + }), + ); + } + } } } Item::Clause(ref clause) => { @@ -493,6 +577,8 @@ impl ProgramLowerer { impl_data, associated_ty_values, associated_ty_data, + associated_const_values, + associated_const_data, opaque_ty_ids: self.opaque_ty_ids, opaque_ty_kinds: self.opaque_ty_kinds, opaque_ty_data, diff --git a/chalk-integration/src/program.rs b/chalk-integration/src/program.rs index a77d5d1915e..d7c36f0e4dd 100644 --- a/chalk-integration/src/program.rs +++ b/chalk-integration/src/program.rs @@ -1,6 +1,6 @@ use crate::interner::ChalkIr; use crate::{tls, Identifier, TypeKind}; -use chalk_ir::{could_match::CouldMatch, UnificationDatabase}; +use chalk_ir::{could_match::CouldMatch, AssocConstId, UnificationDatabase}; use chalk_ir::{debug::Angle, Variance}; use chalk_ir::{ debug::SeparatorTraitRef, AdtId, AliasTy, AssocTypeId, Binders, CanonicalVarKinds, ClosureId, @@ -9,9 +9,10 @@ use chalk_ir::{ Substitution, TraitId, Ty, TyKind, UintTy, Variances, }; use chalk_solve::rust_ir::{ - AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, - FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum, - ImplType, OpaqueTyDatum, TraitDatum, WellKnownTrait, + AdtDatum, AdtRepr, AssociatedConstDatum, AssociatedConstValue, AssociatedConstValueId, + AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, FnDefDatum, + FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum, ImplType, + OpaqueTyDatum, TraitDatum, WellKnownTrait, }; use chalk_solve::split::Split; use chalk_solve::RustIrDatabase; @@ -76,6 +77,10 @@ pub struct Program { pub associated_ty_values: BTreeMap, Arc>>, + /// For each associated ty value `const C: T = XXX` found in an impl: + pub associated_const_values: + BTreeMap, Arc>>, + // From opaque type name to item-id. Used during lowering only. pub opaque_ty_ids: BTreeMap>, @@ -97,6 +102,9 @@ pub struct Program { /// For each associated ty declaration `type Foo` found in a trait: pub associated_ty_data: BTreeMap, Arc>>, + /// For each associated const declaration `const C: T` found in a trait: + pub associated_const_data: BTreeMap, Arc>>, + /// For each user-specified clause pub custom_clauses: Vec>, @@ -161,6 +169,20 @@ impl tls::DebugContext for Program { } } + fn debug_assoc_const_id( + &self, + assoc_const_id: AssocConstId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + if let Some(d) = self.associated_const_data.get(&assoc_const_id) { + write!(fmt, "({:?}::{})", d.trait_id, d.name) + } else { + fmt.debug_struct("InvalidAssocConstId") + .field("index", &assoc_const_id.0) + .finish() + } + } + fn debug_opaque_ty_id( &self, opaque_ty_id: OpaqueTyId, @@ -388,6 +410,13 @@ impl RustIrDatabase for Program { self.associated_ty_data[&ty].clone() } + fn associated_const_data( + &self, + ty: AssocConstId, + ) -> Arc> { + self.associated_const_data[&ty].clone() + } + fn trait_datum(&self, id: TraitId) -> Arc> { self.trait_data[&id].clone() } @@ -403,6 +432,13 @@ impl RustIrDatabase for Program { self.associated_ty_values[&id].clone() } + fn associated_const_value( + &self, + id: AssociatedConstValueId, + ) -> Arc> { + self.associated_const_values[&id].clone() + } + fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { self.opaque_ty_data[&id].clone() } @@ -590,6 +626,14 @@ impl RustIrDatabase for Program { .to_string() } + fn assoc_const_name(&self, assoc_const_id: AssocConstId) -> String { + self.associated_const_data + .get(&assoc_const_id) + .unwrap() + .name + .to_string() + } + // Mirrors current (07a63e6d1fabf3560e8e1e17c1d56b10a06152d9) implementation in rustc fn discriminant_type(&self, ty: Ty) -> Ty { let interner = self.interner(); diff --git a/chalk-integration/src/tls.rs b/chalk-integration/src/tls.rs index 58b1da3dfa8..55e649fd436 100644 --- a/chalk-integration/src/tls.rs +++ b/chalk-integration/src/tls.rs @@ -1,7 +1,7 @@ use crate::interner::ChalkIr; use chalk_ir::{ - debug::SeparatorTraitRef, AdtId, AliasTy, AssocTypeId, CanonicalVarKinds, Constraints, FnDefId, - GenericArg, Goal, Goals, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause, + debug::SeparatorTraitRef, AdtId, AliasTy, AssocConstId, AssocTypeId, CanonicalVarKinds, + Constraints, FnDefId, GenericArg, Goal, Goals, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTy, QuantifiedWhereClauses, Substitution, TraitId, Ty, VariableKinds, Variances, }; @@ -32,6 +32,12 @@ pub trait DebugContext { fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error>; + fn debug_assoc_const_id( + &self, + id: AssocConstId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error>; + fn debug_opaque_ty_id( &self, id: OpaqueTyId, diff --git a/chalk-ir/src/debug.rs b/chalk-ir/src/debug.rs index 4a13346d203..0de712bb041 100644 --- a/chalk-ir/src/debug.rs +++ b/chalk-ir/src/debug.rs @@ -23,6 +23,13 @@ impl Debug for AssocTypeId { } } +impl Debug for AssocConstId { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_assoc_const_id(*self, fmt) + .unwrap_or_else(|| write!(fmt, "AssocConstId({:?})", self.0)) + } +} + impl Debug for FnDefId { fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result { I::debug_fn_def_id(*self, fmt).unwrap_or_else(|| write!(fmt, "FnDefId({:?})", self.0)) @@ -359,6 +366,7 @@ impl Debug for ConstData { ConstValue::InferenceVar(var) => write!(fmt, "{:?}", var), ConstValue::Placeholder(index) => write!(fmt, "{:?}", index), ConstValue::Concrete(evaluated) => write!(fmt, "{:?}", evaluated), + ConstValue::ConstProjection(_) => todo!(), } } } diff --git a/chalk-ir/src/fold.rs b/chalk-ir/src/fold.rs index 426164539d9..e5741a27de5 100644 --- a/chalk-ir/src/fold.rs +++ b/chalk-ir/src/fold.rs @@ -583,6 +583,7 @@ where }), } .intern(folder.interner())), + ConstValue::ConstProjection(_) => todo!(), } } } diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index 7c019216958..22f9a99d623 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -249,6 +249,7 @@ id_fold!(ImplId); id_fold!(AdtId); id_fold!(TraitId); id_fold!(AssocTypeId); +id_fold!(AssocConstId); id_fold!(OpaqueTyId); id_fold!(FnDefId); id_fold!(ClosureId); diff --git a/chalk-ir/src/interner.rs b/chalk-ir/src/interner.rs index b2da60cf8d1..c5583825598 100644 --- a/chalk-ir/src/interner.rs +++ b/chalk-ir/src/interner.rs @@ -1,5 +1,4 @@ //! Encapsulates the concrete representation of core types such as types and goals. -use crate::AliasTy; use crate::AssocTypeId; use crate::CanonicalVarKind; use crate::CanonicalVarKinds; @@ -36,6 +35,7 @@ use crate::VariableKinds; use crate::Variance; use crate::Variances; use crate::{AdtId, TyKind}; +use crate::{AliasTy, AssocConstId}; use crate::{Const, ConstData}; use std::fmt::{self, Debug}; use std::hash::Hash; @@ -206,7 +206,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { None } - /// Prints the debug representation of a type-kind-id. + /// Prints the debug representation of a trait id. /// Returns `None` to fallback to the default debug output (e.g., /// if no info about current program is available from TLS). #[allow(unused_variables)] @@ -217,7 +217,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { None } - /// Prints the debug representation of a type-kind-id. + /// Prints the debug representation of an associated-type-id. /// Returns `None` to fallback to the default debug output. #[allow(unused_variables)] fn debug_assoc_type_id( @@ -227,6 +227,16 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { None } + /// Prints the debug representation of an associated-const-id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_assoc_const_id( + type_id: AssocConstId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + /// Prints the debug representation of an opaque type. /// Returns `None` to fallback to the default debug output. #[allow(unused_variables)] diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 70a29fee9fa..ab1a6d178c8 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -383,6 +383,10 @@ pub struct ClauseId(pub I::DefId); #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct AssocTypeId(pub I::DefId); +/// Id for the associated const of a trait. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AssocConstId(pub I::DefId); + /// Id for an opaque type. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct OpaqueTyId(pub I::DefId); @@ -718,6 +722,7 @@ impl TyKind { ConstValue::Placeholder(_) => { TypeFlags::HAS_CT_PLACEHOLDER | TypeFlags::STILL_FURTHER_SPECIALIZABLE } + ConstValue::ConstProjection(_) => todo!(), } } TyKind::Placeholder(_) => TypeFlags::HAS_TY_PLACEHOLDER, @@ -1180,6 +1185,7 @@ impl Const { ConstValue::InferenceVar(_) => false, ConstValue::Placeholder(_) => false, ConstValue::Concrete(_) => false, + ConstValue::ConstProjection(_) => todo!(), } } } @@ -1204,9 +1210,11 @@ pub enum ConstValue { Placeholder(PlaceholderIndex), /// Concrete constant value. Concrete(ConcreteConst), + /// Projection for associated constant. + ConstProjection(ConstProjection), } -impl Copy for ConstValue where I::InternedConcreteConst: Copy {} +// impl Copy for ConstValue where I::InternedConcreteConst: Copy {} impl ConstData { /// Wraps the constant data in a `Const`. @@ -1230,6 +1238,15 @@ impl ConcreteConst { } } +/// Projection for an associated constant. +#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] +pub struct ConstProjection { + /// The id for the associated constant. + pub associated_const_id: AssocConstId, + /// The substitution for the projection. + pub substitution: Substitution, +} + /// A Rust lifetime. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] pub struct Lifetime { @@ -1514,6 +1531,7 @@ impl GenericArg { | TypeFlags::STILL_FURTHER_SPECIALIZABLE } ConstValue::Concrete(_) => flags, + ConstValue::ConstProjection(_) => todo!(), } } } diff --git a/chalk-ir/src/visit.rs b/chalk-ir/src/visit.rs index c7180d76966..0a0235c7977 100644 --- a/chalk-ir/src/visit.rs +++ b/chalk-ir/src/visit.rs @@ -436,6 +436,7 @@ impl SuperVisit for Const { visitor.visit_free_placeholder(*universe, outer_binder) } ConstValue::Concrete(_) => ControlFlow::CONTINUE, + ConstValue::ConstProjection(_) => todo!(), } } } diff --git a/chalk-ir/src/visit/boring_impls.rs b/chalk-ir/src/visit/boring_impls.rs index eef58ddb3ca..b06a823f585 100644 --- a/chalk-ir/src/visit/boring_impls.rs +++ b/chalk-ir/src/visit/boring_impls.rs @@ -5,11 +5,11 @@ //! The more interesting impls of `Visit` remain in the `visit` module. use crate::{ - try_break, AdtId, AssocTypeId, ClausePriority, ClosureId, Constraints, ControlFlow, - DebruijnIndex, FloatTy, FnDefId, ForeignDefId, GeneratorId, GenericArg, Goals, ImplId, IntTy, - Interner, Mutability, OpaqueTyId, PlaceholderIndex, ProgramClause, ProgramClauses, - QuantifiedWhereClauses, QuantifierKind, Safety, Scalar, Substitution, SuperVisit, TraitId, - UintTy, UniverseIndex, Visit, Visitor, + try_break, AdtId, AssocConstId, AssocTypeId, ClausePriority, ClosureId, Constraints, + ControlFlow, DebruijnIndex, FloatTy, FnDefId, ForeignDefId, GeneratorId, GenericArg, Goals, + ImplId, IntTy, Interner, Mutability, OpaqueTyId, PlaceholderIndex, ProgramClause, + ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Safety, Scalar, Substitution, + SuperVisit, TraitId, UintTy, UniverseIndex, Visit, Visitor, }; use std::{marker::PhantomData, sync::Arc}; @@ -231,6 +231,7 @@ id_visit!(AdtId); id_visit!(TraitId); id_visit!(OpaqueTyId); id_visit!(AssocTypeId); +id_visit!(AssocConstId); id_visit!(FnDefId); id_visit!(ClosureId); id_visit!(GeneratorId); diff --git a/chalk-ir/src/zip.rs b/chalk-ir/src/zip.rs index d7a70d36615..298f8f1daf9 100644 --- a/chalk-ir/src/zip.rs +++ b/chalk-ir/src/zip.rs @@ -321,6 +321,7 @@ macro_rules! eq_zip { eq_zip!(I => AdtId); eq_zip!(I => TraitId); eq_zip!(I => AssocTypeId); +eq_zip!(I => AssocConstId); eq_zip!(I => OpaqueTyId); eq_zip!(I => GeneratorId); eq_zip!(I => ForeignDefId); diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 5b363e5a0f5..db07b89d183 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -140,7 +140,7 @@ pub struct TraitDefn { pub name: Identifier, pub variable_kinds: Vec, pub where_clauses: Vec, - pub assoc_ty_defns: Vec, + pub assoc_item_defns: Vec, pub flags: TraitFlags, pub well_known: Option, } @@ -171,6 +171,30 @@ pub struct TraitFlags { pub object_safe: bool, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum AssocItemDefn { + Ty(AssocTyDefn), + Const(AssocConstDefn), +} + +impl AssocItemDefn { + /// Returns the type value if it is one, `None` otherwise. + pub fn ty(&self) -> Option<&AssocTyDefn> { + match self { + AssocItemDefn::Ty(ty) => Some(ty), + _ => None, + } + } + + /// Returns the const value if it is one, `None` otherwise. + pub fn const_(&self) -> Option<&AssocConstDefn> { + match self { + AssocItemDefn::Const(c) => Some(c), + _ => None, + } + } +} + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AssocTyDefn { pub name: Identifier, @@ -179,6 +203,13 @@ pub struct AssocTyDefn { pub where_clauses: Vec, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AssocConstDefn { + pub name: Identifier, + pub ty: Ty, + pub value: Option, +} + #[derive(Clone, PartialEq, Eq, Debug)] pub struct OpaqueTyDefn { pub ty: Ty, @@ -265,7 +296,7 @@ pub struct Impl { pub trait_ref: TraitRef, pub polarity: Polarity, pub where_clauses: Vec, - pub assoc_ty_values: Vec, + pub assoc_item_values: Vec, pub impl_type: ImplType, } @@ -275,6 +306,30 @@ pub enum ImplType { External, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum AssocItemValue { + Ty(AssocTyValue), + Const(AssocConstValue), +} + +impl AssocItemValue { + /// Returns the type value if it is one, `None` otherwise. + pub fn ty(&self) -> Option<&AssocTyValue> { + match self { + AssocItemValue::Ty(ty) => Some(ty), + _ => None, + } + } + + /// Returns the type value if it is one, `None` otherwise. + pub fn const_(&self) -> Option<&AssocConstValue> { + match self { + AssocItemValue::Const(c) => Some(c), + _ => None, + } + } +} + #[derive(Clone, PartialEq, Eq, Debug)] pub struct AssocTyValue { pub name: Identifier, @@ -283,6 +338,13 @@ pub struct AssocTyValue { pub default: bool, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AssocConstValue { + pub name: Identifier, + pub ty: Ty, + pub value: Const, +} + #[derive(Clone, PartialEq, Eq, Debug)] pub enum Ty { Id { diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index bb655139d2d..c2e198af061 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -252,12 +252,12 @@ ClosureArgs: Vec = { TraitDefn: TraitDefn = { "trait" > - "{" "}" => TraitDefn + "{" "}" => TraitDefn { name: n, variable_kinds: p, where_clauses: w, - assoc_ty_defns: a, + assoc_item_defns: a, well_known, flags: TraitFlags { auto: auto.is_some(), @@ -271,6 +271,11 @@ TraitDefn: TraitDefn = { } }; +AssocItemDefn: AssocItemDefn = { + => AssocItemDefn::Ty(ty), + => AssocItemDefn::Const(c), +} + AssocTyDefn: AssocTyDefn = { "type" > >)?> ";" => @@ -284,6 +289,17 @@ AssocTyDefn: AssocTyDefn = { } }; +AssocConstDefn: AssocConstDefn = { + "const" ":" )?> ";" => + { + AssocConstDefn { + name, + ty, + value + } + } +} + OpaqueTyDefn: OpaqueTyDefn = { "opaque" "type" > >)?> "=" ";" => { @@ -339,7 +355,7 @@ QuantifiedInlineBound: QuantifiedInlineBound = { Impl: Impl = { "impl" > > "for" - "{" "}" => + "{" "}" => { let mut args = vec![GenericArg::Ty(s)]; args.extend(a); @@ -351,7 +367,7 @@ Impl: Impl = { args: args, }, where_clauses: w, - assoc_ty_values: assoc, + assoc_item_values: assoc, impl_type: external.map(|_| ImplType::External).unwrap_or(ImplType::Local), } }, @@ -373,6 +389,11 @@ RawVariance: Variance = { Variances: Vec = "#" "[" "variance" "(" > ")" "]"; +AssocItemValue: AssocItemValue = { + => AssocItemValue::Ty(ty), + => AssocItemValue::Const(c), +} + AssocTyValue: AssocTyValue = { "type" > "=" ";" => AssocTyValue { name: n, @@ -382,6 +403,17 @@ AssocTyValue: AssocTyValue = { }, }; +AssocConstValue: AssocConstValue = { + "const" ":" "=" ";" => + { + AssocConstValue { + name, + ty, + value, + } + } +}; + pub Ty: Ty = { => Ty::Id { name: n }, TyWithoutId, diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index e347a801737..7fd6ada5ced 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -624,7 +624,7 @@ pub fn program_clauses_that_could_match( )?; } - push_program_clauses_for_associated_type_values_in_impls_of( + push_program_clauses_for_associated_values_in_impls_of( builder, environment, trait_id, @@ -722,7 +722,7 @@ fn push_clauses_for_compatible_normalize( /// } /// ``` #[instrument(level = "debug", skip(builder))] -fn push_program_clauses_for_associated_type_values_in_impls_of( +fn push_program_clauses_for_associated_values_in_impls_of( builder: &mut ClauseBuilder<'_, I>, environment: &Environment, trait_id: TraitId, diff --git a/chalk-solve/src/display/identifiers.rs b/chalk-solve/src/display/identifiers.rs index 81a08d71b30..788750b1b68 100644 --- a/chalk-solve/src/display/identifiers.rs +++ b/chalk-solve/src/display/identifiers.rs @@ -42,6 +42,17 @@ impl RenderAsRust for AssocTypeId { } } +impl RenderAsRust for AssocConstId { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // TODO: use debug methods? + write!( + f, + "{}", + s.alias_for_id_name(self.0, s.db().assoc_const_name(*self)) + ) + } +} + impl RenderAsRust for OpaqueTyId { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { // TODO: use debug methods? diff --git a/chalk-solve/src/display/items.rs b/chalk-solve/src/display/items.rs index fc5a8c86e41..2967fd32375 100644 --- a/chalk-solve/src/display/items.rs +++ b/chalk-solve/src/display/items.rs @@ -232,6 +232,17 @@ impl RenderAsRust for TraitDatum { }), "\n" )?; + + write_joined_non_empty_list!( + f, + "\n{}\n", + self.associated_const_ids.iter().map(|assoc_const_id| { + let assoc_const_data = s.db().associated_const_data(*assoc_const_id); + format!("{}{}", s.indent(), (*assoc_const_data).display(s)) + }), + "\n" + )?; + write!(f, "}}")?; Ok(()) } @@ -304,6 +315,17 @@ impl RenderAsRust for ImplDatum { .to_string() }); write_joined_non_empty_list!(f, "\n{}\n", assoc_ty_values, "\n")?; + + let assoc_const_values = + self.associated_const_value_ids + .iter() + .map(|assoc_const_value| { + s.db() + .associated_const_value(*assoc_const_value) + .display(s) + .to_string() + }); + write_joined_non_empty_list!(f, "\n{}\n", assoc_const_values, "\n")?; } write!(f, "}}")?; Ok(()) @@ -447,6 +469,27 @@ impl RenderAsRust for AssociatedTyValue { } } +impl RenderAsRust for AssociatedConstDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + let assoc_const_data = s.db().associated_const_data(self.id); + + write!(f, "{}const {}", s.indent(), assoc_const_data.id.display(s))?; + write!(f, ": {};", assoc_const_data.ty.display(s))?; + Ok(()) + } +} + +impl RenderAsRust for AssociatedConstValue { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + let assoc_const_data = s.db().associated_const_data(self.associated_const_id); + + write!(f, "{}const {}", s.indent(), assoc_const_data.id.display(s))?; + write!(f, ": {}", assoc_const_data.ty.display(s))?; + write!(f, " = {};", self.value.skip_binders().display(s))?; + Ok(()) + } +} + impl RenderAsRust for FnDefDatum { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { let s = &s.add_debrujin_index(None); diff --git a/chalk-solve/src/display/stub.rs b/chalk-solve/src/display/stub.rs index 504b9c9e44e..d8fb90496c9 100644 --- a/chalk-solve/src/display/stub.rs +++ b/chalk-solve/src/display/stub.rs @@ -56,6 +56,14 @@ impl> RustIrDatabase for StubWrapper<'_, D Arc::new(v) } + fn associated_const_data( + &self, + ty: chalk_ir::AssocConstId, + ) -> std::sync::Arc> { + let v = (*self.db.associated_const_data(ty)).clone(); + Arc::new(v) + } + fn trait_datum( &self, trait_id: chalk_ir::TraitId, @@ -119,6 +127,13 @@ impl> RustIrDatabase for StubWrapper<'_, D unreachable!("associated type values should never be stubbed") } + fn associated_const_value( + &self, + _id: crate::rust_ir::AssociatedConstValueId, + ) -> std::sync::Arc> { + unreachable!("associated const values should never be stubbed") + } + fn opaque_ty_data( &self, id: chalk_ir::OpaqueTyId, @@ -250,6 +265,10 @@ impl> RustIrDatabase for StubWrapper<'_, D self.db.assoc_type_name(assoc_ty_id) } + fn assoc_const_name(&self, assoc_const_id: chalk_ir::AssocConstId) -> String { + self.db.assoc_const_name(assoc_const_id) + } + fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { self.db.opaque_type_name(opaque_ty_id) } diff --git a/chalk-solve/src/display/ty.rs b/chalk-solve/src/display/ty.rs index 8135536d1e2..3a1db4b5de6 100644 --- a/chalk-solve/src/display/ty.rs +++ b/chalk-solve/src/display/ty.rs @@ -262,6 +262,7 @@ impl RenderAsRust for ConstValue { ConstValue::InferenceVar(_) => write!(f, "_"), ConstValue::Placeholder(_) => write!(f, ""), ConstValue::Concrete(value) => write!(f, "{:?}", value.interned), + ConstValue::ConstProjection(_) => todo!(), } } } diff --git a/chalk-solve/src/infer/unify.rs b/chalk-solve/src/infer/unify.rs index 2fd745d1798..7a7ed07f4c0 100644 --- a/chalk-solve/src/infer/unify.rs +++ b/chalk-solve/src/infer/unify.rs @@ -1128,6 +1128,8 @@ impl<'t, I: Interner> Unifier<'t, I> { "unification encountered bound variable: a={:?} b={:?}", a, b ), + + (&ConstValue::ConstProjection(_), _) | (_, &ConstValue::ConstProjection(_)) => todo!(), } } diff --git a/chalk-solve/src/lib.rs b/chalk-solve/src/lib.rs index 6805dd9f6dd..2430e3ff8c7 100644 --- a/chalk-solve/src/lib.rs +++ b/chalk-solve/src/lib.rs @@ -49,6 +49,9 @@ pub trait RustIrDatabase: Debug { /// Returns the datum for the associated type with the given id. fn associated_ty_data(&self, ty: AssocTypeId) -> Arc>; + /// Returns the datum for the associated conts with the given id. + fn associated_const_data(&self, ty: AssocConstId) -> Arc>; + /// Returns the datum for the definition with the given id. fn trait_datum(&self, trait_id: TraitId) -> Arc>; @@ -76,6 +79,10 @@ pub trait RustIrDatabase: Debug { /// Returns the `AssociatedTyValue` with the given id. fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc>; + /// Returns the `AssociatedConstValue` with the given id. + fn associated_const_value(&self, id: AssociatedConstValueId) + -> Arc>; + /// Returns the `OpaqueTyDatum` with the given id. fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc>; @@ -164,31 +171,37 @@ pub trait RustIrDatabase: Debug { fn unification_database(&self) -> &dyn UnificationDatabase; /// Retrieves a trait's original name. No uniqueness guarantees, but must - /// a valid Rust identifier. + /// be a valid Rust identifier. fn trait_name(&self, trait_id: TraitId) -> String { sanitize_debug_name(|f| I::debug_trait_id(trait_id, f)) } /// Retrieves a struct's original name. No uniqueness guarantees, but must - /// a valid Rust identifier. + /// be a valid Rust identifier. fn adt_name(&self, adt_id: AdtId) -> String { sanitize_debug_name(|f| I::debug_adt_id(adt_id, f)) } /// Retrieves the name of an associated type. No uniqueness guarantees, but must - /// a valid Rust identifier. + /// be a valid Rust identifier. fn assoc_type_name(&self, assoc_ty_id: AssocTypeId) -> String { sanitize_debug_name(|f| I::debug_assoc_type_id(assoc_ty_id, f)) } + /// Retrieves the name of an associated constant. No uniqueness guarantees, but must + /// be a valid Rust identifier. + fn assoc_const_name(&self, assoc_const_id: AssocConstId) -> String { + sanitize_debug_name(|f| I::debug_assoc_const_id(assoc_const_id, f)) + } + /// Retrieves the name of an opaque type. No uniqueness guarantees, but must - /// a valid Rust identifier. + /// be a valid Rust identifier. fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId) -> String { sanitize_debug_name(|f| I::debug_opaque_ty_id(opaque_ty_id, f)) } /// Retrieves the name of a function definition. No uniqueness guarantees, but must - /// a valid Rust identifier. + /// be a valid Rust identifier. fn fn_def_name(&self, fn_def_id: FnDefId) -> String { sanitize_debug_name(|f| I::debug_fn_def_id(fn_def_id, f)) } diff --git a/chalk-solve/src/logging_db.rs b/chalk-solve/src/logging_db.rs index 4e7fa0c4959..8134a140402 100644 --- a/chalk-solve/src/logging_db.rs +++ b/chalk-solve/src/logging_db.rs @@ -128,6 +128,15 @@ where ty_datum } + fn associated_const_data( + &self, + ty: chalk_ir::AssocConstId, + ) -> Arc> { + let ty_datum = self.ws.db().associated_const_data(ty); + self.record(ty_datum.trait_id); + ty_datum + } + fn trait_datum(&self, trait_id: TraitId) -> Arc> { self.record(trait_id); self.ws.db().trait_datum(trait_id) @@ -175,6 +184,15 @@ where value } + fn associated_const_value( + &self, + id: crate::rust_ir::AssociatedConstValueId, + ) -> Arc> { + let value = self.ws.db().associated_const_value(id); + self.record(value.impl_id); + value + } + fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { self.record(id); self.ws.db().opaque_ty_data(id) @@ -237,6 +255,10 @@ where self.ws.db().assoc_type_name(assoc_ty_id) } + fn assoc_const_name(&self, assoc_const_id: AssocConstId) -> String { + self.ws.db().assoc_const_name(assoc_const_id) + } + fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId) -> String { self.ws.db().opaque_type_name(opaque_ty_id) } @@ -395,6 +417,13 @@ where self.db.associated_ty_data(ty) } + fn associated_const_data( + &self, + ty: chalk_ir::AssocConstId, + ) -> Arc> { + self.db.associated_const_data(ty) + } + fn trait_datum(&self, trait_id: TraitId) -> Arc> { self.db.trait_datum(trait_id) } @@ -430,6 +459,13 @@ where self.db.associated_ty_value(id) } + fn associated_const_value( + &self, + id: crate::rust_ir::AssociatedConstValueId, + ) -> Arc> { + self.db.associated_const_value(id) + } + fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { self.db.opaque_ty_data(id) } @@ -493,6 +529,10 @@ where self.db.assoc_type_name(assoc_ty_id) } + fn assoc_const_name(&self, assoc_const_id: AssocConstId) -> String { + self.db.assoc_const_name(assoc_const_id) + } + fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId) -> String { self.db.opaque_type_name(opaque_ty_id) } diff --git a/chalk-solve/src/logging_db/id_collector.rs b/chalk-solve/src/logging_db/id_collector.rs index 2a627494ad8..dc127ceb138 100644 --- a/chalk-solve/src/logging_db/id_collector.rs +++ b/chalk-solve/src/logging_db/id_collector.rs @@ -9,7 +9,7 @@ use chalk_ir::{ use std::collections::BTreeSet; /// Collects the identifiers needed to resolve all the names for a given -/// set of identifers, excluding identifiers we already have. +/// set of identifiers, excluding identifiers we already have. /// /// When recording identifiers to print, the `LoggingRustIrDatabase` only /// records identifiers the solver uses. But the solver assumes well-formedness, @@ -65,6 +65,10 @@ pub fn collect_unrecorded_ids<'i, I: Interner, DB: RustIrDatabase>( .visit_with(&mut collector, DebruijnIndex::INNERMOST); assoc_ty_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); } + for assoc_const_id in &trait_datum.associated_const_ids { + let assoc_const_datum = collector.db.associated_const_data(*assoc_const_id); + assoc_const_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); + } } RecordedItemId::OpaqueTy(opaque_id) => { collector @@ -82,6 +86,10 @@ pub fn collect_unrecorded_ids<'i, I: Interner, DB: RustIrDatabase>( let assoc_ty_value = collector.db.associated_ty_value(*id); assoc_ty_value.visit_with(&mut collector, DebruijnIndex::INNERMOST); } + for id in &impl_datum.associated_const_value_ids { + let assoc_const_value = collector.db.associated_const_value(*id); + assoc_const_value.visit_with(&mut collector, DebruijnIndex::INNERMOST); + } impl_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); } } diff --git a/chalk-solve/src/rust_ir.rs b/chalk-solve/src/rust_ir.rs index cb1c2774292..b770c5a866e 100644 --- a/chalk-solve/src/rust_ir.rs +++ b/chalk-solve/src/rust_ir.rs @@ -3,9 +3,9 @@ //! compiler. use chalk_derive::{Fold, HasInterner, Visit}; -use chalk_ir::cast::Cast; use chalk_ir::fold::shift::Shift; use chalk_ir::interner::Interner; +use chalk_ir::{cast::Cast, AssocConstId, Const}; use chalk_ir::{ try_break, visit::{ControlFlow, Visit}, @@ -22,12 +22,20 @@ pub struct AssociatedTyValueId(pub I::DefId); chalk_ir::id_visit!(AssociatedTyValueId); chalk_ir::id_fold!(AssociatedTyValueId); +/// Identifier for an "associated const value" found in some impl. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AssociatedConstValueId(pub I::DefId); + +chalk_ir::id_visit!(AssociatedConstValueId); +chalk_ir::id_fold!(AssociatedConstValueId); + #[derive(Clone, Debug, PartialEq, Eq, Hash, Visit)] pub struct ImplDatum { pub polarity: Polarity, pub binders: Binders>, pub impl_type: ImplType, pub associated_ty_value_ids: Vec>, + pub associated_const_value_ids: Vec>, } impl ImplDatum { @@ -238,6 +246,7 @@ pub struct TraitDatum { pub flags: TraitFlags, pub associated_ty_ids: Vec>, + pub associated_const_ids: Vec>, /// If this is a well-known trait, which one? If `None`, this is a regular, /// user-defined trait. @@ -505,6 +514,49 @@ impl Visit for AssociatedTyDatum { } } +/// Represents an associated const declaration found inside of a trait: +/// +/// ```notrust +/// trait Foo { // P0 is Self +/// const Bar: [type] (= [const]); +/// } +/// ``` +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct AssociatedConstDatum { + /// The trait this associated const is defined in. + pub trait_id: TraitId, + + /// The ID of this associated const. + pub id: AssocConstId, + + /// Name of this associated const. + pub name: I::Identifier, + + /// Type of this associated const. + pub ty: Ty, + + /// Value of this associated const with variables `P0...Pn` + /// from the trait the assoc const is in. + pub binders: Option>>, +} + +// Manual implementation to avoid I::Identifier type. +impl Visit for AssociatedConstDatum { + fn visit_with<'i, B>( + &self, + visitor: &mut dyn chalk_ir::visit::Visitor<'i, I, BreakTy = B>, + outer_binder: DebruijnIndex, + ) -> ControlFlow + where + I: 'i, + { + try_break!(self.trait_id.visit_with(visitor, outer_binder)); + try_break!(self.id.visit_with(visitor, outer_binder)); + try_break!(self.ty.visit_with(visitor, outer_binder)); + self.binders.visit_with(visitor, outer_binder) + } +} + /// Encodes the parts of `AssociatedTyDatum` where the parameters /// `P0..Pm` are in scope (`bounds` and `where_clauses`). #[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] @@ -614,6 +666,13 @@ pub struct AssociatedTyValueBound { pub ty: Ty, } +#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)] +pub struct AssociatedConstValue { + pub impl_id: ImplId, + pub associated_const_id: AssocConstId, + pub value: Binders>, +} + /// Represents the bounds for an `impl Trait` type. /// /// ```ignore diff --git a/tests/display/assoc_const.rs b/tests/display/assoc_const.rs new file mode 100644 index 00000000000..cece6d02682 --- /dev/null +++ b/tests/display/assoc_const.rs @@ -0,0 +1,14 @@ +#[test] +fn test_trait_impl_assoc_const() { + reparse_test!( + program { + struct Foo { } + trait Bar { + const C: u32; + } + impl Bar for Foo { + const C: u32 = 3; + } + } + ); +} diff --git a/tests/display/mod.rs b/tests/display/mod.rs index dd522d3c545..b5ab1e0de74 100644 --- a/tests/display/mod.rs +++ b/tests/display/mod.rs @@ -1,6 +1,7 @@ #[macro_use] mod util; +mod assoc_const; mod assoc_ty; mod built_ins; mod const_; diff --git a/tests/display/unique_names.rs b/tests/display/unique_names.rs index a566660a46a..1a2c74e00d9 100644 --- a/tests/display/unique_names.rs +++ b/tests/display/unique_names.rs @@ -49,6 +49,9 @@ where fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId) -> String { "Foo".to_owned() } + fn assoc_const_name(&self, _assoc_const_id: chalk_ir::AssocConstId) -> String { + "Foo".to_owned() + } fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId) -> String { "Foo".to_owned() } @@ -64,6 +67,12 @@ where ) -> std::sync::Arc> { self.db.associated_ty_data(ty) } + fn associated_const_data( + &self, + ty: chalk_ir::AssocConstId, + ) -> std::sync::Arc> { + self.db.associated_const_data(ty) + } fn trait_datum( &self, trait_id: chalk_ir::TraitId, @@ -97,6 +106,12 @@ where ) -> std::sync::Arc> { self.db.associated_ty_value(id) } + fn associated_const_value( + &self, + id: chalk_solve::rust_ir::AssociatedConstValueId, + ) -> std::sync::Arc> { + self.db.associated_const_value(id) + } fn generator_datum( &self, generator_id: chalk_ir::GeneratorId, diff --git a/tests/integration/panic.rs b/tests/integration/panic.rs index 3c282aac0a2..5cb36d24618 100644 --- a/tests/integration/panic.rs +++ b/tests/integration/panic.rs @@ -58,6 +58,13 @@ impl RustIrDatabase for MockDatabase { unimplemented!() } + fn associated_const_data( + &self, + ty: AssocConstId, + ) -> Arc> { + unimplemented!() + } + // `trait Bar`, id `0` fn trait_datum(&self, id: TraitId) -> Arc> { if let PanickingMethod::TraitDatum = self.panicking_method { @@ -82,6 +89,7 @@ impl RustIrDatabase for MockDatabase { coinductive: false, }, associated_ty_ids: vec![], + associated_const_ids: vec![], well_known: None, }) } @@ -115,6 +123,7 @@ impl RustIrDatabase for MockDatabase { binders, impl_type: ImplType::Local, associated_ty_value_ids: vec![], + associated_const_value_ids: vec![], }) } @@ -125,6 +134,13 @@ impl RustIrDatabase for MockDatabase { unimplemented!() } + fn associated_const_value( + &self, + id: AssociatedConstValueId, + ) -> Arc> { + unimplemented!() + } + fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { unimplemented!() }