diff options
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 51 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 11 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 65 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 27 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 34 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 66 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 138 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 109 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 53 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 69 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 22 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 96 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 17 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 20 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 124 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 10 |
20 files changed, 694 insertions, 262 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 23ab042c1..dc5fc759a 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -16,8 +16,8 @@ use crate::{ | |||
16 | to_assoc_type_id, to_chalk_trait_id, | 16 | to_assoc_type_id, to_chalk_trait_id, |
17 | traits::{InEnvironment, Solution}, | 17 | traits::{InEnvironment, Solution}, |
18 | utils::generics, | 18 | utils::generics, |
19 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, | 19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, |
20 | TraitRef, Ty, TyKind, | 20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -27,9 +27,9 @@ pub fn autoderef<'a>( | |||
27 | krate: Option<CrateId>, | 27 | krate: Option<CrateId>, |
28 | ty: InEnvironment<Canonical<Ty>>, | 28 | ty: InEnvironment<Canonical<Ty>>, |
29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
30 | let InEnvironment { value: ty, environment } = ty; | 30 | let InEnvironment { goal: ty, environment } = ty; |
31 | successors(Some(ty), move |ty| { | 31 | successors(Some(ty), move |ty| { |
32 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | 32 | deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() }) |
33 | }) | 33 | }) |
34 | .take(AUTODEREF_RECURSION_LIMIT) | 34 | .take(AUTODEREF_RECURSION_LIMIT) |
35 | } | 35 | } |
@@ -39,8 +39,8 @@ pub(crate) fn deref( | |||
39 | krate: CrateId, | 39 | krate: CrateId, |
40 | ty: InEnvironment<&Canonical<Ty>>, | 40 | ty: InEnvironment<&Canonical<Ty>>, |
41 | ) -> Option<Canonical<Ty>> { | 41 | ) -> Option<Canonical<Ty>> { |
42 | if let Some(derefed) = ty.value.value.builtin_deref() { | 42 | if let Some(derefed) = ty.goal.value.builtin_deref() { |
43 | Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) | 43 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
44 | } else { | 44 | } else { |
45 | deref_by_trait(db, krate, ty) | 45 | deref_by_trait(db, krate, ty) |
46 | } | 46 | } |
@@ -67,15 +67,15 @@ fn deref_by_trait( | |||
67 | // FIXME make the Canonical / bound var handling nicer | 67 | // FIXME make the Canonical / bound var handling nicer |
68 | 68 | ||
69 | let parameters = | 69 | let parameters = |
70 | Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); | 70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); |
71 | 71 | ||
72 | // Check that the type implements Deref at all | 72 | // Check that the type implements Deref at all |
73 | let trait_ref = | 73 | let trait_ref = |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | 74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; |
75 | let implements_goal = Canonical { | 75 | let implements_goal = Canonical { |
76 | kinds: ty.value.kinds.clone(), | 76 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 77 | value: InEnvironment { |
78 | value: trait_ref.cast(&Interner), | 78 | goal: trait_ref.cast(&Interner), |
79 | environment: ty.environment.clone(), | 79 | environment: ty.environment.clone(), |
80 | }, | 80 | }, |
81 | }; | 81 | }; |
@@ -89,18 +89,27 @@ fn deref_by_trait( | |||
89 | associated_ty_id: to_assoc_type_id(target), | 89 | associated_ty_id: to_assoc_type_id(target), |
90 | substitution: parameters, | 90 | substitution: parameters, |
91 | }), | 91 | }), |
92 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) | 92 | ty: TyKind::BoundVar(BoundVar::new( |
93 | .intern(&Interner), | 93 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | ||
95 | )) | ||
96 | .intern(&Interner), | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | let obligation = projection.cast(&Interner); | 99 | let obligation = projection.cast(&Interner); |
97 | 100 | ||
98 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; |
99 | 102 | ||
100 | let canonical = Canonical::new( | 103 | let canonical = Canonical { |
101 | in_env, | 104 | value: in_env, |
102 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | 105 | binders: CanonicalVarKinds::from_iter( |
103 | ); | 106 | &Interner, |
107 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( | ||
108 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
109 | chalk_ir::UniverseIndex::ROOT, | ||
110 | ))), | ||
111 | ), | ||
112 | }; | ||
104 | 113 | ||
105 | let solution = db.trait_solve(krate, canonical)?; | 114 | let solution = db.trait_solve(krate, canonical)?; |
106 | 115 | ||
@@ -121,21 +130,21 @@ fn deref_by_trait( | |||
121 | // assumptions will be broken. We would need to properly introduce | 130 | // assumptions will be broken. We would need to properly introduce |
122 | // new variables in that case | 131 | // new variables in that case |
123 | 132 | ||
124 | for i in 1..vars.0.kinds.len() { | 133 | for i in 1..vars.0.binders.len(&Interner) { |
125 | if vars.0.value[i - 1].interned(&Interner) | 134 | if vars.0.value[i - 1].interned(&Interner) |
126 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 135 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
127 | { | 136 | { |
128 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 137 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
129 | return None; | 138 | return None; |
130 | } | 139 | } |
131 | } | 140 | } |
132 | Some(Canonical { | 141 | Some(Canonical { |
133 | value: vars.0.value[vars.0.value.len() - 1].clone(), | 142 | value: vars.0.value[vars.0.value.len() - 1].clone(), |
134 | kinds: vars.0.kinds.clone(), | 143 | binders: vars.0.binders.clone(), |
135 | }) | 144 | }) |
136 | } | 145 | } |
137 | Solution::Ambig(_) => { | 146 | Solution::Ambig(_) => { |
138 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); | 147 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); |
139 | None | 148 | None |
140 | } | 149 | } |
141 | } | 150 | } |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 91a2e0b5b..58e4247c6 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, |
16 | TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, | 16 | QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
57 | 57 | ||
58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
60 | fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; | 60 | fn generic_predicates_for_param( |
61 | &self, | ||
62 | param_id: TypeParamId, | ||
63 | ) -> Arc<[Binders<QuantifiedWhereClause>]>; | ||
61 | 64 | ||
62 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 65 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
63 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; | 66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; |
64 | 67 | ||
65 | #[salsa::invoke(crate::lower::trait_environment_query)] | 68 | #[salsa::invoke(crate::lower::trait_environment_query)] |
66 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 3845009ae..6149067c7 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::fmt; |
4 | 4 | ||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
@@ -20,7 +20,7 @@ use 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, AliasEq, AliasTy, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 23 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -190,6 +190,7 @@ impl DisplayTarget { | |||
190 | pub enum DisplaySourceCodeError { | 190 | pub enum DisplaySourceCodeError { |
191 | PathNotFound, | 191 | PathNotFound, |
192 | UnknownType, | 192 | UnknownType, |
193 | Closure, | ||
193 | } | 194 | } |
194 | 195 | ||
195 | pub enum HirDisplayError { | 196 | pub enum HirDisplayError { |
@@ -328,9 +329,9 @@ impl HirDisplay for Ty { | |||
328 | 329 | ||
329 | // FIXME: all this just to decide whether to use parentheses... | 330 | // FIXME: all this just to decide whether to use parentheses... |
330 | let datas; | 331 | let datas; |
331 | let predicates = match t.interned(&Interner) { | 332 | let predicates: Vec<_> = match t.interned(&Interner) { |
332 | TyKind::Dyn(predicates) if predicates.len() > 1 => { | 333 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
333 | Cow::Borrowed(predicates.as_ref()) | 334 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
334 | } | 335 | } |
335 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 336 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
336 | opaque_ty_id, | 337 | opaque_ty_id, |
@@ -345,17 +346,21 @@ impl HirDisplay for Ty { | |||
345 | .as_ref() | 346 | .as_ref() |
346 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 347 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
347 | let bounds = data.subst(parameters); | 348 | let bounds = data.subst(parameters); |
348 | Cow::Owned(bounds.value) | 349 | bounds.value |
349 | } else { | 350 | } else { |
350 | Cow::Borrowed(&[][..]) | 351 | Vec::new() |
351 | } | 352 | } |
352 | } | 353 | } |
353 | _ => Cow::Borrowed(&[][..]), | 354 | _ => Vec::new(), |
354 | }; | 355 | }; |
355 | 356 | ||
356 | if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { | 357 | if let Some(WhereClause::Implemented(trait_ref)) = |
358 | predicates.get(0).map(|b| b.skip_binders()) | ||
359 | { | ||
357 | let trait_ = trait_ref.hir_trait_id(); | 360 | let trait_ = trait_ref.hir_trait_id(); |
358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 361 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) |
362 | && predicates.len() <= 2 | ||
363 | { | ||
359 | return write!(f, "{}", ty_display); | 364 | return write!(f, "{}", ty_display); |
360 | } | 365 | } |
361 | } | 366 | } |
@@ -539,6 +544,11 @@ impl HirDisplay for Ty { | |||
539 | } | 544 | } |
540 | } | 545 | } |
541 | TyKind::Closure(.., substs) => { | 546 | TyKind::Closure(.., substs) => { |
547 | if f.display_target.is_source_code() { | ||
548 | return Err(HirDisplayError::DisplaySourceCodeError( | ||
549 | DisplaySourceCodeError::Closure, | ||
550 | )); | ||
551 | } | ||
542 | let sig = substs[0].callable_sig(f.db); | 552 | let sig = substs[0].callable_sig(f.db); |
543 | if let Some(sig) = sig { | 553 | if let Some(sig) = sig { |
544 | if sig.params().is_empty() { | 554 | if sig.params().is_empty() { |
@@ -571,19 +581,32 @@ impl HirDisplay for Ty { | |||
571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 581 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
572 | } | 582 | } |
573 | TypeParamProvenance::ArgumentImplTrait => { | 583 | TypeParamProvenance::ArgumentImplTrait => { |
574 | let bounds = f.db.generic_predicates_for_param(id); | ||
575 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 584 | let substs = Substitution::type_params_for_generics(f.db, &generics); |
576 | write_bounds_like_dyn_trait_with_prefix( | 585 | let bounds = f |
577 | "impl", | 586 | .db |
578 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 587 | .generic_predicates(id.parent) |
579 | f, | 588 | .into_iter() |
580 | )?; | 589 | .map(|pred| pred.clone().subst(&substs)) |
590 | .filter(|wc| match &wc.skip_binders() { | ||
591 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
592 | WhereClause::AliasEq(AliasEq { | ||
593 | alias: AliasTy::Projection(proj), | ||
594 | ty: _, | ||
595 | }) => proj.self_type_parameter() == self, | ||
596 | _ => false, | ||
597 | }) | ||
598 | .collect::<Vec<_>>(); | ||
599 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; | ||
581 | } | 600 | } |
582 | } | 601 | } |
583 | } | 602 | } |
584 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 603 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
585 | TyKind::Dyn(predicates) => { | 604 | TyKind::Dyn(dyn_ty) => { |
586 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 605 | write_bounds_like_dyn_trait_with_prefix( |
606 | "dyn", | ||
607 | dyn_ty.bounds.skip_binders().interned(), | ||
608 | f, | ||
609 | )?; | ||
587 | } | 610 | } |
588 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 611 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
589 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 612 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
@@ -652,7 +675,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
652 | 675 | ||
653 | pub fn write_bounds_like_dyn_trait_with_prefix( | 676 | pub fn write_bounds_like_dyn_trait_with_prefix( |
654 | prefix: &str, | 677 | prefix: &str, |
655 | predicates: &[WhereClause], | 678 | predicates: &[QuantifiedWhereClause], |
656 | f: &mut HirFormatter, | 679 | f: &mut HirFormatter, |
657 | ) -> Result<(), HirDisplayError> { | 680 | ) -> Result<(), HirDisplayError> { |
658 | write!(f, "{}", prefix)?; | 681 | write!(f, "{}", prefix)?; |
@@ -665,7 +688,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
665 | } | 688 | } |
666 | 689 | ||
667 | fn write_bounds_like_dyn_trait( | 690 | fn write_bounds_like_dyn_trait( |
668 | predicates: &[WhereClause], | 691 | predicates: &[QuantifiedWhereClause], |
669 | f: &mut HirFormatter, | 692 | f: &mut HirFormatter, |
670 | ) -> Result<(), HirDisplayError> { | 693 | ) -> Result<(), HirDisplayError> { |
671 | // Note: This code is written to produce nice results (i.e. | 694 | // Note: This code is written to produce nice results (i.e. |
@@ -678,7 +701,7 @@ fn write_bounds_like_dyn_trait( | |||
678 | let mut angle_open = false; | 701 | let mut angle_open = false; |
679 | let mut is_fn_trait = false; | 702 | let mut is_fn_trait = false; |
680 | for p in predicates.iter() { | 703 | for p in predicates.iter() { |
681 | match p { | 704 | match p.skip_binders() { |
682 | WhereClause::Implemented(trait_ref) => { | 705 | WhereClause::Implemented(trait_ref) => { |
683 | let trait_ = trait_ref.hir_trait_id(); | 706 | let trait_ = trait_ref.hir_trait_id(); |
684 | if !is_fn_trait { | 707 | if !is_fn_trait { |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b9e434c78..8f9cf7480 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> { | |||
331 | fn resolve_obligations_as_possible(&mut self) { | 331 | fn resolve_obligations_as_possible(&mut self) { |
332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
333 | for obligation in obligations { | 333 | for obligation in obligations { |
334 | let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); | 334 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); |
335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
336 | let solution = | 336 | let solution = |
337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 07eb96573..9c62932b1 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> { | |||
142 | .build(); | 142 | .build(); |
143 | let trait_ref = | 143 | let trait_ref = |
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
145 | let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); | 145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); |
146 | 146 | ||
147 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> { | |||
170 | self.db, | 170 | self.db, |
171 | self.resolver.krate(), | 171 | self.resolver.krate(), |
172 | InEnvironment { | 172 | InEnvironment { |
173 | value: canonicalized.value.clone(), | 173 | goal: canonicalized.value.clone(), |
174 | environment: self.trait_env.clone(), | 174 | environment: self.trait_env.env.clone(), |
175 | }, | 175 | }, |
176 | ) { | 176 | ) { |
177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 46d713a7b..3f3187ea2 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -89,12 +90,12 @@ impl<'a> InferenceContext<'a> { | |||
89 | let substs = | 90 | let substs = |
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 92 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 93 | let trait_env = self.trait_env.env.clone(); |
93 | let implements_fn_trait: DomainGoal = | 94 | let implements_fn_trait: DomainGoal = |
94 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } | 95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
95 | .cast(&Interner); | 96 | .cast(&Interner); |
96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
97 | value: implements_fn_trait.clone(), | 98 | goal: implements_fn_trait.clone(), |
98 | environment: trait_env, | 99 | environment: trait_env, |
99 | }); | 100 | }); |
100 | if self.db.trait_solve(krate, goal.value).is_some() { | 101 | if self.db.trait_solve(krate, goal.value).is_some() { |
@@ -298,8 +299,8 @@ impl<'a> InferenceContext<'a> { | |||
298 | self.db, | 299 | self.db, |
299 | self.resolver.krate(), | 300 | self.resolver.krate(), |
300 | InEnvironment { | 301 | InEnvironment { |
301 | value: canonicalized.value.clone(), | 302 | goal: canonicalized.value.clone(), |
302 | environment: self.trait_env.clone(), | 303 | environment: self.trait_env.env.clone(), |
303 | }, | 304 | }, |
304 | ); | 305 | ); |
305 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 306 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
@@ -437,8 +438,8 @@ impl<'a> InferenceContext<'a> { | |||
437 | self.db, | 438 | self.db, |
438 | self.resolver.krate(), | 439 | self.resolver.krate(), |
439 | InEnvironment { | 440 | InEnvironment { |
440 | value: canonicalized.value.clone(), | 441 | goal: canonicalized.value.clone(), |
441 | environment: self.trait_env.clone(), | 442 | environment: self.trait_env.env.clone(), |
442 | }, | 443 | }, |
443 | ) | 444 | ) |
444 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
@@ -533,10 +534,10 @@ impl<'a> InferenceContext<'a> { | |||
533 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 534 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
534 | if let Some(box_) = self.resolve_boxed_box() { | 535 | if let Some(box_) = self.resolve_boxed_box() { |
535 | let mut sb = | 536 | let mut sb = |
536 | Substitution::builder(generics(self.db.upcast(), box_.into()).len()); | 537 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); |
537 | sb = sb.push(inner_ty); | 538 | sb = sb.push(inner_ty); |
538 | match self.db.generic_defaults(box_.into()).as_ref() { | 539 | match self.db.generic_defaults(box_.into()).get(1) { |
539 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | 540 | Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { |
540 | sb = sb.push(alloc_ty.value.clone()); | 541 | sb = sb.push(alloc_ty.value.clone()); |
541 | } | 542 | } |
542 | _ => (), | 543 | _ => (), |
@@ -557,8 +558,8 @@ impl<'a> InferenceContext<'a> { | |||
557 | self.db, | 558 | self.db, |
558 | krate, | 559 | krate, |
559 | InEnvironment { | 560 | InEnvironment { |
560 | value: &canonicalized.value, | 561 | goal: &canonicalized.value, |
561 | environment: self.trait_env.clone(), | 562 | environment: self.trait_env.env.clone(), |
562 | }, | 563 | }, |
563 | ) { | 564 | ) { |
564 | Some(derefed_ty) => { | 565 | Some(derefed_ty) => { |
@@ -957,7 +958,9 @@ impl<'a> InferenceContext<'a> { | |||
957 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 958 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
958 | let generic_predicates = self.db.generic_predicates(def.into()); | 959 | let generic_predicates = self.db.generic_predicates(def.into()); |
959 | for predicate in generic_predicates.iter() { | 960 | for predicate in generic_predicates.iter() { |
960 | let predicate = predicate.clone().subst(parameters); | 961 | let (predicate, binders) = |
962 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); | ||
963 | always!(binders == 0); // quantified where clauses not yet handled | ||
961 | self.obligations.push(predicate.cast(&Interner)); | 964 | self.obligations.push(predicate.cast(&Interner)); |
962 | } | 965 | } |
963 | // add obligation for trait implementation, if this is a trait method | 966 | // add obligation for trait implementation, if this is a trait method |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index befa0d69b..474363709 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,7 +13,9 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, | 16 | lower::lower_to_chalk_mutability, |
17 | utils::{generics, variant_data}, | ||
18 | Interner, Substitution, Ty, TyKind, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | impl<'a> InferenceContext<'a> { | 21 | impl<'a> InferenceContext<'a> { |
@@ -38,7 +40,7 @@ impl<'a> InferenceContext<'a> { | |||
38 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
39 | let (pre, post) = match ellipsis { | 41 | let (pre, post) = match ellipsis { |
40 | Some(idx) => subpats.split_at(idx), | 42 | Some(idx) => subpats.split_at(idx), |
41 | None => (&subpats[..], &[][..]), | 43 | None => (subpats, &[][..]), |
42 | }; | 44 | }; |
43 | let post_idx_offset = field_tys.iter().count() - post.len(); | 45 | let post_idx_offset = field_tys.iter().count() - post.len(); |
44 | 46 | ||
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> { | |||
233 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 235 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
234 | Pat::Box { inner } => match self.resolve_boxed_box() { | 236 | Pat::Box { inner } => match self.resolve_boxed_box() { |
235 | Some(box_adt) => { | 237 | Some(box_adt) => { |
236 | let inner_expected = match expected.as_adt() { | 238 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
237 | Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), | 239 | Some((adt, subst)) if adt == box_adt => { |
238 | _ => self.result.standard_types.unknown.clone(), | 240 | (subst[0].clone(), subst.get(1).cloned()) |
241 | } | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); | 245 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
242 | Ty::adt_ty(box_adt, Substitution::single(inner_ty)) | 246 | let mut sb = Substitution::build_for_generics(&generics( |
247 | self.db.upcast(), | ||
248 | box_adt.into(), | ||
249 | )); | ||
250 | sb = sb.push(inner_ty); | ||
251 | if sb.remaining() == 1 { | ||
252 | sb = sb.push(match alloc_ty { | ||
253 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
254 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
255 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
256 | alloc_ty.value.clone() | ||
257 | } | ||
258 | _ => self.table.new_type_var(), | ||
259 | }, | ||
260 | }); | ||
261 | } | ||
262 | Ty::adt_ty(box_adt, sb.build()) | ||
243 | } | 263 | } |
244 | None => self.err_ty(), | 264 | None => self.err_ty(), |
245 | }, | 265 | }, |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 1fc03c8f4..75250a369 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{DomainGoal, InferenceContext}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, | 10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, | 11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); | 79 | let kinds = self |
80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | .free_vars |
81 | .iter() | ||
82 | .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT)); | ||
83 | Canonicalized { | ||
84 | value: Canonical { | ||
85 | value: result, | ||
86 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
87 | }, | ||
88 | free_vars: self.free_vars, | ||
89 | } | ||
81 | } | 90 | } |
82 | 91 | ||
83 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 92 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
89 | mut self, | 98 | mut self, |
90 | obligation: InEnvironment<DomainGoal>, | 99 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<DomainGoal>> { | 100 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 101 | let result = match obligation.goal { |
93 | DomainGoal::Holds(wc) => { | 102 | DomainGoal::Holds(wc) => { |
94 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | 104 | } |
96 | }; | 105 | }; |
97 | self.into_canonicalized(InEnvironment { | 106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
98 | value: result, | ||
99 | environment: obligation.environment, | ||
100 | }) | ||
101 | } | 107 | } |
102 | } | 108 | } |
103 | 109 | ||
@@ -125,12 +131,19 @@ impl<T> Canonicalized<T> { | |||
125 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
126 | let new_vars = Substitution( | 132 | let new_vars = Substitution( |
127 | solution | 133 | solution |
128 | .kinds | 134 | .binders |
129 | .iter() | 135 | .iter(&Interner) |
130 | .map(|k| match k { | 136 | .map(|k| match k.kind { |
131 | TyVariableKind::General => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
132 | TyVariableKind::Integer => ctx.table.new_integer_var(), | 138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
133 | TyVariableKind::Float => ctx.table.new_float_var(), | 139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
141 | // want to just skip them, but to not mess up the indices of | ||
142 | // other variables, we'll just create a new type variable in | ||
143 | // their place instead. This should not matter (we never see the | ||
144 | // actual *uses* of the lifetime variable). | ||
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | ||
146 | _ => panic!("const variable in solution"), | ||
134 | }) | 147 | }) |
135 | .collect(), | 148 | .collect(), |
136 | ); | 149 | ); |
@@ -147,8 +160,8 @@ impl<T> Canonicalized<T> { | |||
147 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
148 | let mut table = InferenceTable::new(); | 161 | let mut table = InferenceTable::new(); |
149 | let vars = Substitution( | 162 | let vars = Substitution( |
150 | tys.kinds | 163 | tys.binders |
151 | .iter() | 164 | .iter(&Interner) |
152 | // we always use type vars here because we want everything to | 165 | // we always use type vars here because we want everything to |
153 | // fallback to Unknown in the end (kind of hacky, as below) | 166 | // fallback to Unknown in the end (kind of hacky, as below) |
154 | .map(|_| table.new_type_var()) | 167 | .map(|_| table.new_type_var()) |
@@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
170 | } | 183 | } |
171 | } | 184 | } |
172 | Some( | 185 | Some( |
173 | Substitution::builder(tys.kinds.len()) | 186 | Substitution::builder(tys.binders.len(&Interner)) |
174 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 187 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
175 | .build(), | 188 | .build(), |
176 | ) | 189 | ) |
@@ -310,9 +323,18 @@ impl InferenceTable { | |||
310 | 323 | ||
311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 324 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
312 | 325 | ||
313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 326 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
314 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 327 | if dyn1.bounds.skip_binders().interned().len() |
315 | if !self.unify_preds(pred1, pred2, depth + 1) { | 328 | == dyn2.bounds.skip_binders().interned().len() => |
329 | { | ||
330 | for (pred1, pred2) in dyn1 | ||
331 | .bounds | ||
332 | .skip_binders() | ||
333 | .interned() | ||
334 | .iter() | ||
335 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
336 | { | ||
337 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
316 | return false; | 338 | return false; |
317 | } | 339 | } |
318 | } | 340 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index c46529879..69265286f 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -61,6 +61,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>; | |||
61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
63 | 63 | ||
64 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | ||
65 | |||
64 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 66 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
65 | 67 | ||
66 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 68 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -106,6 +108,10 @@ impl ProjectionTy { | |||
106 | } | 108 | } |
107 | } | 109 | } |
108 | 110 | ||
111 | pub fn self_type_parameter(&self) -> &Ty { | ||
112 | &self.substitution[0] | ||
113 | } | ||
114 | |||
109 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 115 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
110 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { | 116 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { |
111 | AssocContainerId::TraitId(it) => it, | 117 | AssocContainerId::TraitId(it) => it, |
@@ -128,6 +134,12 @@ impl TypeWalk for ProjectionTy { | |||
128 | } | 134 | } |
129 | } | 135 | } |
130 | 136 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
138 | pub struct DynTy { | ||
139 | /// The unknown self type. | ||
140 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
141 | } | ||
142 | |||
131 | pub type FnSig = chalk_ir::FnSig<Interner>; | 143 | pub type FnSig = chalk_ir::FnSig<Interner>; |
132 | 144 | ||
133 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 145 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -279,7 +291,7 @@ pub enum TyKind { | |||
279 | /// represents the `Self` type inside the bounds. This is currently | 291 | /// represents the `Self` type inside the bounds. This is currently |
280 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | 292 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it |
281 | /// didn't seem worth the overhead yet. | 293 | /// didn't seem worth the overhead yet. |
282 | Dyn(Arc<[WhereClause]>), | 294 | Dyn(DynTy), |
283 | 295 | ||
284 | /// A placeholder for a type which could not be computed; this is propagated | 296 | /// A placeholder for a type which could not be computed; this is propagated |
285 | /// to avoid useless error messages. Doubles as a placeholder where type | 297 | /// to avoid useless error messages. Doubles as a placeholder where type |
@@ -486,6 +498,13 @@ impl<T> Binders<T> { | |||
486 | Self { num_binders, value } | 498 | Self { num_binders, value } |
487 | } | 499 | } |
488 | 500 | ||
501 | pub fn wrap_empty(value: T) -> Self | ||
502 | where | ||
503 | T: TypeWalk, | ||
504 | { | ||
505 | Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } | ||
506 | } | ||
507 | |||
489 | pub fn as_ref(&self) -> Binders<&T> { | 508 | pub fn as_ref(&self) -> Binders<&T> { |
490 | Binders { num_binders: self.num_binders, value: &self.value } | 509 | Binders { num_binders: self.num_binders, value: &self.value } |
491 | } | 510 | } |
@@ -497,6 +516,14 @@ impl<T> Binders<T> { | |||
497 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { | 516 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { |
498 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) | 517 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) |
499 | } | 518 | } |
519 | |||
520 | pub fn skip_binders(&self) -> &T { | ||
521 | &self.value | ||
522 | } | ||
523 | |||
524 | pub fn into_value_and_skipped_binders(self) -> (T, usize) { | ||
525 | (self.value, self.num_binders) | ||
526 | } | ||
500 | } | 527 | } |
501 | 528 | ||
502 | impl<T: Clone> Binders<&T> { | 529 | impl<T: Clone> Binders<&T> { |
@@ -511,12 +538,6 @@ impl<T: TypeWalk> Binders<T> { | |||
511 | assert_eq!(subst.len(), self.num_binders); | 538 | assert_eq!(subst.len(), self.num_binders); |
512 | self.value.subst_bound_vars(subst) | 539 | self.value.subst_bound_vars(subst) |
513 | } | 540 | } |
514 | |||
515 | /// Substitutes just a prefix of the variables (shifting the rest). | ||
516 | pub fn subst_prefix(self, subst: &Substitution) -> Binders<T> { | ||
517 | assert!(subst.len() < self.num_binders); | ||
518 | Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) | ||
519 | } | ||
520 | } | 541 | } |
521 | 542 | ||
522 | impl<T: TypeWalk> TypeWalk for Binders<T> { | 543 | impl<T: TypeWalk> TypeWalk for Binders<T> { |
@@ -610,6 +631,24 @@ impl TypeWalk for WhereClause { | |||
610 | } | 631 | } |
611 | } | 632 | } |
612 | 633 | ||
634 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
635 | |||
636 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
637 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
638 | |||
639 | impl QuantifiedWhereClauses { | ||
640 | pub fn from_iter( | ||
641 | _interner: &Interner, | ||
642 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
643 | ) -> Self { | ||
644 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
645 | } | ||
646 | |||
647 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
648 | &self.0 | ||
649 | } | ||
650 | } | ||
651 | |||
613 | /// Basically a claim (currently not validated / checked) that the contained | 652 | /// Basically a claim (currently not validated / checked) that the contained |
614 | /// type / trait ref contains no inference variables; any inference variables it | 653 | /// type / trait ref contains no inference variables; any inference variables it |
615 | /// contained have been replaced by bound variables, and `kinds` tells us how | 654 | /// contained have been replaced by bound variables, and `kinds` tells us how |
@@ -619,12 +658,18 @@ impl TypeWalk for WhereClause { | |||
619 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 658 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
620 | pub struct Canonical<T> { | 659 | pub struct Canonical<T> { |
621 | pub value: T, | 660 | pub value: T, |
622 | pub kinds: Arc<[TyVariableKind]>, | 661 | pub binders: CanonicalVarKinds, |
623 | } | 662 | } |
624 | 663 | ||
625 | impl<T> Canonical<T> { | 664 | impl<T> Canonical<T> { |
626 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | 665 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
627 | Self { value, kinds: kinds.into_iter().collect() } | 666 | let kinds = kinds.into_iter().map(|tk| { |
667 | chalk_ir::CanonicalVarKind::new( | ||
668 | chalk_ir::VariableKind::Ty(tk), | ||
669 | chalk_ir::UniverseIndex::ROOT, | ||
670 | ) | ||
671 | }); | ||
672 | Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | ||
628 | } | 673 | } |
629 | } | 674 | } |
630 | 675 | ||
@@ -647,7 +692,15 @@ impl CallableSig { | |||
647 | 692 | ||
648 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { | 693 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { |
649 | CallableSig { | 694 | CallableSig { |
650 | params_and_return: fn_ptr.substs.interned(&Interner).iter().cloned().collect(), | 695 | // FIXME: what to do about lifetime params? |
696 | params_and_return: fn_ptr | ||
697 | .substs | ||
698 | .clone() | ||
699 | .shift_bound_vars_out(DebruijnIndex::ONE) | ||
700 | .interned(&Interner) | ||
701 | .iter() | ||
702 | .cloned() | ||
703 | .collect(), | ||
651 | is_varargs: fn_ptr.sig.variadic, | 704 | is_varargs: fn_ptr.sig.variadic, |
652 | } | 705 | } |
653 | } | 706 | } |
@@ -806,12 +859,14 @@ impl Ty { | |||
806 | } | 859 | } |
807 | 860 | ||
808 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | 861 | /// If this is a `dyn Trait` type, this returns the `Trait` part. |
809 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 862 | fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
810 | match self.interned(&Interner) { | 863 | match self.interned(&Interner) { |
811 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { | 864 | TyKind::Dyn(dyn_ty) => { |
812 | WhereClause::Implemented(trait_ref) => Some(trait_ref), | 865 | dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { |
813 | _ => None, | 866 | WhereClause::Implemented(trait_ref) => Some(trait_ref), |
814 | }), | 867 | _ => None, |
868 | }) | ||
869 | } | ||
815 | _ => None, | 870 | _ => None, |
816 | } | 871 | } |
817 | } | 872 | } |
@@ -888,7 +943,7 @@ impl Ty { | |||
888 | } | 943 | } |
889 | } | 944 | } |
890 | 945 | ||
891 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> { | 946 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { |
892 | match self.interned(&Interner) { | 947 | match self.interned(&Interner) { |
893 | TyKind::OpaqueType(opaque_ty_id, ..) => { | 948 | TyKind::OpaqueType(opaque_ty_id, ..) => { |
894 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | 949 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |
@@ -901,10 +956,13 @@ impl Ty { | |||
901 | // This is only used by type walking. | 956 | // This is only used by type walking. |
902 | // Parameters will be walked outside, and projection predicate is not used. | 957 | // Parameters will be walked outside, and projection predicate is not used. |
903 | // So just provide the Future trait. | 958 | // So just provide the Future trait. |
904 | let impl_bound = WhereClause::Implemented(TraitRef { | 959 | let impl_bound = Binders::new( |
905 | trait_id: to_chalk_trait_id(future_trait), | 960 | 0, |
906 | substitution: Substitution::empty(), | 961 | WhereClause::Implemented(TraitRef { |
907 | }); | 962 | trait_id: to_chalk_trait_id(future_trait), |
963 | substitution: Substitution::empty(), | ||
964 | }), | ||
965 | ); | ||
908 | Some(vec![impl_bound]) | 966 | Some(vec![impl_bound]) |
909 | } else { | 967 | } else { |
910 | None | 968 | None |
@@ -936,10 +994,19 @@ impl Ty { | |||
936 | let param_data = &generic_params.types[id.local_id]; | 994 | let param_data = &generic_params.types[id.local_id]; |
937 | match param_data.provenance { | 995 | match param_data.provenance { |
938 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 996 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
997 | let substs = Substitution::type_params(db, id.parent); | ||
939 | let predicates = db | 998 | let predicates = db |
940 | .generic_predicates_for_param(id) | 999 | .generic_predicates(id.parent) |
941 | .into_iter() | 1000 | .into_iter() |
942 | .map(|pred| pred.value.clone()) | 1001 | .map(|pred| pred.clone().subst(&substs)) |
1002 | .filter(|wc| match &wc.skip_binders() { | ||
1003 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
1004 | WhereClause::AliasEq(AliasEq { | ||
1005 | alias: AliasTy::Projection(proj), | ||
1006 | ty: _, | ||
1007 | }) => proj.self_type_parameter() == self, | ||
1008 | _ => false, | ||
1009 | }) | ||
943 | .collect_vec(); | 1010 | .collect_vec(); |
944 | 1011 | ||
945 | Some(predicates) | 1012 | Some(predicates) |
@@ -1066,6 +1133,23 @@ pub trait TypeWalk { | |||
1066 | DebruijnIndex::INNERMOST, | 1133 | DebruijnIndex::INNERMOST, |
1067 | ) | 1134 | ) |
1068 | } | 1135 | } |
1136 | |||
1137 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
1138 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
1139 | where | ||
1140 | Self: Sized + std::fmt::Debug, | ||
1141 | { | ||
1142 | self.fold_binders( | ||
1143 | &mut |ty, binders| match ty.interned(&Interner) { | ||
1144 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1145 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
1146 | .intern(&Interner) | ||
1147 | } | ||
1148 | _ => ty, | ||
1149 | }, | ||
1150 | DebruijnIndex::INNERMOST, | ||
1151 | ) | ||
1152 | } | ||
1069 | } | 1153 | } |
1070 | 1154 | ||
1071 | impl TypeWalk for Ty { | 1155 | impl TypeWalk for Ty { |
@@ -1081,8 +1165,8 @@ impl TypeWalk for Ty { | |||
1081 | t.walk(f); | 1165 | t.walk(f); |
1082 | } | 1166 | } |
1083 | } | 1167 | } |
1084 | TyKind::Dyn(predicates) => { | 1168 | TyKind::Dyn(dyn_ty) => { |
1085 | for p in predicates.iter() { | 1169 | for p in dyn_ty.bounds.value.interned().iter() { |
1086 | p.walk(f); | 1170 | p.walk(f); |
1087 | } | 1171 | } |
1088 | } | 1172 | } |
@@ -1109,8 +1193,8 @@ impl TypeWalk for Ty { | |||
1109 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | 1193 | TyKind::Alias(AliasTy::Projection(p_ty)) => { |
1110 | p_ty.substitution.walk_mut_binders(f, binders); | 1194 | p_ty.substitution.walk_mut_binders(f, binders); |
1111 | } | 1195 | } |
1112 | TyKind::Dyn(predicates) => { | 1196 | TyKind::Dyn(dyn_ty) => { |
1113 | for p in make_mut_slice(predicates) { | 1197 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { |
1114 | p.walk_mut_binders(f, binders.shifted_in()); | 1198 | p.walk_mut_binders(f, binders.shifted_in()); |
1115 | } | 1199 | } |
1116 | } | 1200 | } |
@@ -1160,7 +1244,7 @@ pub struct ReturnTypeImplTraits { | |||
1160 | 1244 | ||
1161 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1245 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1162 | pub(crate) struct ReturnTypeImplTrait { | 1246 | pub(crate) struct ReturnTypeImplTrait { |
1163 | pub(crate) bounds: Binders<Vec<WhereClause>>, | 1247 | pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, |
1164 | } | 1248 | } |
1165 | 1249 | ||
1166 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { | 1250 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index cbbb535e5..c87789d45 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -33,9 +33,10 @@ 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 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -188,10 +189,14 @@ impl<'a> TyLoweringContext<'a> { | |||
188 | TypeRef::DynTrait(bounds) => { | 189 | TypeRef::DynTrait(bounds) => { |
189 | let self_ty = | 190 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 191 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 192 | let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 193 | QuantifiedWhereClauses::from_iter( |
194 | &Interner, | ||
195 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), | ||
196 | ) | ||
193 | }); | 197 | }); |
194 | TyKind::Dyn(predicates).intern(&Interner) | 198 | let bounds = Binders::new(1, bounds); |
199 | TyKind::Dyn(DynTy { bounds }).intern(&Interner) | ||
195 | } | 200 | } |
196 | TypeRef::ImplTrait(bounds) => { | 201 | TypeRef::ImplTrait(bounds) => { |
197 | match self.impl_trait_mode { | 202 | match self.impl_trait_mode { |
@@ -373,7 +378,16 @@ impl<'a> TyLoweringContext<'a> { | |||
373 | // FIXME report error (ambiguous associated type) | 378 | // FIXME report error (ambiguous associated type) |
374 | TyKind::Unknown.intern(&Interner) | 379 | TyKind::Unknown.intern(&Interner) |
375 | } else { | 380 | } else { |
376 | TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner) | 381 | let dyn_ty = DynTy { |
382 | bounds: Binders::new( | ||
383 | 1, | ||
384 | QuantifiedWhereClauses::from_iter( | ||
385 | &Interner, | ||
386 | Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), | ||
387 | ), | ||
388 | ), | ||
389 | }; | ||
390 | TyKind::Dyn(dyn_ty).intern(&Interner) | ||
377 | }; | 391 | }; |
378 | return (ty, None); | 392 | return (ty, None); |
379 | } | 393 | } |
@@ -507,7 +521,7 @@ impl<'a> TyLoweringContext<'a> { | |||
507 | TyDefId::AdtId(it) => Some(it.into()), | 521 | TyDefId::AdtId(it) => Some(it.into()), |
508 | TyDefId::TypeAliasId(it) => Some(it.into()), | 522 | TyDefId::TypeAliasId(it) => Some(it.into()), |
509 | }; | 523 | }; |
510 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args); | 524 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); |
511 | self.db.ty(typeable).subst(&substs) | 525 | self.db.ty(typeable).subst(&substs) |
512 | } | 526 | } |
513 | 527 | ||
@@ -544,7 +558,7 @@ impl<'a> TyLoweringContext<'a> { | |||
544 | (segment, Some(var.parent.into())) | 558 | (segment, Some(var.parent.into())) |
545 | } | 559 | } |
546 | }; | 560 | }; |
547 | self.substs_from_path_segment(segment, generic_def, infer_args) | 561 | self.substs_from_path_segment(segment, generic_def, infer_args, None) |
548 | } | 562 | } |
549 | 563 | ||
550 | fn substs_from_path_segment( | 564 | fn substs_from_path_segment( |
@@ -552,6 +566,7 @@ impl<'a> TyLoweringContext<'a> { | |||
552 | segment: PathSegment<'_>, | 566 | segment: PathSegment<'_>, |
553 | def_generic: Option<GenericDefId>, | 567 | def_generic: Option<GenericDefId>, |
554 | infer_args: bool, | 568 | infer_args: bool, |
569 | explicit_self_ty: Option<Ty>, | ||
555 | ) -> Substitution { | 570 | ) -> Substitution { |
556 | let mut substs = Vec::new(); | 571 | let mut substs = Vec::new(); |
557 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); | 572 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); |
@@ -562,11 +577,19 @@ impl<'a> TyLoweringContext<'a> { | |||
562 | 577 | ||
563 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); | 578 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); |
564 | 579 | ||
580 | let fill_self_params = || { | ||
581 | substs.extend( | ||
582 | explicit_self_ty | ||
583 | .into_iter() | ||
584 | .chain(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
585 | .take(self_params), | ||
586 | ) | ||
587 | }; | ||
565 | let mut had_explicit_type_args = false; | 588 | let mut had_explicit_type_args = false; |
566 | 589 | ||
567 | if let Some(generic_args) = &segment.args_and_bindings { | 590 | if let Some(generic_args) = &segment.args_and_bindings { |
568 | if !generic_args.has_self_type { | 591 | if !generic_args.has_self_type { |
569 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params)); | 592 | fill_self_params(); |
570 | } | 593 | } |
571 | let expected_num = | 594 | let expected_num = |
572 | if generic_args.has_self_type { self_params + type_params } else { type_params }; | 595 | if generic_args.has_self_type { self_params + type_params } else { type_params }; |
@@ -588,6 +611,8 @@ impl<'a> TyLoweringContext<'a> { | |||
588 | GenericArg::Lifetime(_) => {} | 611 | GenericArg::Lifetime(_) => {} |
589 | } | 612 | } |
590 | } | 613 | } |
614 | } else { | ||
615 | fill_self_params(); | ||
591 | } | 616 | } |
592 | 617 | ||
593 | // handle defaults. In expression or pattern path segments without | 618 | // handle defaults. In expression or pattern path segments without |
@@ -636,10 +661,7 @@ impl<'a> TyLoweringContext<'a> { | |||
636 | segment: PathSegment<'_>, | 661 | segment: PathSegment<'_>, |
637 | explicit_self_ty: Option<Ty>, | 662 | explicit_self_ty: Option<Ty>, |
638 | ) -> TraitRef { | 663 | ) -> TraitRef { |
639 | let mut substs = self.trait_ref_substs_from_path(segment, resolved); | 664 | let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); |
640 | if let Some(self_ty) = explicit_self_ty { | ||
641 | substs.0[0] = self_ty; | ||
642 | } | ||
643 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } | 665 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } |
644 | } | 666 | } |
645 | 667 | ||
@@ -659,14 +681,16 @@ impl<'a> TyLoweringContext<'a> { | |||
659 | &self, | 681 | &self, |
660 | segment: PathSegment<'_>, | 682 | segment: PathSegment<'_>, |
661 | resolved: TraitId, | 683 | resolved: TraitId, |
684 | explicit_self_ty: Option<Ty>, | ||
662 | ) -> Substitution { | 685 | ) -> Substitution { |
663 | self.substs_from_path_segment(segment, Some(resolved.into()), false) | 686 | self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) |
664 | } | 687 | } |
665 | 688 | ||
666 | pub(crate) fn lower_where_predicate( | 689 | pub(crate) fn lower_where_predicate( |
667 | &'a self, | 690 | &'a self, |
668 | where_predicate: &'a WherePredicate, | 691 | where_predicate: &'a WherePredicate, |
669 | ) -> impl Iterator<Item = WhereClause> + 'a { | 692 | ignore_bindings: bool, |
693 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { | ||
670 | match where_predicate { | 694 | match where_predicate { |
671 | WherePredicate::ForLifetime { target, bound, .. } | 695 | WherePredicate::ForLifetime { target, bound, .. } |
672 | | WherePredicate::TypeBound { target, bound } => { | 696 | | WherePredicate::TypeBound { target, bound } => { |
@@ -688,7 +712,9 @@ impl<'a> TyLoweringContext<'a> { | |||
688 | .intern(&Interner) | 712 | .intern(&Interner) |
689 | } | 713 | } |
690 | }; | 714 | }; |
691 | self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter() | 715 | self.lower_type_bound(bound, self_ty, ignore_bindings) |
716 | .collect::<Vec<_>>() | ||
717 | .into_iter() | ||
692 | } | 718 | } |
693 | WherePredicate::Lifetime { .. } => vec![].into_iter(), | 719 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
694 | } | 720 | } |
@@ -698,12 +724,13 @@ impl<'a> TyLoweringContext<'a> { | |||
698 | &'a self, | 724 | &'a self, |
699 | bound: &'a TypeBound, | 725 | bound: &'a TypeBound, |
700 | self_ty: Ty, | 726 | self_ty: Ty, |
701 | ) -> impl Iterator<Item = WhereClause> + 'a { | 727 | ignore_bindings: bool, |
728 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { | ||
702 | let mut bindings = None; | 729 | let mut bindings = None; |
703 | let trait_ref = match bound { | 730 | let trait_ref = match bound { |
704 | TypeBound::Path(path) => { | 731 | TypeBound::Path(path) => { |
705 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); | 732 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); |
706 | bindings.clone().map(WhereClause::Implemented) | 733 | bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) |
707 | } | 734 | } |
708 | TypeBound::Lifetime(_) => None, | 735 | TypeBound::Lifetime(_) => None, |
709 | TypeBound::Error => None, | 736 | TypeBound::Error => None, |
@@ -711,6 +738,7 @@ impl<'a> TyLoweringContext<'a> { | |||
711 | trait_ref.into_iter().chain( | 738 | trait_ref.into_iter().chain( |
712 | bindings | 739 | bindings |
713 | .into_iter() | 740 | .into_iter() |
741 | .filter(move |_| !ignore_bindings) | ||
714 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), | 742 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), |
715 | ) | 743 | ) |
716 | } | 744 | } |
@@ -719,7 +747,7 @@ impl<'a> TyLoweringContext<'a> { | |||
719 | &'a self, | 747 | &'a self, |
720 | bound: &'a TypeBound, | 748 | bound: &'a TypeBound, |
721 | trait_ref: TraitRef, | 749 | trait_ref: TraitRef, |
722 | ) -> impl Iterator<Item = WhereClause> + 'a { | 750 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
723 | let last_segment = match bound { | 751 | let last_segment = match bound { |
724 | TypeBound::Path(path) => path.segments().last(), | 752 | TypeBound::Path(path) => path.segments().last(), |
725 | TypeBound::Error | TypeBound::Lifetime(_) => None, | 753 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
@@ -735,7 +763,7 @@ impl<'a> TyLoweringContext<'a> { | |||
735 | &binding.name, | 763 | &binding.name, |
736 | ); | 764 | ); |
737 | let (super_trait_ref, associated_ty) = match found { | 765 | let (super_trait_ref, associated_ty) = match found { |
738 | None => return SmallVec::<[WhereClause; 1]>::new(), | 766 | None => return SmallVec::<[QuantifiedWhereClause; 1]>::new(), |
739 | Some(t) => t, | 767 | Some(t) => t, |
740 | }; | 768 | }; |
741 | let projection_ty = ProjectionTy { | 769 | let projection_ty = ProjectionTy { |
@@ -749,12 +777,13 @@ impl<'a> TyLoweringContext<'a> { | |||
749 | let ty = self.lower_ty(type_ref); | 777 | let ty = self.lower_ty(type_ref); |
750 | let alias_eq = | 778 | let alias_eq = |
751 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; | 779 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; |
752 | preds.push(WhereClause::AliasEq(alias_eq)); | 780 | preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); |
753 | } | 781 | } |
754 | for bound in &binding.bounds { | 782 | for bound in &binding.bounds { |
755 | preds.extend(self.lower_type_bound( | 783 | preds.extend(self.lower_type_bound( |
756 | bound, | 784 | bound, |
757 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), | 785 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), |
786 | false, | ||
758 | )); | 787 | )); |
759 | } | 788 | } |
760 | preds | 789 | preds |
@@ -766,7 +795,7 @@ impl<'a> TyLoweringContext<'a> { | |||
766 | let self_ty = | 795 | let self_ty = |
767 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 796 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
768 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 797 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
769 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 798 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect() |
770 | }); | 799 | }); |
771 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | 800 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } |
772 | } | 801 | } |
@@ -799,14 +828,18 @@ pub fn associated_type_shorthand_candidates<R>( | |||
799 | let traits_from_env: Vec<_> = match res { | 828 | let traits_from_env: Vec<_> = match res { |
800 | TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) { | 829 | TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) { |
801 | None => vec![], | 830 | None => vec![], |
802 | Some(trait_ref) => vec![trait_ref.value], | 831 | // FIXME: how to correctly handle higher-ranked bounds here? |
832 | Some(trait_ref) => vec![trait_ref.value.shift_bound_vars_out(DebruijnIndex::ONE)], | ||
803 | }, | 833 | }, |
804 | TypeNs::GenericParam(param_id) => { | 834 | TypeNs::GenericParam(param_id) => { |
805 | let predicates = db.generic_predicates_for_param(param_id); | 835 | let predicates = db.generic_predicates_for_param(param_id); |
806 | let mut traits_: Vec<_> = predicates | 836 | let mut traits_: Vec<_> = predicates |
807 | .iter() | 837 | .iter() |
808 | .filter_map(|pred| match &pred.value { | 838 | .filter_map(|pred| match &pred.value.value { |
809 | WhereClause::Implemented(tr) => Some(tr.clone()), | 839 | // FIXME: how to correctly handle higher-ranked bounds here? |
840 | WhereClause::Implemented(tr) => { | ||
841 | Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) | ||
842 | } | ||
810 | _ => None, | 843 | _ => None, |
811 | }) | 844 | }) |
812 | .collect(); | 845 | .collect(); |
@@ -878,7 +911,7 @@ pub(crate) fn field_types_query( | |||
878 | pub(crate) fn generic_predicates_for_param_query( | 911 | pub(crate) fn generic_predicates_for_param_query( |
879 | db: &dyn HirDatabase, | 912 | db: &dyn HirDatabase, |
880 | param_id: TypeParamId, | 913 | param_id: TypeParamId, |
881 | ) -> Arc<[Binders<WhereClause>]> { | 914 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
882 | let resolver = param_id.parent.resolver(db.upcast()); | 915 | let resolver = param_id.parent.resolver(db.upcast()); |
883 | let ctx = | 916 | let ctx = |
884 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 917 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
@@ -896,7 +929,9 @@ pub(crate) fn generic_predicates_for_param_query( | |||
896 | }, | 929 | }, |
897 | WherePredicate::Lifetime { .. } => false, | 930 | WherePredicate::Lifetime { .. } => false, |
898 | }) | 931 | }) |
899 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 932 | .flat_map(|pred| { |
933 | ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p)) | ||
934 | }) | ||
900 | .collect() | 935 | .collect() |
901 | } | 936 | } |
902 | 937 | ||
@@ -904,7 +939,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
904 | _db: &dyn HirDatabase, | 939 | _db: &dyn HirDatabase, |
905 | _cycle: &[String], | 940 | _cycle: &[String], |
906 | _param_id: &TypeParamId, | 941 | _param_id: &TypeParamId, |
907 | ) -> Arc<[Binders<WhereClause>]> { | 942 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
908 | Arc::new([]) | 943 | Arc::new([]) |
909 | } | 944 | } |
910 | 945 | ||
@@ -918,8 +953,8 @@ pub(crate) fn trait_environment_query( | |||
918 | let mut traits_in_scope = Vec::new(); | 953 | let mut traits_in_scope = Vec::new(); |
919 | let mut clauses = Vec::new(); | 954 | let mut clauses = Vec::new(); |
920 | for pred in resolver.where_predicates_in_scope() { | 955 | for pred in resolver.where_predicates_in_scope() { |
921 | for pred in ctx.lower_where_predicate(pred) { | 956 | for pred in ctx.lower_where_predicate(pred, false) { |
922 | if let WhereClause::Implemented(tr) = &pred { | 957 | if let WhereClause::Implemented(tr) = &pred.skip_binders() { |
923 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 958 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
924 | } | 959 | } |
925 | let program_clause: chalk_ir::ProgramClause<Interner> = | 960 | let program_clause: chalk_ir::ProgramClause<Interner> = |
@@ -946,8 +981,7 @@ pub(crate) fn trait_environment_query( | |||
946 | let substs = Substitution::type_params(db, trait_id); | 981 | let substs = Substitution::type_params(db, trait_id); |
947 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; | 982 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; |
948 | let pred = WhereClause::Implemented(trait_ref); | 983 | let pred = WhereClause::Implemented(trait_ref); |
949 | let program_clause: chalk_ir::ProgramClause<Interner> = | 984 | let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); |
950 | pred.clone().to_chalk(db).cast(&Interner); | ||
951 | clauses.push(program_clause.into_from_env_clause(&Interner)); | 985 | clauses.push(program_clause.into_from_env_clause(&Interner)); |
952 | } | 986 | } |
953 | 987 | ||
@@ -960,14 +994,16 @@ pub(crate) fn trait_environment_query( | |||
960 | pub(crate) fn generic_predicates_query( | 994 | pub(crate) fn generic_predicates_query( |
961 | db: &dyn HirDatabase, | 995 | db: &dyn HirDatabase, |
962 | def: GenericDefId, | 996 | def: GenericDefId, |
963 | ) -> Arc<[Binders<WhereClause>]> { | 997 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
964 | let resolver = def.resolver(db.upcast()); | 998 | let resolver = def.resolver(db.upcast()); |
965 | let ctx = | 999 | let ctx = |
966 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 1000 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
967 | let generics = generics(db.upcast(), def); | 1001 | let generics = generics(db.upcast(), def); |
968 | resolver | 1002 | resolver |
969 | .where_predicates_in_scope() | 1003 | .where_predicates_in_scope() |
970 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 1004 | .flat_map(|pred| { |
1005 | ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p)) | ||
1006 | }) | ||
971 | .collect() | 1007 | .collect() |
972 | } | 1008 | } |
973 | 1009 | ||
@@ -1124,10 +1160,9 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | |||
1124 | if db.type_alias_data(t).is_extern { | 1160 | if db.type_alias_data(t).is_extern { |
1125 | Binders::new(0, TyKind::ForeignType(crate::to_foreign_def_id(t)).intern(&Interner)) | 1161 | Binders::new(0, TyKind::ForeignType(crate::to_foreign_def_id(t)).intern(&Interner)) |
1126 | } else { | 1162 | } else { |
1127 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | ||
1128 | let type_ref = &db.type_alias_data(t).type_ref; | 1163 | let type_ref = &db.type_alias_data(t).type_ref; |
1129 | let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 1164 | let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
1130 | Binders::new(substs.len(), inner) | 1165 | Binders::new(generics.len(), inner) |
1131 | } | 1166 | } |
1132 | } | 1167 | } |
1133 | 1168 | ||
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 54192ec30..84d9a1e18 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::{cast::Cast, Mutability}; | 9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; |
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, | 11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, |
12 | ImplId, Lookup, ModuleId, TraitId, | 12 | ImplId, Lookup, ModuleId, TraitId, |
@@ -21,8 +21,9 @@ use crate::{ | |||
21 | primitive::{self, FloatTy, IntTy, UintTy}, | 21 | primitive::{self, FloatTy, IntTy, UintTy}, |
22 | to_chalk_trait_id, | 22 | to_chalk_trait_id, |
23 | utils::all_super_traits, | 23 | utils::all_super_traits, |
24 | AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner, | 24 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, |
25 | Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, | 25 | InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, |
26 | TypeWalk, | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | /// This is used as a key for indexing impls. | 29 | /// This is used as a key for indexing impls. |
@@ -380,7 +381,7 @@ fn iterate_method_candidates_impl( | |||
380 | // Also note that when we've got a receiver like &S, even if the method we | 381 | // Also note that when we've got a receiver like &S, even if the method we |
381 | // find in the end takes &self, we still do the autoderef step (just as | 382 | // find in the end takes &self, we still do the autoderef step (just as |
382 | // rustc does an autoderef and then autoref again). | 383 | // rustc does an autoderef and then autoref again). |
383 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 384 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
384 | 385 | ||
385 | // We have to be careful about the order we're looking at candidates | 386 | // We have to be careful about the order we're looking at candidates |
386 | // in here. Consider the case where we're resolving `x.clone()` | 387 | // in here. Consider the case where we're resolving `x.clone()` |
@@ -452,7 +453,7 @@ fn iterate_method_candidates_with_autoref( | |||
452 | return true; | 453 | return true; |
453 | } | 454 | } |
454 | let refed = Canonical { | 455 | let refed = Canonical { |
455 | kinds: deref_chain[0].kinds.clone(), | 456 | binders: deref_chain[0].binders.clone(), |
456 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), | 457 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), |
457 | }; | 458 | }; |
458 | if iterate_method_candidates_by_receiver( | 459 | if iterate_method_candidates_by_receiver( |
@@ -469,7 +470,7 @@ fn iterate_method_candidates_with_autoref( | |||
469 | return true; | 470 | return true; |
470 | } | 471 | } |
471 | let ref_muted = Canonical { | 472 | let ref_muted = Canonical { |
472 | kinds: deref_chain[0].kinds.clone(), | 473 | binders: deref_chain[0].binders.clone(), |
473 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), | 474 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), |
474 | }; | 475 | }; |
475 | if iterate_method_candidates_by_receiver( | 476 | if iterate_method_candidates_by_receiver( |
@@ -646,7 +647,7 @@ pub fn resolve_indexing_op( | |||
646 | krate: CrateId, | 647 | krate: CrateId, |
647 | index_trait: TraitId, | 648 | index_trait: TraitId, |
648 | ) -> Option<Canonical<Ty>> { | 649 | ) -> Option<Canonical<Ty>> { |
649 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 650 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
650 | let deref_chain = autoderef_method_receiver(db, krate, ty); | 651 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
651 | for ty in deref_chain { | 652 | for ty in deref_chain { |
652 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); | 653 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); |
@@ -710,19 +711,28 @@ pub(crate) fn inherent_impl_substs( | |||
710 | // we create a var for each type parameter of the impl; we need to keep in | 711 | // we create a var for each type parameter of the impl; we need to keep in |
711 | // mind here that `self_ty` might have vars of its own | 712 | // mind here that `self_ty` might have vars of its own |
712 | let vars = Substitution::build_for_def(db, impl_id) | 713 | let vars = Substitution::build_for_def(db, impl_id) |
713 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len()) | 714 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) |
714 | .build(); | 715 | .build(); |
715 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | 716 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); |
716 | let mut kinds = self_ty.kinds.to_vec(); | 717 | let mut kinds = self_ty.binders.interned().to_vec(); |
717 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len())); | 718 | kinds.extend( |
718 | let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; | 719 | iter::repeat(chalk_ir::WithKind::new( |
720 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
721 | UniverseIndex::ROOT, | ||
722 | )) | ||
723 | .take(vars.len()), | ||
724 | ); | ||
725 | let tys = Canonical { | ||
726 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
727 | value: (self_ty_with_vars, self_ty.value.clone()), | ||
728 | }; | ||
719 | let substs = super::infer::unify(&tys); | 729 | let substs = super::infer::unify(&tys); |
720 | // We only want the substs for the vars we added, not the ones from self_ty. | 730 | // We only want the substs for the vars we added, not the ones from self_ty. |
721 | // Also, if any of the vars we added are still in there, we replace them by | 731 | // Also, if any of the vars we added are still in there, we replace them by |
722 | // Unknown. I think this can only really happen if self_ty contained | 732 | // Unknown. I think this can only really happen if self_ty contained |
723 | // Unknown, and in that case we want the result to contain Unknown in those | 733 | // Unknown, and in that case we want the result to contain Unknown in those |
724 | // places again. | 734 | // places again. |
725 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len())) | 735 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner))) |
726 | } | 736 | } |
727 | 737 | ||
728 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past | 738 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past |
@@ -801,15 +811,24 @@ fn generic_implements_goal( | |||
801 | trait_: TraitId, | 811 | trait_: TraitId, |
802 | self_ty: Canonical<Ty>, | 812 | self_ty: Canonical<Ty>, |
803 | ) -> Canonical<InEnvironment<super::DomainGoal>> { | 813 | ) -> Canonical<InEnvironment<super::DomainGoal>> { |
804 | let mut kinds = self_ty.kinds.to_vec(); | 814 | let mut kinds = self_ty.binders.interned().to_vec(); |
805 | let substs = super::Substitution::build_for_def(db, trait_) | 815 | let substs = super::Substitution::build_for_def(db, trait_) |
806 | .push(self_ty.value) | 816 | .push(self_ty.value) |
807 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) | 817 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) |
808 | .build(); | 818 | .build(); |
809 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); | 819 | kinds.extend( |
820 | iter::repeat(chalk_ir::WithKind::new( | ||
821 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
822 | UniverseIndex::ROOT, | ||
823 | )) | ||
824 | .take(substs.len() - 1), | ||
825 | ); | ||
810 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; | 826 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; |
811 | let obligation = trait_ref.cast(&Interner); | 827 | let obligation = trait_ref.cast(&Interner); |
812 | Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } | 828 | Canonical { |
829 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
830 | value: InEnvironment::new(env.env.clone(), obligation), | ||
831 | } | ||
813 | } | 832 | } |
814 | 833 | ||
815 | fn autoderef_method_receiver( | 834 | fn autoderef_method_receiver( |
@@ -822,9 +841,9 @@ fn autoderef_method_receiver( | |||
822 | if let Some(TyKind::Array(parameters)) = | 841 | if let Some(TyKind::Array(parameters)) = |
823 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) | 842 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) |
824 | { | 843 | { |
825 | let kinds = deref_chain.last().unwrap().kinds.clone(); | 844 | let kinds = deref_chain.last().unwrap().binders.clone(); |
826 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); | 845 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); |
827 | deref_chain.push(Canonical { value: unsized_ty, kinds }) | 846 | deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) |
828 | } | 847 | } |
829 | deref_chain | 848 | deref_chain |
830 | } | 849 | } |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0a4141e69..ad283c1e0 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -369,3 +369,72 @@ fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) { | |||
369 | actual.push('\n'); | 369 | actual.push('\n'); |
370 | expect.assert_eq(&actual); | 370 | expect.assert_eq(&actual); |
371 | } | 371 | } |
372 | |||
373 | #[test] | ||
374 | fn salsa_bug() { | ||
375 | let (mut db, pos) = TestDB::with_position( | ||
376 | " | ||
377 | //- /lib.rs | ||
378 | trait Index { | ||
379 | type Output; | ||
380 | } | ||
381 | |||
382 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
383 | |||
384 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
385 | type Key; | ||
386 | |||
387 | fn len(&self) -> usize; | ||
388 | } | ||
389 | |||
390 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
391 | fn push(&mut self, value: Self::Key); | ||
392 | } | ||
393 | |||
394 | fn main() { | ||
395 | let x = 1; | ||
396 | x.push(1);$0 | ||
397 | } | ||
398 | ", | ||
399 | ); | ||
400 | |||
401 | let module = db.module_for_file(pos.file_id); | ||
402 | let crate_def_map = module.def_map(&db); | ||
403 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
404 | db.infer(def); | ||
405 | }); | ||
406 | |||
407 | let new_text = " | ||
408 | //- /lib.rs | ||
409 | trait Index { | ||
410 | type Output; | ||
411 | } | ||
412 | |||
413 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
414 | |||
415 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
416 | type Key; | ||
417 | |||
418 | fn len(&self) -> usize; | ||
419 | } | ||
420 | |||
421 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
422 | fn push(&mut self, value: Self::Key); | ||
423 | } | ||
424 | |||
425 | fn main() { | ||
426 | |||
427 | let x = 1; | ||
428 | x.push(1); | ||
429 | } | ||
430 | " | ||
431 | .to_string(); | ||
432 | |||
433 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
434 | |||
435 | let module = db.module_for_file(pos.file_id); | ||
436 | let crate_def_map = module.def_map(&db); | ||
437 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
438 | db.infer(def); | ||
439 | }); | ||
440 | } | ||
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 88ba9b118..7eda51866 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -607,6 +607,29 @@ fn bar() -> u32 {0} | |||
607 | } | 607 | } |
608 | 608 | ||
609 | #[test] | 609 | #[test] |
610 | fn infer_builtin_macros_include_child_mod() { | ||
611 | check_types( | ||
612 | r#" | ||
613 | //- /main.rs | ||
614 | #[rustc_builtin_macro] | ||
615 | macro_rules! include {() => {}} | ||
616 | |||
617 | include!("f/foo.rs"); | ||
618 | |||
619 | fn main() { | ||
620 | bar::bar(); | ||
621 | } //^ u32 | ||
622 | |||
623 | //- /f/foo.rs | ||
624 | pub mod bar; | ||
625 | |||
626 | //- /f/bar.rs | ||
627 | pub fn bar() -> u32 {0} | ||
628 | "#, | ||
629 | ); | ||
630 | } | ||
631 | |||
632 | #[test] | ||
610 | fn infer_builtin_macros_include_str() { | 633 | fn infer_builtin_macros_include_str() { |
611 | check_types( | 634 | check_types( |
612 | r#" | 635 | r#" |
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 5da19ba5f..85a28e76b 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -658,6 +658,28 @@ fn slice_tail_pattern() { | |||
658 | fn box_pattern() { | 658 | fn box_pattern() { |
659 | check_infer( | 659 | check_infer( |
660 | r#" | 660 | r#" |
661 | pub struct Global; | ||
662 | #[lang = "owned_box"] | ||
663 | pub struct Box<T, A = Global>(T); | ||
664 | |||
665 | fn foo(params: Box<i32>) { | ||
666 | match params { | ||
667 | box integer => {} | ||
668 | } | ||
669 | } | ||
670 | "#, | ||
671 | expect![[r#" | ||
672 | 83..89 'params': Box<i32, Global> | ||
673 | 101..155 '{ ... } }': () | ||
674 | 107..153 'match ... }': () | ||
675 | 113..119 'params': Box<i32, Global> | ||
676 | 130..141 'box integer': Box<i32, Global> | ||
677 | 134..141 'integer': i32 | ||
678 | 145..147 '{}': () | ||
679 | "#]], | ||
680 | ); | ||
681 | check_infer( | ||
682 | r#" | ||
661 | #[lang = "owned_box"] | 683 | #[lang = "owned_box"] |
662 | pub struct Box<T>(T); | 684 | pub struct Box<T>(T); |
663 | 685 | ||
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 69314e245..b69f86050 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -961,3 +961,16 @@ fn issue_6852() { | |||
961 | "#]], | 961 | "#]], |
962 | ); | 962 | ); |
963 | } | 963 | } |
964 | |||
965 | #[test] | ||
966 | fn param_overrides_fn() { | ||
967 | check_types( | ||
968 | r#" | ||
969 | fn example(example: i32) { | ||
970 | fn f() {} | ||
971 | example; | ||
972 | //^^^^^^^ i32 | ||
973 | } | ||
974 | "#, | ||
975 | ) | ||
976 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index f7ee6def6..2ba97f814 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -2272,6 +2272,56 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | #[test] | 2274 | #[test] |
2275 | fn unselected_projection_in_trait_env_cycle_3() { | ||
2276 | // this is a cycle for rustc; we currently accept it | ||
2277 | check_types( | ||
2278 | r#" | ||
2279 | //- /main.rs | ||
2280 | trait Trait { | ||
2281 | type Item; | ||
2282 | type OtherItem; | ||
2283 | } | ||
2284 | |||
2285 | fn test<T>() where T: Trait<OtherItem = T::Item> { | ||
2286 | let x: T::Item = no_matter; | ||
2287 | } //^ Trait::Item<T> | ||
2288 | "#, | ||
2289 | ); | ||
2290 | } | ||
2291 | |||
2292 | #[test] | ||
2293 | fn unselected_projection_in_trait_env_no_cycle() { | ||
2294 | // this is not a cycle | ||
2295 | check_types( | ||
2296 | r#" | ||
2297 | //- /main.rs | ||
2298 | trait Index { | ||
2299 | type Output; | ||
2300 | } | ||
2301 | |||
2302 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
2303 | |||
2304 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
2305 | type Key; | ||
2306 | |||
2307 | fn len(&self) -> usize; | ||
2308 | } | ||
2309 | |||
2310 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
2311 | fn push(&mut self, value: Self::Key); | ||
2312 | } | ||
2313 | |||
2314 | fn test<T>(t: T) where T: UnificationStoreMut { | ||
2315 | let x; | ||
2316 | t.push(x); | ||
2317 | let y: Key<T>; | ||
2318 | (x, y); | ||
2319 | } //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | ||
2320 | "#, | ||
2321 | ); | ||
2322 | } | ||
2323 | |||
2324 | #[test] | ||
2275 | fn inline_assoc_type_bounds_1() { | 2325 | fn inline_assoc_type_bounds_1() { |
2276 | check_types( | 2326 | check_types( |
2277 | r#" | 2327 | r#" |
@@ -3274,3 +3324,49 @@ fn f() { | |||
3274 | "#]], | 3324 | "#]], |
3275 | ) | 3325 | ) |
3276 | } | 3326 | } |
3327 | |||
3328 | #[test] | ||
3329 | fn infer_default_trait_type_parameter() { | ||
3330 | check_infer( | ||
3331 | r#" | ||
3332 | struct A; | ||
3333 | |||
3334 | trait Op<RHS=Self> { | ||
3335 | type Output; | ||
3336 | |||
3337 | fn do_op(self, rhs: RHS) -> Self::Output; | ||
3338 | } | ||
3339 | |||
3340 | impl Op for A { | ||
3341 | type Output = bool; | ||
3342 | |||
3343 | fn do_op(self, rhs: Self) -> Self::Output { | ||
3344 | true | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | fn test() { | ||
3349 | let x = A; | ||
3350 | let y = A; | ||
3351 | let r = x.do_op(y); | ||
3352 | } | ||
3353 | "#, | ||
3354 | expect![[r#" | ||
3355 | 63..67 'self': Self | ||
3356 | 69..72 'rhs': RHS | ||
3357 | 153..157 'self': A | ||
3358 | 159..162 'rhs': A | ||
3359 | 186..206 '{ ... }': bool | ||
3360 | 196..200 'true': bool | ||
3361 | 220..277 '{ ...(y); }': () | ||
3362 | 230..231 'x': A | ||
3363 | 234..235 'A': A | ||
3364 | 245..246 'y': A | ||
3365 | 249..250 'A': A | ||
3366 | 260..261 'r': bool | ||
3367 | 264..265 'x': A | ||
3368 | 264..274 'x.do_op(y)': bool | ||
3369 | 272..273 'y': A | ||
3370 | "#]], | ||
3371 | ) | ||
3372 | } | ||
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 7dadd1ffb..ccee0e5ad 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::env::var; | 2 | use std::env::var; |
3 | use std::sync::Arc; | ||
4 | 3 | ||
5 | use base_db::CrateId; | 4 | use base_db::CrateId; |
6 | use chalk_ir::cast::Cast; | 5 | use chalk_ir::cast::Cast; |
@@ -44,7 +43,7 @@ pub struct TraitEnvironment { | |||
44 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, | 43 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, |
45 | // but for now it's too annoying... | 44 | // but for now it's too annoying... |
46 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, | 45 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, |
47 | pub(crate) env: chalk_ir::Environment<Interner>, | 46 | pub env: chalk_ir::Environment<Interner>, |
48 | } | 47 | } |
49 | 48 | ||
50 | impl TraitEnvironment { | 49 | impl TraitEnvironment { |
@@ -74,13 +73,13 @@ impl Default for TraitEnvironment { | |||
74 | /// Something (usually a goal), along with an environment. | 73 | /// Something (usually a goal), along with an environment. |
75 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 74 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
76 | pub struct InEnvironment<T> { | 75 | pub struct InEnvironment<T> { |
77 | pub environment: Arc<TraitEnvironment>, | 76 | pub environment: chalk_ir::Environment<Interner>, |
78 | pub value: T, | 77 | pub goal: T, |
79 | } | 78 | } |
80 | 79 | ||
81 | impl<T> InEnvironment<T> { | 80 | impl<T> InEnvironment<T> { |
82 | pub fn new(environment: Arc<TraitEnvironment>, value: T) -> InEnvironment<T> { | 81 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { |
83 | InEnvironment { environment, value } | 82 | InEnvironment { environment, goal: value } |
84 | } | 83 | } |
85 | } | 84 | } |
86 | 85 | ||
@@ -126,18 +125,18 @@ pub(crate) fn trait_solve_query( | |||
126 | krate: CrateId, | 125 | krate: CrateId, |
127 | goal: Canonical<InEnvironment<DomainGoal>>, | 126 | goal: Canonical<InEnvironment<DomainGoal>>, |
128 | ) -> Option<Solution> { | 127 | ) -> Option<Solution> { |
129 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { | 128 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal { |
130 | DomainGoal::Holds(WhereClause::Implemented(it)) => { | 129 | DomainGoal::Holds(WhereClause::Implemented(it)) => { |
131 | db.trait_data(it.hir_trait_id()).name.to_string() | 130 | db.trait_data(it.hir_trait_id()).name.to_string() |
132 | } | 131 | } |
133 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), | 132 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), |
134 | }); | 133 | }); |
135 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 134 | log::info!("trait_solve_query({})", goal.value.goal.display(db)); |
136 | 135 | ||
137 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { | 136 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { |
138 | alias: AliasTy::Projection(projection_ty), | 137 | alias: AliasTy::Projection(projection_ty), |
139 | .. | 138 | .. |
140 | })) = &goal.value.value | 139 | })) = &goal.value.goal |
141 | { | 140 | { |
142 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { | 141 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { |
143 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 142 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 734679414..011bef6f6 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 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy, | 24 | AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, |
25 | Substitution, TraitRef, Ty, TyKind, WhereClause, | 25 | TraitRef, Ty, TyKind, WhereClause, |
26 | }; | 26 | }; |
27 | use mapping::{ | 27 | use 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, |
@@ -238,7 +238,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
238 | }); | 238 | }); |
239 | let bound = OpaqueTyDatumBound { | 239 | let bound = OpaqueTyDatumBound { |
240 | bounds: make_binders( | 240 | bounds: make_binders( |
241 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | 241 | vec![ |
242 | wrap_in_empty_binders(impl_bound).to_chalk(self.db), | ||
243 | wrap_in_empty_binders(proj_bound).to_chalk(self.db), | ||
244 | ], | ||
242 | 1, | 245 | 1, |
243 | ), | 246 | ), |
244 | where_clauses: make_binders(vec![], 0), | 247 | where_clauses: make_binders(vec![], 0), |
@@ -285,9 +288,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
285 | ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { | 288 | ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { |
286 | let sig_ty: Ty = | 289 | let sig_ty: Ty = |
287 | from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone()); | 290 | from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone()); |
288 | let sig = CallableSig::from_substs( | 291 | let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); |
289 | &sig_ty.substs().expect("first closure param should be fn ptr"), | ||
290 | ); | ||
291 | let io = rust_ir::FnDefInputsAndOutputDatum { | 292 | let io = rust_ir::FnDefInputsAndOutputDatum { |
292 | argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), | 293 | argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), |
293 | return_type: sig.ret().clone().to_chalk(self.db), | 294 | return_type: sig.ret().clone().to_chalk(self.db), |
@@ -395,9 +396,8 @@ pub(crate) fn associated_ty_data_query( | |||
395 | let bounds = type_alias_data | 396 | let bounds = type_alias_data |
396 | .bounds | 397 | .bounds |
397 | .iter() | 398 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) | 399 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 400 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | ||
401 | .collect(); | 401 | .collect(); |
402 | 402 | ||
403 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | 403 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); |
@@ -720,3 +720,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { | |||
720 | chalk_ir::ClosureId(id.as_intern_id()) | 720 | chalk_ir::ClosureId(id.as_intern_id()) |
721 | } | 721 | } |
722 | } | 722 | } |
723 | |||
724 | fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> { | ||
725 | crate::Binders::wrap_empty(value) | ||
726 | } | ||
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 65feb82e5..aef6b8a15 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa | |||
7 | use chalk_solve::rust_ir; | 7 | use chalk_solve::rust_ir; |
8 | 8 | ||
9 | use base_db::salsa::InternKey; | 9 | use base_db::salsa::InternKey; |
10 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | ||
15 | primitive::UintTy, | 14 | primitive::UintTy, |
16 | traits::{Canonical, DomainGoal}, | 15 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, | 16 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, |
18 | TraitRef, Ty, WhereClause, | 17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, |
19 | }; | 18 | }; |
20 | 19 | ||
21 | use super::interner::*; | 20 | use super::interner::*; |
@@ -95,10 +94,10 @@ impl ToChalk for Ty { | |||
95 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), | 94 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), |
96 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), | 95 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), |
97 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), | 96 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), |
98 | TyKind::Dyn(predicates) => { | 97 | TyKind::Dyn(dyn_ty) => { |
99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( | 98 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
100 | &Interner, | 99 | &Interner, |
101 | predicates.iter().cloned().map(|p| p.to_chalk(db)), | 100 | dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), |
102 | ); | 101 | ); |
103 | let bounded_ty = chalk_ir::DynTy { | 102 | let bounded_ty = chalk_ir::DynTy { |
104 | bounds: make_binders(where_clauses, 1), | 103 | bounds: make_binders(where_clauses, 1), |
@@ -144,13 +143,17 @@ impl ToChalk for Ty { | |||
144 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, | 143 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, |
145 | chalk_ir::TyKind::Dyn(where_clauses) => { | 144 | chalk_ir::TyKind::Dyn(where_clauses) => { |
146 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | 145 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); |
147 | let predicates = where_clauses | 146 | let bounds = where_clauses |
148 | .bounds | 147 | .bounds |
149 | .skip_binders() | 148 | .skip_binders() |
150 | .iter(&Interner) | 149 | .iter(&Interner) |
151 | .map(|c| from_chalk(db, c.clone())) | 150 | .map(|c| from_chalk(db, c.clone())); |
152 | .collect(); | 151 | TyKind::Dyn(crate::DynTy { |
153 | TyKind::Dyn(predicates) | 152 | bounds: crate::Binders::new( |
153 | 1, | ||
154 | crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), | ||
155 | ), | ||
156 | }) | ||
154 | } | 157 | } |
155 | 158 | ||
156 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), | 159 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), |
@@ -305,33 +308,22 @@ impl ToChalk for TypeAliasAsValue { | |||
305 | } | 308 | } |
306 | 309 | ||
307 | impl ToChalk for WhereClause { | 310 | impl ToChalk for WhereClause { |
308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | 311 | type Chalk = chalk_ir::WhereClause<Interner>; |
309 | 312 | ||
310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | 313 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> { |
311 | match self { | 314 | match self { |
312 | WhereClause::Implemented(trait_ref) => { | 315 | WhereClause::Implemented(trait_ref) => { |
313 | let chalk_trait_ref = trait_ref.to_chalk(db); | 316 | chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)) |
314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
316 | } | 317 | } |
317 | WhereClause::AliasEq(alias_eq) => make_binders( | 318 | WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)), |
318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), | ||
319 | 0, | ||
320 | ), | ||
321 | } | 319 | } |
322 | } | 320 | } |
323 | 321 | ||
324 | fn from_chalk( | 322 | fn from_chalk( |
325 | db: &dyn HirDatabase, | 323 | db: &dyn HirDatabase, |
326 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 324 | where_clause: chalk_ir::WhereClause<Interner>, |
327 | ) -> WhereClause { | 325 | ) -> WhereClause { |
328 | // we don't produce any where clauses with binders and can't currently deal with them | 326 | match where_clause { |
329 | match where_clause | ||
330 | .skip_binders() | ||
331 | .clone() | ||
332 | .shifted_out(&Interner) | ||
333 | .expect("unexpected bound vars in where clause") | ||
334 | { | ||
335 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), | 327 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
336 | chalk_ir::WhereClause::AliasEq(alias_eq) => { | 328 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
337 | WhereClause::AliasEq(from_chalk(db, alias_eq)) | 329 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
@@ -447,35 +439,12 @@ where | |||
447 | type Chalk = chalk_ir::Canonical<T::Chalk>; | 439 | type Chalk = chalk_ir::Canonical<T::Chalk>; |
448 | 440 | ||
449 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | 441 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { |
450 | let kinds = self.kinds.iter().map(|&tk| { | ||
451 | chalk_ir::CanonicalVarKind::new( | ||
452 | chalk_ir::VariableKind::Ty(tk), | ||
453 | chalk_ir::UniverseIndex::ROOT, | ||
454 | ) | ||
455 | }); | ||
456 | let value = self.value.to_chalk(db); | 442 | let value = self.value.to_chalk(db); |
457 | chalk_ir::Canonical { | 443 | chalk_ir::Canonical { value, binders: self.binders } |
458 | value, | ||
459 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
460 | } | ||
461 | } | 444 | } |
462 | 445 | ||
463 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 446 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
464 | let kinds = canonical | 447 | Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) } |
465 | .binders | ||
466 | .iter(&Interner) | ||
467 | .map(|k| match k.kind { | ||
468 | chalk_ir::VariableKind::Ty(tk) => tk, | ||
469 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
470 | // want to just skip them, but to not mess up the indices of | ||
471 | // other variables, we'll just create a new type variable in | ||
472 | // their place instead. This should not matter (we never see the | ||
473 | // actual *uses* of the lifetime variable). | ||
474 | chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General, | ||
475 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), | ||
476 | }) | ||
477 | .collect(); | ||
478 | Canonical { kinds, value: from_chalk(db, canonical.value) } | ||
479 | } | 448 | } |
480 | } | 449 | } |
481 | 450 | ||
@@ -486,10 +455,7 @@ where | |||
486 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 455 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
487 | 456 | ||
488 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | 457 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { |
489 | chalk_ir::InEnvironment { | 458 | chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) } |
490 | environment: self.environment.env.clone(), | ||
491 | goal: self.value.to_chalk(db), | ||
492 | } | ||
493 | } | 459 | } |
494 | 460 | ||
495 | fn from_chalk( | 461 | fn from_chalk( |
@@ -500,6 +466,29 @@ where | |||
500 | } | 466 | } |
501 | } | 467 | } |
502 | 468 | ||
469 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
470 | where | ||
471 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
472 | { | ||
473 | type Chalk = chalk_ir::Binders<T::Chalk>; | ||
474 | |||
475 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { | ||
476 | chalk_ir::Binders::new( | ||
477 | chalk_ir::VariableKinds::from_iter( | ||
478 | &Interner, | ||
479 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | ||
480 | .take(self.num_binders), | ||
481 | ), | ||
482 | self.value.to_chalk(db), | ||
483 | ) | ||
484 | } | ||
485 | |||
486 | fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { | ||
487 | let (v, b) = binders.into_value_and_skipped_binders(); | ||
488 | crate::Binders::new(b.len(&Interner), from_chalk(db, v)) | ||
489 | } | ||
490 | } | ||
491 | |||
503 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 492 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
504 | where | 493 | where |
505 | T: HasInterner<Interner = Interner>, | 494 | T: HasInterner<Interner = Interner>, |
@@ -529,14 +518,15 @@ pub(super) fn convert_where_clauses( | |||
529 | 518 | ||
530 | pub(super) fn generic_predicate_to_inline_bound( | 519 | pub(super) fn generic_predicate_to_inline_bound( |
531 | db: &dyn HirDatabase, | 520 | db: &dyn HirDatabase, |
532 | pred: &WhereClause, | 521 | pred: &QuantifiedWhereClause, |
533 | self_ty: &Ty, | 522 | self_ty: &Ty, |
534 | ) -> Option<rust_ir::InlineBound<Interner>> { | 523 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
535 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 524 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
536 | // We don't have a special type for this, but Chalk does. | 525 | // We don't have a special type for this, but Chalk does. |
537 | match pred { | 526 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
527 | match &pred.value { | ||
538 | WhereClause::Implemented(trait_ref) => { | 528 | WhereClause::Implemented(trait_ref) => { |
539 | if &trait_ref.substitution[0] != self_ty { | 529 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { |
540 | // we can only convert predicates back to type bounds if they | 530 | // we can only convert predicates back to type bounds if they |
541 | // have the expected self type | 531 | // have the expected self type |
542 | return None; | 532 | return None; |
@@ -546,19 +536,13 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 536 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
547 | .collect(); | 537 | .collect(); |
548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 538 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 539 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
550 | } | 540 | } |
551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 541 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
552 | if &projection_ty.substitution[0] != self_ty { | 542 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
553 | return None; | 543 | return None; |
554 | } | 544 | } |
555 | let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) | 545 | let trait_ = projection_ty.trait_(db); |
556 | .lookup(db.upcast()) | ||
557 | .container | ||
558 | { | ||
559 | AssocContainerId::TraitId(t) => t, | ||
560 | _ => panic!("associated type not in trait"), | ||
561 | }; | ||
562 | let args_no_self = projection_ty.substitution[1..] | 546 | let args_no_self = projection_ty.substitution[1..] |
563 | .iter() | 547 | .iter() |
564 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 548 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
@@ -569,7 +553,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
569 | associated_ty_id: projection_ty.associated_ty_id, | 553 | associated_ty_id: projection_ty.associated_ty_id, |
570 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 554 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
571 | }; | 555 | }; |
572 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 556 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
573 | } | 557 | } |
574 | _ => None, | 558 | _ => None, |
575 | } | 559 | } |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 1ec1ecd43..42d7af146 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use chalk_ir::DebruijnIndex; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | adt::VariantData, | 7 | adt::VariantData, |
7 | db::DefDatabase, | 8 | db::DefDatabase, |
@@ -15,7 +16,7 @@ use hir_def::{ | |||
15 | }; | 16 | }; |
16 | use hir_expand::name::{name, Name}; | 17 | use hir_expand::name::{name, Name}; |
17 | 18 | ||
18 | use crate::{db::HirDatabase, TraitRef, WhereClause}; | 19 | use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; |
19 | 20 | ||
20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 21 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
21 | let resolver = trait_.resolver(db); | 22 | let resolver = trait_.resolver(db); |
@@ -63,8 +64,11 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
63 | db.generic_predicates_for_param(trait_self) | 64 | db.generic_predicates_for_param(trait_self) |
64 | .iter() | 65 | .iter() |
65 | .filter_map(|pred| { | 66 | .filter_map(|pred| { |
66 | pred.as_ref().filter_map(|pred| match pred { | 67 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { |
67 | WhereClause::Implemented(tr) => Some(tr.clone()), | 68 | // FIXME: how to correctly handle higher-ranked bounds here? |
69 | WhereClause::Implemented(tr) => { | ||
70 | Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) | ||
71 | } | ||
68 | _ => None, | 72 | _ => None, |
69 | }) | 73 | }) |
70 | }) | 74 | }) |