diff --git a/chalk-engine/src/slg.rs b/chalk-engine/src/slg.rs index f3522e77765..057133a3dc1 100644 --- a/chalk-engine/src/slg.rs +++ b/chalk-engine/src/slg.rs @@ -306,15 +306,15 @@ impl MayInvalidate { fn aggregate_projection_tys( &mut self, - new: &ProjectionTy, - current: &ProjectionTy, + new: &ProjectionTerm, + current: &ProjectionTerm, ) -> bool { - let ProjectionTy { - associated_ty_id: new_name, + let ProjectionTerm { + associated_term_id: new_name, substitution: new_substitution, } = new; - let ProjectionTy { - associated_ty_id: current_name, + let ProjectionTerm { + associated_term_id: current_name, substitution: current_substitution, } = current; diff --git a/chalk-engine/src/slg/aggregate.rs b/chalk-engine/src/slg/aggregate.rs index cce4e14dd61..761709a261c 100644 --- a/chalk-engine/src/slg/aggregate.rs +++ b/chalk-engine/src/slg/aggregate.rs @@ -382,23 +382,23 @@ impl AntiUnifier<'_, I> { fn aggregate_projection_tys( &mut self, - proj1: &ProjectionTy, - proj2: &ProjectionTy, + proj1: &ProjectionTerm, + proj2: &ProjectionTerm, ) -> Ty { let interner = self.interner; - let ProjectionTy { - associated_ty_id: name1, + let ProjectionTerm { + associated_term_id: name1, substitution: substitution1, } = proj1; - let ProjectionTy { - associated_ty_id: name2, + let ProjectionTerm { + associated_term_id: name2, substitution: substitution2, } = proj2; self.aggregate_name_and_substs(name1, substitution1, name2, substitution2) - .map(|(&associated_ty_id, substitution)| { - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id, + .map(|(&associated_term_id, substitution)| { + TyKind::Alias(AliasTy::Projection(ProjectionTerm { + associated_term_id, substitution, })) .intern(interner) diff --git a/chalk-integration/src/db.rs b/chalk-integration/src/db.rs index fda52182653..9d5b5a0d38d 100644 --- a/chalk-integration/src/db.rs +++ b/chalk-integration/src/db.rs @@ -7,15 +7,15 @@ use crate::{ tls, SolverChoice, }; use chalk_ir::{ - AdtId, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId, ConstrainedSubst, + AdtId, AssocItemId, 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, AdtSizeAlign, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, - ClosureKind, FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, - ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait, + AdtDatum, AdtRepr, AdtSizeAlign, AssociatedTermDatum, AssociatedTermValue, + AssociatedTermValueId, ClosureKind, FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, + GeneratorWitnessDatum, ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait, }; use chalk_solve::{RustIrDatabase, Solution, SubstitutionResult}; use salsa::Database; @@ -87,8 +87,8 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().custom_clauses() } - fn associated_ty_data(&self, ty: AssocTypeId) -> Arc> { - self.program_ir().unwrap().associated_ty_data(ty) + fn associated_term_data(&self, ty: AssocItemId) -> Arc> { + self.program_ir().unwrap().associated_term_data(ty) } fn trait_datum(&self, id: TraitId) -> Arc> { @@ -99,11 +99,11 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().impl_datum(id) } - fn associated_ty_value( + fn associated_term_value( &self, - id: AssociatedTyValueId, - ) -> Arc> { - self.program_ir().unwrap().associated_ty_values[&id].clone() + id: AssociatedTermValueId, + ) -> Arc> { + self.program_ir().unwrap().associated_term_values[&id].clone() } fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { @@ -235,7 +235,7 @@ impl RustIrDatabase for ChalkDatabase { self.program_ir().unwrap().adt_name(struct_id) } - fn assoc_type_name(&self, assoc_ty_id: AssocTypeId) -> String { + fn assoc_type_name(&self, assoc_ty_id: AssocItemId) -> String { self.program_ir().unwrap().assoc_type_name(assoc_ty_id) } diff --git a/chalk-integration/src/interner.rs b/chalk-integration/src/interner.rs index cef01c2cd42..e026fcd8e83 100644 --- a/chalk-integration/src/interner.rs +++ b/chalk-integration/src/interner.rs @@ -4,9 +4,9 @@ use chalk_ir::{ TyKind, }; use chalk_ir::{ - AdtId, AliasTy, AssocTypeId, CanonicalVarKind, CanonicalVarKinds, ConstData, Constraint, + AdtId, AliasTy, AssocItemId, CanonicalVarKind, CanonicalVarKinds, ConstData, Constraint, Constraints, FnDefId, Goals, InEnvironment, Lifetime, OpaqueTy, OpaqueTyId, - ProgramClauseImplication, ProgramClauses, ProjectionTy, QuantifiedWhereClauses, + ProgramClauseImplication, ProgramClauses, ProjectionTerm, QuantifiedWhereClauses, SeparatorTraitRef, Substitution, TraitId, Ty, TyData, VariableKind, VariableKinds, Variances, }; use chalk_ir::{ @@ -91,7 +91,7 @@ impl Interner for ChalkIr { } fn debug_assoc_type_id( - id: AssocTypeId, + id: AssocItemId, fmt: &mut fmt::Formatter<'_>, ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) @@ -113,7 +113,7 @@ impl Interner for ChalkIr { } fn debug_projection_ty( - proj: &ProjectionTy, + proj: &ProjectionTerm, fmt: &mut fmt::Formatter<'_>, ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index 425534d535e..05f25e6ce8a 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -48,7 +48,7 @@ impl Lower for Program { .map(|_| lowerer.next_item_id()) .collect::>(); - lowerer.extract_associated_types(self, &raw_ids)?; + lowerer.extract_associated_terms(self, &raw_ids)?; lowerer.extract_ids(self, &raw_ids)?; lowerer.lower(self, &raw_ids) } @@ -164,10 +164,10 @@ impl LowerWithEnv for WhereClause { WhereClause::Implemented { trait_ref } => { vec![chalk_ir::WhereClause::Implemented(trait_ref.lower(env)?)] } - WhereClause::ProjectionEq { projection, ty } => vec![ + WhereClause::ProjectionEq { projection, term } => vec![ chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias: chalk_ir::AliasTy::Projection(projection.lower(env)?), - ty: ty.lower(env)?, + term: term.lower(env)?, }), chalk_ir::WhereClause::Implemented(projection.trait_ref.lower(env)?), ], @@ -216,10 +216,10 @@ impl LowerWithEnv for DomainGoal { .into_iter() .casted(interner) .collect(), - DomainGoal::Normalize { projection, ty } => { + DomainGoal::Normalize { projection, term } => { vec![chalk_ir::DomainGoal::Normalize(chalk_ir::Normalize { alias: chalk_ir::AliasTy::Projection(projection.lower(env)?), - ty: ty.lower(env)?, + term: term.lower(env)?, })] } DomainGoal::TyWellFormed { ty } => vec![chalk_ir::DomainGoal::WellFormed( @@ -495,7 +495,7 @@ impl LowerWithEnv for AliasEqBound { fn lower(&self, env: &Env) -> LowerResult { let trait_bound = self.trait_bound.lower(env)?; - let lookup = env.lookup_associated_ty(trait_bound.trait_id, &self.name)?; + let lookup = env.lookup_associated_term(trait_bound.trait_id, &self.name)?; let args: Vec<_> = self .args .iter() @@ -618,11 +618,11 @@ impl Lower for TraitFlags { } } -impl LowerWithEnv for ProjectionTy { - type Lowered = chalk_ir::ProjectionTy; +impl LowerWithEnv for ProjectionTerm { + type Lowered = chalk_ir::ProjectionTerm; fn lower(&self, env: &Env) -> LowerResult { - let ProjectionTy { + let ProjectionTerm { ref trait_ref, ref name, ref args, @@ -632,7 +632,7 @@ impl LowerWithEnv for ProjectionTy { trait_id, substitution: trait_substitution, } = trait_ref.lower(env)?; - let lookup = env.lookup_associated_ty(trait_id, name)?; + let lookup = env.lookup_associated_term(trait_id, name)?; let mut args: Vec<_> = args .iter() .map(|a| a.lower(env)) @@ -658,8 +658,8 @@ impl LowerWithEnv for ProjectionTy { args.extend(trait_substitution.iter(interner).cloned()); - Ok(chalk_ir::ProjectionTy { - associated_ty_id: lookup.id, + Ok(chalk_ir::ProjectionTerm { + associated_term_id: lookup.id, substitution: chalk_ir::Substitution::from_iter(interner, args), }) } @@ -846,6 +846,17 @@ impl LowerWithEnv for Const { } } +impl LowerWithEnv for Term { + type Lowered = chalk_ir::Term; + + fn lower(&self, env: &Env) -> LowerResult { + Ok(match self { + Term::Ty(t) => chalk_ir::Term::Ty(t.lower(env)?), + Term::Const(c) => chalk_ir::Term::Const(c.lower(env)?), + }) + } +} + impl LowerWithEnv for GenericArg { type Lowered = chalk_ir::GenericArg; @@ -892,11 +903,11 @@ impl LowerWithEnv for Lifetime { } } -impl LowerWithEnv for (&Impl, ImplId, &AssociatedTyValueIds) { +impl LowerWithEnv for (&Impl, ImplId, &AssociatedTermValueIds) { 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_term_value_ids) = self; let polarity = impl_.polarity.lower(); let binders = env.in_binders(impl_.all_parameters(), |env| { @@ -917,22 +928,28 @@ impl LowerWithEnv for (&Impl, ImplId, &AssociatedTyValueIds) { }) })?; - // lookup the ids for each of the "associated type values" + // lookup the ids for each of the "associated term values" // within the impl, which should have already assigned and // stored in the map - let associated_ty_value_ids = impl_ + let assoc_const_values = impl_ + .assoc_const_values + .iter() + .map(|av| associated_term_value_ids[&(*impl_id, av.name.str.clone())]); + + let associated_term_value_ids = impl_ .assoc_ty_values .iter() - .map(|atv| associated_ty_value_ids[&(*impl_id, atv.name.str.clone())]) + .map(|av| associated_term_value_ids[&(*impl_id, av.name.str.clone())]) + .chain(assoc_const_values) .collect(); - debug!(?associated_ty_value_ids); + debug!(?associated_term_value_ids); Ok(rust_ir::ImplDatum { polarity, binders, impl_type: impl_.impl_type.lower(), - associated_ty_value_ids, + associated_term_value_ids, }) } } @@ -1000,17 +1017,25 @@ impl LowerWithEnv for (&TraitDefn, chalk_ir::TraitId) { }) })?; - let associated_ty_ids: Vec<_> = trait_defn - .assoc_ty_defns - .iter() - .map(|defn| env.lookup_associated_ty(*trait_id, &defn.name).unwrap().id) - .collect(); + let assoc_ct_ids = trait_defn.assoc_const_defns.iter().map(|defn| { + env.lookup_associated_term(*trait_id, &defn.name) + .unwrap() + .id + }); + + let assoc_ty_ids = trait_defn.assoc_ty_defns.iter().map(|defn| { + env.lookup_associated_term(*trait_id, &defn.name) + .unwrap() + .id + }); + + let associated_term_ids: Vec<_> = assoc_ty_ids.chain(assoc_ct_ids).collect(); let trait_datum = rust_ir::TraitDatum { id: *trait_id, binders, flags: trait_defn.flags.lower(), - associated_ty_ids, + associated_term_ids, well_known: trait_defn.well_known.map(|def| def.lower()), }; @@ -1022,17 +1047,17 @@ impl LowerWithEnv for (&TraitDefn, chalk_ir::TraitId) { pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult> { let interner = ChalkIr; - let associated_ty_lookups: BTreeMap<_, _> = program - .associated_ty_data + let associated_term_lookups: BTreeMap<_, _> = program + .associated_term_data .iter() - .map(|(&associated_ty_id, datum)| { + .map(|(&associated_term_id, datum)| { let trait_datum = &program.trait_data[&datum.trait_id]; let num_trait_params = trait_datum.binders.len(interner); let num_addl_params = datum.binders.len(interner) - num_trait_params; let addl_variable_kinds = datum.binders.binders.as_slice(interner)[..num_addl_params].to_owned(); - let lookup = AssociatedTyLookup { - id: associated_ty_id, + let lookup = AssociatedTermLookup { + id: associated_term_id, addl_variable_kinds, }; ((datum.trait_id, datum.name.clone()), lookup) @@ -1058,7 +1083,7 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult, TypeKind>; pub type AutoTraits = BTreeMap, bool>; pub type OpaqueTyVariableKinds = BTreeMap, TypeKind>; pub type GeneratorKinds = BTreeMap, TypeKind>; -pub type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId, Ident), AssociatedTyLookup>; -pub type AssociatedTyValueIds = - BTreeMap<(chalk_ir::ImplId, Ident), AssociatedTyValueId>; + +pub type AssociatedTermLookups = + BTreeMap<(chalk_ir::TraitId, Ident), AssociatedTermLookup>; +pub type AssociatedTermValueIds = + BTreeMap<(chalk_ir::ImplId, Ident), AssociatedTermValueId>; pub type ForeignIds = BTreeMap>; pub type ParameterMap = BTreeMap>; @@ -46,7 +48,7 @@ pub struct Env<'k> { pub trait_kinds: &'k TraitKinds, pub opaque_ty_ids: &'k OpaqueTyIds, pub opaque_ty_kinds: &'k OpaqueTyVariableKinds, - pub associated_ty_lookups: &'k AssociatedTyLookups, + pub associated_term_lookups: &'k AssociatedTermLookups, pub auto_traits: &'k AutoTraits, pub foreign_ty_ids: &'k ForeignIds, pub generator_ids: &'k GeneratorIds, @@ -70,8 +72,8 @@ pub struct Env<'k> { /// } /// ``` #[derive(Debug, PartialEq, Eq)] -pub struct AssociatedTyLookup { - pub id: chalk_ir::AssocTypeId, +pub struct AssociatedTermLookup { + pub id: chalk_ir::AssocItemId, pub addl_variable_kinds: Vec>, } @@ -212,12 +214,12 @@ impl Env<'_> { &self.generator_kinds[&id] } - pub fn lookup_associated_ty( + pub fn lookup_associated_term( &self, trait_id: TraitId, ident: &Identifier, - ) -> LowerResult<&AssociatedTyLookup> { - self.associated_ty_lookups + ) -> LowerResult<&AssociatedTermLookup> { + self.associated_term_lookups .get(&(trait_id, ident.str.clone())) .ok_or_else(|| RustIrError::MissingAssociatedType(ident.clone())) } diff --git a/chalk-integration/src/lowering/program_lowerer.rs b/chalk-integration/src/lowering/program_lowerer.rs index 187ded13d9e..f4f8104760a 100644 --- a/chalk-integration/src/lowering/program_lowerer.rs +++ b/chalk-integration/src/lowering/program_lowerer.rs @@ -1,12 +1,12 @@ use chalk_ir::cast::Cast; use chalk_ir::{ - self, AdtId, AssocTypeId, BoundVar, ClosureId, DebruijnIndex, FnDefId, ForeignDefId, + self, AdtId, AssocItemId, BoundVar, ClosureId, DebruijnIndex, FnDefId, ForeignDefId, GeneratorId, ImplId, OpaqueTyId, TraitId, TyVariableKind, VariableKinds, }; use chalk_parse::ast::*; use chalk_solve::rust_ir::{ - self, Anonymize, AssociatedTyValueId, GeneratorDatum, GeneratorInputOutputDatum, - GeneratorWitnessDatum, GeneratorWitnessExistential, OpaqueTyDatum, OpaqueTyDatumBound, + self, Anonymize, GeneratorDatum, GeneratorInputOutputDatum, GeneratorWitnessDatum, + GeneratorWitnessExistential, OpaqueTyDatum, OpaqueTyDatumBound, }; use rust_ir::IntoWhereClauses; use std::collections::{BTreeMap, HashSet}; @@ -23,8 +23,9 @@ use crate::{interner::ChalkIr, TypeKind, TypeSort}; pub(super) struct ProgramLowerer { next_item_index: u32, - associated_ty_lookups: AssociatedTyLookups, - associated_ty_value_ids: AssociatedTyValueIds, + associated_term_lookups: AssociatedTermLookups, + associated_term_value_ids: AssociatedTermValueIds, + adt_ids: AdtIds, fn_def_ids: FnDefIds, closure_ids: ClosureIds, @@ -50,7 +51,7 @@ impl ProgramLowerer { } /// Create ids for associated type declarations and values - pub fn extract_associated_types( + pub fn extract_associated_terms( &mut self, program: &Program, raw_ids: &[RawId], @@ -63,19 +64,32 @@ impl ProgramLowerer { } for defn in &d.assoc_ty_defns { let addl_variable_kinds = defn.all_parameters(); - let lookup = AssociatedTyLookup { - id: AssocTypeId(self.next_item_id()), + let lookup = AssociatedTermLookup { + id: AssocItemId(self.next_item_id()), addl_variable_kinds: addl_variable_kinds.anonymize(), }; - self.associated_ty_lookups + self.associated_term_lookups + .insert((TraitId(raw_id), defn.name.str.clone()), lookup); + } + for defn in &d.assoc_const_defns { + let lookup = AssociatedTermLookup { + id: AssocItemId(self.next_item_id()), + addl_variable_kinds: vec![], + }; + self.associated_term_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 + let atv_id = rust_ir::AssociatedTermValueId(self.next_item_id()); + self.associated_term_value_ids + .insert((ImplId(raw_id), atv.name.str.clone()), atv_id); + } + for atv in &d.assoc_const_values { + let atv_id = rust_ir::AssociatedTermValueId(self.next_item_id()); + self.associated_term_value_ids .insert((ImplId(raw_id), atv.name.str.clone()), atv_id); } } @@ -153,8 +167,8 @@ impl ProgramLowerer { let mut trait_data = BTreeMap::new(); let mut well_known_traits = BTreeMap::new(); let mut impl_data = BTreeMap::new(); - let mut associated_ty_data = BTreeMap::new(); - let mut associated_ty_values = BTreeMap::new(); + let mut associated_term_data = BTreeMap::new(); + let mut associated_term_values = BTreeMap::new(); let mut opaque_ty_data = BTreeMap::new(); let mut generator_data = BTreeMap::new(); let mut generator_witness_data = BTreeMap::new(); @@ -175,7 +189,7 @@ impl ProgramLowerer { opaque_ty_kinds: &self.opaque_ty_kinds, generator_ids: &self.generator_ids, generator_kinds: &self.generator_kinds, - associated_ty_lookups: &self.associated_ty_lookups, + associated_term_lookups: &self.associated_term_lookups, parameter_map: BTreeMap::new(), auto_traits: &self.auto_traits, foreign_ty_ids: &self.foreign_ty_ids, @@ -269,7 +283,7 @@ 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 + let lookup = &self.associated_term_lookups [&(trait_id, assoc_ty_defn.name.str.clone())]; // The parameters in scope for the associated @@ -296,15 +310,16 @@ impl ProgramLowerer { variable_kinds.extend(trait_defn.all_parameters()); let binders = empty_env.in_binders(variable_kinds, |env| { - Ok(rust_ir::AssociatedTyDatumBound { + Ok(rust_ir::AssociatedTermDatumBound { bounds: assoc_ty_defn.bounds.lower(env)?, where_clauses: assoc_ty_defn.where_clauses.lower(env)?, + assoc_const_ty: None, }) })?; - associated_ty_data.insert( + associated_term_data.insert( lookup.id, - Arc::new(rust_ir::AssociatedTyDatum { + Arc::new(rust_ir::AssociatedTermDatum { trait_id: TraitId(raw_id), id: lookup.id, name: assoc_ty_defn.name.str.clone(), @@ -312,18 +327,41 @@ impl ProgramLowerer { }), ); } + + for assoc_ct_defn in &trait_defn.assoc_const_defns { + let lookup = &self.associated_term_lookups + [&(trait_id, assoc_ct_defn.name.str.clone())]; + let binders = empty_env.in_binders(trait_defn.all_parameters(), |env| { + Ok(rust_ir::AssociatedTermDatumBound { + bounds: vec![], + where_clauses: vec![], + assoc_const_ty: Some(assoc_ct_defn.ty.lower(env)?), + }) + })?; + associated_term_data.insert( + lookup.id, + Arc::new(rust_ir::AssociatedTermDatum { + trait_id: TraitId(raw_id), + id: lookup.id, + name: assoc_ct_defn.name.str.clone(), + 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_term_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())]; + let atv_id = + self.associated_term_value_ids[&(impl_id, atv.name.str.clone())]; + let lookup = + &self.associated_term_lookups[&(trait_id, atv.name.str.clone())]; // The parameters in scope for the associated // type definitions are *both* those from the @@ -334,16 +372,35 @@ impl ProgramLowerer { 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)?, - }) + Ok(rust_ir::AssociatedTermValueBound::Ty(atv.value.lower(env)?)) })?; - associated_ty_values.insert( + associated_term_values.insert( atv_id, - Arc::new(rust_ir::AssociatedTyValue { + Arc::new(rust_ir::AssociatedTermValue { + impl_id, + associated_term_id: lookup.id, + value, + }), + ); + } + + for acv in &impl_defn.assoc_const_values { + let acv_id = + self.associated_term_value_ids[&(impl_id, acv.name.str.clone())]; + let lookup = + &self.associated_term_lookups[&(trait_id, acv.name.str.clone())]; + + let value = empty_env.in_binders(vec![], |env| { + Ok(rust_ir::AssociatedTermValueBound::Const( + acv.value.lower(env)?, + )) + })?; + associated_term_values.insert( + acv_id, + Arc::new(rust_ir::AssociatedTermValue { impl_id, - associated_ty_id: lookup.id, + associated_term_id: lookup.id, value, }), ); @@ -495,8 +552,8 @@ impl ProgramLowerer { trait_data, well_known_traits, impl_data, - associated_ty_values, - associated_ty_data, + associated_term_values, + associated_term_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 b82bd9db99e..49ed1eb4859 100644 --- a/chalk-integration/src/program.rs +++ b/chalk-integration/src/program.rs @@ -3,15 +3,15 @@ use crate::{tls, Identifier, TypeKind}; use chalk_ir::{could_match::CouldMatch, UnificationDatabase}; use chalk_ir::{debug::Angle, Variance}; use chalk_ir::{ - debug::SeparatorTraitRef, AdtId, AliasTy, AssocTypeId, Binders, CanonicalVarKinds, ClosureId, + debug::SeparatorTraitRef, AdtId, AliasTy, AssocItemId, Binders, CanonicalVarKinds, ClosureId, FnDefId, ForeignDefId, GeneratorId, GenericArg, Goal, Goals, ImplId, IntTy, Lifetime, OpaqueTy, - OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTy, Scalar, + OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTerm, Scalar, Substitution, TraitId, Ty, TyKind, UintTy, Variances, }; use chalk_solve::rust_ir::{ - AdtDatum, AdtRepr, AdtSizeAlign, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, - ClosureKind, FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, - ImplDatum, ImplType, OpaqueTyDatum, TraitDatum, WellKnownTrait, + AdtDatum, AdtRepr, AdtSizeAlign, AssociatedTermDatum, AssociatedTermValue, + AssociatedTermValueId, ClosureKind, FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, + GeneratorWitnessDatum, ImplDatum, ImplType, OpaqueTyDatum, TraitDatum, WellKnownTrait, }; use chalk_solve::split::Split; use chalk_solve::RustIrDatabase; @@ -75,8 +75,11 @@ pub struct Program { pub impl_data: BTreeMap, Arc>>, /// For each associated ty value `type Foo = XXX` found in an impl: - pub associated_ty_values: - BTreeMap, Arc>>, + pub associated_term_values: + BTreeMap, Arc>>, + + /// For each associated ty declaration `type Foo` found in a trait: + pub associated_term_data: BTreeMap, Arc>>, // From opaque type name to item-id. Used during lowering only. pub opaque_ty_ids: BTreeMap>, @@ -96,9 +99,6 @@ pub struct Program { /// For each trait lang item pub well_known_traits: BTreeMap>, - /// For each associated ty declaration `type Foo` found in a trait: - pub associated_ty_data: BTreeMap, Arc>>, - /// For each user-specified clause pub custom_clauses: Vec>, @@ -151,13 +151,13 @@ impl tls::DebugContext for Program { fn debug_assoc_type_id( &self, - assoc_type_id: AssocTypeId, + assoc_type_id: AssocItemId, fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error> { - if let Some(d) = self.associated_ty_data.get(&assoc_type_id) { + if let Some(d) = self.associated_term_data.get(&assoc_type_id) { write!(fmt, "({:?}::{})", d.trait_id, d.name) } else { - fmt.debug_struct("InvalidAssocTypeId") + fmt.debug_struct("InvalidAssocItemId") .field("index", &assoc_type_id.0) .finish() } @@ -204,7 +204,7 @@ impl tls::DebugContext for Program { fn debug_projection_ty( &self, - projection_ty: &ProjectionTy, + projection_ty: &ProjectionTerm, fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error> { let (associated_ty_data, trait_params, other_params) = self.split_projection(projection_ty); @@ -386,8 +386,11 @@ impl RustIrDatabase for Program { self.custom_clauses.clone() } - fn associated_ty_data(&self, ty: AssocTypeId) -> Arc> { - self.associated_ty_data[&ty].clone() + fn associated_term_data( + &self, + term: AssocItemId, + ) -> Arc> { + self.associated_term_data[&term].clone() } fn trait_datum(&self, id: TraitId) -> Arc> { @@ -398,11 +401,11 @@ impl RustIrDatabase for Program { self.impl_data[&id].clone() } - fn associated_ty_value( + fn associated_term_value( &self, - id: AssociatedTyValueId, - ) -> Arc> { - self.associated_ty_values[&id].clone() + id: AssociatedTermValueId, + ) -> Arc> { + self.associated_term_values[&id].clone() } fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { @@ -587,8 +590,8 @@ impl RustIrDatabase for Program { // normally acceptable, but causes the re-parse tests for the .chalk syntax // writer to fail. This is because they use the `Eq` implementation on // Program, which checks for name equality. - fn assoc_type_name(&self, assoc_type_id: AssocTypeId) -> String { - self.associated_ty_data + fn assoc_type_name(&self, assoc_type_id: AssocItemId) -> String { + self.associated_term_data .get(&assoc_type_id) .unwrap() .name diff --git a/chalk-integration/src/query.rs b/chalk-integration/src/query.rs index 1d074b953d9..f1d213e2949 100644 --- a/chalk-integration/src/query.rs +++ b/chalk-integration/src/query.rs @@ -205,7 +205,7 @@ fn environment(db: &dyn LoweringDatabase) -> Result, Cha let env = chalk_ir::Environment::new(builder.interner()); program - .associated_ty_data + .associated_term_data .values() .for_each(|d| d.to_program_clauses(builder, &env)); @@ -238,10 +238,10 @@ fn environment(db: &dyn LoweringDatabase) -> Result, Cha if datum.is_positive() { datum.to_program_clauses(builder, &env); datum - .associated_ty_value_ids + .associated_term_value_ids .iter() - .map(|&atv_id| db.associated_ty_value(atv_id)) - .for_each(|atv| atv.to_program_clauses(builder, &env)); + .map(|&av_id| db.associated_term_value(av_id)) + .for_each(|av| av.to_program_clauses(builder, &env)); } } diff --git a/chalk-integration/src/test_macros.rs b/chalk-integration/src/test_macros.rs index 96bfeb0d61e..305c7f615b7 100644 --- a/chalk-integration/src/test_macros.rs +++ b/chalk-integration/src/test_macros.rs @@ -39,8 +39,8 @@ macro_rules! ty { }; (projection (item $n:tt) $($arg:tt)*) => { - chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id: AssocTypeId(chalk_integration::interner::RawId { index: $n }), + chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTerm { + associated_term_id: AssocItemId(chalk_integration::interner::RawId { index: $n }), substitution: chalk_ir::Substitution::from_iter( chalk_integration::interner::ChalkIr, vec![$(arg!($arg)),*] as Vec> diff --git a/chalk-integration/src/tls.rs b/chalk-integration/src/tls.rs index 58b1da3dfa8..f7bf22ae3e1 100644 --- a/chalk-integration/src/tls.rs +++ b/chalk-integration/src/tls.rs @@ -1,8 +1,8 @@ use crate::interner::ChalkIr; use chalk_ir::{ - debug::SeparatorTraitRef, AdtId, AliasTy, AssocTypeId, CanonicalVarKinds, Constraints, FnDefId, + debug::SeparatorTraitRef, AdtId, AliasTy, AssocItemId, CanonicalVarKinds, Constraints, FnDefId, GenericArg, Goal, Goals, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause, - ProgramClauseImplication, ProgramClauses, ProjectionTy, QuantifiedWhereClauses, Substitution, + ProgramClauseImplication, ProgramClauses, ProjectionTerm, QuantifiedWhereClauses, Substitution, TraitId, Ty, VariableKinds, Variances, }; use std::cell::RefCell; @@ -28,7 +28,7 @@ pub trait DebugContext { fn debug_assoc_type_id( &self, - id: AssocTypeId, + id: AssocItemId, fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error>; @@ -58,7 +58,7 @@ pub trait DebugContext { fn debug_projection_ty( &self, - proj: &ProjectionTy, + proj: &ProjectionTerm, fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error>; diff --git a/chalk-ir/src/debug.rs b/chalk-ir/src/debug.rs index 08a1be78a4b..346ad683704 100644 --- a/chalk-ir/src/debug.rs +++ b/chalk-ir/src/debug.rs @@ -30,10 +30,10 @@ impl Debug for AdtId { } } -impl Debug for AssocTypeId { +impl Debug for AssocItemId { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { I::debug_assoc_type_id(*self, fmt) - .unwrap_or_else(|| write!(fmt, "AssocTypeId({:?})", self.0)) + .unwrap_or_else(|| write!(fmt, "AssocItemId({:?})", self.0)) } } @@ -150,10 +150,10 @@ impl Debug for QuantifiedWhereClauses { } } -impl Debug for ProjectionTy { +impl Debug for ProjectionTerm { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { I::debug_projection_ty(self, fmt).unwrap_or_else(|| { - unimplemented!("cannot format ProjectionTy without setting Program in tls") + unimplemented!("cannot format ProjectionTerm without setting Program in tls") }) } } @@ -694,30 +694,30 @@ impl Debug for TypeOutlives { /// Helper struct for showing debug output for projection types. pub struct ProjectionTyDebug<'a, I: Interner> { - projection_ty: &'a ProjectionTy, + projection_term: &'a ProjectionTerm, interner: I, } impl<'a, I: Interner> Debug for ProjectionTyDebug<'a, I> { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { let ProjectionTyDebug { - projection_ty, + projection_term, interner, } = self; write!( fmt, "({:?}){:?}", - projection_ty.associated_ty_id, - projection_ty.substitution.with_angle(*interner) + projection_term.associated_term_id, + projection_term.substitution.with_angle(*interner) ) } } -impl ProjectionTy { +impl ProjectionTerm { /// Show debug output for the projection type. pub fn debug(&self, interner: I) -> ProjectionTyDebug<'_, I> { ProjectionTyDebug { - projection_ty: self, + projection_term: self, interner, } } @@ -776,13 +776,13 @@ impl<'a, T: Debug> Debug for Angle<'a, T> { impl Debug for Normalize { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { - write!(fmt, "Normalize({:?} -> {:?})", self.alias, self.ty) + write!(fmt, "Normalize({:?} -> {:?})", self.alias, self.term) } } impl Debug for AliasEq { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { - write!(fmt, "AliasEq({:?} = {:?})", self.alias, self.ty) + write!(fmt, "AliasEq({:?} = {:?})", self.alias, self.term) } } diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index 9210ecac8c9..5b8d5bca675 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -213,7 +213,7 @@ macro_rules! id_fold { id_fold!(ImplId); id_fold!(AdtId); id_fold!(TraitId); -id_fold!(AssocTypeId); +id_fold!(AssocItemId); id_fold!(OpaqueTyId); id_fold!(FnDefId); id_fold!(ClosureId); diff --git a/chalk-ir/src/interner.rs b/chalk-ir/src/interner.rs index 8a3f88cc4af..40988c67321 100644 --- a/chalk-ir/src/interner.rs +++ b/chalk-ir/src/interner.rs @@ -1,6 +1,6 @@ //! Encapsulates the concrete representation of core types such as types and goals. use crate::AliasTy; -use crate::AssocTypeId; +use crate::AssocItemId; use crate::CanonicalVarKind; use crate::CanonicalVarKinds; use crate::ClosureId; @@ -23,7 +23,7 @@ use crate::ProgramClause; use crate::ProgramClauseData; use crate::ProgramClauseImplication; use crate::ProgramClauses; -use crate::ProjectionTy; +use crate::ProjectionTerm; use crate::QuantifiedWhereClause; use crate::QuantifiedWhereClauses; use crate::SeparatorTraitRef; @@ -221,7 +221,7 @@ pub trait Interner: Debug + Copy + Eq + Hash + Sized { /// Returns `None` to fallback to the default debug output. #[allow(unused_variables)] fn debug_assoc_type_id( - type_id: AssocTypeId, + type_id: AssocItemId, fmt: &mut fmt::Formatter<'_>, ) -> Option { None @@ -289,11 +289,11 @@ pub trait Interner: Debug + Copy + Eq + Hash + Sized { None } - /// Prints the debug representation of a ProjectionTy. + /// Prints the debug representation of a ProjectionTerm. /// Returns `None` to fallback to the default debug output. #[allow(unused_variables)] fn debug_projection_ty( - projection_ty: &ProjectionTy, + projection_ty: &ProjectionTerm, fmt: &mut fmt::Formatter<'_>, ) -> Option { None diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 9376a6563b0..6fd1259414a 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -382,7 +382,7 @@ pub struct ClauseId(pub I::DefId); /// /// [`associated_ty_data`]: ../chalk_solve/trait.RustIrDatabase.html#tymethod.associated_ty_data #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct AssocTypeId(pub I::DefId); +pub struct AssocItemId(pub I::DefId); /// Id for an opaque type. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -412,6 +412,22 @@ pub struct Ty { interned: I::InternedType, } +/// A Rust term (const or type). Used for associated items. +#[derive(Debug, Clone, PartialEq, Eq, Hash, HasInterner, Fold, Visit, Zip)] +pub enum Term { + /// On a trait, associated type. + Ty(Ty), + /// On a trait, associated const. + Const(Const), +} + +impl Copy for Term +where + I::InternedType: Copy, + I::InternedConst: Copy, +{ +} + impl Ty { /// Creates a type from `TyKind`. pub fn new(interner: I, data: impl CastTo>) -> Self { @@ -582,7 +598,7 @@ pub enum TyKind { Adt(AdtId, Substitution), /// an associated type like `Iterator::Item`; see `AssociatedType` for details - AssociatedType(AssocTypeId, Substitution), + AssociatedType(AssocItemId, Substitution), /// a scalar type like `bool` or `u32` Scalar(Scalar), @@ -726,7 +742,13 @@ impl TyKind { } WhereClause::AliasEq(alias_eq) => { dyn_flags |= alias_eq.alias.compute_flags(interner); - dyn_flags |= alias_eq.ty.data(interner).flags; + dyn_flags |= match &alias_eq.term { + Term::Ty(ty) => ty.data(interner).flags, + Term::Const(ct) => { + let const_data = ct.data(interner); + const_data.ty.data(interner).flags + } + }; } WhereClause::LifetimeOutlives(lifetime_outlives) => { dyn_flags |= lifetime_outlives.a.compute_flags(interner) @@ -1604,7 +1626,7 @@ pub type CanonicalVarKind = WithKind; #[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] pub enum AliasTy { /// An associated type projection. - Projection(ProjectionTy), + Projection(ProjectionTerm), /// An opaque type. Opaque(OpaqueTy), } @@ -1632,16 +1654,16 @@ impl AliasTy { /// A projection `>::AssocItem`. #[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct ProjectionTy { +pub struct ProjectionTerm { /// The id for the associated type member. - pub associated_ty_id: AssocTypeId, + pub associated_term_id: AssocItemId, /// The substitution for the projection. pub substitution: Substitution, } -impl Copy for ProjectionTy where I::InternedSubstitution: Copy {} +impl Copy for ProjectionTerm where I::InternedSubstitution: Copy {} -impl ProjectionTy { +impl ProjectionTerm { /// Gets the type parameters of the `Self` type in this alias type. pub fn self_type_parameter(&self, interner: I) -> Ty { self.substitution @@ -1737,7 +1759,7 @@ where pub enum WhereClause { /// Type implements a trait. Implemented(TraitRef), - /// Type is equal to an alias. + /// Term is equal to an alias. AliasEq(AliasEq), /// One lifetime outlives another. LifetimeOutlives(LifetimeOutlives), @@ -1750,6 +1772,7 @@ where I::InternedSubstitution: Copy, I::InternedLifetime: Copy, I::InternedType: Copy, + I::InternedConst: Copy, { } @@ -1842,7 +1865,7 @@ pub enum DomainGoal { /// True if the trait ref can be derived from in-scope where clauses. FromEnv(FromEnv), - /// True if the alias type can be normalized to some other type + /// True if the alias term can be normalized to some other term Normalize(Normalize), /// True if a type is considered to have been "defined" by the current crate. This is true for @@ -1908,6 +1931,7 @@ where I::InternedSubstitution: Copy, I::InternedLifetime: Copy, I::InternedType: Copy, + I::InternedConst: Copy, { } @@ -2017,28 +2041,30 @@ impl Copy for SubtypeGoal where I::InternedType: Copy {} #[allow(missing_docs)] pub struct Normalize { pub alias: AliasTy, - pub ty: Ty, + pub term: Term, } impl Copy for Normalize where I::InternedSubstitution: Copy, I::InternedType: Copy, + I::InternedConst: Copy, { } -/// Proves **equality** between an alias and a type. +/// Proves **equality** between an alias and a term. #[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, Zip)] #[allow(missing_docs)] pub struct AliasEq { pub alias: AliasTy, - pub ty: Ty, + pub term: Term, } impl Copy for AliasEq where I::InternedSubstitution: Copy, I::InternedType: Copy, + I::InternedConst: Copy, { } @@ -2610,6 +2636,7 @@ pub enum GoalData { impl Copy for GoalData where I::InternedType: Copy, + I::InternedConst: Copy, I::InternedLifetime: Copy, I::InternedGenericArg: Copy, I::InternedSubstitution: Copy, diff --git a/chalk-ir/src/visit/boring_impls.rs b/chalk-ir/src/visit/boring_impls.rs index d4e52d15b35..36884306016 100644 --- a/chalk-ir/src/visit/boring_impls.rs +++ b/chalk-ir/src/visit/boring_impls.rs @@ -5,7 +5,7 @@ //! The more interesting impls of `Visit` remain in the `visit` module. use crate::{ - try_break, AdtId, AssocTypeId, ClausePriority, ClosureId, Constraints, ControlFlow, + try_break, AdtId, AssocItemId, 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, @@ -196,7 +196,7 @@ id_visit!(ImplId); id_visit!(AdtId); id_visit!(TraitId); id_visit!(OpaqueTyId); -id_visit!(AssocTypeId); +id_visit!(AssocItemId); id_visit!(FnDefId); id_visit!(ClosureId); id_visit!(GeneratorId); diff --git a/chalk-ir/src/zip.rs b/chalk-ir/src/zip.rs index f17a5f84bf2..5c71be20786 100644 --- a/chalk-ir/src/zip.rs +++ b/chalk-ir/src/zip.rs @@ -282,7 +282,7 @@ macro_rules! eq_zip { eq_zip!(I => AdtId); eq_zip!(I => TraitId); -eq_zip!(I => AssocTypeId); +eq_zip!(I => AssocItemId); eq_zip!(I => OpaqueTyId); eq_zip!(I => GeneratorId); eq_zip!(I => ForeignDefId); @@ -457,7 +457,7 @@ impl Zip for TraitRef { } } -impl Zip for ProjectionTy { +impl Zip for ProjectionTerm { fn zip_with>( zipper: &mut Z, variance: Variance, @@ -465,7 +465,12 @@ impl Zip for ProjectionTy { b: &Self, ) -> Fallible<()> { let interner = zipper.interner(); - Zip::zip_with(zipper, variance, &a.associated_ty_id, &b.associated_ty_id)?; + Zip::zip_with( + zipper, + variance, + &a.associated_term_id, + &b.associated_term_id, + )?; zipper.zip_substs( variance, None, diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 3ed826479ad..60199d1c96d 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -142,6 +142,7 @@ pub struct TraitDefn { pub variable_kinds: Vec, pub where_clauses: Vec, pub assoc_ty_defns: Vec, + pub assoc_const_defns: Vec, pub flags: TraitFlags, pub well_known: Option, } @@ -182,6 +183,12 @@ pub struct AssocTyDefn { pub where_clauses: Vec, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AssocConstDefn { + pub name: Identifier, + pub ty: Ty, +} + #[derive(Clone, PartialEq, Eq, Debug)] pub struct OpaqueTyDefn { pub ty: Ty, @@ -269,6 +276,7 @@ pub struct Impl { pub polarity: Polarity, pub where_clauses: Vec, pub assoc_ty_values: Vec, + pub assoc_const_values: Vec, pub impl_type: ImplType, } @@ -286,6 +294,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 { @@ -300,7 +315,7 @@ pub enum Ty { args: Vec, }, Projection { - proj: ProjectionTy, + proj: ProjectionTerm, }, ForAll { lifetime_names: Vec, @@ -395,7 +410,13 @@ pub enum Lifetime { } #[derive(Clone, PartialEq, Eq, Debug)] -pub struct ProjectionTy { +pub enum Term { + Ty(Ty), + Const(Const), +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ProjectionTerm { pub trait_ref: TraitRef, pub name: Identifier, pub args: Vec, @@ -440,28 +461,66 @@ impl fmt::Display for Identifier { #[derive(Clone, PartialEq, Eq, Debug)] pub enum WhereClause { - Implemented { trait_ref: TraitRef }, - ProjectionEq { projection: ProjectionTy, ty: Ty }, - LifetimeOutlives { a: Lifetime, b: Lifetime }, - TypeOutlives { ty: Ty, lifetime: Lifetime }, + Implemented { + trait_ref: TraitRef, + }, + ProjectionEq { + projection: ProjectionTerm, + term: Term, + }, + LifetimeOutlives { + a: Lifetime, + b: Lifetime, + }, + TypeOutlives { + ty: Ty, + lifetime: Lifetime, + }, } #[derive(Clone, PartialEq, Eq, Debug)] pub enum DomainGoal { - Holds { where_clause: WhereClause }, - Normalize { projection: ProjectionTy, ty: Ty }, - TraitRefWellFormed { trait_ref: TraitRef }, - TyWellFormed { ty: Ty }, - TyFromEnv { ty: Ty }, - TraitRefFromEnv { trait_ref: TraitRef }, - IsLocal { ty: Ty }, - IsUpstream { ty: Ty }, - IsFullyVisible { ty: Ty }, - LocalImplAllowed { trait_ref: TraitRef }, + Holds { + where_clause: WhereClause, + }, + + Normalize { + projection: ProjectionTerm, + term: Term, + }, + + TraitRefWellFormed { + trait_ref: TraitRef, + }, + TyWellFormed { + ty: Ty, + }, + TyFromEnv { + ty: Ty, + }, + TraitRefFromEnv { + trait_ref: TraitRef, + }, + IsLocal { + ty: Ty, + }, + IsUpstream { + ty: Ty, + }, + IsFullyVisible { + ty: Ty, + }, + LocalImplAllowed { + trait_ref: TraitRef, + }, Compatible, - DownstreamType { ty: Ty }, + DownstreamType { + ty: Ty, + }, Reveal, - ObjectSafe { id: Identifier }, + ObjectSafe { + id: Identifier, + }, } #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 0eaa460facd..ce6b8bafe5d 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -257,12 +257,13 @@ ClosureArgs: Vec = { TraitDefn: TraitDefn = { "trait" > - "{" "}" => TraitDefn + "{" "}" => TraitDefn { name: n, variable_kinds: p, where_clauses: w, assoc_ty_defns: a, + assoc_const_defns: ac, well_known, flags: TraitFlags { auto: auto.is_some(), @@ -289,6 +290,15 @@ AssocTyDefn: AssocTyDefn = { } }; +AssocConstDefn: AssocConstDefn = { + "const" ":" ";" => { + AssocConstDefn { + name: name, + ty: ty, + } + } +}; + OpaqueTyDefn: OpaqueTyDefn = { "opaque" "type" > >)?> "=" ";" => { @@ -344,7 +354,7 @@ QuantifiedInlineBound: QuantifiedInlineBound = { Impl: Impl = { "impl" > > "for" - "{" "}" => + "{" "}" => { let mut args = vec![GenericArg::Ty(s)]; args.extend(a); @@ -357,6 +367,7 @@ Impl: Impl = { }, where_clauses: w, assoc_ty_values: assoc, + assoc_const_values: assoc_const, impl_type: external.map(|_| ImplType::External).unwrap_or(ImplType::Local), } }, @@ -387,6 +398,14 @@ AssocTyValue: AssocTyValue = { }, }; +AssocConstValue: AssocConstValue = { + "const" ":" "=" ";" => AssocConstValue { + name:n, + ty: ty, + value:v, + }, +}; + pub Ty: Ty = { => Ty::Id { name: n }, TyWithoutId, @@ -429,7 +448,7 @@ TyWithoutId: Ty = { lifetime: l, }, "<" > ">" => Ty::Apply { name: n, args: a }, - => Ty::Projection { proj: p }, + => Ty::Projection { proj: p }, "(" ")" => t, "*" => Ty::Raw{ mutability: m, ty: Box::new(t) }, "&" "mut" => Ty::Ref{ mutability: Mutability::Mut, lifetime: l, ty: Box::new(t) }, @@ -467,7 +486,7 @@ FloatTy: FloatTy = { ScalarType: ScalarType = { => ScalarType::Int(i), => ScalarType::Uint(u), - => ScalarType::Float(f), + => ScalarType::Float(f), "bool" => ScalarType::Bool, "char" => ScalarType::Char, }; @@ -511,8 +530,8 @@ GenericArg: GenericArg = { ConstWithoutId => GenericArg::Const(<>), }; -ProjectionTy: ProjectionTy = { - "<" > ">" "::" > => ProjectionTy { +ProjectionTerm: ProjectionTerm = { + "<" > ">" "::" > => ProjectionTerm { trait_ref: t, name: n, args: a }, }; @@ -569,6 +588,14 @@ InlineClause: Clause = { WhereClause: WhereClause = { > => WhereClause::Implemented { trait_ref: t }, + ":" "<" "const" "=" ">" => { + let args = vec![GenericArg::Ty(s)]; + let trait_ref = TraitRef { trait_name: t, args: args }; + let projection = ProjectionTerm { trait_ref, name, args: vec![] }; + + WhereClause::ProjectionEq { projection, term: Term::Const(val) } + }, + // `T: Foo` -- projection equality ":" "<" > ",")?> > "=" ">" => @@ -576,8 +603,8 @@ WhereClause: WhereClause = { let mut args = vec![GenericArg::Ty(s)]; if let Some(a) = a { args.extend(a); } let trait_ref = TraitRef { trait_name: t, args: args }; - let projection = ProjectionTy { trait_ref, name, args: a2 }; - WhereClause::ProjectionEq { projection, ty } + let projection = ProjectionTerm { trait_ref, name, args: a2 }; + WhereClause::ProjectionEq { projection, term: Term::Ty(ty) } }, // 'a: 'b @@ -620,7 +647,8 @@ DomainGoal: DomainGoal = { "FromEnv" "(" > ")" => DomainGoal::TraitRefFromEnv { trait_ref: t }, // `::U -> Bar` -- a normalization - "Normalize" "(" "->" ")" => DomainGoal::Normalize { projection: s, ty: t }, + "Normalize" "(" "->" ")" => + DomainGoal::Normalize { projection: s, term: Term::Ty(t) }, "IsLocal" "(" ")" => DomainGoal::IsLocal { ty }, "IsUpstream" "(" ")" => DomainGoal::IsUpstream { ty }, diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index e795c8fd63e..c5612b7603a 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -513,7 +513,7 @@ pub fn program_clauses_that_could_match( push_alias_alias_eq_clause( builder, proj.clone(), - alias_eq.ty.clone(), + alias_eq.term.clone(), alias.clone(), ); return Ok(clauses); @@ -531,7 +531,7 @@ pub fn program_clauses_that_could_match( _ => {} } - db.associated_ty_data(proj.associated_ty_id) + db.associated_term_data(proj.associated_term_id) .to_program_clauses(builder, environment) } AliasTy::Opaque(opaque_ty) => db @@ -586,7 +586,7 @@ pub fn program_clauses_that_could_match( | DomainGoal::IsFullyVisible(ty) | DomainGoal::IsLocal(ty) => match_ty(builder, environment, ty)?, DomainGoal::FromEnv(_) => (), // Computed in the environment - DomainGoal::Normalize(Normalize { alias, ty: _ }) => match alias { + DomainGoal::Normalize(Normalize { alias, term: _ }) => match alias { AliasTy::Projection(proj) => { // Normalize goals derive from `AssociatedTyValue` datums, // which are found in impls. That is, if we are @@ -599,7 +599,7 @@ pub fn program_clauses_that_could_match( // type Item = Bar; // <-- associated type value // } // ``` - let associated_ty_datum = db.associated_ty_data(proj.associated_ty_id); + let associated_ty_datum = db.associated_term_data(proj.associated_term_id); let trait_id = associated_ty_datum.trait_id; let trait_parameters = db.trait_parameters_from_projection(proj); @@ -639,7 +639,7 @@ pub fn program_clauses_that_could_match( builder, interner, trait_id, - proj.associated_ty_id, + proj.associated_term_id, ); } } @@ -665,13 +665,13 @@ fn push_clauses_for_compatible_normalize( builder: &mut ClauseBuilder<'_, I>, interner: I, trait_id: TraitId, - associated_ty_id: AssocTypeId, + associated_ty_id: AssocItemId, ) { let trait_datum = db.trait_datum(trait_id); let trait_binders = trait_datum.binders.map_ref(|b| &b.where_clauses).cloned(); builder.push_binders(trait_binders, |builder, where_clauses| { - let projection = ProjectionTy { - associated_ty_id, + let projection = ProjectionTerm { + associated_term_id: associated_ty_id, substitution: builder.substitution_in_scope(), }; let trait_ref = TraitRef { @@ -684,7 +684,7 @@ fn push_clauses_for_compatible_normalize( for i in 0..type_parameters.len() { builder.push_clause( DomainGoal::Normalize(Normalize { - ty: target_ty.clone(), + term: Term::Ty(target_ty.clone()), alias: AliasTy::Projection(projection.clone()), }), where_clauses @@ -741,8 +741,8 @@ fn push_program_clauses_for_associated_type_values_in_impls_of( debug!(?impl_id); - for &atv_id in &impl_datum.associated_ty_value_ids { - let atv = builder.db.associated_ty_value(atv_id); + for &atv_id in &impl_datum.associated_term_value_ids { + let atv = builder.db.associated_term_value(atv_id); debug!(?atv_id, ?atv); atv.to_program_clauses(builder, environment); } @@ -787,7 +787,7 @@ fn push_alias_implemented_clause( DomainGoal::Holds(WhereClause::Implemented(fresh_self_trait_ref)), DomainGoal::Holds(WhereClause::AliasEq(AliasEq { alias: alias.clone(), - ty: bound_var, + term: Term::Ty(bound_var), })), ], ); @@ -797,19 +797,19 @@ fn push_alias_implemented_clause( fn push_alias_alias_eq_clause( builder: &mut ClauseBuilder<'_, I>, - projection_ty: ProjectionTy, - ty: Ty, + projection_term: ProjectionTerm, + term: Term, alias: AliasTy, ) { let interner = builder.interner(); assert_eq!( - *projection_ty.self_type_parameter(interner).kind(interner), + *projection_term.self_type_parameter(interner).kind(interner), TyKind::Alias(alias.clone()) ); // TODO: instead generate clauses without reference to the specific type parameters of the goal? - let generalized = generalize::Generalize::apply(interner, (projection_ty, ty, alias)); - builder.push_binders(generalized, |builder, (projection_ty, ty, alias)| { + let generalized = generalize::Generalize::apply(interner, (projection_term, term, alias)); + builder.push_binders(generalized, |builder, (projection_term, term, alias)| { let binders = Binders::with_fresh_type_var(interner, |ty_var| ty_var); // forall<..., T> { @@ -819,28 +819,28 @@ fn push_alias_alias_eq_clause( let fresh_self_subst = Substitution::from_iter( interner, std::iter::once(bound_var.clone().cast(interner)).chain( - projection_ty.substitution.as_slice(interner)[1..] + projection_term.substitution.as_slice(interner)[1..] .iter() .cloned(), ), ); - let fresh_alias = AliasTy::Projection(ProjectionTy { - associated_ty_id: projection_ty.associated_ty_id, + let fresh_alias = AliasTy::Projection(ProjectionTerm { + associated_term_id: projection_term.associated_term_id, substitution: fresh_self_subst, }); builder.push_clause( DomainGoal::Holds(WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(projection_ty.clone()), - ty: ty.clone(), + alias: AliasTy::Projection(projection_term.clone()), + term: term.clone(), })), &[ DomainGoal::Holds(WhereClause::AliasEq(AliasEq { alias: fresh_alias, - ty: ty.clone(), + term: term.clone(), })), DomainGoal::Holds(WhereClause::AliasEq(AliasEq { alias: alias.clone(), - ty: bound_var, + term: Term::Ty(bound_var), })), ], ); @@ -880,7 +880,7 @@ fn match_ty( TyKind::Error => {} TyKind::AssociatedType(type_id, _) => builder .db - .associated_ty_data(*type_id) + .associated_term_data(*type_id) .to_program_clauses(builder, environment), TyKind::FnDef(fn_def_id, _) => builder .db @@ -1033,7 +1033,7 @@ fn match_ty( } TyKind::Alias(AliasTy::Projection(proj)) => builder .db - .associated_ty_data(proj.associated_ty_id) + .associated_term_data(proj.associated_term_id) .to_program_clauses(builder, environment), TyKind::Alias(AliasTy::Opaque(opaque_ty)) => builder .db @@ -1089,10 +1089,10 @@ fn match_alias_ty( environment: &Environment, alias: &AliasTy, ) { - if let AliasTy::Projection(projection_ty) = alias { + if let AliasTy::Projection(projection_term) = alias { builder .db - .associated_ty_data(projection_ty.associated_ty_id) + .associated_term_data(projection_term.associated_term_id) .to_program_clauses(builder, environment) } } diff --git a/chalk-solve/src/clauses/builder.rs b/chalk-solve/src/clauses/builder.rs index de63f33dabc..5969890dbbe 100644 --- a/chalk-solve/src/clauses/builder.rs +++ b/chalk-solve/src/clauses/builder.rs @@ -201,6 +201,28 @@ impl<'me, I: Interner> ClauseBuilder<'me, I> { }); } + /// Push a single binder, for a const, at the end of the binder + /// list. The indices of previously bound variables are + /// unaffected and hence the context remains usable. Invokes `op`, + /// passing a const representing this new const variable in as an + /// argument. + pub fn push_bound_const(&mut self, ty: Ty, op: impl FnOnce(&mut Self, Const)) { + let interner = self.interner(); + let binders = Binders::new( + VariableKinds::from1(interner, VariableKind::Const(ty)), + PhantomData::, + ); + self.push_binders(binders, |this, PhantomData| { + let ct = this + .placeholders_in_scope() + .last() + .unwrap() + .assert_const_ref(interner) + .clone(); + op(this, ct) + }); + } + pub fn interner(&self) -> I { self.db.interner() } diff --git a/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs b/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs index 27d49df7597..62ab24cf7b4 100644 --- a/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs +++ b/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs @@ -1,7 +1,7 @@ use crate::clauses::ClauseBuilder; use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait}; use chalk_ir::{ - AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind, TyVariableKind, + AliasTy, Floundered, Normalize, ProjectionTerm, Substitution, Term, Ty, TyKind, TyVariableKind, }; pub fn add_discriminant_clauses( @@ -50,7 +50,7 @@ pub fn add_discriminant_clauses( .unwrap(); let trait_datum = db.trait_datum(trait_id); - let associated_ty_id = trait_datum.associated_ty_ids[0]; + let associated_ty_id = trait_datum.associated_term_ids[0]; let substitution = Substitution::from1(interner, self_ty); let trait_ref = TraitRef { @@ -59,11 +59,11 @@ pub fn add_discriminant_clauses( }; let normalize = Normalize { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id, + alias: AliasTy::Projection(ProjectionTerm { + associated_term_id: associated_ty_id, substitution, }), - ty: disc_ty, + term: Term::Ty(disc_ty), }; builder.push_fact(trait_ref); diff --git a/chalk-solve/src/clauses/builtin_traits/fn_family.rs b/chalk-solve/src/clauses/builtin_traits/fn_family.rs index f2358bc7300..768703dbf41 100644 --- a/chalk-solve/src/clauses/builtin_traits/fn_family.rs +++ b/chalk-solve/src/clauses/builtin_traits/fn_family.rs @@ -3,7 +3,7 @@ use crate::rust_ir::{ClosureKind, FnDefInputsAndOutputDatum, WellKnownTrait}; use crate::{Interner, RustIrDatabase, TraitRef}; use chalk_ir::cast::Cast; use chalk_ir::{ - AliasTy, Binders, Normalize, ProjectionTy, Safety, Substitution, TraitId, Ty, TyKind, + AliasTy, Binders, Normalize, ProjectionTerm, Safety, Substitution, Term, TraitId, Ty, TyKind, }; fn push_clauses( @@ -28,21 +28,21 @@ fn push_clauses( if let WellKnownTrait::FnOnce = well_known { let trait_datum = db.trait_datum(trait_id); assert_eq!( - trait_datum.associated_ty_ids.len(), + trait_datum.associated_term_ids.len(), 1, "FnOnce trait should have exactly one associated type, found {:?}", - trait_datum.associated_ty_ids + trait_datum.associated_term_ids ); // Constructs the alias. For `Fn`, for example, this would look like // `Normalize( B as FnOnce<(A,)>>::Output -> B)` - let output_id = trait_datum.associated_ty_ids[0]; - let alias = AliasTy::Projection(ProjectionTy { - associated_ty_id: output_id, + let output_id = trait_datum.associated_term_ids[0]; + let alias = AliasTy::Projection(ProjectionTerm { + associated_term_id: output_id, substitution, }); builder.push_fact(Normalize { alias, - ty: return_type, + term: Term::Ty(return_type), }); } } diff --git a/chalk-solve/src/clauses/builtin_traits/generator.rs b/chalk-solve/src/clauses/builtin_traits/generator.rs index 67415bfd76d..141a31c10ee 100644 --- a/chalk-solve/src/clauses/builtin_traits/generator.rs +++ b/chalk-solve/src/clauses/builtin_traits/generator.rs @@ -2,7 +2,7 @@ use crate::clauses::ClauseBuilder; use crate::rust_ir::WellKnownTrait; use crate::{Interner, RustIrDatabase, TraitRef}; use chalk_ir::cast::Cast; -use chalk_ir::{AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind}; +use chalk_ir::{AliasTy, Floundered, Normalize, ProjectionTerm, Substitution, Term, Ty, TyKind}; /// Add implicit impls of the generator trait, i.e., add a clause that all generators implement /// `Generator` and clauses for `Generator`'s associated types. @@ -24,10 +24,10 @@ pub fn add_generator_program_clauses( let trait_id = db.well_known_trait_id(WellKnownTrait::Generator).unwrap(); let trait_datum = db.trait_datum(trait_id); assert_eq!( - trait_datum.associated_ty_ids.len(), + trait_datum.associated_term_ids.len(), 2, "Generator trait should have exactly two associated types, found {:?}", - trait_datum.associated_ty_ids + trait_datum.associated_term_ids ); let substitution = Substitution::from_iter( @@ -45,25 +45,25 @@ pub fn add_generator_program_clauses( }); // `Generator::Yield` - let yield_id = trait_datum.associated_ty_ids[0]; - let yield_alias = AliasTy::Projection(ProjectionTy { - associated_ty_id: yield_id, + let yield_id = trait_datum.associated_term_ids[0]; + let yield_alias = AliasTy::Projection(ProjectionTerm { + associated_term_id: yield_id, substitution: substitution.clone(), }); builder.push_fact(Normalize { alias: yield_alias, - ty: generator_io_datum.yield_type, + term: Term::Ty(generator_io_datum.yield_type), }); // `Generator::Return` - let return_id = trait_datum.associated_ty_ids[1]; - let return_alias = AliasTy::Projection(ProjectionTy { - associated_ty_id: return_id, + let return_id = trait_datum.associated_term_ids[1]; + let return_alias = AliasTy::Projection(ProjectionTerm { + associated_term_id: return_id, substitution, }); builder.push_fact(Normalize { alias: return_alias, - ty: generator_io_datum.return_type, + term: Term::Ty(generator_io_datum.return_type), }); Ok(()) diff --git a/chalk-solve/src/clauses/env_elaborator.rs b/chalk-solve/src/clauses/env_elaborator.rs index 3c490258029..d0009b5189e 100644 --- a/chalk-solve/src/clauses/env_elaborator.rs +++ b/chalk-solve/src/clauses/env_elaborator.rs @@ -91,9 +91,9 @@ impl<'me, 'builder, I: Interner> Visitor for EnvElaborator<'me, 'builder, I> // If we know that `T: Iterator`, then we also know // things about `::Item`, so push those // implied bounds too: - for &associated_ty_id in &trait_datum.associated_ty_ids { + for &ai in &trait_datum.associated_term_ids { self.db - .associated_ty_data(associated_ty_id) + .associated_term_data(ai) .to_program_clauses(self.builder, self.environment); } ControlFlow::Continue(()) diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 19811ff8b30..ae908ae781b 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -49,7 +49,7 @@ impl ToProgramClauses for ImplDatum { } } -impl ToProgramClauses for AssociatedTyValue { +impl ToProgramClauses for AssociatedTermValue { /// Given the following trait: /// /// ```notrust @@ -81,9 +81,9 @@ impl ToProgramClauses for AssociatedTyValue { _environment: &Environment, ) { let impl_datum = builder.db.impl_datum(self.impl_id); - let associated_ty = builder.db.associated_ty_data(self.associated_ty_id); + let associated_term = builder.db.associated_term_data(self.associated_term_id); - builder.push_binders(self.value.clone(), |builder, assoc_ty_value| { + builder.push_binders(self.value.clone(), |builder, assoc_term_value| { let all_parameters = builder.placeholders_in_scope().to_vec(); // Get the projection for this associated type: @@ -107,7 +107,7 @@ impl ToProgramClauses for AssociatedTyValue { // 2. any where-clauses from the `type` declaration in the trait: the // parameters must be substituted with those of the impl - let assoc_ty_where_clauses = associated_ty + let assoc_term_where_clauses = associated_term .binders .map_ref(|b| &b.where_clauses) .into_iter() @@ -123,13 +123,20 @@ impl ToProgramClauses for AssociatedTyValue { // Implemented(Iter<'a, T>: 'a). // (2) // } // ``` - builder.push_clause( - Normalize { - alias: AliasTy::Projection(projection.clone()), - ty: assoc_ty_value.ty, - }, - impl_where_clauses.chain(assoc_ty_where_clauses), - ); + match assoc_term_value { + AssociatedTermValueBound::Ty(ty) => { + builder.push_clause( + Normalize { + alias: AliasTy::Projection(projection.clone()), + term: Term::Ty(ty), + }, + impl_where_clauses.chain(assoc_term_where_clauses), + ); + } + AssociatedTermValueBound::Const(ct) => { + todo!(); + } + } }); } } @@ -167,7 +174,7 @@ impl ToProgramClauses for OpaqueTyDatum { DomainGoal::Holds( AliasEq { alias: alias.clone(), - ty: builder.db.hidden_opaque_type(self.opaque_ty_id), + term: Term::Ty(builder.db.hidden_opaque_type(self.opaque_ty_id)), } .cast(interner), ), @@ -178,7 +185,7 @@ impl ToProgramClauses for OpaqueTyDatum { builder.push_fact(DomainGoal::Holds( AliasEq { alias, - ty: alias_placeholder_ty.clone(), + term: Term::Ty(alias_placeholder_ty.clone()), } .cast(interner), )); @@ -722,7 +729,7 @@ impl ToProgramClauses for TraitDatum { } } -impl ToProgramClauses for AssociatedTyDatum { +impl ToProgramClauses for AssociatedTermDatum { /// For each associated type, we define the "projection /// equality" rules. There are always two; one for a successful normalization, /// and one for the "fallback" notion of equality. @@ -798,17 +805,20 @@ impl ToProgramClauses for AssociatedTyDatum { ) { let interner = builder.interner(); let binders = self.binders.clone(); + // otherwise known to be a type. + builder.push_binders( binders, |builder, - AssociatedTyDatumBound { + AssociatedTermDatumBound { where_clauses, bounds, + assoc_const_ty, }| { let substitution = builder.substitution_in_scope(); - let projection = ProjectionTy { - associated_ty_id: self.id, + let projection = ProjectionTerm { + associated_term_id: self.id, substitution: substitution.clone(), }; let projection_ty = AliasTy::Projection(projection.clone()).intern(interner); @@ -822,7 +832,7 @@ impl ToProgramClauses for AssociatedTyDatum { let projection_eq = AliasEq { alias: AliasTy::Projection(projection.clone()), - ty: ty.clone(), + term: Term::Ty(ty.clone()), }; // Fallback rule. The solver uses this to move between the projection @@ -879,8 +889,8 @@ impl ToProgramClauses for AssociatedTyDatum { // forall { // FromEnv(::Assoc: Bounds) :- FromEnv(Self: Foo), WC // } - for quantified_bound in bounds { - builder.push_binders(quantified_bound, |builder, bound| { + for quantified_bound in bounds.iter() { + builder.push_binders(quantified_bound.clone(), |builder, bound| { for wc in bound.into_where_clauses(interner, projection_ty.clone()) { builder.push_clause( wc.into_from_env_goal(interner), @@ -898,13 +908,13 @@ impl ToProgramClauses for AssociatedTyDatum { // `Normalize(::Assoc -> U)` let normalize = Normalize { alias: AliasTy::Projection(projection.clone()), - ty: ty.clone(), + term: Term::Ty(ty.clone()), }; // `AliasEq(::Assoc = U)` let projection_eq = AliasEq { - alias: AliasTy::Projection(projection), - ty, + alias: AliasTy::Projection(projection.clone()), + term: Term::Ty(ty), }; // Projection equality rule from above. @@ -915,6 +925,17 @@ impl ToProgramClauses for AssociatedTyDatum { // } builder.push_clause(projection_eq, Some(normalize)); }); + if let Some(act) = assoc_const_ty { + builder.push_bound_const(act, |builder, ct| { + // `AliasEq(::Assoc = U)` + let projection_eq = AliasEq { + alias: AliasTy::Projection(projection), + term: Term::Const(ct), + }; + builder.push_fact(projection_eq); + }); + // todo!() + } }, ); } diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs index 3110b03e8d1..7e99b8fc134 100644 --- a/chalk-solve/src/clauses/super_traits.rs +++ b/chalk-solve/src/clauses/super_traits.rs @@ -93,9 +93,9 @@ pub fn super_traits( } Some(tr.clone()) } - WhereClause::AliasEq(_) => None, - WhereClause::LifetimeOutlives(..) => None, - WhereClause::TypeOutlives(..) => None, + WhereClause::AliasEq(_) + | WhereClause::LifetimeOutlives(..) + | WhereClause::TypeOutlives(..) => None, }) }) .collect::>() diff --git a/chalk-solve/src/coinductive_goal.rs b/chalk-solve/src/coinductive_goal.rs index cdb5cca108d..4b3ef490c54 100644 --- a/chalk-solve/src/coinductive_goal.rs +++ b/chalk-solve/src/coinductive_goal.rs @@ -23,9 +23,9 @@ impl IsCoinductive for Goal { db.trait_datum(tr.trait_id).is_auto_trait() || db.trait_datum(tr.trait_id).is_coinductive_trait() } - WhereClause::AliasEq(..) => false, - WhereClause::LifetimeOutlives(..) => false, - WhereClause::TypeOutlives(..) => false, + WhereClause::AliasEq(_) + | WhereClause::LifetimeOutlives(..) + | WhereClause::TypeOutlives(..) => false, }, GoalData::DomainGoal(DomainGoal::WellFormed(WellFormed::Trait(..))) => true, GoalData::Quantified(QuantifierKind::ForAll, goal) => { diff --git a/chalk-solve/src/display.rs b/chalk-solve/src/display.rs index bb1f7a3c542..00334ba6b88 100644 --- a/chalk-solve/src/display.rs +++ b/chalk-solve/src/display.rs @@ -159,7 +159,7 @@ fn display_self_where_clauses_as_bounds<'a, I: Interner>( assoc_ty_datum, &trait_params[1..], assoc_type_params, - &alias_eq.ty, + &alias_eq.term, ) .fmt(f) } @@ -198,10 +198,10 @@ fn display_type_with_generics<'a, I: Interner>( /// This is shared between where bounds & dyn Trait. fn display_trait_with_assoc_ty_value<'a, I: Interner>( s: &'a InternalWriterState<'a, I>, - assoc_ty_datum: Arc>, + assoc_ty_datum: Arc>, trait_params: &'a [GenericArg], assoc_ty_params: &'a [GenericArg], - assoc_ty_value: &'a Ty, + assoc_term_value: &'a Term, ) -> impl Display + 'a { as_display(move |f| { write!(f, "{}<", assoc_ty_datum.trait_id.display(s))?; @@ -218,7 +218,10 @@ fn display_trait_with_assoc_ty_value<'a, I: Interner>( assoc_ty_params.iter().map(|param| param.display(s)), ", " )?; - write!(f, "={}>", assoc_ty_value.display(s))?; + match assoc_term_value { + Term::Ty(t) => write!(f, "={}>", t.display(s))?, + Term::Const(ct) => write!(f, "={}>", ct.display(s))?, + } Ok(()) }) } diff --git a/chalk-solve/src/display/bounds.rs b/chalk-solve/src/display/bounds.rs index 3c6bfde14f4..fe684c7c192 100644 --- a/chalk-solve/src/display/bounds.rs +++ b/chalk-solve/src/display/bounds.rs @@ -34,10 +34,10 @@ impl RenderAsRust for AliasEqBound { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { display_trait_with_assoc_ty_value( s, - s.db().associated_ty_data(self.associated_ty_id), + s.db().associated_term_data(self.associated_ty_id), &self.trait_bound.args_no_self, &self.parameters, - &self.value, + &Term::Ty(self.value.clone()), ) .fmt(f) } @@ -144,7 +144,7 @@ impl RenderAsRust for AliasEq { assoc_ty_datum, &trait_params[1..], assoc_type_params, - &self.ty + &self.term, ), ) } diff --git a/chalk-solve/src/display/identifiers.rs b/chalk-solve/src/display/identifiers.rs index 81a08d71b30..1476a0cff43 100644 --- a/chalk-solve/src/display/identifiers.rs +++ b/chalk-solve/src/display/identifiers.rs @@ -31,7 +31,7 @@ impl RenderAsRust for TraitId { } } -impl RenderAsRust for AssocTypeId { +impl RenderAsRust for AssocItemId { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { // TODO: use debug methods? write!( diff --git a/chalk-solve/src/display/items.rs b/chalk-solve/src/display/items.rs index 78ebbfac184..32f0419bcd4 100644 --- a/chalk-solve/src/display/items.rs +++ b/chalk-solve/src/display/items.rs @@ -228,9 +228,9 @@ impl RenderAsRust for TraitDatum { write_joined_non_empty_list!( f, "\n{}\n", - self.associated_ty_ids.iter().map(|assoc_ty_id| { - let assoc_ty_data = s.db().associated_ty_data(*assoc_ty_id); - format!("{}{}", s.indent(), (*assoc_ty_data).display(s)) + self.associated_term_ids.iter().map(|assoc_id| { + let assoc_data = s.db().associated_term_data(*assoc_id); + format!("{}{}", s.indent(), (*assoc_data).display(s)) }), "\n" )?; @@ -299,12 +299,10 @@ impl RenderAsRust for ImplDatum { write!(f, "{{")?; { let s = &s.add_indent(); - let assoc_ty_values = self.associated_ty_value_ids.iter().map(|assoc_ty_value| { - s.db() - .associated_ty_value(*assoc_ty_value) - .display(s) - .to_string() - }); + let assoc_ty_values = self + .associated_term_value_ids + .iter() + .map(|av| s.db().associated_term_value(*av).display(s).to_string()); write_joined_non_empty_list!(f, "\n{}\n", assoc_ty_values, "\n")?; } write!(f, "}}")?; @@ -336,14 +334,14 @@ impl RenderAsRust for OpaqueTyDatum { } } -impl RenderAsRust for AssociatedTyDatum { +impl RenderAsRust for AssociatedTermDatum { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { // In lowering, a completely new empty environment is created for each - // AssociatedTyDatum, and it's given generic parameters for each generic + // AssociatedTermDatum, and it's given generic parameters for each generic // parameter that its trait had. We want to map the new binders for // those generic parameters back into their original names. To do that, // first find their original names (trait_binder_names), then the names - // they have inside the AssociatedTyDatum (assoc_ty_names_for_trait_params), + // they have inside the AssociatedTermDatum (assoc_ty_names_for_trait_params), // and then add that mapping to the WriterState when writing bounds and // where clauses. let trait_datum = s.db().trait_datum(self.trait_id); @@ -409,11 +407,11 @@ impl RenderAsRust for AssociatedTyDatum { } } -impl RenderAsRust for AssociatedTyValue { +impl RenderAsRust for AssociatedTermValue { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { - // see comments for a similar empty env operation in AssociatedTyDatum's + // see comments for a similar empty env operation in AssociatedTermDatum's // impl of RenderAsRust. - let assoc_ty_data = s.db().associated_ty_data(self.associated_ty_id); + let assoc_ty_data = s.db().associated_term_data(self.associated_term_id); let impl_datum = s.db().impl_datum(self.impl_id); let impl_param_names_in_impl_env = s.binder_var_indices(&impl_datum.binders.binders); @@ -444,7 +442,10 @@ impl RenderAsRust for AssociatedTyValue { write!(f, "{}type {}", s.indent(), assoc_ty_data.id.display(s))?; write_joined_non_empty_list!(f, "<{}>", assoc_ty_value_display, ", ")?; - write!(f, " = {};", value.ty.display(s))?; + match value { + AssociatedTermValueBound::Ty(ty) => write!(f, " = {};", ty.display(s))?, + AssociatedTermValueBound::Const(ct) => write!(f, " = const {};", ct.display(s))?, + } Ok(()) } } diff --git a/chalk-solve/src/display/stub.rs b/chalk-solve/src/display/stub.rs index ec209bc91a0..c2af3241ac3 100644 --- a/chalk-solve/src/display/stub.rs +++ b/chalk-solve/src/display/stub.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use crate::rust_ir::{GeneratorDatum, GeneratorWitnessDatum}; use crate::{ rust_ir::{ - AdtDatumBound, AdtKind, AdtVariantDatum, AssociatedTyDatumBound, FnDefDatumBound, + AdtDatumBound, AdtKind, AdtVariantDatum, AssociatedTermDatumBound, FnDefDatumBound, OpaqueTyDatumBound, TraitDatumBound, }, RustIrDatabase, @@ -41,16 +41,17 @@ impl> RustIrDatabase for StubWrapper<'_, D self.db.custom_clauses() } - fn associated_ty_data( + fn associated_term_data( &self, - ty: chalk_ir::AssocTypeId, - ) -> std::sync::Arc> { - let mut v = (*self.db.associated_ty_data(ty)).clone(); + id: chalk_ir::AssocItemId, + ) -> Arc> { + let mut v = (*self.db.associated_term_data(id)).clone(); v.binders = Binders::new( v.binders.binders.clone(), - AssociatedTyDatumBound { + AssociatedTermDatumBound { where_clauses: Vec::new(), bounds: Vec::new(), + assoc_const_ty: None, }, ); Arc::new(v) @@ -116,10 +117,10 @@ impl> RustIrDatabase for StubWrapper<'_, D unreachable!("impl items should never be stubbed") } - fn associated_ty_value( + fn associated_term_value( &self, - _id: crate::rust_ir::AssociatedTyValueId, - ) -> std::sync::Arc> { + _id: crate::rust_ir::AssociatedTermValueId, + ) -> std::sync::Arc> { unreachable!("associated type values should never be stubbed") } @@ -250,7 +251,7 @@ impl> RustIrDatabase for StubWrapper<'_, D self.db.adt_name(struct_id) } - fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String { + fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocItemId) -> String { self.db.assoc_type_name(assoc_ty_id) } diff --git a/chalk-solve/src/display/ty.rs b/chalk-solve/src/display/ty.rs index 8012de5f5df..cc28e1dac87 100644 --- a/chalk-solve/src/display/ty.rs +++ b/chalk-solve/src/display/ty.rs @@ -22,10 +22,10 @@ impl RenderAsRust for TyKind { let parameters = parameters.iter().map(|param| param.display(s)); write_joined_non_empty_list!(f, "<{}>", parameters, ", ") } - TyKind::AssociatedType(assoc_type_id, substitution) => { + TyKind::AssociatedType(assoc_id, substitution) => { // (Iterator::Item)(x) // should be written in Rust as ::Item - let datum = s.db().associated_ty_data(*assoc_type_id); + let datum = s.db().associated_term_data(*assoc_id); assert!( substitution .iter(interner) @@ -134,7 +134,7 @@ impl RenderAsRust for AliasTy { } } -impl RenderAsRust for ProjectionTy { +impl RenderAsRust for ProjectionTerm { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { // >::Z @@ -296,6 +296,17 @@ impl RenderAsRust for Const { } } +/* +impl RenderAsRust for Term { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + match self { + Term::Ty(ty) => ty.fmt(s, f), + Term::Const(ct) => ct.fmt(s, f), + } + } +} +*/ + impl RenderAsRust for GenericArg { fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { // delegate to GenericArgData diff --git a/chalk-solve/src/infer/unify.rs b/chalk-solve/src/infer/unify.rs index e5e169fdc75..d11829905bc 100644 --- a/chalk-solve/src/infer/unify.rs +++ b/chalk-solve/src/infer/unify.rs @@ -181,8 +181,12 @@ impl<'t, I: Interner> Unifier<'t, I> { ), // Unifying an alias type with some other type `U`. - (_, &TyKind::Alias(ref alias)) => self.relate_alias_ty(variance.invert(), alias, a), - (&TyKind::Alias(ref alias), _) => self.relate_alias_ty(variance, alias, b), + (_, &TyKind::Alias(ref alias)) => { + self.relate_alias_term(variance.invert(), alias, &Term::Ty(a.clone())) + } + (&TyKind::Alias(ref alias), _) => { + self.relate_alias_term(variance, alias, &Term::Ty(b.clone())) + } (&TyKind::InferenceVar(var, kind), ty_data) => { let ty = ty_data.clone().intern(interner); @@ -452,11 +456,11 @@ impl<'t, I: Interner> Unifier<'t, I> { /// ``` /// and relates `?X` and `ty`. #[instrument(level = "debug", skip(self))] - fn relate_alias_ty( + fn relate_alias_term( &mut self, variance: Variance, alias: &AliasTy, - ty: &Ty, + term: &Term, ) -> Fallible<()> { let interner = self.interner; match variance { @@ -465,27 +469,44 @@ impl<'t, I: Interner> Unifier<'t, I> { self.environment, AliasEq { alias: alias.clone(), - ty: ty.clone(), + term: term.clone(), } .cast(interner), )); Ok(()) } - Variance::Covariant | Variance::Contravariant => { - let var = self - .table - .new_variable(UniverseIndex::root()) - .to_ty(interner); - self.goals.push(InEnvironment::new( - self.environment, - AliasEq { - alias: alias.clone(), - ty: var.clone(), - } - .cast(interner), - )); - self.relate_ty_ty(variance, &var, ty) - } + Variance::Covariant | Variance::Contravariant => match term { + Term::Ty(ty) => { + let var = self + .table + .new_variable(UniverseIndex::root()) + .to_ty(interner); + self.goals.push(InEnvironment::new( + self.environment, + AliasEq { + alias: alias.clone(), + term: Term::Ty(var.clone()), + } + .cast(interner), + )); + self.relate_ty_ty(variance, &var, ty) + } + Term::Const(ct) => { + let var = self + .table + .new_variable(UniverseIndex::root()) + .to_const(interner, ct.data(interner).ty.clone()); + self.goals.push(InEnvironment::new( + self.environment, + AliasEq { + alias: alias.clone(), + term: Term::Const(var.clone()), + } + .cast(interner), + )); + self.relate_const_const(variance, &var, ct) + } + }, } } @@ -629,7 +650,8 @@ impl<'t, I: Interner> Unifier<'t, I> { }) } WhereClause::AliasEq(alias_eq) => { - let AliasEq { alias, ty: _ } = alias_eq; + let AliasEq { alias, term } = alias_eq; + assert!(matches!(term, Term::Ty(_))); let alias = match alias { AliasTy::Opaque(opaque_ty) => { let OpaqueTy { @@ -647,9 +669,9 @@ impl<'t, I: Interner> Unifier<'t, I> { }) } AliasTy::Projection(projection_ty) => { - let ProjectionTy { + let ProjectionTerm { ref substitution, - associated_ty_id, + associated_term_id, } = *projection_ty; // TODO: We should be skipping "self", which // would be the first element of @@ -662,15 +684,17 @@ impl<'t, I: Interner> Unifier<'t, I> { universe_index, |_| variance, ); - AliasTy::Projection(ProjectionTy { + AliasTy::Projection(ProjectionTerm { substitution, - associated_ty_id, + associated_term_id, }) } }; - let ty = + // TODO need to convert this to a type or a const. + let term = self.table.new_variable(universe_index).to_ty(interner); - WhereClause::AliasEq(AliasEq { alias, ty }) + let term = Term::Ty(term); + WhereClause::AliasEq(AliasEq { alias, term }) } WhereClause::TypeOutlives(_) => { let lifetime_var = self.table.new_variable(universe_index); diff --git a/chalk-solve/src/lib.rs b/chalk-solve/src/lib.rs index a870a0c4961..30f7e42072f 100644 --- a/chalk-solve/src/lib.rs +++ b/chalk-solve/src/lib.rs @@ -47,7 +47,7 @@ pub trait RustIrDatabase: Debug { fn custom_clauses(&self) -> Vec>; /// Returns the datum for the associated type with the given id. - fn associated_ty_data(&self, ty: AssocTypeId) -> Arc>; + fn associated_term_data(&self, ty: AssocItemId) -> Arc>; /// Returns the datum for the definition with the given id. fn trait_datum(&self, trait_id: TraitId) -> Arc>; @@ -76,8 +76,8 @@ pub trait RustIrDatabase: Debug { /// Returns the datum for the impl with the given id. fn impl_datum(&self, impl_id: ImplId) -> Arc>; - /// Returns the `AssociatedTyValue` with the given id. - fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc>; + /// Returns the `AssociatedTermValue` with the given id. + fn associated_term_value(&self, id: AssociatedTermValueId) -> Arc>; /// Returns the `OpaqueTyDatum` with the given id. fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc>; @@ -180,7 +180,7 @@ pub trait RustIrDatabase: Debug { /// Retrieves the name of an associated type. No uniqueness guarantees, but must /// a valid Rust identifier. - fn assoc_type_name(&self, assoc_ty_id: AssocTypeId) -> String { + fn assoc_type_name(&self, assoc_ty_id: AssocItemId) -> String { sanitize_debug_name(|f| I::debug_assoc_type_id(assoc_ty_id, f)) } diff --git a/chalk-solve/src/logging_db.rs b/chalk-solve/src/logging_db.rs index 12d8b052a2b..d90eff08484 100644 --- a/chalk-solve/src/logging_db.rs +++ b/chalk-solve/src/logging_db.rs @@ -119,11 +119,11 @@ where self.ws.db().custom_clauses() } - fn associated_ty_data( + fn associated_term_data( &self, - ty: chalk_ir::AssocTypeId, - ) -> Arc> { - let ty_datum = self.ws.db().associated_ty_data(ty); + ty: chalk_ir::AssocItemId, + ) -> Arc> { + let ty_datum = self.ws.db().associated_term_data(ty); self.record(ty_datum.trait_id); ty_datum } @@ -171,11 +171,11 @@ where self.ws.db().hidden_opaque_type(id) } - fn associated_ty_value( + fn associated_term_value( &self, - id: crate::rust_ir::AssociatedTyValueId, - ) -> Arc> { - let value = self.ws.db().associated_ty_value(id); + id: crate::rust_ir::AssociatedTermValueId, + ) -> Arc> { + let value = self.ws.db().associated_term_value(id); self.record(value.impl_id); value } @@ -240,7 +240,7 @@ where self.ws.db().adt_name(adt_id) } - fn assoc_type_name(&self, assoc_ty_id: AssocTypeId) -> String { + fn assoc_type_name(&self, assoc_ty_id: AssocItemId) -> String { self.ws.db().assoc_type_name(assoc_ty_id) } @@ -395,11 +395,11 @@ where self.db.custom_clauses() } - fn associated_ty_data( + fn associated_term_data( &self, - ty: chalk_ir::AssocTypeId, - ) -> Arc> { - self.db.associated_ty_data(ty) + ty: chalk_ir::AssocItemId, + ) -> Arc> { + self.db.associated_term_data(ty) } fn trait_datum(&self, trait_id: TraitId) -> Arc> { @@ -434,11 +434,11 @@ where self.db.impl_datum(impl_id) } - fn associated_ty_value( + fn associated_term_value( &self, - id: crate::rust_ir::AssociatedTyValueId, - ) -> Arc> { - self.db.associated_ty_value(id) + id: crate::rust_ir::AssociatedTermValueId, + ) -> Arc> { + self.db.associated_term_value(id) } fn opaque_ty_data(&self, id: OpaqueTyId) -> Arc> { @@ -500,7 +500,7 @@ where self.db.adt_name(adt_id) } - fn assoc_type_name(&self, assoc_ty_id: AssocTypeId) -> String { + fn assoc_type_name(&self, assoc_ty_id: AssocItemId) -> String { self.db.assoc_type_name(assoc_ty_id) } diff --git a/chalk-solve/src/logging_db/id_collector.rs b/chalk-solve/src/logging_db/id_collector.rs index 893652b70c4..afc635a749f 100644 --- a/chalk-solve/src/logging_db/id_collector.rs +++ b/chalk-solve/src/logging_db/id_collector.rs @@ -60,12 +60,12 @@ pub fn collect_unrecorded_ids>( let trait_datum = collector.db.trait_datum(trait_id); trait_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); - for assoc_ty_id in &trait_datum.associated_ty_ids { - let assoc_ty_datum = collector.db.associated_ty_data(*assoc_ty_id); - assoc_ty_datum + for assoc_id in &trait_datum.associated_term_ids { + let assoc_datum = collector.db.associated_term_data(*assoc_id); + assoc_datum .bounds_on_self(collector.db.interner()) .visit_with(&mut collector, DebruijnIndex::INNERMOST); - assoc_ty_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); + assoc_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); } } RecordedItemId::OpaqueTy(opaque_id) => { @@ -80,8 +80,8 @@ pub fn collect_unrecorded_ids>( } RecordedItemId::Impl(impl_id) => { let impl_datum = collector.db.impl_datum(impl_id); - for id in &impl_datum.associated_ty_value_ids { - let assoc_ty_value = collector.db.associated_ty_value(*id); + for id in &impl_datum.associated_term_value_ids { + let assoc_ty_value = collector.db.associated_term_value(*id); assoc_ty_value.visit_with(&mut collector, DebruijnIndex::INNERMOST); } impl_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST); @@ -108,7 +108,9 @@ impl<'i, I: Interner, DB: RustIrDatabase> IdCollector<'i, I, DB> { fn visit_alias(&mut self, alias: &AliasTy) { match alias { AliasTy::Projection(projection_ty) => { - let assoc_ty_datum = self.db.associated_ty_data(projection_ty.associated_ty_id); + let assoc_ty_datum = self + .db + .associated_term_data(projection_ty.associated_term_id); self.record(assoc_ty_datum.trait_id) } AliasTy::Opaque(opaque_ty) => self.record(opaque_ty.opaque_ty_id), diff --git a/chalk-solve/src/rust_ir.rs b/chalk-solve/src/rust_ir.rs index 7983b75f2e4..1723ff915d7 100644 --- a/chalk-solve/src/rust_ir.rs +++ b/chalk-solve/src/rust_ir.rs @@ -7,26 +7,26 @@ use chalk_ir::cast::Cast; use chalk_ir::fold::shift::Shift; use chalk_ir::interner::Interner; use chalk_ir::{ - try_break, visit::Visit, AdtId, AliasEq, AliasTy, AssocTypeId, Binders, DebruijnIndex, FnDefId, - GenericArg, ImplId, OpaqueTyId, ProjectionTy, QuantifiedWhereClause, Substitution, - ToGenericArg, TraitId, TraitRef, Ty, TyKind, VariableKind, WhereClause, WithKind, + try_break, visit::Visit, AdtId, AliasEq, AliasTy, AssocItemId, Binders, Const, DebruijnIndex, + FnDefId, GenericArg, ImplId, OpaqueTyId, ProjectionTerm, QuantifiedWhereClause, Substitution, + Term, ToGenericArg, TraitId, TraitRef, Ty, TyKind, VariableKind, WhereClause, WithKind, }; use std::iter; use std::ops::ControlFlow; -/// Identifier for an "associated type value" found in some impl. +/// Identifier for an "associated term value" found in some impl. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct AssociatedTyValueId(pub I::DefId); +pub struct AssociatedTermValueId(pub I::DefId); -chalk_ir::id_visit!(AssociatedTyValueId); -chalk_ir::id_fold!(AssociatedTyValueId); +chalk_ir::id_visit!(AssociatedTermValueId); +chalk_ir::id_fold!(AssociatedTermValueId); #[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_term_value_ids: Vec>, } impl ImplDatum { @@ -249,7 +249,8 @@ pub struct TraitDatum { /// chalk we add annotations like `#[auto]`. pub flags: TraitFlags, - pub associated_ty_ids: Vec>, + /// Types and consts associated with this trait. + pub associated_term_ids: Vec>, /// If this is a well-known trait, which one? If `None`, this is a regular, /// user-defined trait. @@ -423,7 +424,7 @@ impl TraitBound { #[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)] pub struct AliasEqBound { pub trait_bound: TraitBound, - pub associated_ty_id: AssocTypeId, + pub associated_ty_id: AssocItemId, /// Does not include trait parameters. pub parameters: Vec>, pub value: Ty, @@ -444,11 +445,12 @@ impl AliasEqBound { vec![ WhereClause::Implemented(trait_ref), WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id: self.associated_ty_id, + alias: AliasTy::Projection(ProjectionTerm { + associated_term_id: self.associated_ty_id, substitution, }), - ty: self.value.clone(), + // TODO here self.value should be a Term already. + term: Term::Ty(self.value.clone()), }), ] } @@ -485,12 +487,12 @@ impl Anonymize for [WithKind] { /// * The *where clauses* `where_clauses` are things that the impl can *assume* to be true /// (but which projectors must prove). #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct AssociatedTyDatum { +pub struct AssociatedTermDatum { /// The trait this associated type is defined in. pub trait_id: TraitId, /// The ID of this associated type - pub id: AssocTypeId, + pub id: AssocItemId, /// Name of this associated type. pub name: I::Identifier, @@ -500,11 +502,11 @@ pub struct AssociatedTyDatum { /// from `Bar` come first (corresponding to the de bruijn concept /// that "inner" binders are lower indices, although within a /// given binder we do not have an ordering). - pub binders: Binders>, + pub binders: Binders>, } // Manual implementation to avoid I::Identifier type. -impl Visit for AssociatedTyDatum { +impl Visit for AssociatedTermDatum { fn visit_with( &self, visitor: &mut dyn chalk_ir::visit::Visitor, @@ -516,10 +518,10 @@ impl Visit for AssociatedTyDatum { } } -/// Encodes the parts of `AssociatedTyDatum` where the parameters +/// Encodes the parts of `AssociatedTermDatum` where the parameters /// `P0..Pm` are in scope (`bounds` and `where_clauses`). #[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct AssociatedTyDatumBound { +pub struct AssociatedTermDatumBound { /// Bounds on the associated type itself. /// /// These must be proven by the implementer, for all possible parameters that @@ -528,9 +530,12 @@ pub struct AssociatedTyDatumBound { /// Where clauses that must hold for the projection to be well-formed. pub where_clauses: Vec>, + + /// If the associated term is a constant, what type is it? + pub assoc_const_ty: Option>, } -impl AssociatedTyDatum { +impl AssociatedTermDatum { /// Returns the associated ty's bounds applied to the projection type, e.g.: /// /// ```notrust @@ -552,8 +557,8 @@ impl AssociatedTyDatum { ); // The self type will be `>::Item` etc - let self_ty = TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: self.id, + let self_ty = TyKind::Alias(AliasTy::Projection(ProjectionTerm { + associated_term_id: self.id, substitution, })) .intern(interner); @@ -581,7 +586,7 @@ impl AssociatedTyDatum { /// } /// ``` #[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)] -pub struct AssociatedTyValue { +pub struct AssociatedTermValue { /// Impl in which this associated type value is found. You might /// need to look at this to find the generic parameters defined on /// the impl, for example. @@ -604,7 +609,7 @@ pub struct AssociatedTyValue { /// type Item; // <-- refers to this declaration here! /// } /// ``` - pub associated_ty_id: AssocTypeId, + pub associated_term_id: AssocItemId, /// Additional binders declared on the associated type itself, /// beyond those from the impl. This would be empty for normal @@ -616,13 +621,13 @@ pub struct AssociatedTyValue { /// // ^^^^ refers to these generics here /// } /// ``` - pub value: Binders>, + pub value: Binders>, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct AssociatedTyValueBound { - /// Type that we normalize to. The X in `type Foo<'a> = X`. - pub ty: Ty, +pub enum AssociatedTermValueBound { + Ty(Ty), + Const(Const), } /// Represents the bounds for an `impl Trait` type. diff --git a/chalk-solve/src/split.rs b/chalk-solve/src/split.rs index bea24044db8..a46cc5668c6 100644 --- a/chalk-solve/src/split.rs +++ b/chalk-solve/src/split.rs @@ -16,19 +16,19 @@ pub trait Split: RustIrDatabase { /// any type parameters itself. fn split_projection<'p>( &self, - projection: &'p ProjectionTy, + projection: &'p ProjectionTerm, ) -> ( - Arc>, + Arc>, &'p [GenericArg], &'p [GenericArg], ) { let interner = self.interner(); - let ProjectionTy { - associated_ty_id, + let ProjectionTerm { + associated_term_id, ref substitution, } = *projection; let parameters = substitution.as_slice(interner); - let associated_ty_data = &self.associated_ty_data(associated_ty_id); + let associated_ty_data = &self.associated_term_data(associated_term_id); let (trait_params, other_params) = self.split_associated_ty_parameters(parameters, &**associated_ty_data); (associated_ty_data.clone(), trait_params, other_params) @@ -39,7 +39,7 @@ pub trait Split: RustIrDatabase { /// `split_projection`). fn trait_parameters_from_projection<'p>( &self, - projection: &'p ProjectionTy, + projection: &'p ProjectionTerm, ) -> &'p [GenericArg] { let (_, trait_params, _) = self.split_projection(projection); trait_params @@ -48,7 +48,7 @@ pub trait Split: RustIrDatabase { /// Given a projection `>::Item`, /// returns the trait parameters `[P0..Pn]` (see /// `split_projection`). - fn trait_ref_from_projection(&self, projection: &ProjectionTy) -> TraitRef { + fn trait_ref_from_projection(&self, projection: &ProjectionTerm) -> TraitRef { let interner = self.interner(); let (associated_ty_data, trait_params, _) = self.split_projection(projection); TraitRef { @@ -83,7 +83,7 @@ pub trait Split: RustIrDatabase { fn split_associated_ty_value_parameters<'p, P>( &self, parameters: &'p [P], - associated_ty_value: &AssociatedTyValue, + associated_ty_value: &AssociatedTermValue, ) -> (&'p [P], &'p [P]) { let interner = self.interner(); let impl_datum = self.impl_datum(associated_ty_value.impl_id); @@ -123,8 +123,8 @@ pub trait Split: RustIrDatabase { fn impl_parameters_and_projection_from_associated_ty_value<'p>( &self, parameters: &'p [GenericArg], - associated_ty_value: &AssociatedTyValue, - ) -> (&'p [GenericArg], ProjectionTy) { + associated_ty_value: &AssociatedTermValue, + ) -> (&'p [GenericArg], ProjectionTerm) { let interner = self.interner(); let impl_datum = self.impl_datum(associated_ty_value.impl_id); @@ -150,8 +150,8 @@ pub trait Split: RustIrDatabase { .cloned(), ); - let projection = ProjectionTy { - associated_ty_id: associated_ty_value.associated_ty_id, + let projection = ProjectionTerm { + associated_term_id: associated_ty_value.associated_term_id, substitution: projection_substitution, }; @@ -186,7 +186,7 @@ pub trait Split: RustIrDatabase { fn split_associated_ty_parameters<'p, P>( &self, parameters: &'p [P], - associated_ty_datum: &AssociatedTyDatum, + associated_ty_datum: &AssociatedTermDatum, ) -> (&'p [P], &'p [P]) { let trait_datum = &self.trait_datum(associated_ty_datum.trait_id); let trait_num_params = trait_datum.binders.len(self.interner()); diff --git a/chalk-solve/src/wf.rs b/chalk-solve/src/wf.rs index 60d92860faa..9d6e87becdd 100644 --- a/chalk-solve/src/wf.rs +++ b/chalk-solve/src/wf.rs @@ -320,7 +320,7 @@ where interner, impl_header_wf_goal(self.db, impl_id).into_iter().chain( impl_datum - .associated_ty_value_ids + .associated_term_value_ids .iter() .filter_map(|&id| compute_assoc_ty_goal(self.db, id)), ), @@ -558,26 +558,29 @@ fn impl_wf_environment<'i, I: Interner>( /// ``` fn compute_assoc_ty_goal( db: &dyn RustIrDatabase, - assoc_ty_id: AssociatedTyValueId, + assoc_term_id: AssociatedTermValueId, ) -> Option> { let mut gb = GoalBuilder::new(db); - let assoc_ty = &db.associated_ty_value(assoc_ty_id); + let assoc = &db.associated_term_value(assoc_term_id); // Create `forall { .. }` Some(gb.forall( - &assoc_ty.value.map_ref(|v| &v.ty), - assoc_ty_id, - |gb, assoc_ty_substitution, value_ty, assoc_ty_id| { + &assoc.value.map_ref(|v| match v { + AssociatedTermValueBound::Ty(ty) => Term::Ty(ty.clone()), + AssociatedTermValueBound::Const(ct) => Term::Const(ct.clone()), + }), + assoc_term_id, + |gb, assoc_ty_substitution, value_term, assoc_ty_id| { let interner = gb.interner(); let db = gb.db(); - // Hmm, because `Arc` does not implement `Fold`, we can't pass this value through, + // Hmm, because `Arc` does not implement `Fold`, we can't pass this value through, // just the id, so we have to fetch `assoc_ty` from the database again. - // Implementing `Fold` for `AssociatedTyValue` doesn't *quite* seem right though, as that + // Implementing `Fold` for `AssociatedTermValue` doesn't *quite* seem right though, as that // would result in a deep clone, and the value is inert. We could do some more refatoring // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't // seem worth it. - let assoc_ty = &db.associated_ty_value(assoc_ty_id); + let assoc_ty = &db.associated_term_value(assoc_ty_id); let (impl_parameters, projection) = db .impl_parameters_and_projection_from_associated_ty_value( @@ -611,10 +614,11 @@ fn compute_assoc_ty_goal( // * where clauses // * original in trait, `Self: 'a` // * after substituting impl parameters, `Box: '!a` - let assoc_ty_datum = db.associated_ty_data(projection.associated_ty_id); - let AssociatedTyDatumBound { + let assoc_ty_datum = db.associated_term_data(projection.associated_term_id); + let AssociatedTermDatumBound { bounds: defn_bounds, where_clauses: defn_where_clauses, + assoc_const_ty: _, } = assoc_ty_datum .binders .clone() @@ -627,7 +631,7 @@ fn compute_assoc_ty_goal( .cloned() .map(|qwc| qwc.into_from_env_goal(interner)), |gb| { - let types = InputTypeCollector::types_in(gb.interner(), value_ty); + let types = InputTypeCollector::types_in(gb.interner(), value_term); // We require that `WellFormed(T)` for each type that appears in the value let wf_goals = types @@ -642,10 +646,16 @@ fn compute_assoc_ty_goal( // In our example, the bound was `Clone`, so the combined // result is `Box: Clone`. This is then converted to a // well-formed goal like `WellFormed(Box: Clone)`. + // + // In the case that the value_term is a const, we don't need to do + // anything extra, since all we have to check there is equality. let bound_goals = defn_bounds .iter() .cloned() - .flat_map(|qb| qb.into_where_clauses(interner, (*value_ty).clone())) + .flat_map(|qb| match value_term { + Term::Ty(ty) => qb.into_where_clauses(interner, (*ty).clone()), + Term::Const(_ct) => vec![], + }) .map(|qwc| qwc.into_well_formed_goal(interner)) .casted(interner); diff --git a/tests/display/unique_names.rs b/tests/display/unique_names.rs index cd26f299ae3..71642e72a07 100644 --- a/tests/display/unique_names.rs +++ b/tests/display/unique_names.rs @@ -46,7 +46,7 @@ where fn adt_name(&self, _adt_id: chalk_ir::AdtId) -> String { "Foo".to_owned() } - fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId) -> String { + fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocItemId) -> String { "Foo".to_owned() } fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId) -> String { @@ -58,11 +58,11 @@ where fn custom_clauses(&self) -> Vec> { self.db.custom_clauses() } - fn associated_ty_data( + fn associated_term_data( &self, - ty: chalk_ir::AssocTypeId, - ) -> std::sync::Arc> { - self.db.associated_ty_data(ty) + ty: chalk_ir::AssocItemId, + ) -> std::sync::Arc> { + self.db.associated_term_data(ty) } fn trait_datum( &self, @@ -94,11 +94,11 @@ where ) -> std::sync::Arc> { self.db.impl_datum(impl_id) } - fn associated_ty_value( + fn associated_term_value( &self, - id: chalk_solve::rust_ir::AssociatedTyValueId, - ) -> std::sync::Arc> { - self.db.associated_ty_value(id) + id: chalk_solve::rust_ir::AssociatedTermValueId, + ) -> std::sync::Arc> { + self.db.associated_term_value(id) } fn generator_datum( &self, diff --git a/tests/integration/panic.rs b/tests/integration/panic.rs index d0cbfdb7c92..872dbd7f768 100644 --- a/tests/integration/panic.rs +++ b/tests/integration/panic.rs @@ -54,7 +54,7 @@ impl RustIrDatabase for MockDatabase { vec![] } - fn associated_ty_data(&self, ty: AssocTypeId) -> Arc> { + fn associated_term_data(&self, ty: AssocItemId) -> Arc> { unimplemented!() } @@ -81,7 +81,7 @@ impl RustIrDatabase for MockDatabase { non_enumerable: false, coinductive: false, }, - associated_ty_ids: vec![], + associated_term_ids: vec![], well_known: None, }) } @@ -114,14 +114,14 @@ impl RustIrDatabase for MockDatabase { polarity: Polarity::Positive, binders, impl_type: ImplType::Local, - associated_ty_value_ids: vec![], + associated_term_value_ids: vec![], }) } - fn associated_ty_value( + fn associated_term_value( &self, - id: AssociatedTyValueId, - ) -> Arc> { + id: AssociatedTermValueId, + ) -> Arc> { unimplemented!() } diff --git a/tests/lowering/mod.rs b/tests/lowering/mod.rs index 0a74b297132..1273c157a04 100644 --- a/tests/lowering/mod.rs +++ b/tests/lowering/mod.rs @@ -13,6 +13,33 @@ fn lower_success() { } } +#[test] +fn lower_assoc_term() { + lowering_success! { + program { + trait Bar { + const N: usize; + } + struct Foo {} + impl Bar for Foo { + const N: usize = 100; + } + } + } + + lowering_success! { + program { + trait Bar { + type T; + } + struct Foo {} + impl Bar for Foo { + type T = usize; + } + } + } +} + #[test] fn not_trait() { lowering_error! { @@ -184,17 +211,17 @@ fn atc_accounting() { db.with_program(|program| { let atv_text = format!( "{:#?}", - &program.associated_ty_values.values().next().unwrap() + &program.associated_term_values.values().next().unwrap() ); println!("{}", atv_text); assert_eq!( &atv_text[..].replace(",\n", "\n"), - &r#"AssociatedTyValue { + &r#"AssociatedTermValue { impl_id: ImplId(#2), - associated_ty_id: (Iterable::Iter), - value: for AssociatedTyValueBound { - ty: Iter<'^0.0, ^0.1> - }, + associated_term_id: (Iterable::Iter), + value: for Ty( + Iter<'^0.0, ^0.1> + ), }"# .replace(",\n", "\n"), ); @@ -211,7 +238,7 @@ fn atc_accounting() { "ForAll { \ ForAll { \ ForAll { \ - all(AliasEq(<^2.0 as Iterable>::Iter<'^1.0> = ^0.0), \ + all(AliasEq(<^2.0 as Iterable>::Iter<'^1.0> = Ty(^0.0)), \ Implemented(^2.0: Iterable)) \ } \ } \ diff --git a/tests/test/projection.rs b/tests/test/projection.rs index aaddd17ffa8..3ddb604d135 100644 --- a/tests/test/projection.rs +++ b/tests/test/projection.rs @@ -1107,3 +1107,22 @@ fn projection_to_opaque() { } } } + +#[test] +fn const_projection() { + test! { + program { + trait ConstTrait { const N: usize; } + struct Foo {} + impl ConstTrait for Foo { const N: usize = 3; } + impl ConstTrait for () { const N: usize = 3; } + impl ConstTrait for i32 { const N: usize = 5; } + } + + goal { + ::N = 3 + } yields { + expect![[r#"No possible solution"#]] + } + } +} diff --git a/tests/test/type_flags.rs b/tests/test/type_flags.rs index 5678781eab6..b8a9ecab5bc 100644 --- a/tests/test/type_flags.rs +++ b/tests/test/type_flags.rs @@ -1,7 +1,7 @@ use chalk_integration::interner::ChalkIr; use chalk_integration::{empty_substitution, lifetime, ty}; use chalk_ir::cast::Cast; -use chalk_ir::{PlaceholderIndex, TyKind, TypeFlags, UniverseIndex}; +use chalk_ir::{PlaceholderIndex, Term, TyKind, TypeFlags, UniverseIndex}; #[test] fn placeholder_ty_flags_correct() { @@ -45,8 +45,8 @@ fn opaque_ty_flags_correct() { #[test] fn dyn_ty_flags_correct() { let internal_ty = TyKind::Scalar(chalk_ir::Scalar::Bool).intern(ChalkIr); - let projection_ty = chalk_ir::ProjectionTy { - associated_ty_id: chalk_ir::AssocTypeId(chalk_integration::interner::RawId { index: 0 }), + let projection_ty = chalk_ir::ProjectionTerm { + associated_term_id: chalk_ir::AssocItemId(chalk_integration::interner::RawId { index: 0 }), substitution: empty_substitution!(), }; let bounds = chalk_ir::Binders::>::empty( @@ -56,7 +56,7 @@ fn dyn_ty_flags_correct() { vec![chalk_ir::Binders::>::empty( ChalkIr, chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { - ty: internal_ty, + term: Term::Ty(internal_ty), alias: chalk_ir::AliasTy::Projection(projection_ty), }), )],