aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/lib.rs4
-rw-r--r--crates/ra_hir_ty/src/lower.rs69
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs36
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs10
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::{
39pub struct TyLoweringContext<'a> { 39pub 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.
798fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 827fn 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
883fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 912fn 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 f6e3e07cd..a46f03b7f 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]
1214fn dyn_trait_in_impl() {
1215 assert_snapshot!(
1216 infer(r#"
1217trait Trait<T, U> {
1218 fn foo(&self) -> (T, U);
1219}
1220struct S<T, U> {}
1221impl<T, U> S<T, U> {
1222 fn bar(&self) -> &dyn Trait<T, U> { loop {} }
1223}
1224trait Trait2<T, U> {
1225 fn baz(&self) -> (T, U);
1226}
1227impl<T, U> Trait2<T, U> for dyn Trait<T, U> { }
1228
1229fn 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]
1214fn dyn_trait_bare() { 1250fn 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::{
17use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 17use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
18use crate::{ 18use 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
23pub(super) mod tls; 23pub(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