From 8996b1a2353539cb9c264d0effbde80567de6586 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 19 Mar 2021 02:07:15 +0100 Subject: Replace Projection variant in GenericPredicate with AliasEq --- crates/hir_ty/src/autoderef.rs | 15 ++--- crates/hir_ty/src/display.rs | 58 +++++++++++-------- crates/hir_ty/src/infer.rs | 18 +++--- crates/hir_ty/src/infer/unify.rs | 35 ++++++++---- crates/hir_ty/src/lib.rs | 49 +++++++++++++--- crates/hir_ty/src/lower.rs | 10 ++-- crates/hir_ty/src/traits.rs | 37 +++++++------ crates/hir_ty/src/traits/chalk.rs | 16 +++--- crates/hir_ty/src/traits/chalk/mapping.rs | 92 ++++++++++++++++++++----------- 9 files changed, 210 insertions(+), 120 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index ad4e6f23b..33b966026 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -15,7 +15,8 @@ use crate::{ to_assoc_type_id, to_chalk_trait_id, traits::{InEnvironment, Solution}, utils::generics, - BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, + AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy, + Substitution, TraitRef, Ty, TyKind, }; const AUTODEREF_RECURSION_LIMIT: usize = 10; @@ -82,16 +83,16 @@ fn deref_by_trait( } // Now do the assoc type projection - let projection = super::traits::ProjectionPredicate { - ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) - .intern(&Interner), - projection_ty: super::ProjectionTy { + let projection = AliasEq { + alias: AliasTy::Projection(ProjectionTy { associated_ty_id: to_assoc_type_id(target), substitution: parameters, - }, + }), + ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) + .intern(&Interner), }; - let obligation = super::Obligation::Projection(projection); + let obligation = super::Obligation::AliasEq(projection); let in_env = InEnvironment { value: obligation, environment: ty.environment }; diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index c6b4f37e5..59a1bd9b0 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -18,9 +18,9 @@ use hir_expand::name::Name; use crate::{ db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, - to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId, - CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, - ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, + to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, + CallableDefId, CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, + OpaqueTy, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, }; pub struct HirFormatter<'a> { @@ -268,6 +268,16 @@ impl HirDisplay for ProjectionTy { } } +impl HirDisplay for OpaqueTy { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + if f.should_truncate() { + return write!(f, "{}", TYPE_HINT_TRUNCATION); + } + + self.substitution[0].hir_fmt(f) + } +} + impl HirDisplay for Ty { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { if f.should_truncate() { @@ -700,12 +710,12 @@ fn write_bounds_like_dyn_trait( } } } - GenericPredicate::Projection(projection_pred) if is_fn_trait => { + GenericPredicate::AliasEq(alias_eq) if is_fn_trait => { is_fn_trait = false; write!(f, " -> ")?; - projection_pred.ty.hir_fmt(f)?; + alias_eq.ty.hir_fmt(f)?; } - GenericPredicate::Projection(projection_pred) => { + GenericPredicate::AliasEq(AliasEq { ty, alias }) => { // in types in actual Rust, these will always come // after the corresponding Implemented predicate if angle_open { @@ -714,11 +724,12 @@ fn write_bounds_like_dyn_trait( write!(f, "<")?; angle_open = true; } - let type_alias = f.db.type_alias_data(from_assoc_type_id( - projection_pred.projection_ty.associated_ty_id, - )); - write!(f, "{} = ", type_alias.name)?; - projection_pred.ty.hir_fmt(f)?; + if let AliasTy::Projection(proj) = alias { + let type_alias = + f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id)); + write!(f, "{} = ", type_alias.name)?; + } + ty.hir_fmt(f)?; } GenericPredicate::Error => { if angle_open { @@ -775,20 +786,20 @@ impl HirDisplay for GenericPredicate { match self { GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, - GenericPredicate::Projection(projection_pred) => { + GenericPredicate::AliasEq(AliasEq { + alias: AliasTy::Projection(projection_ty), + ty, + }) => { write!(f, "<")?; - projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; + projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; write!( f, ">::{} = ", - f.db.type_alias_data(from_assoc_type_id( - projection_pred.projection_ty.associated_ty_id - )) - .name, + f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name, )?; - projection_pred.ty.hir_fmt(f)?; + ty.hir_fmt(f)?; } - GenericPredicate::Error => write!(f, "{{error}}")?, + GenericPredicate::AliasEq(_) | GenericPredicate::Error => write!(f, "{{error}}")?, } Ok(()) } @@ -815,11 +826,14 @@ impl HirDisplay for Obligation { tr.hir_fmt(f)?; write!(f, ")") } - Obligation::Projection(proj) => { + Obligation::AliasEq(AliasEq { alias, ty }) => { write!(f, "Normalize(")?; - proj.projection_ty.hir_fmt(f)?; + match alias { + AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?, + AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?, + } write!(f, " => ")?; - proj.ty.hir_fmt(f)?; + ty.hir_fmt(f)?; write!(f, ")") } } diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b6ae4fc65..82186979a 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -37,12 +37,12 @@ use stdx::impl_from; use syntax::SmolStr; use super::{ - traits::{Guidance, Obligation, ProjectionPredicate, Solution}, + traits::{Guidance, Obligation, Solution}, InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, - to_assoc_type_id, to_chalk_trait_id, AliasTy, Interner, TyKind, + to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, }; pub(crate) use unify::unify; @@ -396,15 +396,15 @@ impl<'a> InferenceContext<'a> { .build(); let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; - let projection = ProjectionPredicate { - ty: ty.clone(), - projection_ty: ProjectionTy { + let alias_eq = AliasEq { + alias: AliasTy::Projection(ProjectionTy { associated_ty_id: to_assoc_type_id(res_assoc_ty), substitution: substs, - }, + }), + ty: ty.clone(), }; self.obligations.push(Obligation::Trait(trait_ref)); - self.obligations.push(Obligation::Projection(projection)); + self.obligations.push(Obligation::AliasEq(alias_eq)); self.resolve_ty_as_possible(ty) } None => self.err_ty(), @@ -429,8 +429,8 @@ impl<'a> InferenceContext<'a> { fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { let var = self.table.new_type_var(); - let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() }; - let obligation = Obligation::Projection(predicate); + let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; + let obligation = Obligation::AliasEq(alias_eq); self.obligations.push(obligation); var } diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index f5ea09698..4738ec08a 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; use super::{InferenceContext, Obligation}; use crate::{ - BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar, - Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, + AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, + InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, }; impl<'a> InferenceContext<'a> { @@ -93,8 +93,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { Obligation::Trait(tr) => { Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) } - Obligation::Projection(pr) => { - Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST)) + Obligation::AliasEq(alias_eq) => { + Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST)) } }; self.into_canonicalized(InEnvironment { @@ -394,14 +394,25 @@ impl InferenceTable { { self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) } - (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2)) - if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id => - { - self.unify_substs( - &proj1.projection_ty.substitution, - &proj2.projection_ty.substitution, - depth + 1, - ) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1) + ( + GenericPredicate::AliasEq(AliasEq { alias: alias1, ty: ty1 }), + GenericPredicate::AliasEq(AliasEq { alias: alias2, ty: ty2 }), + ) => { + let (substitution1, substitution2) = match (alias1, alias2) { + (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2)) + if projection_ty1.associated_ty_id == projection_ty2.associated_ty_id => + { + (&projection_ty1.substitution, &projection_ty2.substitution) + } + (AliasTy::Opaque(opaque1), AliasTy::Opaque(opaque2)) + if opaque1.opaque_ty_id == opaque2.opaque_ty_id => + { + (&opaque1.substitution, &opaque2.substitution) + } + _ => return false, + }; + self.unify_substs(&substitution1, &substitution2, depth + 1) + && self.unify_inner(&ty1, &ty2, depth + 1) } _ => false, } diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 3859dbfa1..2afcb5413 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -45,7 +45,7 @@ pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, }; -pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; +pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment}; pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; @@ -72,6 +72,20 @@ pub struct OpaqueTy { pub substitution: Substitution, } +impl TypeWalk for OpaqueTy { + fn walk(&self, f: &mut impl FnMut(&Ty)) { + self.substitution.walk(f); + } + + fn walk_mut_binders( + &mut self, + f: &mut impl FnMut(&mut Ty, DebruijnIndex), + binders: DebruijnIndex, + ) { + self.substitution.walk_mut_binders(f, binders); + } +} + /// A "projection" type corresponds to an (unnormalized) /// projection like `>::Foo`. Note that the /// trait and all its parameters are fully known. @@ -133,6 +147,25 @@ pub enum AliasTy { Opaque(OpaqueTy), } +impl TypeWalk for AliasTy { + fn walk(&self, f: &mut impl FnMut(&Ty)) { + match self { + AliasTy::Projection(it) => it.walk(f), + AliasTy::Opaque(it) => it.walk(f), + } + } + + fn walk_mut_binders( + &mut self, + f: &mut impl FnMut(&mut Ty, DebruijnIndex), + binders: DebruijnIndex, + ) { + match self { + AliasTy::Projection(it) => it.walk_mut_binders(f, binders), + AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), + } + } +} /// A type. /// /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents @@ -535,7 +568,7 @@ pub enum GenericPredicate { /// The given trait needs to be implemented for its type parameters. Implemented(TraitRef), /// An associated type bindings like in `Iterator`. - Projection(ProjectionPredicate), + AliasEq(AliasEq), /// We couldn't resolve the trait reference. (If some type parameters can't /// be resolved, they will just be Unknown). Error, @@ -553,8 +586,10 @@ impl GenericPredicate { pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option { match self { GenericPredicate::Implemented(tr) => Some(tr.clone()), - GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)), - GenericPredicate::Error => None, + GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { + Some(proj.trait_ref(db)) + } + GenericPredicate::AliasEq(_) | GenericPredicate::Error => None, } } } @@ -563,7 +598,7 @@ impl TypeWalk for GenericPredicate { fn walk(&self, f: &mut impl FnMut(&Ty)) { match self { GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), - GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), + GenericPredicate::AliasEq(alias_eq) => alias_eq.walk(f), GenericPredicate::Error => {} } } @@ -575,9 +610,7 @@ impl TypeWalk for GenericPredicate { ) { match self { GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), - GenericPredicate::Projection(projection_pred) => { - projection_pred.walk_mut_binders(f, binders) - } + GenericPredicate::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), GenericPredicate::Error => {} } } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 5d950a017..7d22c3df5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -33,8 +33,8 @@ use crate::{ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, variant_data, }, - AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, - ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, + AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, + GenericPredicate, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, }; @@ -750,9 +750,9 @@ impl<'a> TyLoweringContext<'a> { ); if let Some(type_ref) = &binding.type_ref { let ty = self.lower_ty(type_ref); - let projection_predicate = - ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; - preds.push(GenericPredicate::Projection(projection_predicate)); + let alias_eq = + AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; + preds.push(GenericPredicate::AliasEq(alias_eq)); } for bound in &binding.bounds { preds.extend(self.lower_type_bound( diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index a7287dea1..ac7de7605 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -8,10 +8,9 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; use hir_def::{lang_item::LangItemTarget, TraitId}; use stdx::panic_context; -use crate::{db::HirDatabase, DebruijnIndex, Substitution}; - -use super::{ - Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk, +use crate::{ + db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution, + TraitRef, Ty, TyKind, TypeWalk, }; use self::chalk::{from_chalk, Interner, ToChalk}; @@ -93,31 +92,32 @@ pub enum Obligation { /// Prove that a certain type implements a trait (the type is the `Self` type /// parameter to the `TraitRef`). Trait(TraitRef), - Projection(ProjectionPredicate), + AliasEq(AliasEq), } impl Obligation { pub fn from_predicate(predicate: GenericPredicate) -> Option { match predicate { GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), - GenericPredicate::Projection(projection_pred) => { - Some(Obligation::Projection(projection_pred)) - } + GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)), GenericPredicate::Error => None, } } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct ProjectionPredicate { - pub projection_ty: ProjectionTy, +pub struct AliasEq { + pub alias: AliasTy, pub ty: Ty, } -impl TypeWalk for ProjectionPredicate { +impl TypeWalk for AliasEq { fn walk(&self, f: &mut impl FnMut(&Ty)) { - self.projection_ty.walk(f); self.ty.walk(f); + match &self.alias { + AliasTy::Projection(projection_ty) => projection_ty.walk(f), + AliasTy::Opaque(opaque) => opaque.walk(f), + } } fn walk_mut_binders( @@ -125,8 +125,11 @@ impl TypeWalk for ProjectionPredicate { f: &mut impl FnMut(&mut Ty, DebruijnIndex), binders: DebruijnIndex, ) { - self.projection_ty.walk_mut_binders(f, binders); self.ty.walk_mut_binders(f, binders); + match &mut self.alias { + AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), + AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), + } } } @@ -138,12 +141,14 @@ pub(crate) fn trait_solve_query( ) -> Option { let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), - Obligation::Projection(_) => "projection".to_string(), + Obligation::AliasEq(_) => "alias_eq".to_string(), }); log::info!("trait_solve_query({})", goal.value.value.display(db)); - if let Obligation::Projection(pred) = &goal.value.value { - if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) { + if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) = + &goal.value.value + { + if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible return Some(Solution::Ambig(Guidance::Unknown)); } diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index bac70f5aa..080764e76 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -21,8 +21,8 @@ use crate::{ method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, utils::generics, - BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate, - ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, + AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, + GenericPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, }; use mapping::{ convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, @@ -229,18 +229,18 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { .intern(&Interner), ), }); - let proj_bound = GenericPredicate::Projection(ProjectionPredicate { - // The parameter of the opaque type. - ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) - .intern(&Interner), - projection_ty: ProjectionTy { + let proj_bound = GenericPredicate::AliasEq(AliasEq { + alias: AliasTy::Projection(ProjectionTy { associated_ty_id: to_assoc_type_id(future_output), // Self type as the first parameter. substitution: Substitution::single( TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) .intern(&Interner), ), - }, + }), + // The parameter of the opaque type. + ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) + .intern(&Interner), }); let bound = OpaqueTyDatumBound { bounds: make_binders( diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 0086ce1e9..62b779008 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -14,8 +14,8 @@ use crate::{ from_assoc_type_id, primitive::UintTy, traits::{Canonical, Obligation}, - AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, - ProjectionPredicate, ProjectionTy, Scalar, Substitution, TraitRef, Ty, + AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, ProjectionTy, + Scalar, Substitution, TraitRef, Ty, }; use super::interner::*; @@ -314,12 +314,10 @@ impl ToChalk for GenericPredicate { let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) } - GenericPredicate::Projection(projection_pred) => { - let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); - let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); - let alias = chalk_ir::AliasTy::Projection(projection); - make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) - } + GenericPredicate::AliasEq(alias_eq) => make_binders( + chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), + 0, + ), GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), } } @@ -338,16 +336,8 @@ impl ToChalk for GenericPredicate { chalk_ir::WhereClause::Implemented(tr) => { GenericPredicate::Implemented(from_chalk(db, tr)) } - chalk_ir::WhereClause::AliasEq(projection_eq) => { - let projection_ty = from_chalk( - db, - match projection_eq.alias { - chalk_ir::AliasTy::Projection(p) => p, - _ => unimplemented!(), - }, - ); - let ty = from_chalk(db, projection_eq.ty); - GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty }) + chalk_ir::WhereClause::AliasEq(alias_eq) => { + GenericPredicate::AliasEq(from_chalk(db, alias_eq)) } chalk_ir::WhereClause::LifetimeOutlives(_) => { @@ -383,19 +373,55 @@ impl ToChalk for ProjectionTy { } } } +impl ToChalk for OpaqueTy { + type Chalk = chalk_ir::OpaqueTy; + + fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { + chalk_ir::OpaqueTy { + opaque_ty_id: self.opaque_ty_id, + substitution: self.substitution.to_chalk(db), + } + } + + fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { + OpaqueTy { + opaque_ty_id: chalk.opaque_ty_id, + substitution: from_chalk(db, chalk.substitution), + } + } +} + +impl ToChalk for AliasTy { + type Chalk = chalk_ir::AliasTy; + + fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { + match self { + AliasTy::Projection(projection_ty) => { + chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db)) + } + AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)), + } + } + + fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { + match chalk { + chalk_ir::AliasTy::Projection(projection_ty) => { + AliasTy::Projection(from_chalk(db, projection_ty)) + } + chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)), + } + } +} -impl ToChalk for ProjectionPredicate { +impl ToChalk for AliasEq { type Chalk = chalk_ir::AliasEq; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq { - chalk_ir::AliasEq { - alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), - ty: self.ty.to_chalk(db), - } + chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) } } - fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq) -> Self { - unimplemented!() + fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq) -> Self { + AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) } } } @@ -405,7 +431,7 @@ impl ToChalk for Obligation { fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal { match self { Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), - Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), + Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner), } } @@ -527,29 +553,29 @@ pub(super) fn generic_predicate_to_inline_bound( let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; Some(rust_ir::InlineBound::TraitBound(trait_bound)) } - GenericPredicate::Projection(proj) => { - if &proj.projection_ty.substitution[0] != self_ty { + GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { + if &projection_ty.substitution[0] != self_ty { return None; } - let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id) + let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) .lookup(db.upcast()) .container { AssocContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), }; - let args_no_self = proj.projection_ty.substitution[1..] + let args_no_self = projection_ty.substitution[1..] .iter() .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) .collect(); let alias_eq_bound = rust_ir::AliasEqBound { - value: proj.ty.clone().to_chalk(db), + value: ty.clone().to_chalk(db), trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, - associated_ty_id: proj.projection_ty.associated_ty_id, + associated_ty_id: projection_ty.associated_ty_id, parameters: Vec::new(), // FIXME we don't support generic associated types yet }; Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) } - GenericPredicate::Error => None, + _ => None, } } -- cgit v1.2.3