diff options
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 69 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 10 |
4 files changed, 92 insertions, 27 deletions
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 2677f3af2..a4b8d6683 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -396,12 +396,12 @@ impl Substs { | |||
396 | } | 396 | } |
397 | 397 | ||
398 | /// Return Substs that replace each parameter by a bound variable. | 398 | /// Return Substs that replace each parameter by a bound variable. |
399 | pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { | 399 | pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substs { |
400 | Substs( | 400 | Substs( |
401 | generic_params | 401 | generic_params |
402 | .iter() | 402 | .iter() |
403 | .enumerate() | 403 | .enumerate() |
404 | .map(|(idx, _)| Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))) | 404 | .map(|(idx, _)| Ty::Bound(BoundVar::new(debruijn, idx))) |
405 | .collect(), | 405 | .collect(), |
406 | ) | 406 | ) |
407 | } | 407 | } |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index cc1ac8e3e..c2812e178 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -39,6 +39,7 @@ use crate::{ | |||
39 | pub struct TyLoweringContext<'a> { | 39 | pub struct TyLoweringContext<'a> { |
40 | pub db: &'a dyn HirDatabase, | 40 | pub db: &'a dyn HirDatabase, |
41 | pub resolver: &'a Resolver, | 41 | pub resolver: &'a Resolver, |
42 | in_binders: DebruijnIndex, | ||
42 | /// Note: Conceptually, it's thinkable that we could be in a location where | 43 | /// Note: Conceptually, it's thinkable that we could be in a location where |
43 | /// some type params should be represented as placeholders, and others | 44 | /// some type params should be represented as placeholders, and others |
44 | /// should be converted to variables. I think in practice, this isn't | 45 | /// should be converted to variables. I think in practice, this isn't |
@@ -53,7 +54,27 @@ impl<'a> TyLoweringContext<'a> { | |||
53 | let impl_trait_counter = std::cell::Cell::new(0); | 54 | let impl_trait_counter = std::cell::Cell::new(0); |
54 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | 55 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; |
55 | let type_param_mode = TypeParamLoweringMode::Placeholder; | 56 | let type_param_mode = TypeParamLoweringMode::Placeholder; |
56 | Self { db, resolver, impl_trait_mode, impl_trait_counter, type_param_mode } | 57 | let in_binders = DebruijnIndex::INNERMOST; |
58 | Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } | ||
59 | } | ||
60 | |||
61 | pub fn with_shifted_in<T>( | ||
62 | &self, | ||
63 | debruijn: DebruijnIndex, | ||
64 | f: impl FnOnce(&TyLoweringContext) -> T, | ||
65 | ) -> T { | ||
66 | let new_ctx = Self { | ||
67 | in_binders: self.in_binders.shifted_in_from(debruijn), | ||
68 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), | ||
69 | ..*self | ||
70 | }; | ||
71 | let result = f(&new_ctx); | ||
72 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); | ||
73 | result | ||
74 | } | ||
75 | |||
76 | pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { | ||
77 | Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } | ||
57 | } | 78 | } |
58 | 79 | ||
59 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | 80 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { |
@@ -134,22 +155,26 @@ impl Ty { | |||
134 | } | 155 | } |
135 | TypeRef::DynTrait(bounds) => { | 156 | TypeRef::DynTrait(bounds) => { |
136 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | 157 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); |
137 | let predicates = bounds | 158 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
138 | .iter() | 159 | bounds |
139 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) | 160 | .iter() |
140 | .collect(); | 161 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) |
162 | .collect() | ||
163 | }); | ||
141 | Ty::Dyn(predicates) | 164 | Ty::Dyn(predicates) |
142 | } | 165 | } |
143 | TypeRef::ImplTrait(bounds) => { | 166 | TypeRef::ImplTrait(bounds) => { |
144 | match ctx.impl_trait_mode { | 167 | match ctx.impl_trait_mode { |
145 | ImplTraitLoweringMode::Opaque => { | 168 | ImplTraitLoweringMode::Opaque => { |
146 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | 169 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); |
147 | let predicates = bounds | 170 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
148 | .iter() | 171 | bounds |
149 | .flat_map(|b| { | 172 | .iter() |
150 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) | 173 | .flat_map(|b| { |
151 | }) | 174 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) |
152 | .collect(); | 175 | }) |
176 | .collect() | ||
177 | }); | ||
153 | Ty::Opaque(predicates) | 178 | Ty::Opaque(predicates) |
154 | } | 179 | } |
155 | ImplTraitLoweringMode::Param => { | 180 | ImplTraitLoweringMode::Param => { |
@@ -180,7 +205,7 @@ impl Ty { | |||
180 | (0, 0, 0, 0) | 205 | (0, 0, 0, 0) |
181 | }; | 206 | }; |
182 | Ty::Bound(BoundVar::new( | 207 | Ty::Bound(BoundVar::new( |
183 | DebruijnIndex::INNERMOST, | 208 | ctx.in_binders, |
184 | idx as usize + parent_params + self_params + list_params, | 209 | idx as usize + parent_params + self_params + list_params, |
185 | )) | 210 | )) |
186 | } | 211 | } |
@@ -293,7 +318,7 @@ impl Ty { | |||
293 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), | 318 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), |
294 | TypeParamLoweringMode::Variable => { | 319 | TypeParamLoweringMode::Variable => { |
295 | let idx = generics.param_idx(param_id).expect("matching generics"); | 320 | let idx = generics.param_idx(param_id).expect("matching generics"); |
296 | Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) | 321 | Ty::Bound(BoundVar::new(ctx.in_binders, idx)) |
297 | } | 322 | } |
298 | } | 323 | } |
299 | } | 324 | } |
@@ -303,7 +328,9 @@ impl Ty { | |||
303 | TypeParamLoweringMode::Placeholder => { | 328 | TypeParamLoweringMode::Placeholder => { |
304 | Substs::type_params_for_generics(&generics) | 329 | Substs::type_params_for_generics(&generics) |
305 | } | 330 | } |
306 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 331 | TypeParamLoweringMode::Variable => { |
332 | Substs::bound_vars(&generics, ctx.in_binders) | ||
333 | } | ||
307 | }; | 334 | }; |
308 | ctx.db.impl_self_ty(impl_id).subst(&substs) | 335 | ctx.db.impl_self_ty(impl_id).subst(&substs) |
309 | } | 336 | } |
@@ -313,7 +340,9 @@ impl Ty { | |||
313 | TypeParamLoweringMode::Placeholder => { | 340 | TypeParamLoweringMode::Placeholder => { |
314 | Substs::type_params_for_generics(&generics) | 341 | Substs::type_params_for_generics(&generics) |
315 | } | 342 | } |
316 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 343 | TypeParamLoweringMode::Variable => { |
344 | Substs::bound_vars(&generics, ctx.in_binders) | ||
345 | } | ||
317 | }; | 346 | }; |
318 | ctx.db.ty(adt.into()).subst(&substs) | 347 | ctx.db.ty(adt.into()).subst(&substs) |
319 | } | 348 | } |
@@ -797,7 +826,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | |||
797 | /// function body. | 826 | /// function body. |
798 | fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { | 827 | fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { |
799 | let generics = generics(db.upcast(), def.into()); | 828 | let generics = generics(db.upcast(), def.into()); |
800 | let substs = Substs::bound_vars(&generics); | 829 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
801 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) | 830 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
802 | } | 831 | } |
803 | 832 | ||
@@ -851,7 +880,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T | |||
851 | return type_for_adt(db, def.into()); | 880 | return type_for_adt(db, def.into()); |
852 | } | 881 | } |
853 | let generics = generics(db.upcast(), def.into()); | 882 | let generics = generics(db.upcast(), def.into()); |
854 | let substs = Substs::bound_vars(&generics); | 883 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
855 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) | 884 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
856 | } | 885 | } |
857 | 886 | ||
@@ -876,13 +905,13 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - | |||
876 | return type_for_adt(db, def.parent.into()); | 905 | return type_for_adt(db, def.parent.into()); |
877 | } | 906 | } |
878 | let generics = generics(db.upcast(), def.parent.into()); | 907 | let generics = generics(db.upcast(), def.parent.into()); |
879 | let substs = Substs::bound_vars(&generics); | 908 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
880 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) | 909 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
881 | } | 910 | } |
882 | 911 | ||
883 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { | 912 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { |
884 | let generics = generics(db.upcast(), adt.into()); | 913 | let generics = generics(db.upcast(), adt.into()); |
885 | let substs = Substs::bound_vars(&generics); | 914 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
886 | Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) | 915 | Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) |
887 | } | 916 | } |
888 | 917 | ||
@@ -892,7 +921,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | |||
892 | let ctx = | 921 | let ctx = |
893 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 922 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
894 | let type_ref = &db.type_alias_data(t).type_ref; | 923 | let type_ref = &db.type_alias_data(t).type_ref; |
895 | let substs = Substs::bound_vars(&generics); | 924 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
896 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 925 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
897 | Binders::new(substs.len(), inner) | 926 | Binders::new(substs.len(), inner) |
898 | } | 927 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 0a889f805..36f53b264 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1211,6 +1211,42 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | |||
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | #[test] | 1213 | #[test] |
1214 | fn dyn_trait_in_impl() { | ||
1215 | assert_snapshot!( | ||
1216 | infer(r#" | ||
1217 | trait Trait<T, U> { | ||
1218 | fn foo(&self) -> (T, U); | ||
1219 | } | ||
1220 | struct S<T, U> {} | ||
1221 | impl<T, U> S<T, U> { | ||
1222 | fn bar(&self) -> &dyn Trait<T, U> { loop {} } | ||
1223 | } | ||
1224 | trait Trait2<T, U> { | ||
1225 | fn baz(&self) -> (T, U); | ||
1226 | } | ||
1227 | impl<T, U> Trait2<T, U> for dyn Trait<T, U> { } | ||
1228 | |||
1229 | fn test(s: S<u32, i32>) { | ||
1230 | s.bar().baz(); | ||
1231 | } | ||
1232 | "#), | ||
1233 | @r###" | ||
1234 | [33; 37) 'self': &Self | ||
1235 | [103; 107) 'self': &S<T, U> | ||
1236 | [129; 140) '{ loop {} }': &dyn Trait<T, U> | ||
1237 | [131; 138) 'loop {}': ! | ||
1238 | [136; 138) '{}': () | ||
1239 | [176; 180) 'self': &Self | ||
1240 | [252; 253) 's': S<u32, i32> | ||
1241 | [268; 290) '{ ...z(); }': () | ||
1242 | [274; 275) 's': S<u32, i32> | ||
1243 | [274; 281) 's.bar()': &dyn Trait<u32, i32> | ||
1244 | [274; 287) 's.bar().baz()': (u32, i32) | ||
1245 | "### | ||
1246 | ); | ||
1247 | } | ||
1248 | |||
1249 | #[test] | ||
1214 | fn dyn_trait_bare() { | 1250 | fn dyn_trait_bare() { |
1215 | assert_snapshot!( | 1251 | assert_snapshot!( |
1216 | infer(r#" | 1252 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 60d70d18e..e00a82db2 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -17,7 +17,7 @@ use ra_db::{ | |||
17 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 17 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
18 | use crate::{ | 18 | use crate::{ |
19 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 19 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, |
20 | ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 20 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | pub(super) mod tls; | 23 | pub(super) mod tls; |
@@ -815,7 +815,7 @@ pub(crate) fn associated_ty_data_query( | |||
815 | // Lower bounds -- we could/should maybe move this to a separate query in `lower` | 815 | // Lower bounds -- we could/should maybe move this to a separate query in `lower` |
816 | let type_alias_data = db.type_alias_data(type_alias); | 816 | let type_alias_data = db.type_alias_data(type_alias); |
817 | let generic_params = generics(db.upcast(), type_alias.into()); | 817 | let generic_params = generics(db.upcast(), type_alias.into()); |
818 | let bound_vars = Substs::bound_vars(&generic_params); | 818 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
819 | let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); | 819 | let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); |
820 | let ctx = crate::TyLoweringContext::new(db, &resolver) | 820 | let ctx = crate::TyLoweringContext::new(db, &resolver) |
821 | .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); | 821 | .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); |
@@ -849,7 +849,7 @@ pub(crate) fn trait_datum_query( | |||
849 | let trait_data = db.trait_data(trait_); | 849 | let trait_data = db.trait_data(trait_); |
850 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); | 850 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); |
851 | let generic_params = generics(db.upcast(), trait_.into()); | 851 | let generic_params = generics(db.upcast(), trait_.into()); |
852 | let bound_vars = Substs::bound_vars(&generic_params); | 852 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
853 | let flags = chalk_rust_ir::TraitFlags { | 853 | let flags = chalk_rust_ir::TraitFlags { |
854 | auto: trait_data.auto, | 854 | auto: trait_data.auto, |
855 | upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, | 855 | upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, |
@@ -888,7 +888,7 @@ pub(crate) fn struct_datum_query( | |||
888 | .as_generic_def() | 888 | .as_generic_def() |
889 | .map(|generic_def| { | 889 | .map(|generic_def| { |
890 | let generic_params = generics(db.upcast(), generic_def); | 890 | let generic_params = generics(db.upcast(), generic_def); |
891 | let bound_vars = Substs::bound_vars(&generic_params); | 891 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
892 | convert_where_clauses(db, generic_def, &bound_vars) | 892 | convert_where_clauses(db, generic_def, &bound_vars) |
893 | }) | 893 | }) |
894 | .unwrap_or_else(Vec::new); | 894 | .unwrap_or_else(Vec::new); |
@@ -934,7 +934,7 @@ fn impl_def_datum( | |||
934 | let impl_data = db.impl_data(impl_id); | 934 | let impl_data = db.impl_data(impl_id); |
935 | 935 | ||
936 | let generic_params = generics(db.upcast(), impl_id.into()); | 936 | let generic_params = generics(db.upcast(), impl_id.into()); |
937 | let bound_vars = Substs::bound_vars(&generic_params); | 937 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
938 | let trait_ = trait_ref.trait_; | 938 | let trait_ = trait_ref.trait_; |
939 | let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { | 939 | let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { |
940 | chalk_rust_ir::ImplType::Local | 940 | chalk_rust_ir::ImplType::Local |