aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-03-19 01:07:15 +0000
committerLukas Wirth <[email protected]>2021-03-19 11:12:18 +0000
commit8996b1a2353539cb9c264d0effbde80567de6586 (patch)
tree4702a4384ee97782670c20e597c40e7da61b4fc2 /crates/hir_ty/src
parent86878443b1789cac0e48177f5f2b95ad0d6e912c (diff)
Replace Projection variant in GenericPredicate with AliasEq
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/autoderef.rs15
-rw-r--r--crates/hir_ty/src/display.rs58
-rw-r--r--crates/hir_ty/src/infer.rs18
-rw-r--r--crates/hir_ty/src/infer/unify.rs35
-rw-r--r--crates/hir_ty/src/lib.rs49
-rw-r--r--crates/hir_ty/src/lower.rs10
-rw-r--r--crates/hir_ty/src/traits.rs37
-rw-r--r--crates/hir_ty/src/traits/chalk.rs16
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs92
9 files changed, 210 insertions, 120 deletions
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::{
15 to_assoc_type_id, to_chalk_trait_id, 15 to_assoc_type_id, to_chalk_trait_id,
16 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
17 utils::generics, 17 utils::generics,
18 BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, 18 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy,
19 Substitution, TraitRef, Ty, TyKind,
19}; 20};
20 21
21const AUTODEREF_RECURSION_LIMIT: usize = 10; 22const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -82,16 +83,16 @@ fn deref_by_trait(
82 } 83 }
83 84
84 // Now do the assoc type projection 85 // Now do the assoc type projection
85 let projection = super::traits::ProjectionPredicate { 86 let projection = AliasEq {
86 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) 87 alias: AliasTy::Projection(ProjectionTy {
87 .intern(&Interner),
88 projection_ty: super::ProjectionTy {
89 associated_ty_id: to_assoc_type_id(target), 88 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters, 89 substitution: parameters,
91 }, 90 }),
91 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
92 .intern(&Interner),
92 }; 93 };
93 94
94 let obligation = super::Obligation::Projection(projection); 95 let obligation = super::Obligation::AliasEq(projection);
95 96
96 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 97 let in_env = InEnvironment { value: obligation, environment: ty.environment };
97 98
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;
18 18
19use crate::{ 19use crate::{
20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId, 21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
22 CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, 22 CallableDefId, CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation,
23 ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, 23 OpaqueTy, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind,
24}; 24};
25 25
26pub struct HirFormatter<'a> { 26pub struct HirFormatter<'a> {
@@ -268,6 +268,16 @@ impl HirDisplay for ProjectionTy {
268 } 268 }
269} 269}
270 270
271impl HirDisplay for OpaqueTy {
272 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
273 if f.should_truncate() {
274 return write!(f, "{}", TYPE_HINT_TRUNCATION);
275 }
276
277 self.substitution[0].hir_fmt(f)
278 }
279}
280
271impl HirDisplay for Ty { 281impl HirDisplay for Ty {
272 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 282 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
273 if f.should_truncate() { 283 if f.should_truncate() {
@@ -700,12 +710,12 @@ fn write_bounds_like_dyn_trait(
700 } 710 }
701 } 711 }
702 } 712 }
703 GenericPredicate::Projection(projection_pred) if is_fn_trait => { 713 GenericPredicate::AliasEq(alias_eq) if is_fn_trait => {
704 is_fn_trait = false; 714 is_fn_trait = false;
705 write!(f, " -> ")?; 715 write!(f, " -> ")?;
706 projection_pred.ty.hir_fmt(f)?; 716 alias_eq.ty.hir_fmt(f)?;
707 } 717 }
708 GenericPredicate::Projection(projection_pred) => { 718 GenericPredicate::AliasEq(AliasEq { ty, alias }) => {
709 // in types in actual Rust, these will always come 719 // in types in actual Rust, these will always come
710 // after the corresponding Implemented predicate 720 // after the corresponding Implemented predicate
711 if angle_open { 721 if angle_open {
@@ -714,11 +724,12 @@ fn write_bounds_like_dyn_trait(
714 write!(f, "<")?; 724 write!(f, "<")?;
715 angle_open = true; 725 angle_open = true;
716 } 726 }
717 let type_alias = f.db.type_alias_data(from_assoc_type_id( 727 if let AliasTy::Projection(proj) = alias {
718 projection_pred.projection_ty.associated_ty_id, 728 let type_alias =
719 )); 729 f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id));
720 write!(f, "{} = ", type_alias.name)?; 730 write!(f, "{} = ", type_alias.name)?;
721 projection_pred.ty.hir_fmt(f)?; 731 }
732 ty.hir_fmt(f)?;
722 } 733 }
723 GenericPredicate::Error => { 734 GenericPredicate::Error => {
724 if angle_open { 735 if angle_open {
@@ -775,20 +786,20 @@ impl HirDisplay for GenericPredicate {
775 786
776 match self { 787 match self {
777 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 788 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
778 GenericPredicate::Projection(projection_pred) => { 789 GenericPredicate::AliasEq(AliasEq {
790 alias: AliasTy::Projection(projection_ty),
791 ty,
792 }) => {
779 write!(f, "<")?; 793 write!(f, "<")?;
780 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 794 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
781 write!( 795 write!(
782 f, 796 f,
783 ">::{} = ", 797 ">::{} = ",
784 f.db.type_alias_data(from_assoc_type_id( 798 f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
785 projection_pred.projection_ty.associated_ty_id
786 ))
787 .name,
788 )?; 799 )?;
789 projection_pred.ty.hir_fmt(f)?; 800 ty.hir_fmt(f)?;
790 } 801 }
791 GenericPredicate::Error => write!(f, "{{error}}")?, 802 GenericPredicate::AliasEq(_) | GenericPredicate::Error => write!(f, "{{error}}")?,
792 } 803 }
793 Ok(()) 804 Ok(())
794 } 805 }
@@ -815,11 +826,14 @@ impl HirDisplay for Obligation {
815 tr.hir_fmt(f)?; 826 tr.hir_fmt(f)?;
816 write!(f, ")") 827 write!(f, ")")
817 } 828 }
818 Obligation::Projection(proj) => { 829 Obligation::AliasEq(AliasEq { alias, ty }) => {
819 write!(f, "Normalize(")?; 830 write!(f, "Normalize(")?;
820 proj.projection_ty.hir_fmt(f)?; 831 match alias {
832 AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
833 AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
834 }
821 write!(f, " => ")?; 835 write!(f, " => ")?;
822 proj.ty.hir_fmt(f)?; 836 ty.hir_fmt(f)?;
823 write!(f, ")") 837 write!(f, ")")
824 } 838 }
825 } 839 }
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;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 40 traits::{Guidance, Obligation, Solution},
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, to_chalk_trait_id, AliasTy, Interner, TyKind, 45 to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind,
46}; 46};
47 47
48pub(crate) use unify::unify; 48pub(crate) use unify::unify;
@@ -396,15 +396,15 @@ impl<'a> InferenceContext<'a> {
396 .build(); 396 .build();
397 let trait_ref = 397 let trait_ref =
398 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; 398 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
399 let projection = ProjectionPredicate { 399 let alias_eq = AliasEq {
400 ty: ty.clone(), 400 alias: AliasTy::Projection(ProjectionTy {
401 projection_ty: ProjectionTy {
402 associated_ty_id: to_assoc_type_id(res_assoc_ty), 401 associated_ty_id: to_assoc_type_id(res_assoc_ty),
403 substitution: substs, 402 substitution: substs,
404 }, 403 }),
404 ty: ty.clone(),
405 }; 405 };
406 self.obligations.push(Obligation::Trait(trait_ref)); 406 self.obligations.push(Obligation::Trait(trait_ref));
407 self.obligations.push(Obligation::Projection(projection)); 407 self.obligations.push(Obligation::AliasEq(alias_eq));
408 self.resolve_ty_as_possible(ty) 408 self.resolve_ty_as_possible(ty)
409 } 409 }
410 None => self.err_ty(), 410 None => self.err_ty(),
@@ -429,8 +429,8 @@ impl<'a> InferenceContext<'a> {
429 429
430 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 430 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
431 let var = self.table.new_type_var(); 431 let var = self.table.new_type_var();
432 let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() }; 432 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
433 let obligation = Obligation::Projection(predicate); 433 let obligation = Obligation::AliasEq(alias_eq);
434 self.obligations.push(obligation); 434 self.obligations.push(obligation);
435 var 435 var
436 } 436 }
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};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{InferenceContext, Obligation};
9use crate::{ 9use crate::{
10 BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar, 10 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate,
11 Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, 11 InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk,
12}; 12};
13 13
14impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
@@ -93,8 +93,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
93 Obligation::Trait(tr) => { 93 Obligation::Trait(tr) => {
94 Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) 94 Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
95 } 95 }
96 Obligation::Projection(pr) => { 96 Obligation::AliasEq(alias_eq) => {
97 Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST)) 97 Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
98 } 98 }
99 }; 99 };
100 self.into_canonicalized(InEnvironment { 100 self.into_canonicalized(InEnvironment {
@@ -394,14 +394,25 @@ impl InferenceTable {
394 { 394 {
395 self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) 395 self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1)
396 } 396 }
397 (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2)) 397 (
398 if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id => 398 GenericPredicate::AliasEq(AliasEq { alias: alias1, ty: ty1 }),
399 { 399 GenericPredicate::AliasEq(AliasEq { alias: alias2, ty: ty2 }),
400 self.unify_substs( 400 ) => {
401 &proj1.projection_ty.substitution, 401 let (substitution1, substitution2) = match (alias1, alias2) {
402 &proj2.projection_ty.substitution, 402 (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2))
403 depth + 1, 403 if projection_ty1.associated_ty_id == projection_ty2.associated_ty_id =>
404 ) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1) 404 {
405 (&projection_ty1.substitution, &projection_ty2.substitution)
406 }
407 (AliasTy::Opaque(opaque1), AliasTy::Opaque(opaque2))
408 if opaque1.opaque_ty_id == opaque2.opaque_ty_id =>
409 {
410 (&opaque1.substitution, &opaque2.substitution)
411 }
412 _ => return false,
413 };
414 self.unify_substs(&substitution1, &substitution2, depth + 1)
415 && self.unify_inner(&ty1, &ty2, depth + 1)
405 } 416 }
406 _ => false, 417 _ => false,
407 } 418 }
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::{
45 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 45 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
46 TyDefId, TyLoweringContext, ValueTyDefId, 46 TyDefId, TyLoweringContext, ValueTyDefId,
47}; 47};
48pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 48pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment};
49 49
50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; 50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind};
51 51
@@ -72,6 +72,20 @@ pub struct OpaqueTy {
72 pub substitution: Substitution, 72 pub substitution: Substitution,
73} 73}
74 74
75impl TypeWalk for OpaqueTy {
76 fn walk(&self, f: &mut impl FnMut(&Ty)) {
77 self.substitution.walk(f);
78 }
79
80 fn walk_mut_binders(
81 &mut self,
82 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
83 binders: DebruijnIndex,
84 ) {
85 self.substitution.walk_mut_binders(f, binders);
86 }
87}
88
75/// A "projection" type corresponds to an (unnormalized) 89/// A "projection" type corresponds to an (unnormalized)
76/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the 90/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
77/// trait and all its parameters are fully known. 91/// trait and all its parameters are fully known.
@@ -133,6 +147,25 @@ pub enum AliasTy {
133 Opaque(OpaqueTy), 147 Opaque(OpaqueTy),
134} 148}
135 149
150impl TypeWalk for AliasTy {
151 fn walk(&self, f: &mut impl FnMut(&Ty)) {
152 match self {
153 AliasTy::Projection(it) => it.walk(f),
154 AliasTy::Opaque(it) => it.walk(f),
155 }
156 }
157
158 fn walk_mut_binders(
159 &mut self,
160 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
161 binders: DebruijnIndex,
162 ) {
163 match self {
164 AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
165 AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
166 }
167 }
168}
136/// A type. 169/// A type.
137/// 170///
138/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents 171/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
@@ -535,7 +568,7 @@ pub enum GenericPredicate {
535 /// The given trait needs to be implemented for its type parameters. 568 /// The given trait needs to be implemented for its type parameters.
536 Implemented(TraitRef), 569 Implemented(TraitRef),
537 /// An associated type bindings like in `Iterator<Item = T>`. 570 /// An associated type bindings like in `Iterator<Item = T>`.
538 Projection(ProjectionPredicate), 571 AliasEq(AliasEq),
539 /// We couldn't resolve the trait reference. (If some type parameters can't 572 /// We couldn't resolve the trait reference. (If some type parameters can't
540 /// be resolved, they will just be Unknown). 573 /// be resolved, they will just be Unknown).
541 Error, 574 Error,
@@ -553,8 +586,10 @@ impl GenericPredicate {
553 pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { 586 pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
554 match self { 587 match self {
555 GenericPredicate::Implemented(tr) => Some(tr.clone()), 588 GenericPredicate::Implemented(tr) => Some(tr.clone()),
556 GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)), 589 GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
557 GenericPredicate::Error => None, 590 Some(proj.trait_ref(db))
591 }
592 GenericPredicate::AliasEq(_) | GenericPredicate::Error => None,
558 } 593 }
559 } 594 }
560} 595}
@@ -563,7 +598,7 @@ impl TypeWalk for GenericPredicate {
563 fn walk(&self, f: &mut impl FnMut(&Ty)) { 598 fn walk(&self, f: &mut impl FnMut(&Ty)) {
564 match self { 599 match self {
565 GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), 600 GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
566 GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), 601 GenericPredicate::AliasEq(alias_eq) => alias_eq.walk(f),
567 GenericPredicate::Error => {} 602 GenericPredicate::Error => {}
568 } 603 }
569 } 604 }
@@ -575,9 +610,7 @@ impl TypeWalk for GenericPredicate {
575 ) { 610 ) {
576 match self { 611 match self {
577 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), 612 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
578 GenericPredicate::Projection(projection_pred) => { 613 GenericPredicate::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
579 projection_pred.walk_mut_binders(f, binders)
580 }
581 GenericPredicate::Error => {} 614 GenericPredicate::Error => {}
582 } 615 }
583 } 616 }
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::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
34 variant_data, 34 variant_data,
35 }, 35 },
36 AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, 37 GenericPredicate, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait,
38 ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, 38 ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
39}; 39};
40 40
@@ -750,9 +750,9 @@ impl<'a> TyLoweringContext<'a> {
750 ); 750 );
751 if let Some(type_ref) = &binding.type_ref { 751 if let Some(type_ref) = &binding.type_ref {
752 let ty = self.lower_ty(type_ref); 752 let ty = self.lower_ty(type_ref);
753 let projection_predicate = 753 let alias_eq =
754 ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; 754 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
755 preds.push(GenericPredicate::Projection(projection_predicate)); 755 preds.push(GenericPredicate::AliasEq(alias_eq));
756 } 756 }
757 for bound in &binding.bounds { 757 for bound in &binding.bounds {
758 preds.extend(self.lower_type_bound( 758 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};
8use hir_def::{lang_item::LangItemTarget, TraitId}; 8use hir_def::{lang_item::LangItemTarget, TraitId};
9use stdx::panic_context; 9use stdx::panic_context;
10 10
11use crate::{db::HirDatabase, DebruijnIndex, Substitution}; 11use crate::{
12 12 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution,
13use super::{ 13 TraitRef, Ty, TyKind, TypeWalk,
14 Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
15}; 14};
16 15
17use self::chalk::{from_chalk, Interner, ToChalk}; 16use self::chalk::{from_chalk, Interner, ToChalk};
@@ -93,31 +92,32 @@ pub enum Obligation {
93 /// Prove that a certain type implements a trait (the type is the `Self` type 92 /// Prove that a certain type implements a trait (the type is the `Self` type
94 /// parameter to the `TraitRef`). 93 /// parameter to the `TraitRef`).
95 Trait(TraitRef), 94 Trait(TraitRef),
96 Projection(ProjectionPredicate), 95 AliasEq(AliasEq),
97} 96}
98 97
99impl Obligation { 98impl Obligation {
100 pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { 99 pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> {
101 match predicate { 100 match predicate {
102 GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), 101 GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
103 GenericPredicate::Projection(projection_pred) => { 102 GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
104 Some(Obligation::Projection(projection_pred))
105 }
106 GenericPredicate::Error => None, 103 GenericPredicate::Error => None,
107 } 104 }
108 } 105 }
109} 106}
110 107
111#[derive(Clone, Debug, PartialEq, Eq, Hash)] 108#[derive(Clone, Debug, PartialEq, Eq, Hash)]
112pub struct ProjectionPredicate { 109pub struct AliasEq {
113 pub projection_ty: ProjectionTy, 110 pub alias: AliasTy,
114 pub ty: Ty, 111 pub ty: Ty,
115} 112}
116 113
117impl TypeWalk for ProjectionPredicate { 114impl TypeWalk for AliasEq {
118 fn walk(&self, f: &mut impl FnMut(&Ty)) { 115 fn walk(&self, f: &mut impl FnMut(&Ty)) {
119 self.projection_ty.walk(f);
120 self.ty.walk(f); 116 self.ty.walk(f);
117 match &self.alias {
118 AliasTy::Projection(projection_ty) => projection_ty.walk(f),
119 AliasTy::Opaque(opaque) => opaque.walk(f),
120 }
121 } 121 }
122 122
123 fn walk_mut_binders( 123 fn walk_mut_binders(
@@ -125,8 +125,11 @@ impl TypeWalk for ProjectionPredicate {
125 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 125 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
126 binders: DebruijnIndex, 126 binders: DebruijnIndex,
127 ) { 127 ) {
128 self.projection_ty.walk_mut_binders(f, binders);
129 self.ty.walk_mut_binders(f, binders); 128 self.ty.walk_mut_binders(f, binders);
129 match &mut self.alias {
130 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
131 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
132 }
130 } 133 }
131} 134}
132 135
@@ -138,12 +141,14 @@ pub(crate) fn trait_solve_query(
138) -> Option<Solution> { 141) -> Option<Solution> {
139 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { 142 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
140 Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), 143 Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(),
141 Obligation::Projection(_) => "projection".to_string(), 144 Obligation::AliasEq(_) => "alias_eq".to_string(),
142 }); 145 });
143 log::info!("trait_solve_query({})", goal.value.value.display(db)); 146 log::info!("trait_solve_query({})", goal.value.value.display(db));
144 147
145 if let Obligation::Projection(pred) = &goal.value.value { 148 if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) =
146 if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) { 149 &goal.value.value
150 {
151 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
147 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 152 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
148 return Some(Solution::Ambig(Guidance::Unknown)); 153 return Some(Solution::Ambig(Guidance::Unknown));
149 } 154 }
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::{
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, to_chalk_trait_id, 22 to_assoc_type_id, to_chalk_trait_id,
23 utils::generics, 23 utils::generics,
24 BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate, 24 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId,
25 ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, 25 GenericPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
26}; 26};
27use mapping::{ 27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, 28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -229,18 +229,18 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
229 .intern(&Interner), 229 .intern(&Interner),
230 ), 230 ),
231 }); 231 });
232 let proj_bound = GenericPredicate::Projection(ProjectionPredicate { 232 let proj_bound = GenericPredicate::AliasEq(AliasEq {
233 // The parameter of the opaque type. 233 alias: AliasTy::Projection(ProjectionTy {
234 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
235 .intern(&Interner),
236 projection_ty: ProjectionTy {
237 associated_ty_id: to_assoc_type_id(future_output), 234 associated_ty_id: to_assoc_type_id(future_output),
238 // Self type as the first parameter. 235 // Self type as the first parameter.
239 substitution: Substitution::single( 236 substitution: Substitution::single(
240 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 237 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
241 .intern(&Interner), 238 .intern(&Interner),
242 ), 239 ),
243 }, 240 }),
241 // The parameter of the opaque type.
242 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
243 .intern(&Interner),
244 }); 244 });
245 let bound = OpaqueTyDatumBound { 245 let bound = OpaqueTyDatumBound {
246 bounds: make_binders( 246 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::{
14 from_assoc_type_id, 14 from_assoc_type_id,
15 primitive::UintTy, 15 primitive::UintTy,
16 traits::{Canonical, Obligation}, 16 traits::{Canonical, Obligation},
17 AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, 17 AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, ProjectionTy,
18 ProjectionPredicate, ProjectionTy, Scalar, Substitution, TraitRef, Ty, 18 Scalar, Substitution, TraitRef, Ty,
19}; 19};
20 20
21use super::interner::*; 21use super::interner::*;
@@ -314,12 +314,10 @@ impl ToChalk for GenericPredicate {
314 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); 314 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
315 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) 315 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
316 } 316 }
317 GenericPredicate::Projection(projection_pred) => { 317 GenericPredicate::AliasEq(alias_eq) => make_binders(
318 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); 318 chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)),
319 let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); 319 0,
320 let alias = chalk_ir::AliasTy::Projection(projection); 320 ),
321 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
322 }
323 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), 321 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
324 } 322 }
325 } 323 }
@@ -338,16 +336,8 @@ impl ToChalk for GenericPredicate {
338 chalk_ir::WhereClause::Implemented(tr) => { 336 chalk_ir::WhereClause::Implemented(tr) => {
339 GenericPredicate::Implemented(from_chalk(db, tr)) 337 GenericPredicate::Implemented(from_chalk(db, tr))
340 } 338 }
341 chalk_ir::WhereClause::AliasEq(projection_eq) => { 339 chalk_ir::WhereClause::AliasEq(alias_eq) => {
342 let projection_ty = from_chalk( 340 GenericPredicate::AliasEq(from_chalk(db, alias_eq))
343 db,
344 match projection_eq.alias {
345 chalk_ir::AliasTy::Projection(p) => p,
346 _ => unimplemented!(),
347 },
348 );
349 let ty = from_chalk(db, projection_eq.ty);
350 GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty })
351 } 341 }
352 342
353 chalk_ir::WhereClause::LifetimeOutlives(_) => { 343 chalk_ir::WhereClause::LifetimeOutlives(_) => {
@@ -383,19 +373,55 @@ impl ToChalk for ProjectionTy {
383 } 373 }
384 } 374 }
385} 375}
376impl ToChalk for OpaqueTy {
377 type Chalk = chalk_ir::OpaqueTy<Interner>;
378
379 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
380 chalk_ir::OpaqueTy {
381 opaque_ty_id: self.opaque_ty_id,
382 substitution: self.substitution.to_chalk(db),
383 }
384 }
385
386 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
387 OpaqueTy {
388 opaque_ty_id: chalk.opaque_ty_id,
389 substitution: from_chalk(db, chalk.substitution),
390 }
391 }
392}
393
394impl ToChalk for AliasTy {
395 type Chalk = chalk_ir::AliasTy<Interner>;
396
397 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
398 match self {
399 AliasTy::Projection(projection_ty) => {
400 chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
401 }
402 AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
403 }
404 }
405
406 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
407 match chalk {
408 chalk_ir::AliasTy::Projection(projection_ty) => {
409 AliasTy::Projection(from_chalk(db, projection_ty))
410 }
411 chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
412 }
413 }
414}
386 415
387impl ToChalk for ProjectionPredicate { 416impl ToChalk for AliasEq {
388 type Chalk = chalk_ir::AliasEq<Interner>; 417 type Chalk = chalk_ir::AliasEq<Interner>;
389 418
390 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { 419 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
391 chalk_ir::AliasEq { 420 chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
392 alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)),
393 ty: self.ty.to_chalk(db),
394 }
395 } 421 }
396 422
397 fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { 423 fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
398 unimplemented!() 424 AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
399 } 425 }
400} 426}
401 427
@@ -405,7 +431,7 @@ impl ToChalk for Obligation {
405 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { 431 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
406 match self { 432 match self {
407 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), 433 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
408 Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), 434 Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner),
409 } 435 }
410 } 436 }
411 437
@@ -527,29 +553,29 @@ pub(super) fn generic_predicate_to_inline_bound(
527 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; 553 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
528 Some(rust_ir::InlineBound::TraitBound(trait_bound)) 554 Some(rust_ir::InlineBound::TraitBound(trait_bound))
529 } 555 }
530 GenericPredicate::Projection(proj) => { 556 GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
531 if &proj.projection_ty.substitution[0] != self_ty { 557 if &projection_ty.substitution[0] != self_ty {
532 return None; 558 return None;
533 } 559 }
534 let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id) 560 let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id)
535 .lookup(db.upcast()) 561 .lookup(db.upcast())
536 .container 562 .container
537 { 563 {
538 AssocContainerId::TraitId(t) => t, 564 AssocContainerId::TraitId(t) => t,
539 _ => panic!("associated type not in trait"), 565 _ => panic!("associated type not in trait"),
540 }; 566 };
541 let args_no_self = proj.projection_ty.substitution[1..] 567 let args_no_self = projection_ty.substitution[1..]
542 .iter() 568 .iter()
543 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 569 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
544 .collect(); 570 .collect();
545 let alias_eq_bound = rust_ir::AliasEqBound { 571 let alias_eq_bound = rust_ir::AliasEqBound {
546 value: proj.ty.clone().to_chalk(db), 572 value: ty.clone().to_chalk(db),
547 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, 573 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
548 associated_ty_id: proj.projection_ty.associated_ty_id, 574 associated_ty_id: projection_ty.associated_ty_id,
549 parameters: Vec::new(), // FIXME we don't support generic associated types yet 575 parameters: Vec::new(), // FIXME we don't support generic associated types yet
550 }; 576 };
551 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) 577 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound))
552 } 578 }
553 GenericPredicate::Error => None, 579 _ => None,
554 } 580 }
555} 581}