diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 34 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 263 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 14 |
9 files changed, 220 insertions, 188 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index eb521c7a0..fea122a8b 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use ra_prof::profile; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::CrateImplBlocks, | 13 | method_resolution::CrateImplBlocks, |
14 | traits::{chalk, AssocTyValue, Impl}, | 14 | traits::{chalk, AssocTyValue, Impl}, |
15 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, | 15 | CallableDef, PolyFnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, |
16 | ValueTyDefId, | 16 | ValueTyDefId, Binders, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #[salsa::query_group(HirDatabaseStorage)] | 19 | #[salsa::query_group(HirDatabaseStorage)] |
@@ -27,14 +27,14 @@ pub trait HirDatabase: DefDatabase { | |||
27 | 27 | ||
28 | #[salsa::invoke(crate::lower::ty_query)] | 28 | #[salsa::invoke(crate::lower::ty_query)] |
29 | #[salsa::cycle(crate::lower::ty_recover)] | 29 | #[salsa::cycle(crate::lower::ty_recover)] |
30 | fn ty(&self, def: TyDefId) -> Ty; | 30 | fn ty(&self, def: TyDefId) -> Binders<Ty>; |
31 | 31 | ||
32 | #[salsa::invoke(crate::lower::value_ty_query)] | 32 | #[salsa::invoke(crate::lower::value_ty_query)] |
33 | fn value_ty(&self, def: ValueTyDefId) -> Ty; | 33 | fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>; |
34 | 34 | ||
35 | #[salsa::invoke(crate::lower::impl_self_ty_query)] | 35 | #[salsa::invoke(crate::lower::impl_self_ty_query)] |
36 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] | 36 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] |
37 | fn impl_self_ty(&self, def: ImplId) -> Ty; | 37 | fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; |
38 | 38 | ||
39 | #[salsa::invoke(crate::lower::impl_trait_query)] | 39 | #[salsa::invoke(crate::lower::impl_trait_query)] |
40 | fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; | 40 | fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; |
@@ -43,7 +43,7 @@ pub trait HirDatabase: DefDatabase { | |||
43 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; | 43 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; |
44 | 44 | ||
45 | #[salsa::invoke(crate::callable_item_sig)] | 45 | #[salsa::invoke(crate::callable_item_sig)] |
46 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 46 | fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; |
47 | 47 | ||
48 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 48 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
49 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 49 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index b4a3e1675..f7ef09f0e 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -279,11 +279,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
279 | impl_trait_mode: ImplTraitLoweringMode, | 279 | impl_trait_mode: ImplTraitLoweringMode, |
280 | ) -> Ty { | 280 | ) -> Ty { |
281 | // FIXME use right resolver for block | 281 | // FIXME use right resolver for block |
282 | let ctx = crate::lower::TyLoweringContext { | 282 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver).with_impl_trait_mode(impl_trait_mode); |
283 | db: self.db, | ||
284 | resolver: &self.resolver, | ||
285 | impl_trait_mode, | ||
286 | }; | ||
287 | let ty = Ty::from_hir(&ctx, type_ref); | 283 | let ty = Ty::from_hir(&ctx, type_ref); |
288 | let ty = self.insert_type_vars(ty); | 284 | let ty = self.insert_type_vars(ty); |
289 | self.normalize_associated_types_in(ty) | 285 | self.normalize_associated_types_in(ty) |
@@ -457,24 +453,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
457 | None => return (Ty::Unknown, None), | 453 | None => return (Ty::Unknown, None), |
458 | }; | 454 | }; |
459 | let resolver = &self.resolver; | 455 | let resolver = &self.resolver; |
460 | let ctx = crate::lower::TyLoweringContext { | 456 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
461 | db: self.db, | ||
462 | resolver: &self.resolver, | ||
463 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
464 | }; | ||
465 | // FIXME: this should resolve assoc items as well, see this example: | 457 | // FIXME: this should resolve assoc items as well, see this example: |
466 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 458 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
467 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { | 459 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { |
468 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 460 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { |
469 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); | 461 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); |
470 | let ty = self.db.ty(strukt.into()); | 462 | let ty = self.db.ty(strukt.into()); |
471 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 463 | let ty = self.insert_type_vars(ty.subst(&substs)); |
472 | (ty, Some(strukt.into())) | 464 | (ty, Some(strukt.into())) |
473 | } | 465 | } |
474 | Some(TypeNs::EnumVariantId(var)) => { | 466 | Some(TypeNs::EnumVariantId(var)) => { |
475 | let substs = Ty::substs_from_path(&ctx, path, var.into()); | 467 | let substs = Ty::substs_from_path(&ctx, path, var.into()); |
476 | let ty = self.db.ty(var.parent.into()); | 468 | let ty = self.db.ty(var.parent.into()); |
477 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 469 | let ty = self.insert_type_vars(ty.subst(&substs)); |
478 | (ty, Some(var.into())) | 470 | (ty, Some(var.into())) |
479 | } | 471 | } |
480 | Some(_) | None => (Ty::Unknown, None), | 472 | Some(_) | None => (Ty::Unknown, None), |
@@ -492,7 +484,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
492 | 484 | ||
493 | self.infer_pat(*pat, &ty, BindingMode::default()); | 485 | self.infer_pat(*pat, &ty, BindingMode::default()); |
494 | } | 486 | } |
495 | let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Placeholder); | 487 | let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Variable); |
496 | self.return_ty = self.insert_vars_for_impl_trait(return_ty); | 488 | self.return_ty = self.insert_vars_for_impl_trait(return_ty); |
497 | } | 489 | } |
498 | 490 | ||
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 97cb20cea..e1fdb356d 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | traits::InEnvironment, | 20 | traits::InEnvironment, |
21 | utils::{generics, variant_data, Generics}, | 21 | utils::{generics, variant_data, Generics}, |
22 | ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty, | 22 | ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty, |
23 | TypeCtor, TypeWalk, Uncertain, | 23 | TypeCtor, TypeWalk, Uncertain, Binders, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; |
@@ -588,10 +588,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
588 | self.write_method_resolution(tgt_expr, func); | 588 | self.write_method_resolution(tgt_expr, func); |
589 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) | 589 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) |
590 | } | 590 | } |
591 | None => (receiver_ty, Ty::Unknown, None), | 591 | None => (receiver_ty, Binders::new(0, Ty::Unknown), None), |
592 | }; | 592 | }; |
593 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | 593 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); |
594 | let method_ty = method_ty.apply_substs(substs); | 594 | let method_ty = method_ty.subst(&substs); |
595 | let method_ty = self.insert_type_vars(method_ty); | 595 | let method_ty = self.insert_type_vars(method_ty); |
596 | self.register_obligations_for_call(&method_ty); | 596 | self.register_obligations_for_call(&method_ty); |
597 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 597 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 02fc99288..39aa346eb 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -10,8 +10,8 @@ use hir_def::{ | |||
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, lower::ImplTraitLoweringMode, method_resolution, Substs, Ty, TypeWalk, | 13 | db::HirDatabase, method_resolution, Substs, Ty, |
14 | ValueTyDefId, | 14 | ValueTyDefId |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 17 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
@@ -42,11 +42,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
42 | } | 42 | } |
43 | let ty = self.make_ty(type_ref); | 43 | let ty = self.make_ty(type_ref); |
44 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); | 44 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); |
45 | let ctx = crate::lower::TyLoweringContext { | 45 | let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver); |
46 | db: self.db, | ||
47 | resolver: &resolver, | ||
48 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
49 | }; | ||
50 | let ty = Ty::from_type_relative_path(&ctx, ty, remaining_segments_for_ty); | 46 | let ty = Ty::from_type_relative_path(&ctx, ty, remaining_segments_for_ty); |
51 | self.resolve_ty_assoc_item( | 47 | self.resolve_ty_assoc_item( |
52 | ty, | 48 | ty, |
@@ -77,17 +73,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
77 | ValueNs::EnumVariantId(it) => it.into(), | 73 | ValueNs::EnumVariantId(it) => it.into(), |
78 | }; | 74 | }; |
79 | 75 | ||
80 | let mut ty = self.db.value_ty(typable); | 76 | let ty = self.db.value_ty(typable); |
81 | if let Some(self_subst) = self_subst { | 77 | // self_subst is just for the parent |
82 | ty = ty.subst(&self_subst); | 78 | let parent_substs = self_subst.unwrap_or_else(Substs::empty); |
83 | } | 79 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
84 | let ctx = crate::lower::TyLoweringContext { | ||
85 | db: self.db, | ||
86 | resolver: &self.resolver, | ||
87 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
88 | }; | ||
89 | let substs = Ty::substs_from_path(&ctx, path, typable); | 80 | let substs = Ty::substs_from_path(&ctx, path, typable); |
90 | let ty = ty.subst(&substs); | 81 | let full_substs = Substs::builder(substs.len()) |
82 | .use_parent_substs(&parent_substs) | ||
83 | .fill(substs.0[parent_substs.len()..].iter().cloned()) | ||
84 | .build(); | ||
85 | let ty = ty.subst(&full_substs); | ||
91 | Some(ty) | 86 | Some(ty) |
92 | } | 87 | } |
93 | 88 | ||
@@ -111,11 +106,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
111 | (TypeNs::TraitId(trait_), true) => { | 106 | (TypeNs::TraitId(trait_), true) => { |
112 | let segment = | 107 | let segment = |
113 | remaining_segments.last().expect("there should be at least one segment here"); | 108 | remaining_segments.last().expect("there should be at least one segment here"); |
114 | let ctx = crate::lower::TyLoweringContext { | 109 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
115 | db: self.db, | ||
116 | resolver: &self.resolver, | ||
117 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
118 | }; | ||
119 | let trait_ref = | 110 | let trait_ref = |
120 | TraitRef::from_resolved_path(&ctx, trait_.into(), resolved_segment, None); | 111 | TraitRef::from_resolved_path(&ctx, trait_.into(), resolved_segment, None); |
121 | self.resolve_trait_assoc_item(trait_ref, segment, id) | 112 | self.resolve_trait_assoc_item(trait_ref, segment, id) |
@@ -127,11 +118,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
127 | // as Iterator>::Item::default`) | 118 | // as Iterator>::Item::default`) |
128 | let remaining_segments_for_ty = | 119 | let remaining_segments_for_ty = |
129 | remaining_segments.take(remaining_segments.len() - 1); | 120 | remaining_segments.take(remaining_segments.len() - 1); |
130 | let ctx = crate::lower::TyLoweringContext { | 121 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
131 | db: self.db, | ||
132 | resolver: &self.resolver, | ||
133 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
134 | }; | ||
135 | let ty = Ty::from_partly_resolved_hir_path( | 122 | let ty = Ty::from_partly_resolved_hir_path( |
136 | &ctx, | 123 | &ctx, |
137 | def, | 124 | def, |
@@ -235,12 +222,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
235 | .fill(iter::repeat_with(|| self.table.new_type_var())) | 222 | .fill(iter::repeat_with(|| self.table.new_type_var())) |
236 | .build(); | 223 | .build(); |
237 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); | 224 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); |
238 | let substs = Substs::build_for_def(self.db, item) | ||
239 | .use_parent_substs(&impl_substs) | ||
240 | .fill_with_params() | ||
241 | .build(); | ||
242 | self.unify(&impl_self_ty, &ty); | 225 | self.unify(&impl_self_ty, &ty); |
243 | Some(substs) | 226 | Some(impl_substs) |
244 | } | 227 | } |
245 | AssocContainerId::TraitId(trait_) => { | 228 | AssocContainerId::TraitId(trait_) => { |
246 | // we're picking this method | 229 | // we're picking this method |
@@ -248,15 +231,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
248 | .push(ty.clone()) | 231 | .push(ty.clone()) |
249 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 232 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
250 | .build(); | 233 | .build(); |
251 | let substs = Substs::build_for_def(self.db, item) | ||
252 | .use_parent_substs(&trait_substs) | ||
253 | .fill_with_params() | ||
254 | .build(); | ||
255 | self.obligations.push(super::Obligation::Trait(TraitRef { | 234 | self.obligations.push(super::Obligation::Trait(TraitRef { |
256 | trait_, | 235 | trait_, |
257 | substs: trait_substs, | 236 | substs: trait_substs.clone(), |
258 | })); | 237 | })); |
259 | Some(substs) | 238 | Some(trait_substs) |
260 | } | 239 | } |
261 | AssocContainerId::ContainerId(_) => None, | 240 | AssocContainerId::ContainerId(_) => None, |
262 | }; | 241 | }; |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index cb7a60352..79084bb3e 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -453,6 +453,30 @@ impl Deref for Substs { | |||
453 | } | 453 | } |
454 | } | 454 | } |
455 | 455 | ||
456 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
457 | pub struct Binders<T> { | ||
458 | pub num_binders: usize, | ||
459 | pub value: T, | ||
460 | } | ||
461 | |||
462 | impl<T> Binders<T> { | ||
463 | pub fn new(num_binders: usize, value: T) -> Self { Self { num_binders, value } } | ||
464 | } | ||
465 | |||
466 | impl<T: TypeWalk> Binders<T> { | ||
467 | /// Substitutes all variables. | ||
468 | pub fn subst(self, subst: &Substs) -> T { | ||
469 | assert_eq!(subst.len(), self.num_binders); | ||
470 | self.value.subst_bound_vars(subst) | ||
471 | } | ||
472 | |||
473 | /// Substitutes just a prefix of the variables (shifting the rest). | ||
474 | pub fn subst_prefix(self, subst: &Substs) -> Binders<T> { | ||
475 | assert!(subst.len() < self.num_binders); | ||
476 | Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) | ||
477 | } | ||
478 | } | ||
479 | |||
456 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 480 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
457 | /// Name to be bikeshedded: TraitBound? TraitImplements? | 481 | /// Name to be bikeshedded: TraitBound? TraitImplements? |
458 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 482 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -553,6 +577,9 @@ pub struct FnSig { | |||
553 | params_and_return: Arc<[Ty]>, | 577 | params_and_return: Arc<[Ty]>, |
554 | } | 578 | } |
555 | 579 | ||
580 | /// A polymorphic function signature. | ||
581 | pub type PolyFnSig = Binders<FnSig>; | ||
582 | |||
556 | impl FnSig { | 583 | impl FnSig { |
557 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { | 584 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { |
558 | params.push(ret); | 585 | params.push(ret); |
@@ -757,6 +784,9 @@ pub trait TypeWalk { | |||
757 | &mut Ty::Bound(idx) => { | 784 | &mut Ty::Bound(idx) => { |
758 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { | 785 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
759 | *ty = substs.0[idx as usize - binders].clone(); | 786 | *ty = substs.0[idx as usize - binders].clone(); |
787 | } else if idx as usize >= binders + substs.len() { | ||
788 | // shift free binders | ||
789 | *ty = Ty::Bound(idx - substs.len() as u32); | ||
760 | } | 790 | } |
761 | } | 791 | } |
762 | _ => {} | 792 | _ => {} |
@@ -903,8 +933,8 @@ impl HirDisplay for ApplicationTy { | |||
903 | write!(f, ">")?; | 933 | write!(f, ">")?; |
904 | } | 934 | } |
905 | write!(f, "(")?; | 935 | write!(f, "(")?; |
906 | f.write_joined(sig.params(), ", ")?; | 936 | f.write_joined(sig.value.params(), ", ")?; |
907 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 937 | write!(f, ") -> {}", sig.value.ret().display(f.db))?; |
908 | } | 938 | } |
909 | TypeCtor::Adt(def_id) => { | 939 | TypeCtor::Adt(def_id) => { |
910 | let name = match def_id { | 940 | let name = match def_id { |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 6f7681475..006101f2f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -28,32 +28,62 @@ use crate::{ | |||
28 | variant_data, | 28 | variant_data, |
29 | }, | 29 | }, |
30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | 30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, |
31 | Ty, TypeCtor, TypeWalk, | 31 | Ty, TypeCtor, PolyFnSig, Binders, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | #[derive(Clone, Debug)] | 34 | #[derive(Debug)] |
35 | pub struct TyLoweringContext<'a, DB: HirDatabase> { | 35 | pub struct TyLoweringContext<'a, DB: HirDatabase> { |
36 | pub db: &'a DB, | 36 | pub db: &'a DB, |
37 | pub resolver: &'a Resolver, | 37 | pub resolver: &'a Resolver, |
38 | /// Note: Conceptually, it's thinkable that we could be in a location where | ||
39 | /// some type params are quantified universally (and should be represented | ||
40 | /// as placeholders), and others are quantified existentially (and should be | ||
41 | /// converted to variables). I think in practice, this isn't possible | ||
42 | /// currently, so this should be fine for now. | ||
43 | pub type_param_mode: TypeParamLoweringMode, | ||
38 | pub impl_trait_mode: ImplTraitLoweringMode, | 44 | pub impl_trait_mode: ImplTraitLoweringMode, |
45 | pub impl_trait_counter: std::cell::Cell<u16>, | ||
39 | } | 46 | } |
40 | 47 | ||
41 | #[derive(Clone, Debug)] | 48 | impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> { |
49 | pub fn new(db: &'a DB, resolver: &'a Resolver) -> Self { | ||
50 | let impl_trait_counter = std::cell::Cell::new(0); | ||
51 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | ||
52 | let type_param_mode = TypeParamLoweringMode::Placeholder; | ||
53 | Self { db, resolver, impl_trait_mode, impl_trait_counter, type_param_mode } | ||
54 | } | ||
55 | |||
56 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | ||
57 | Self { impl_trait_mode, ..self } | ||
58 | } | ||
59 | |||
60 | pub fn with_type_param_mode(self, type_param_mode: TypeParamLoweringMode) -> Self { | ||
61 | Self { type_param_mode, ..self } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | #[derive(Copy, Clone, Debug)] | ||
42 | pub enum ImplTraitLoweringMode { | 66 | pub enum ImplTraitLoweringMode { |
43 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with | 67 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with |
44 | /// anything except itself. This is used in places where values flow 'out', | 68 | /// anything except itself. This is used in places where values flow 'out', |
45 | /// i.e. for arguments of the function we're currently checking, and return | 69 | /// i.e. for arguments of the function we're currently checking, and return |
46 | /// types of functions we're calling. | 70 | /// types of functions we're calling. |
47 | Opaque, | 71 | Opaque, |
48 | /// `impl Trait` gets lowered into a placeholder that can unify with some | 72 | /// `impl Trait` gets lowered into a variable that can unify with some |
49 | /// type. This is used in places where values flow 'in', i.e. for arguments | 73 | /// type. This is used in places where values flow 'in', i.e. for arguments |
50 | /// of functions we're calling, and the return type of the function we're | 74 | /// of functions we're calling, and the return type of the function we're |
51 | /// currently checking. | 75 | /// currently checking. |
52 | Placeholder, | 76 | Variable, |
53 | /// `impl Trait` is disallowed and will be an error. | 77 | /// `impl Trait` is disallowed and will be an error. |
54 | Disallowed, | 78 | Disallowed, |
55 | } | 79 | } |
56 | 80 | ||
81 | #[derive(Copy, Clone, Debug)] | ||
82 | pub enum TypeParamLoweringMode { | ||
83 | Placeholder, | ||
84 | Variable, | ||
85 | } | ||
86 | |||
57 | impl Ty { | 87 | impl Ty { |
58 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { | 88 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { |
59 | match type_ref { | 89 | match type_ref { |
@@ -101,17 +131,25 @@ impl Ty { | |||
101 | let self_ty = Ty::Bound(0); | 131 | let self_ty = Ty::Bound(0); |
102 | let predicates = bounds | 132 | let predicates = bounds |
103 | .iter() | 133 | .iter() |
104 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) | 134 | .flat_map(|b| { |
135 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) | ||
136 | }) | ||
105 | .collect(); | 137 | .collect(); |
106 | Ty::Opaque(predicates) | 138 | Ty::Opaque(predicates) |
107 | }, | 139 | } |
108 | ImplTraitLoweringMode::Placeholder => { | 140 | ImplTraitLoweringMode::Variable => { |
109 | todo!() | 141 | let idx = ctx.impl_trait_counter.get(); |
110 | }, | 142 | ctx.impl_trait_counter.set(idx + 1); |
143 | let generics = | ||
144 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); | ||
145 | let (self_params, list_params, impl_trait_params) = generics.provenance_split(); | ||
146 | assert!((idx as usize) < impl_trait_params); | ||
147 | Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) | ||
148 | } | ||
111 | ImplTraitLoweringMode::Disallowed => { | 149 | ImplTraitLoweringMode::Disallowed => { |
112 | // FIXME: report error | 150 | // FIXME: report error |
113 | Ty::Unknown | 151 | Ty::Unknown |
114 | }, | 152 | } |
115 | } | 153 | } |
116 | } | 154 | } |
117 | TypeRef::Error => Ty::Unknown, | 155 | TypeRef::Error => Ty::Unknown, |
@@ -205,12 +243,31 @@ impl Ty { | |||
205 | let generics = | 243 | let generics = |
206 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); | 244 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); |
207 | let idx = generics.param_idx(param_id); | 245 | let idx = generics.param_idx(param_id); |
208 | // FIXME: maybe return name in resolution? | 246 | match ctx.type_param_mode { |
209 | let name = generics.param_name(param_id); | 247 | TypeParamLoweringMode::Placeholder => { |
210 | Ty::Param { idx, name } | 248 | // FIXME: maybe return name in resolution? |
249 | let name = generics.param_name(param_id); | ||
250 | Ty::Param { idx, name } | ||
251 | }, | ||
252 | TypeParamLoweringMode::Variable => Ty::Bound(idx), | ||
253 | } | ||
211 | } | 254 | } |
212 | TypeNs::SelfType(impl_id) => ctx.db.impl_self_ty(impl_id).clone(), | 255 | TypeNs::SelfType(impl_id) => { |
213 | TypeNs::AdtSelfType(adt) => ctx.db.ty(adt.into()), | 256 | let generics = generics(ctx.db, impl_id.into()); |
257 | let substs = match ctx.type_param_mode { | ||
258 | TypeParamLoweringMode::Placeholder => Substs::identity(&generics), | ||
259 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
260 | }; | ||
261 | ctx.db.impl_self_ty(impl_id).subst(&substs) | ||
262 | }, | ||
263 | TypeNs::AdtSelfType(adt) => { | ||
264 | let generics = generics(ctx.db, adt.into()); | ||
265 | let substs = match ctx.type_param_mode { | ||
266 | TypeParamLoweringMode::Placeholder => Substs::identity(&generics), | ||
267 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
268 | }; | ||
269 | ctx.db.ty(adt.into()).subst(&substs) | ||
270 | }, | ||
214 | 271 | ||
215 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 272 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
216 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 273 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
@@ -341,7 +398,7 @@ pub(super) fn substs_from_path_segment( | |||
341 | // Self type as an implicit first type parameter, but it can't be | 398 | // Self type as an implicit first type parameter, but it can't be |
342 | // actually provided in the type arguments | 399 | // actually provided in the type arguments |
343 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | 400 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) |
344 | // TODO handle this using type param provenance | 401 | // TODO handle this using type param provenance (if there's a self param, and not one provided, add unknown) |
345 | substs.push(Ty::Unknown); | 402 | substs.push(Ty::Unknown); |
346 | } | 403 | } |
347 | if let Some(generic_args) = &segment.args_and_bindings { | 404 | if let Some(generic_args) = &segment.args_and_bindings { |
@@ -493,7 +550,7 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
493 | } | 550 | } |
494 | 551 | ||
495 | /// Build the signature of a callable item (function, struct or enum variant). | 552 | /// Build the signature of a callable item (function, struct or enum variant). |
496 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | 553 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { |
497 | match def { | 554 | match def { |
498 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), | 555 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), |
499 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), | 556 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), |
@@ -513,11 +570,7 @@ pub(crate) fn field_types_query( | |||
513 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | 570 | VariantId::EnumVariantId(it) => it.parent.resolver(db), |
514 | }; | 571 | }; |
515 | let mut res = ArenaMap::default(); | 572 | let mut res = ArenaMap::default(); |
516 | let ctx = TyLoweringContext { | 573 | let ctx = TyLoweringContext::new(db, &resolver); |
517 | db, | ||
518 | resolver: &resolver, | ||
519 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
520 | }; | ||
521 | for (field_id, field_data) in var_data.fields().iter() { | 574 | for (field_id, field_data) in var_data.fields().iter() { |
522 | res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) | 575 | res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) |
523 | } | 576 | } |
@@ -538,11 +591,7 @@ pub(crate) fn generic_predicates_for_param_query( | |||
538 | param_idx: u32, | 591 | param_idx: u32, |
539 | ) -> Arc<[GenericPredicate]> { | 592 | ) -> Arc<[GenericPredicate]> { |
540 | let resolver = def.resolver(db); | 593 | let resolver = def.resolver(db); |
541 | let ctx = TyLoweringContext { | 594 | let ctx = TyLoweringContext::new(db, &resolver); |
542 | db, | ||
543 | resolver: &resolver, | ||
544 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
545 | }; | ||
546 | resolver | 595 | resolver |
547 | .where_predicates_in_scope() | 596 | .where_predicates_in_scope() |
548 | // we have to filter out all other predicates *first*, before attempting to lower them | 597 | // we have to filter out all other predicates *first*, before attempting to lower them |
@@ -562,8 +611,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
562 | 611 | ||
563 | impl TraitEnvironment { | 612 | impl TraitEnvironment { |
564 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | 613 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
565 | let ctx = | 614 | let ctx = TyLoweringContext::new(db, &resolver); |
566 | TyLoweringContext { db, resolver, impl_trait_mode: ImplTraitLoweringMode::Disallowed }; | ||
567 | let predicates = resolver | 615 | let predicates = resolver |
568 | .where_predicates_in_scope() | 616 | .where_predicates_in_scope() |
569 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) | 617 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) |
@@ -579,11 +627,7 @@ pub(crate) fn generic_predicates_query( | |||
579 | def: GenericDefId, | 627 | def: GenericDefId, |
580 | ) -> Arc<[GenericPredicate]> { | 628 | ) -> Arc<[GenericPredicate]> { |
581 | let resolver = def.resolver(db); | 629 | let resolver = def.resolver(db); |
582 | let ctx = TyLoweringContext { | 630 | let ctx = TyLoweringContext::new(db, &resolver); |
583 | db, | ||
584 | resolver: &resolver, | ||
585 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
586 | }; | ||
587 | resolver | 631 | resolver |
588 | .where_predicates_in_scope() | 632 | .where_predicates_in_scope() |
589 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) | 633 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) |
@@ -593,11 +637,7 @@ pub(crate) fn generic_predicates_query( | |||
593 | /// Resolve the default type params from generics | 637 | /// Resolve the default type params from generics |
594 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { | 638 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { |
595 | let resolver = def.resolver(db); | 639 | let resolver = def.resolver(db); |
596 | let ctx = TyLoweringContext { | 640 | let ctx = TyLoweringContext::new(db, &resolver); |
597 | db, | ||
598 | resolver: &resolver, | ||
599 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
600 | }; | ||
601 | let generic_params = generics(db, def.into()); | 641 | let generic_params = generics(db, def.into()); |
602 | 642 | ||
603 | let defaults = generic_params | 643 | let defaults = generic_params |
@@ -608,56 +648,46 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) - | |||
608 | Substs(defaults) | 648 | Substs(defaults) |
609 | } | 649 | } |
610 | 650 | ||
611 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { | 651 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> PolyFnSig { |
612 | let data = db.function_data(def); | 652 | let data = db.function_data(def); |
613 | let resolver = def.resolver(db); | 653 | let resolver = def.resolver(db); |
614 | let ctx_params = TyLoweringContext { | 654 | let ctx_params = TyLoweringContext::new(db, &resolver) |
615 | db, | 655 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) |
616 | resolver: &resolver, | 656 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
617 | impl_trait_mode: ImplTraitLoweringMode::Placeholder, | ||
618 | }; | ||
619 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); | 657 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); |
620 | let ctx_ret = TyLoweringContext { | 658 | let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); |
621 | db, | ||
622 | resolver: &resolver, | ||
623 | impl_trait_mode: ImplTraitLoweringMode::Opaque, | ||
624 | }; | ||
625 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); | 659 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); |
626 | FnSig::from_params_and_return(params, ret) | 660 | let generics = generics(db, def.into()); |
661 | let num_binders = generics.len(); | ||
662 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) | ||
627 | } | 663 | } |
628 | 664 | ||
629 | /// Build the declared type of a function. This should not need to look at the | 665 | /// Build the declared type of a function. This should not need to look at the |
630 | /// function body. | 666 | /// function body. |
631 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { | 667 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Binders<Ty> { |
632 | let generics = generics(db, def.into()); | 668 | let generics = generics(db, def.into()); |
633 | let substs = Substs::identity(&generics); | 669 | let substs = Substs::bound_vars(&generics); |
634 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 670 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
635 | } | 671 | } |
636 | 672 | ||
637 | /// Build the declared type of a const. | 673 | /// Build the declared type of a const. |
638 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { | 674 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders<Ty> { |
639 | let data = db.const_data(def); | 675 | let data = db.const_data(def); |
676 | let generics = generics(db, def.into()); | ||
640 | let resolver = def.resolver(db); | 677 | let resolver = def.resolver(db); |
641 | let ctx = TyLoweringContext { | 678 | let ctx = TyLoweringContext::new(db, &resolver) |
642 | db, | 679 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
643 | resolver: &resolver, | ||
644 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
645 | }; | ||
646 | 680 | ||
647 | Ty::from_hir(&ctx, &data.type_ref) | 681 | Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) |
648 | } | 682 | } |
649 | 683 | ||
650 | /// Build the declared type of a static. | 684 | /// Build the declared type of a static. |
651 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { | 685 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Binders<Ty> { |
652 | let data = db.static_data(def); | 686 | let data = db.static_data(def); |
653 | let resolver = def.resolver(db); | 687 | let resolver = def.resolver(db); |
654 | let ctx = TyLoweringContext { | 688 | let ctx = TyLoweringContext::new(db, &resolver); |
655 | db, | ||
656 | resolver: &resolver, | ||
657 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
658 | }; | ||
659 | 689 | ||
660 | Ty::from_hir(&ctx, &data.type_ref) | 690 | Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) |
661 | } | 691 | } |
662 | 692 | ||
663 | /// Build the declared type of a static. | 693 | /// Build the declared type of a static. |
@@ -671,79 +701,71 @@ fn type_for_builtin(def: BuiltinType) -> Ty { | |||
671 | }) | 701 | }) |
672 | } | 702 | } |
673 | 703 | ||
674 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { | 704 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFnSig { |
675 | let struct_data = db.struct_data(def.into()); | 705 | let struct_data = db.struct_data(def.into()); |
676 | let fields = struct_data.variant_data.fields(); | 706 | let fields = struct_data.variant_data.fields(); |
677 | let resolver = def.resolver(db); | 707 | let resolver = def.resolver(db); |
678 | let ctx = TyLoweringContext { | 708 | let ctx = TyLoweringContext::new(db, &resolver) |
679 | db, | 709 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
680 | resolver: &resolver, | ||
681 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
682 | }; | ||
683 | let params = | 710 | let params = |
684 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 711 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
685 | let ret = type_for_adt(db, def.into()); | 712 | let ret = type_for_adt(db, def.into()); |
686 | FnSig::from_params_and_return(params, ret) | 713 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) |
687 | } | 714 | } |
688 | 715 | ||
689 | /// Build the type of a tuple struct constructor. | 716 | /// Build the type of a tuple struct constructor. |
690 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { | 717 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { |
691 | let struct_data = db.struct_data(def.into()); | 718 | let struct_data = db.struct_data(def.into()); |
692 | if struct_data.variant_data.is_unit() { | 719 | if struct_data.variant_data.is_unit() { |
693 | return type_for_adt(db, def.into()); // Unit struct | 720 | return type_for_adt(db, def.into()); // Unit struct |
694 | } | 721 | } |
695 | let generics = generics(db, def.into()); | 722 | let generics = generics(db, def.into()); |
696 | let substs = Substs::identity(&generics); | 723 | let substs = Substs::bound_vars(&generics); |
697 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 724 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
698 | } | 725 | } |
699 | 726 | ||
700 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { | 727 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> PolyFnSig { |
701 | let enum_data = db.enum_data(def.parent); | 728 | let enum_data = db.enum_data(def.parent); |
702 | let var_data = &enum_data.variants[def.local_id]; | 729 | let var_data = &enum_data.variants[def.local_id]; |
703 | let fields = var_data.variant_data.fields(); | 730 | let fields = var_data.variant_data.fields(); |
704 | let resolver = def.parent.resolver(db); | 731 | let resolver = def.parent.resolver(db); |
705 | let ctx = TyLoweringContext { | 732 | let ctx = TyLoweringContext::new(db, &resolver); |
706 | db, | ||
707 | resolver: &resolver, | ||
708 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
709 | }; | ||
710 | let params = | 733 | let params = |
711 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 734 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
712 | let generics = generics(db, def.parent.into()); | 735 | let generics = generics(db, def.parent.into()); |
713 | let substs = Substs::identity(&generics); | 736 | let substs = Substs::bound_vars(&generics); |
714 | let ret = type_for_adt(db, def.parent.into()).subst(&substs); | 737 | let ret = type_for_adt(db, def.parent.into()).subst(&substs); |
715 | FnSig::from_params_and_return(params, ret) | 738 | let num_binders = generics.len(); |
739 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) | ||
716 | } | 740 | } |
717 | 741 | ||
718 | /// Build the type of a tuple enum variant constructor. | 742 | /// Build the type of a tuple enum variant constructor. |
719 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { | 743 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { |
720 | let enum_data = db.enum_data(def.parent); | 744 | let enum_data = db.enum_data(def.parent); |
721 | let var_data = &enum_data.variants[def.local_id].variant_data; | 745 | let var_data = &enum_data.variants[def.local_id].variant_data; |
722 | if var_data.is_unit() { | 746 | if var_data.is_unit() { |
723 | return type_for_adt(db, def.parent.into()); // Unit variant | 747 | return type_for_adt(db, def.parent.into()); // Unit variant |
724 | } | 748 | } |
725 | let generics = generics(db, def.parent.into()); | 749 | let generics = generics(db, def.parent.into()); |
726 | let substs = Substs::identity(&generics); | 750 | let substs = Substs::bound_vars(&generics); |
727 | Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) | 751 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)) |
728 | } | 752 | } |
729 | 753 | ||
730 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { | 754 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders<Ty> { |
731 | let generics = generics(db, adt.into()); | 755 | let generics = generics(db, adt.into()); |
732 | Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) | 756 | let substs = Substs::bound_vars(&generics); |
757 | Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) | ||
733 | } | 758 | } |
734 | 759 | ||
735 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { | 760 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
736 | let generics = generics(db, t.into()); | 761 | let generics = generics(db, t.into()); |
737 | let resolver = t.resolver(db); | 762 | let resolver = t.resolver(db); |
738 | let ctx = TyLoweringContext { | 763 | let ctx = TyLoweringContext::new(db, &resolver) |
739 | db, | 764 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
740 | resolver: &resolver, | ||
741 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
742 | }; | ||
743 | let type_ref = &db.type_alias_data(t).type_ref; | 765 | let type_ref = &db.type_alias_data(t).type_ref; |
744 | let substs = Substs::identity(&generics); | 766 | let substs = Substs::bound_vars(&generics); |
745 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 767 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
746 | inner.subst(&substs) | 768 | Binders::new(substs.len(), inner) |
747 | } | 769 | } |
748 | 770 | ||
749 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 771 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
@@ -797,19 +819,20 @@ impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId | |||
797 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 819 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
798 | /// the constructor function `(usize) -> Foo` which lives in the values | 820 | /// the constructor function `(usize) -> Foo` which lives in the values |
799 | /// namespace. | 821 | /// namespace. |
800 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { | 822 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders<Ty> { |
801 | match def { | 823 | match def { |
802 | TyDefId::BuiltinType(it) => type_for_builtin(it), | 824 | TyDefId::BuiltinType(it) => Binders::new(0, type_for_builtin(it)), |
803 | TyDefId::AdtId(it) => type_for_adt(db, it), | 825 | TyDefId::AdtId(it) => type_for_adt(db, it), |
804 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | 826 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), |
805 | } | 827 | } |
806 | } | 828 | } |
807 | 829 | ||
808 | pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { | 830 | pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Binders<Ty> { |
809 | Ty::Unknown | 831 | // TODO still need correct number of binders here |
832 | Binders::new(0, Ty::Unknown) | ||
810 | } | 833 | } |
811 | 834 | ||
812 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | 835 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders<Ty> { |
813 | match def { | 836 | match def { |
814 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 837 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
815 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 838 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), |
@@ -819,34 +842,30 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | |||
819 | } | 842 | } |
820 | } | 843 | } |
821 | 844 | ||
822 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { | 845 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Binders<Ty> { |
823 | let impl_data = db.impl_data(impl_id); | 846 | let impl_data = db.impl_data(impl_id); |
824 | let resolver = impl_id.resolver(db); | 847 | let resolver = impl_id.resolver(db); |
825 | let ctx = TyLoweringContext { | 848 | let generics = generics(db, impl_id.into()); |
826 | db, | 849 | let ctx = TyLoweringContext::new(db, &resolver) |
827 | resolver: &resolver, | 850 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
828 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | 851 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) |
829 | }; | ||
830 | Ty::from_hir(&ctx, &impl_data.target_type) | ||
831 | } | 852 | } |
832 | 853 | ||
833 | pub(crate) fn impl_self_ty_recover( | 854 | pub(crate) fn impl_self_ty_recover( |
834 | _db: &impl HirDatabase, | 855 | db: &impl HirDatabase, |
835 | _cycle: &[String], | 856 | _cycle: &[String], |
836 | _impl_id: &ImplId, | 857 | impl_id: &ImplId, |
837 | ) -> Ty { | 858 | ) -> Binders<Ty> { |
838 | Ty::Unknown | 859 | let generics = generics(db, (*impl_id).into()); |
860 | Binders::new(generics.len(), Ty::Unknown) | ||
839 | } | 861 | } |
840 | 862 | ||
841 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { | 863 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { |
842 | let impl_data = db.impl_data(impl_id); | 864 | let impl_data = db.impl_data(impl_id); |
843 | let resolver = impl_id.resolver(db); | 865 | let resolver = impl_id.resolver(db); |
844 | let ctx = TyLoweringContext { | 866 | let generics = generics(db, impl_id.into()); |
845 | db, | 867 | let ctx = TyLoweringContext::new(db, &resolver); |
846 | resolver: &resolver, | 868 | let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); |
847 | impl_trait_mode: ImplTraitLoweringMode::Disallowed, | ||
848 | }; | ||
849 | let self_ty = db.impl_self_ty(impl_id); | ||
850 | let target_trait = impl_data.target_trait.as_ref()?; | 869 | let target_trait = impl_data.target_trait.as_ref()?; |
851 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) | 870 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) |
852 | } | 871 | } |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 5bacbbd7c..eab2149dc 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -65,7 +65,7 @@ impl CrateImplBlocks { | |||
65 | } | 65 | } |
66 | None => { | 66 | None => { |
67 | let self_ty = db.impl_self_ty(impl_id); | 67 | let self_ty = db.impl_self_ty(impl_id); |
68 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { | 68 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { |
69 | res.impls.entry(self_ty_fp).or_default().push(impl_id); | 69 | res.impls.entry(self_ty_fp).or_default().push(impl_id); |
70 | } | 70 | } |
71 | } | 71 | } |
@@ -496,7 +496,7 @@ fn transform_receiver_ty( | |||
496 | AssocContainerId::ContainerId(_) => unreachable!(), | 496 | AssocContainerId::ContainerId(_) => unreachable!(), |
497 | }; | 497 | }; |
498 | let sig = db.callable_item_signature(function_id.into()); | 498 | let sig = db.callable_item_signature(function_id.into()); |
499 | Some(sig.params()[0].clone().subst(&substs)) | 499 | Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) |
500 | } | 500 | } |
501 | 501 | ||
502 | pub fn implements_trait( | 502 | pub fn implements_trait( |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index fdab9c187..f1238506b 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -1220,7 +1220,7 @@ fn test() { | |||
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | #[test] | 1222 | #[test] |
1223 | fn infer_impl_generics() { | 1223 | fn infer_impl_generics_basic() { |
1224 | assert_snapshot!( | 1224 | assert_snapshot!( |
1225 | infer(r#" | 1225 | infer(r#" |
1226 | struct A<T1, T2> { | 1226 | struct A<T1, T2> { |
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 314a3241f..f116b95e7 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -5,7 +5,7 @@ use std::sync::Arc; | |||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | adt::VariantData, | 6 | adt::VariantData, |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | generics::{GenericParams, TypeParamData}, | 8 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
9 | path::Path, | 9 | path::Path, |
10 | resolver::{HasResolver, TypeNs}, | 10 | resolver::{HasResolver, TypeNs}, |
11 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
@@ -117,19 +117,31 @@ impl Generics { | |||
117 | pub(crate) fn len(&self) -> usize { | 117 | pub(crate) fn len(&self) -> usize { |
118 | self.len_split().0 | 118 | self.len_split().0 |
119 | } | 119 | } |
120 | |||
120 | /// (total, parents, child) | 121 | /// (total, parents, child) |
121 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { | 122 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { |
122 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); | 123 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); |
123 | let child = self.params.types.len(); | 124 | let child = self.params.types.len(); |
124 | (parent + child, parent, child) | 125 | (parent + child, parent, child) |
125 | } | 126 | } |
127 | |||
128 | /// (self, type param list, impl trait) | ||
129 | pub(crate) fn provenance_split(&self) -> (usize, usize, usize) { | ||
130 | let self_params = self.params.types.iter().filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf).count(); | ||
131 | let list_params = self.params.types.iter().filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList).count(); | ||
132 | let impl_trait_params = self.params.types.iter().filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait).count(); | ||
133 | (self_params, list_params, impl_trait_params) | ||
134 | } | ||
135 | |||
126 | pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { | 136 | pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { |
127 | self.find_param(param).0 | 137 | self.find_param(param).0 |
128 | } | 138 | } |
139 | |||
129 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { | 140 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { |
130 | // FIXME make this return Option | 141 | // FIXME make this return Option |
131 | self.find_param(param).1.name.clone().unwrap_or_else(Name::missing) | 142 | self.find_param(param).1.name.clone().unwrap_or_else(Name::missing) |
132 | } | 143 | } |
144 | |||
133 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { | 145 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { |
134 | if param.parent == self.def { | 146 | if param.parent == self.def { |
135 | let (idx, (_local_id, data)) = self | 147 | let (idx, (_local_id, data)) = self |