diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-02-09 11:35:08 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-02-09 11:35:08 +0000 |
commit | 01836a0f35fa163025c64cabe1d0c34bb4f69c92 (patch) | |
tree | aa1a3cf97173b2885f8b6d23002c73196f9a0b61 /crates/ra_hir_ty/src | |
parent | 961a69b88f923d4477ca4f746a793217a0cc8576 (diff) | |
parent | eefe02ce6e1750b771cf99125429358e87485745 (diff) |
Merge #3050
3050: Refactor type parameters, implement argument position impl trait r=matklad a=flodiebold
I wanted to implement APIT by lowering to type parameters because we need to do that anyway for correctness and don't need Chalk support for it; this grew into some more wide-ranging refactoring of how type parameters are handled :sweat_smile:
- use Ty::Bound instead of Ty::Param to represent polymorphism, and explicitly
count binders. This gets us closer to Chalk's way of doing things, and means
that we now only use Param as a placeholder for an unknown type, e.g. within
a generic function. I.e. we're never using Param in a situation where we want
to substitute it, and the method to do that is gone; `subst` now always works
on bound variables. (This changes how the types of generic functions print;
previously, you'd get something like `fn identity<i32>(T) -> T`, but now we
display the substituted signature `fn identity<i32>(i32) -> i32`, which I think
makes more sense.)
- once we do this, it's more natural to represent `Param` by a globally unique
ID; the use of indices was mostly to make substituting easier. This also
means we fix the bug where `Param` loses its name when going through Chalk.
- I would actually like to rename `Param` to `Placeholder` to better reflect its use and
get closer to Chalk, but I'll leave that to a follow-up.
- introduce a context for type lowering, to allow lowering `impl Trait` to
different things depending on where we are. And since we have that, we can
also lower type parameters directly to variables instead of placeholders.
Also, we'll be able to use this later to collect diagnostics.
- implement argument position impl trait by lowering it to type parameters.
I've realized that this is necessary to correctly implement it; e.g. consider
`fn foo(impl Display) -> impl Something`. It's observable that the return
type of e.g. `foo(1u32)` unifies with itself, but doesn't unify with e.g.
`foo(1i32)`; so the return type needs to be parameterized by the argument
type.
This fixes a few bugs as well:
- type parameters 'losing' their name when they go through Chalk, as mentioned
above (i.e. getting `[missing name]` somewhere)
- impl trait not being considered as implementing the super traits (very
noticeable for the `db` in RA)
- the fact that argument impl trait was only turned into variables when the
function got called caused type mismatches when the function was used as a
value (fixes a few type mismatches in RA)
The one thing I'm not so happy with here is how we're lowering `impl Trait` types to variables; since `TypeRef`s don't have an identity currently, we just count how many of them we have seen while going through the function signature. That's quite fragile though, since we have to do it while desugaring generics and while lowering the type signature, and in the exact same order in both cases. We could consider either giving only `TypeRef::ImplTrait` a local id, or maybe just giving all `TypeRef`s an identity after all (we talked about this before)...
Follow-up tasks:
- handle return position impl trait; we basically need to create a variable and some trait obligations for that variable
- rename `Param` to `Placeholder`
Co-authored-by: Florian Diebold <[email protected]>
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 34 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 66 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 262 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 577 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 42 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 312 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 91 |
18 files changed, 1026 insertions, 587 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index eb521c7a0..e9bfcfa17 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -3,17 +3,18 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, | 6 | db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, TypeParamId, |
7 | VariantId, | ||
7 | }; | 8 | }; |
8 | use ra_arena::map::ArenaMap; | 9 | use ra_arena::map::ArenaMap; |
9 | use ra_db::{salsa, CrateId}; | 10 | use ra_db::{impl_intern_key, salsa, CrateId}; |
10 | use ra_prof::profile; | 11 | use ra_prof::profile; |
11 | 12 | ||
12 | use crate::{ | 13 | use crate::{ |
13 | method_resolution::CrateImplBlocks, | 14 | method_resolution::CrateImplBlocks, |
14 | traits::{chalk, AssocTyValue, Impl}, | 15 | traits::{chalk, AssocTyValue, Impl}, |
15 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, | 16 | Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty, |
16 | ValueTyDefId, | 17 | TyDefId, TypeCtor, ValueTyDefId, |
17 | }; | 18 | }; |
18 | 19 | ||
19 | #[salsa::query_group(HirDatabaseStorage)] | 20 | #[salsa::query_group(HirDatabaseStorage)] |
@@ -27,34 +28,33 @@ pub trait HirDatabase: DefDatabase { | |||
27 | 28 | ||
28 | #[salsa::invoke(crate::lower::ty_query)] | 29 | #[salsa::invoke(crate::lower::ty_query)] |
29 | #[salsa::cycle(crate::lower::ty_recover)] | 30 | #[salsa::cycle(crate::lower::ty_recover)] |
30 | fn ty(&self, def: TyDefId) -> Ty; | 31 | fn ty(&self, def: TyDefId) -> Binders<Ty>; |
31 | 32 | ||
32 | #[salsa::invoke(crate::lower::value_ty_query)] | 33 | #[salsa::invoke(crate::lower::value_ty_query)] |
33 | fn value_ty(&self, def: ValueTyDefId) -> Ty; | 34 | fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>; |
34 | 35 | ||
35 | #[salsa::invoke(crate::lower::impl_self_ty_query)] | 36 | #[salsa::invoke(crate::lower::impl_self_ty_query)] |
36 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] | 37 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] |
37 | fn impl_self_ty(&self, def: ImplId) -> Ty; | 38 | fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; |
38 | 39 | ||
39 | #[salsa::invoke(crate::lower::impl_trait_query)] | 40 | #[salsa::invoke(crate::lower::impl_trait_query)] |
40 | fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; | 41 | fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>; |
41 | 42 | ||
42 | #[salsa::invoke(crate::lower::field_types_query)] | 43 | #[salsa::invoke(crate::lower::field_types_query)] |
43 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; | 44 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>>; |
44 | 45 | ||
45 | #[salsa::invoke(crate::callable_item_sig)] | 46 | #[salsa::invoke(crate::callable_item_sig)] |
46 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 47 | fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; |
47 | 48 | ||
48 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 49 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
49 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 50 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
50 | fn generic_predicates_for_param( | 51 | fn generic_predicates_for_param( |
51 | &self, | 52 | &self, |
52 | def: GenericDefId, | 53 | param_id: TypeParamId, |
53 | param_idx: u32, | 54 | ) -> Arc<[Binders<GenericPredicate>]>; |
54 | ) -> Arc<[GenericPredicate]>; | ||
55 | 55 | ||
56 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 56 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
57 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[GenericPredicate]>; | 57 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; |
58 | 58 | ||
59 | #[salsa::invoke(crate::lower::generic_defaults_query)] | 59 | #[salsa::invoke(crate::lower::generic_defaults_query)] |
60 | fn generic_defaults(&self, def: GenericDefId) -> Substs; | 60 | fn generic_defaults(&self, def: GenericDefId) -> Substs; |
@@ -77,6 +77,8 @@ pub trait HirDatabase: DefDatabase { | |||
77 | #[salsa::interned] | 77 | #[salsa::interned] |
78 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; | 78 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; |
79 | #[salsa::interned] | 79 | #[salsa::interned] |
80 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; | ||
81 | #[salsa::interned] | ||
80 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; | 82 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; |
81 | #[salsa::interned] | 83 | #[salsa::interned] |
82 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; | 84 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; |
@@ -117,3 +119,7 @@ fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { | |||
117 | fn hir_database_is_object_safe() { | 119 | fn hir_database_is_object_safe() { |
118 | fn _assert_object_safe(_: &dyn HirDatabase) {} | 120 | fn _assert_object_safe(_: &dyn HirDatabase) {} |
119 | } | 121 | } |
122 | |||
123 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
124 | pub struct GlobalTypeParamId(salsa::InternId); | ||
125 | impl_intern_key!(GlobalTypeParamId); | ||
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index e2eda3134..a9d958c8b 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -34,7 +34,6 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name}; | |||
34 | use ra_arena::map::ArenaMap; | 34 | use ra_arena::map::ArenaMap; |
35 | use ra_prof::profile; | 35 | use ra_prof::profile; |
36 | use ra_syntax::SmolStr; | 36 | use ra_syntax::SmolStr; |
37 | use test_utils::tested_by; | ||
38 | 37 | ||
39 | use super::{ | 38 | use super::{ |
40 | primitive::{FloatTy, IntTy}, | 39 | primitive::{FloatTy, IntTy}, |
@@ -42,7 +41,9 @@ use super::{ | |||
42 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, | 41 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, |
43 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, | 42 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
44 | }; | 43 | }; |
45 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 44 | use crate::{ |
45 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | ||
46 | }; | ||
46 | 47 | ||
47 | pub(crate) use unify::unify; | 48 | pub(crate) use unify::unify; |
48 | 49 | ||
@@ -271,38 +272,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
271 | self.result.diagnostics.push(diagnostic); | 272 | self.result.diagnostics.push(diagnostic); |
272 | } | 273 | } |
273 | 274 | ||
274 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { | 275 | fn make_ty_with_mode( |
275 | let ty = Ty::from_hir( | 276 | &mut self, |
276 | self.db, | 277 | type_ref: &TypeRef, |
277 | // FIXME use right resolver for block | 278 | impl_trait_mode: ImplTraitLoweringMode, |
278 | &self.resolver, | 279 | ) -> Ty { |
279 | type_ref, | 280 | // FIXME use right resolver for block |
280 | ); | 281 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) |
282 | .with_impl_trait_mode(impl_trait_mode); | ||
283 | let ty = Ty::from_hir(&ctx, type_ref); | ||
281 | let ty = self.insert_type_vars(ty); | 284 | let ty = self.insert_type_vars(ty); |
282 | self.normalize_associated_types_in(ty) | 285 | self.normalize_associated_types_in(ty) |
283 | } | 286 | } |
284 | 287 | ||
285 | /// Replaces `impl Trait` in `ty` by type variables and obligations for | 288 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
286 | /// those variables. This is done for function arguments when calling a | 289 | self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed) |
287 | /// function, and for return types when inside the function body, i.e. in | ||
288 | /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl | ||
289 | /// Trait` is represented by `Ty::Opaque`. | ||
290 | fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty { | ||
291 | ty.fold(&mut |ty| match ty { | ||
292 | Ty::Opaque(preds) => { | ||
293 | tested_by!(insert_vars_for_impl_trait); | ||
294 | let var = self.table.new_type_var(); | ||
295 | let var_subst = Substs::builder(1).push(var.clone()).build(); | ||
296 | self.obligations.extend( | ||
297 | preds | ||
298 | .iter() | ||
299 | .map(|pred| pred.clone().subst_bound_vars(&var_subst)) | ||
300 | .filter_map(Obligation::from_predicate), | ||
301 | ); | ||
302 | var | ||
303 | } | ||
304 | _ => ty, | ||
305 | }) | ||
306 | } | 290 | } |
307 | 291 | ||
308 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 292 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
@@ -446,19 +430,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
446 | None => return (Ty::Unknown, None), | 430 | None => return (Ty::Unknown, None), |
447 | }; | 431 | }; |
448 | let resolver = &self.resolver; | 432 | let resolver = &self.resolver; |
433 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | ||
449 | // FIXME: this should resolve assoc items as well, see this example: | 434 | // FIXME: this should resolve assoc items as well, see this example: |
450 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 435 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
451 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { | 436 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { |
452 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 437 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { |
453 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); | 438 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); |
454 | let ty = self.db.ty(strukt.into()); | 439 | let ty = self.db.ty(strukt.into()); |
455 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 440 | let ty = self.insert_type_vars(ty.subst(&substs)); |
456 | (ty, Some(strukt.into())) | 441 | (ty, Some(strukt.into())) |
457 | } | 442 | } |
458 | Some(TypeNs::EnumVariantId(var)) => { | 443 | Some(TypeNs::EnumVariantId(var)) => { |
459 | let substs = Ty::substs_from_path(self.db, resolver, path, var.into()); | 444 | let substs = Ty::substs_from_path(&ctx, path, var.into()); |
460 | let ty = self.db.ty(var.parent.into()); | 445 | let ty = self.db.ty(var.parent.into()); |
461 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 446 | let ty = self.insert_type_vars(ty.subst(&substs)); |
462 | (ty, Some(var.into())) | 447 | (ty, Some(var.into())) |
463 | } | 448 | } |
464 | Some(_) | None => (Ty::Unknown, None), | 449 | Some(_) | None => (Ty::Unknown, None), |
@@ -471,13 +456,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
471 | 456 | ||
472 | fn collect_fn(&mut self, data: &FunctionData) { | 457 | fn collect_fn(&mut self, data: &FunctionData) { |
473 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 458 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
474 | for (type_ref, pat) in data.params.iter().zip(body.params.iter()) { | 459 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) |
475 | let ty = self.make_ty(type_ref); | 460 | .with_impl_trait_mode(ImplTraitLoweringMode::Param); |
461 | let param_tys = | ||
462 | data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>(); | ||
463 | for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) { | ||
464 | let ty = self.insert_type_vars(ty); | ||
465 | let ty = self.normalize_associated_types_in(ty); | ||
476 | 466 | ||
477 | self.infer_pat(*pat, &ty, BindingMode::default()); | 467 | self.infer_pat(*pat, &ty, BindingMode::default()); |
478 | } | 468 | } |
479 | let return_ty = self.make_ty(&data.ret_type); | 469 | let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT |
480 | self.return_ty = self.insert_vars_for_impl_trait(return_ty); | 470 | self.return_ty = return_ty; |
481 | } | 471 | } |
482 | 472 | ||
483 | fn infer_body(&mut self) { | 473 | fn infer_body(&mut self) { |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 83c0c2c3f..f68a1439f 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -57,8 +57,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
57 | let trait_ref = db.impl_trait(impl_id)?; | 57 | let trait_ref = db.impl_trait(impl_id)?; |
58 | 58 | ||
59 | // `CoerseUnsized` has one generic parameter for the target type. | 59 | // `CoerseUnsized` has one generic parameter for the target type. |
60 | let cur_from_ty = trait_ref.substs.0.get(0)?; | 60 | let cur_from_ty = trait_ref.value.substs.0.get(0)?; |
61 | let cur_to_ty = trait_ref.substs.0.get(1)?; | 61 | let cur_to_ty = trait_ref.value.substs.0.get(1)?; |
62 | 62 | ||
63 | match (&cur_from_ty, cur_to_ty) { | 63 | match (&cur_from_ty, cur_to_ty) { |
64 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { | 64 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { |
@@ -66,9 +66,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
66 | // This works for smart-pointer-like coercion, which covers all impls from std. | 66 | // This works for smart-pointer-like coercion, which covers all impls from std. |
67 | st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { | 67 | st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { |
68 | match (ty1, ty2) { | 68 | match (ty1, ty2) { |
69 | (Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. }) | 69 | (Ty::Bound(idx1), Ty::Bound(idx2)) if idx1 != idx2 => { |
70 | if p1 != p2 => | ||
71 | { | ||
72 | Some(((*ctor1, *ctor2), i)) | 70 | Some(((*ctor1, *ctor2), i)) |
73 | } | 71 | } |
74 | _ => None, | 72 | _ => None, |
@@ -256,8 +254,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
256 | let unsize_generic_index = { | 254 | let unsize_generic_index = { |
257 | let mut index = None; | 255 | let mut index = None; |
258 | let mut multiple_param = false; | 256 | let mut multiple_param = false; |
259 | field_tys[last_field_id].walk(&mut |ty| match ty { | 257 | field_tys[last_field_id].value.walk(&mut |ty| match ty { |
260 | &Ty::Param { idx, .. } => { | 258 | &Ty::Bound(idx) => { |
261 | if index.is_none() { | 259 | if index.is_none() { |
262 | index = Some(idx); | 260 | index = Some(idx); |
263 | } else if Some(idx) != index { | 261 | } else if Some(idx) != index { |
@@ -276,10 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
276 | // Check other fields do not involve it. | 274 | // Check other fields do not involve it. |
277 | let mut multiple_used = false; | 275 | let mut multiple_used = false; |
278 | fields.for_each(|(field_id, _data)| { | 276 | fields.for_each(|(field_id, _data)| { |
279 | field_tys[field_id].walk(&mut |ty| match ty { | 277 | field_tys[field_id].value.walk(&mut |ty| match ty { |
280 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | 278 | &Ty::Bound(idx) if idx == unsize_generic_index => multiple_used = true, |
281 | multiple_used = true | ||
282 | } | ||
283 | _ => {} | 279 | _ => {} |
284 | }) | 280 | }) |
285 | }); | 281 | }); |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 31259a01d..3c9c02d03 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, AssocContainerId, Lookup, StructFieldId, | 11 | AdtId, AssocContainerId, Lookup, StructFieldId, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::Name; |
14 | use ra_syntax::ast::RangeOp; | 14 | use ra_syntax::ast::RangeOp; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
@@ -19,8 +19,8 @@ use crate::{ | |||
19 | method_resolution, op, | 19 | method_resolution, op, |
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, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, |
23 | TypeCtor, TypeWalk, Uncertain, | 23 | Ty, TypeCtor, Uncertain, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; |
@@ -236,8 +236,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
236 | self.result.record_field_resolutions.insert(field.expr, field_def); | 236 | self.result.record_field_resolutions.insert(field.expr, field_def); |
237 | } | 237 | } |
238 | let field_ty = field_def | 238 | let field_ty = field_def |
239 | .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) | 239 | .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs)); |
240 | .subst(&substs); | ||
241 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 240 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
242 | } | 241 | } |
243 | if let Some(expr) = spread { | 242 | if let Some(expr) = spread { |
@@ -588,10 +587,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
588 | self.write_method_resolution(tgt_expr, func); | 587 | self.write_method_resolution(tgt_expr, func); |
589 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) | 588 | (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) |
590 | } | 589 | } |
591 | None => (receiver_ty, Ty::Unknown, None), | 590 | None => (receiver_ty, Binders::new(0, Ty::Unknown), None), |
592 | }; | 591 | }; |
593 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | 592 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); |
594 | let method_ty = method_ty.apply_substs(substs); | 593 | let method_ty = method_ty.subst(&substs); |
595 | let method_ty = self.insert_type_vars(method_ty); | 594 | let method_ty = self.insert_type_vars(method_ty); |
596 | self.register_obligations_for_call(&method_ty); | 595 | self.register_obligations_for_call(&method_ty); |
597 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 596 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
@@ -635,7 +634,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
635 | continue; | 634 | continue; |
636 | } | 635 | } |
637 | 636 | ||
638 | let param_ty = self.insert_vars_for_impl_trait(param_ty); | ||
639 | let param_ty = self.normalize_associated_types_in(param_ty); | 637 | let param_ty = self.normalize_associated_types_in(param_ty); |
640 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); | 638 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); |
641 | } | 639 | } |
@@ -648,13 +646,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
648 | generic_args: Option<&GenericArgs>, | 646 | generic_args: Option<&GenericArgs>, |
649 | receiver_ty: &Ty, | 647 | receiver_ty: &Ty, |
650 | ) -> Substs { | 648 | ) -> Substs { |
651 | let (total_len, _parent_len, child_len) = | 649 | let (parent_params, self_params, type_params, impl_trait_params) = |
652 | def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split()); | 650 | def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split()); |
651 | assert_eq!(self_params, 0); // method shouldn't have another Self param | ||
652 | let total_len = parent_params + type_params + impl_trait_params; | ||
653 | let mut substs = Vec::with_capacity(total_len); | 653 | let mut substs = Vec::with_capacity(total_len); |
654 | // Parent arguments are unknown, except for the receiver type | 654 | // Parent arguments are unknown, except for the receiver type |
655 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 655 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { |
656 | for (_id, param) in parent_generics { | 656 | for (_id, param) in parent_generics { |
657 | if param.name == name![Self] { | 657 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
658 | substs.push(receiver_ty.clone()); | 658 | substs.push(receiver_ty.clone()); |
659 | } else { | 659 | } else { |
660 | substs.push(Ty::Unknown); | 660 | substs.push(Ty::Unknown); |
@@ -664,7 +664,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
664 | // handle provided type arguments | 664 | // handle provided type arguments |
665 | if let Some(generic_args) = generic_args { | 665 | if let Some(generic_args) = generic_args { |
666 | // if args are provided, it should be all of them, but we can't rely on that | 666 | // if args are provided, it should be all of them, but we can't rely on that |
667 | for arg in generic_args.args.iter().take(child_len) { | 667 | for arg in generic_args.args.iter().take(type_params) { |
668 | match arg { | 668 | match arg { |
669 | GenericArg::Type(type_ref) => { | 669 | GenericArg::Type(type_ref) => { |
670 | let ty = self.make_ty(type_ref); | 670 | let ty = self.make_ty(type_ref); |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index a14662884..e7283f24c 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -12,7 +12,7 @@ use hir_expand::name::Name; | |||
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use super::{BindingMode, InferenceContext}; | 14 | use super::{BindingMode, InferenceContext}; |
15 | use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}; | 15 | use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor}; |
16 | 16 | ||
17 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 17 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
18 | fn infer_tuple_struct_pat( | 18 | fn infer_tuple_struct_pat( |
@@ -34,8 +34,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
34 | let expected_ty = var_data | 34 | let expected_ty = var_data |
35 | .as_ref() | 35 | .as_ref() |
36 | .and_then(|d| d.field(&Name::new_tuple_field(i))) | 36 | .and_then(|d| d.field(&Name::new_tuple_field(i))) |
37 | .map_or(Ty::Unknown, |field| field_tys[field].clone()) | 37 | .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); |
38 | .subst(&substs); | ||
39 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 38 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
40 | self.infer_pat(subpat, &expected_ty, default_bm); | 39 | self.infer_pat(subpat, &expected_ty, default_bm); |
41 | } | 40 | } |
@@ -65,7 +64,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
65 | for subpat in subpats { | 64 | for subpat in subpats { |
66 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); | 65 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); |
67 | let expected_ty = | 66 | let expected_ty = |
68 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs); | 67 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); |
69 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 68 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
70 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 69 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
71 | } | 70 | } |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 2c1d4831d..686ce7a21 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -9,9 +9,9 @@ use hir_def::{ | |||
9 | }; | 9 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; | 12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, ValueTyDefId}; |
13 | 13 | ||
14 | use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef}; | 14 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
15 | 15 | ||
16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
17 | pub(super) fn infer_path( | 17 | pub(super) fn infer_path( |
@@ -39,7 +39,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
39 | } | 39 | } |
40 | let ty = self.make_ty(type_ref); | 40 | let ty = self.make_ty(type_ref); |
41 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); | 41 | let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); |
42 | let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); | 42 | let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver); |
43 | let ty = Ty::from_type_relative_path(&ctx, ty, remaining_segments_for_ty); | ||
43 | self.resolve_ty_assoc_item( | 44 | self.resolve_ty_assoc_item( |
44 | ty, | 45 | ty, |
45 | &path.segments().last().expect("path had at least one segment").name, | 46 | &path.segments().last().expect("path had at least one segment").name, |
@@ -69,12 +70,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
69 | ValueNs::EnumVariantId(it) => it.into(), | 70 | ValueNs::EnumVariantId(it) => it.into(), |
70 | }; | 71 | }; |
71 | 72 | ||
72 | let mut ty = self.db.value_ty(typable); | 73 | let ty = self.db.value_ty(typable); |
73 | if let Some(self_subst) = self_subst { | 74 | // self_subst is just for the parent |
74 | ty = ty.subst(&self_subst); | 75 | let parent_substs = self_subst.unwrap_or_else(Substs::empty); |
75 | } | 76 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
76 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 77 | let substs = Ty::substs_from_path(&ctx, path, typable); |
77 | let ty = ty.subst(&substs); | 78 | let full_substs = Substs::builder(substs.len()) |
79 | .use_parent_substs(&parent_substs) | ||
80 | .fill(substs.0[parent_substs.len()..].iter().cloned()) | ||
81 | .build(); | ||
82 | let ty = ty.subst(&full_substs); | ||
78 | Some(ty) | 83 | Some(ty) |
79 | } | 84 | } |
80 | 85 | ||
@@ -98,13 +103,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
98 | (TypeNs::TraitId(trait_), true) => { | 103 | (TypeNs::TraitId(trait_), true) => { |
99 | let segment = | 104 | let segment = |
100 | remaining_segments.last().expect("there should be at least one segment here"); | 105 | remaining_segments.last().expect("there should be at least one segment here"); |
101 | let trait_ref = TraitRef::from_resolved_path( | 106 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
102 | self.db, | 107 | let trait_ref = |
103 | &self.resolver, | 108 | TraitRef::from_resolved_path(&ctx, trait_.into(), resolved_segment, None); |
104 | trait_.into(), | ||
105 | resolved_segment, | ||
106 | None, | ||
107 | ); | ||
108 | self.resolve_trait_assoc_item(trait_ref, segment, id) | 109 | self.resolve_trait_assoc_item(trait_ref, segment, id) |
109 | } | 110 | } |
110 | (def, _) => { | 111 | (def, _) => { |
@@ -114,9 +115,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
114 | // as Iterator>::Item::default`) | 115 | // as Iterator>::Item::default`) |
115 | let remaining_segments_for_ty = | 116 | let remaining_segments_for_ty = |
116 | remaining_segments.take(remaining_segments.len() - 1); | 117 | remaining_segments.take(remaining_segments.len() - 1); |
118 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | ||
117 | let ty = Ty::from_partly_resolved_hir_path( | 119 | let ty = Ty::from_partly_resolved_hir_path( |
118 | self.db, | 120 | &ctx, |
119 | &self.resolver, | ||
120 | def, | 121 | def, |
121 | resolved_segment, | 122 | resolved_segment, |
122 | remaining_segments_for_ty, | 123 | remaining_segments_for_ty, |
@@ -173,13 +174,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
173 | AssocItemId::ConstId(c) => ValueNs::ConstId(c), | 174 | AssocItemId::ConstId(c) => ValueNs::ConstId(c), |
174 | AssocItemId::TypeAliasId(_) => unreachable!(), | 175 | AssocItemId::TypeAliasId(_) => unreachable!(), |
175 | }; | 176 | }; |
176 | let substs = Substs::build_for_def(self.db, item) | ||
177 | .use_parent_substs(&trait_ref.substs) | ||
178 | .fill_with_params() | ||
179 | .build(); | ||
180 | 177 | ||
181 | self.write_assoc_resolution(id, item); | 178 | self.write_assoc_resolution(id, item); |
182 | Some((def, Some(substs))) | 179 | Some((def, Some(trait_ref.substs))) |
183 | } | 180 | } |
184 | 181 | ||
185 | fn resolve_ty_assoc_item( | 182 | fn resolve_ty_assoc_item( |
@@ -193,14 +190,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
193 | } | 190 | } |
194 | 191 | ||
195 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); | 192 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
196 | let env = TraitEnvironment::lower(self.db, &self.resolver); | ||
197 | let krate = self.resolver.krate()?; | 193 | let krate = self.resolver.krate()?; |
198 | let traits_in_scope = self.resolver.traits_in_scope(self.db); | 194 | let traits_in_scope = self.resolver.traits_in_scope(self.db); |
199 | 195 | ||
200 | method_resolution::iterate_method_candidates( | 196 | method_resolution::iterate_method_candidates( |
201 | &canonical_ty.value, | 197 | &canonical_ty.value, |
202 | self.db, | 198 | self.db, |
203 | env, | 199 | self.trait_env.clone(), |
204 | krate, | 200 | krate, |
205 | &traits_in_scope, | 201 | &traits_in_scope, |
206 | Some(name), | 202 | Some(name), |
@@ -219,12 +215,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
219 | .fill(iter::repeat_with(|| self.table.new_type_var())) | 215 | .fill(iter::repeat_with(|| self.table.new_type_var())) |
220 | .build(); | 216 | .build(); |
221 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); | 217 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); |
222 | let substs = Substs::build_for_def(self.db, item) | ||
223 | .use_parent_substs(&impl_substs) | ||
224 | .fill_with_params() | ||
225 | .build(); | ||
226 | self.unify(&impl_self_ty, &ty); | 218 | self.unify(&impl_self_ty, &ty); |
227 | Some(substs) | 219 | Some(impl_substs) |
228 | } | 220 | } |
229 | AssocContainerId::TraitId(trait_) => { | 221 | AssocContainerId::TraitId(trait_) => { |
230 | // we're picking this method | 222 | // we're picking this method |
@@ -232,15 +224,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
232 | .push(ty.clone()) | 224 | .push(ty.clone()) |
233 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 225 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
234 | .build(); | 226 | .build(); |
235 | let substs = Substs::build_for_def(self.db, item) | ||
236 | .use_parent_substs(&trait_substs) | ||
237 | .fill_with_params() | ||
238 | .build(); | ||
239 | self.obligations.push(super::Obligation::Trait(TraitRef { | 227 | self.obligations.push(super::Obligation::Trait(TraitRef { |
240 | trait_, | 228 | trait_, |
241 | substs: trait_substs, | 229 | substs: trait_substs.clone(), |
242 | })); | 230 | })); |
243 | Some(substs) | 231 | Some(trait_substs) |
244 | } | 232 | } |
245 | AssocContainerId::ContainerId(_) => None, | 233 | AssocContainerId::ContainerId(_) => None, |
246 | }; | 234 | }; |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 08d501ccd..c5fe18c85 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -44,8 +44,8 @@ use std::sync::Arc; | |||
44 | use std::{fmt, iter, mem}; | 44 | use std::{fmt, iter, mem}; |
45 | 45 | ||
46 | use hir_def::{ | 46 | use hir_def::{ |
47 | expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, | 47 | expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId, |
48 | HasModule, Lookup, TraitId, TypeAliasId, | 48 | DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, |
49 | }; | 49 | }; |
50 | use hir_expand::name::Name; | 50 | use hir_expand::name::Name; |
51 | use ra_db::{impl_intern_key, salsa, CrateId}; | 51 | use ra_db::{impl_intern_key, salsa, CrateId}; |
@@ -60,7 +60,9 @@ use display::{HirDisplay, HirFormatter}; | |||
60 | pub use autoderef::autoderef; | 60 | pub use autoderef::autoderef; |
61 | pub use infer::{do_infer_query, InferTy, InferenceResult}; | 61 | pub use infer::{do_infer_query, InferTy, InferenceResult}; |
62 | pub use lower::CallableDef; | 62 | pub use lower::CallableDef; |
63 | pub use lower::{callable_item_sig, TyDefId, ValueTyDefId}; | 63 | pub use lower::{ |
64 | callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, | ||
65 | }; | ||
64 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 66 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
65 | 67 | ||
66 | /// A type constructor or type name: this might be something like the primitive | 68 | /// A type constructor or type name: this might be something like the primitive |
@@ -285,22 +287,20 @@ pub enum Ty { | |||
285 | /// trait and all its parameters are fully known. | 287 | /// trait and all its parameters are fully known. |
286 | Projection(ProjectionTy), | 288 | Projection(ProjectionTy), |
287 | 289 | ||
288 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | 290 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) |
289 | Param { | 291 | /// {}` when we're type-checking the body of that function. In this |
290 | /// The index of the parameter (starting with parameters from the | 292 | /// situation, we know this stands for *some* type, but don't know the exact |
291 | /// surrounding impl, then the current function). | 293 | /// type. |
292 | idx: u32, | 294 | Param(TypeParamId), |
293 | /// The name of the parameter, for displaying. | 295 | |
294 | // FIXME get rid of this | 296 | /// A bound type variable. This is used in various places: when representing |
295 | name: Name, | 297 | /// some polymorphic type like the type of function `fn f<T>`, the type |
296 | }, | 298 | /// parameters get turned into variables; during trait resolution, inference |
297 | 299 | /// variables get turned into bound variables and back; and in `Dyn` the | |
298 | /// A bound type variable. Used during trait resolution to represent Chalk | 300 | /// `Self` type is represented with a bound variable as well. |
299 | /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. | ||
300 | Bound(u32), | 301 | Bound(u32), |
301 | 302 | ||
302 | /// A type variable used during type checking. Not to be confused with a | 303 | /// A type variable used during type checking. |
303 | /// type parameter. | ||
304 | Infer(InferTy), | 304 | Infer(InferTy), |
305 | 305 | ||
306 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | 306 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). |
@@ -364,15 +364,19 @@ impl Substs { | |||
364 | } | 364 | } |
365 | 365 | ||
366 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | 366 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). |
367 | pub(crate) fn identity(generic_params: &Generics) -> Substs { | 367 | pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs { |
368 | Substs( | 368 | Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect()) |
369 | generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(), | 369 | } |
370 | ) | 370 | |
371 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
372 | pub fn type_params(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> Substs { | ||
373 | let params = generics(db, def.into()); | ||
374 | Substs::type_params_for_generics(¶ms) | ||
371 | } | 375 | } |
372 | 376 | ||
373 | /// Return Substs that replace each parameter by a bound variable. | 377 | /// Return Substs that replace each parameter by a bound variable. |
374 | pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { | 378 | pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { |
375 | Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect()) | 379 | Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect()) |
376 | } | 380 | } |
377 | 381 | ||
378 | pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { | 382 | pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { |
@@ -420,11 +424,6 @@ impl SubstsBuilder { | |||
420 | self.fill((starting_from..).map(Ty::Bound)) | 424 | self.fill((starting_from..).map(Ty::Bound)) |
421 | } | 425 | } |
422 | 426 | ||
423 | pub fn fill_with_params(self) -> Self { | ||
424 | let start = self.vec.len() as u32; | ||
425 | self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() })) | ||
426 | } | ||
427 | |||
428 | pub fn fill_with_unknown(self) -> Self { | 427 | pub fn fill_with_unknown(self) -> Self { |
429 | self.fill(iter::repeat(Ty::Unknown)) | 428 | self.fill(iter::repeat(Ty::Unknown)) |
430 | } | 429 | } |
@@ -451,6 +450,32 @@ impl Deref for Substs { | |||
451 | } | 450 | } |
452 | } | 451 | } |
453 | 452 | ||
453 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
454 | pub struct Binders<T> { | ||
455 | pub num_binders: usize, | ||
456 | pub value: T, | ||
457 | } | ||
458 | |||
459 | impl<T> Binders<T> { | ||
460 | pub fn new(num_binders: usize, value: T) -> Self { | ||
461 | Self { num_binders, value } | ||
462 | } | ||
463 | } | ||
464 | |||
465 | impl<T: TypeWalk> Binders<T> { | ||
466 | /// Substitutes all variables. | ||
467 | pub fn subst(self, subst: &Substs) -> T { | ||
468 | assert_eq!(subst.len(), self.num_binders); | ||
469 | self.value.subst_bound_vars(subst) | ||
470 | } | ||
471 | |||
472 | /// Substitutes just a prefix of the variables (shifting the rest). | ||
473 | pub fn subst_prefix(self, subst: &Substs) -> Binders<T> { | ||
474 | assert!(subst.len() < self.num_binders); | ||
475 | Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) | ||
476 | } | ||
477 | } | ||
478 | |||
454 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 479 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
455 | /// Name to be bikeshedded: TraitBound? TraitImplements? | 480 | /// Name to be bikeshedded: TraitBound? TraitImplements? |
456 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 481 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -551,6 +576,9 @@ pub struct FnSig { | |||
551 | params_and_return: Arc<[Ty]>, | 576 | params_and_return: Arc<[Ty]>, |
552 | } | 577 | } |
553 | 578 | ||
579 | /// A polymorphic function signature. | ||
580 | pub type PolyFnSig = Binders<FnSig>; | ||
581 | |||
554 | impl FnSig { | 582 | impl FnSig { |
555 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { | 583 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { |
556 | params.push(ret); | 584 | params.push(ret); |
@@ -730,22 +758,7 @@ pub trait TypeWalk { | |||
730 | self | 758 | self |
731 | } | 759 | } |
732 | 760 | ||
733 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. | 761 | /// Substitutes `Ty::Bound` vars with the given substitution. |
734 | /// if `self` is `&[T]`, where type parameter T has index 0, and the | ||
735 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | ||
736 | fn subst(self, substs: &Substs) -> Self | ||
737 | where | ||
738 | Self: Sized, | ||
739 | { | ||
740 | self.fold(&mut |ty| match ty { | ||
741 | Ty::Param { idx, name } => { | ||
742 | substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) | ||
743 | } | ||
744 | ty => ty, | ||
745 | }) | ||
746 | } | ||
747 | |||
748 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | ||
749 | fn subst_bound_vars(mut self, substs: &Substs) -> Self | 762 | fn subst_bound_vars(mut self, substs: &Substs) -> Self |
750 | where | 763 | where |
751 | Self: Sized, | 764 | Self: Sized, |
@@ -755,6 +768,9 @@ pub trait TypeWalk { | |||
755 | &mut Ty::Bound(idx) => { | 768 | &mut Ty::Bound(idx) => { |
756 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { | 769 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
757 | *ty = substs.0[idx as usize - binders].clone(); | 770 | *ty = substs.0[idx as usize - binders].clone(); |
771 | } else if idx as usize >= binders + substs.len() { | ||
772 | // shift free binders | ||
773 | *ty = Ty::Bound(idx - substs.len() as u32); | ||
758 | } | 774 | } |
759 | } | 775 | } |
760 | _ => {} | 776 | _ => {} |
@@ -880,7 +896,7 @@ impl HirDisplay for ApplicationTy { | |||
880 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 896 | write!(f, ") -> {}", sig.ret().display(f.db))?; |
881 | } | 897 | } |
882 | TypeCtor::FnDef(def) => { | 898 | TypeCtor::FnDef(def) => { |
883 | let sig = f.db.callable_item_signature(def); | 899 | let sig = f.db.callable_item_signature(def).subst(&self.parameters); |
884 | let name = match def { | 900 | let name = match def { |
885 | CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), | 901 | CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), |
886 | CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), | 902 | CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), |
@@ -896,9 +912,16 @@ impl HirDisplay for ApplicationTy { | |||
896 | } | 912 | } |
897 | } | 913 | } |
898 | if self.parameters.len() > 0 { | 914 | if self.parameters.len() > 0 { |
899 | write!(f, "<")?; | 915 | let generics = generics(f.db, def.into()); |
900 | f.write_joined(&*self.parameters.0, ", ")?; | 916 | let (parent_params, self_param, type_params, _impl_trait_params) = |
901 | write!(f, ">")?; | 917 | generics.provenance_split(); |
918 | let total_len = parent_params + self_param + type_params; | ||
919 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | ||
920 | if total_len > 0 { | ||
921 | write!(f, "<")?; | ||
922 | f.write_joined(&self.parameters.0[..total_len], ", ")?; | ||
923 | write!(f, ">")?; | ||
924 | } | ||
902 | } | 925 | } |
903 | write!(f, "(")?; | 926 | write!(f, "(")?; |
904 | f.write_joined(sig.params(), ", ")?; | 927 | f.write_joined(sig.params(), ", ")?; |
@@ -1009,7 +1032,24 @@ impl HirDisplay for Ty { | |||
1009 | match self { | 1032 | match self { |
1010 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | 1033 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, |
1011 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, | 1034 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, |
1012 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 1035 | Ty::Param(id) => { |
1036 | let generics = generics(f.db, id.parent); | ||
1037 | let param_data = &generics.params.types[id.local_id]; | ||
1038 | match param_data.provenance { | ||
1039 | TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { | ||
1040 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | ||
1041 | } | ||
1042 | TypeParamProvenance::ArgumentImplTrait => { | ||
1043 | write!(f, "impl ")?; | ||
1044 | let bounds = f.db.generic_predicates_for_param(*id); | ||
1045 | let substs = Substs::type_params_for_generics(&generics); | ||
1046 | write_bounds_like_dyn_trait( | ||
1047 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | ||
1048 | f, | ||
1049 | )?; | ||
1050 | } | ||
1051 | } | ||
1052 | } | ||
1013 | Ty::Bound(idx) => write!(f, "?{}", idx)?, | 1053 | Ty::Bound(idx) => write!(f, "?{}", idx)?, |
1014 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 1054 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
1015 | match self { | 1055 | match self { |
@@ -1017,66 +1057,7 @@ impl HirDisplay for Ty { | |||
1017 | Ty::Opaque(_) => write!(f, "impl ")?, | 1057 | Ty::Opaque(_) => write!(f, "impl ")?, |
1018 | _ => unreachable!(), | 1058 | _ => unreachable!(), |
1019 | }; | 1059 | }; |
1020 | // Note: This code is written to produce nice results (i.e. | 1060 | write_bounds_like_dyn_trait(&predicates, f)?; |
1021 | // corresponding to surface Rust) for types that can occur in | ||
1022 | // actual Rust. It will have weird results if the predicates | ||
1023 | // aren't as expected (i.e. self types = $0, projection | ||
1024 | // predicates for a certain trait come after the Implemented | ||
1025 | // predicate for that trait). | ||
1026 | let mut first = true; | ||
1027 | let mut angle_open = false; | ||
1028 | for p in predicates.iter() { | ||
1029 | match p { | ||
1030 | GenericPredicate::Implemented(trait_ref) => { | ||
1031 | if angle_open { | ||
1032 | write!(f, ">")?; | ||
1033 | } | ||
1034 | if !first { | ||
1035 | write!(f, " + ")?; | ||
1036 | } | ||
1037 | // We assume that the self type is $0 (i.e. the | ||
1038 | // existential) here, which is the only thing that's | ||
1039 | // possible in actual Rust, and hence don't print it | ||
1040 | write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; | ||
1041 | if trait_ref.substs.len() > 1 { | ||
1042 | write!(f, "<")?; | ||
1043 | f.write_joined(&trait_ref.substs[1..], ", ")?; | ||
1044 | // there might be assoc type bindings, so we leave the angle brackets open | ||
1045 | angle_open = true; | ||
1046 | } | ||
1047 | } | ||
1048 | GenericPredicate::Projection(projection_pred) => { | ||
1049 | // in types in actual Rust, these will always come | ||
1050 | // after the corresponding Implemented predicate | ||
1051 | if angle_open { | ||
1052 | write!(f, ", ")?; | ||
1053 | } else { | ||
1054 | write!(f, "<")?; | ||
1055 | angle_open = true; | ||
1056 | } | ||
1057 | let name = | ||
1058 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty) | ||
1059 | .name | ||
1060 | .clone(); | ||
1061 | write!(f, "{} = ", name)?; | ||
1062 | projection_pred.ty.hir_fmt(f)?; | ||
1063 | } | ||
1064 | GenericPredicate::Error => { | ||
1065 | if angle_open { | ||
1066 | // impl Trait<X, {error}> | ||
1067 | write!(f, ", ")?; | ||
1068 | } else if !first { | ||
1069 | // impl Trait + {error} | ||
1070 | write!(f, " + ")?; | ||
1071 | } | ||
1072 | p.hir_fmt(f)?; | ||
1073 | } | ||
1074 | } | ||
1075 | first = false; | ||
1076 | } | ||
1077 | if angle_open { | ||
1078 | write!(f, ">")?; | ||
1079 | } | ||
1080 | } | 1061 | } |
1081 | Ty::Unknown => write!(f, "{{unknown}}")?, | 1062 | Ty::Unknown => write!(f, "{{unknown}}")?, |
1082 | Ty::Infer(..) => write!(f, "_")?, | 1063 | Ty::Infer(..) => write!(f, "_")?, |
@@ -1085,6 +1066,71 @@ impl HirDisplay for Ty { | |||
1085 | } | 1066 | } |
1086 | } | 1067 | } |
1087 | 1068 | ||
1069 | fn write_bounds_like_dyn_trait( | ||
1070 | predicates: &[GenericPredicate], | ||
1071 | f: &mut HirFormatter<impl HirDatabase>, | ||
1072 | ) -> fmt::Result { | ||
1073 | // Note: This code is written to produce nice results (i.e. | ||
1074 | // corresponding to surface Rust) for types that can occur in | ||
1075 | // actual Rust. It will have weird results if the predicates | ||
1076 | // aren't as expected (i.e. self types = $0, projection | ||
1077 | // predicates for a certain trait come after the Implemented | ||
1078 | // predicate for that trait). | ||
1079 | let mut first = true; | ||
1080 | let mut angle_open = false; | ||
1081 | for p in predicates.iter() { | ||
1082 | match p { | ||
1083 | GenericPredicate::Implemented(trait_ref) => { | ||
1084 | if angle_open { | ||
1085 | write!(f, ">")?; | ||
1086 | } | ||
1087 | if !first { | ||
1088 | write!(f, " + ")?; | ||
1089 | } | ||
1090 | // We assume that the self type is $0 (i.e. the | ||
1091 | // existential) here, which is the only thing that's | ||
1092 | // possible in actual Rust, and hence don't print it | ||
1093 | write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; | ||
1094 | if trait_ref.substs.len() > 1 { | ||
1095 | write!(f, "<")?; | ||
1096 | f.write_joined(&trait_ref.substs[1..], ", ")?; | ||
1097 | // there might be assoc type bindings, so we leave the angle brackets open | ||
1098 | angle_open = true; | ||
1099 | } | ||
1100 | } | ||
1101 | GenericPredicate::Projection(projection_pred) => { | ||
1102 | // in types in actual Rust, these will always come | ||
1103 | // after the corresponding Implemented predicate | ||
1104 | if angle_open { | ||
1105 | write!(f, ", ")?; | ||
1106 | } else { | ||
1107 | write!(f, "<")?; | ||
1108 | angle_open = true; | ||
1109 | } | ||
1110 | let name = | ||
1111 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name.clone(); | ||
1112 | write!(f, "{} = ", name)?; | ||
1113 | projection_pred.ty.hir_fmt(f)?; | ||
1114 | } | ||
1115 | GenericPredicate::Error => { | ||
1116 | if angle_open { | ||
1117 | // impl Trait<X, {error}> | ||
1118 | write!(f, ", ")?; | ||
1119 | } else if !first { | ||
1120 | // impl Trait + {error} | ||
1121 | write!(f, " + ")?; | ||
1122 | } | ||
1123 | p.hir_fmt(f)?; | ||
1124 | } | ||
1125 | } | ||
1126 | first = false; | ||
1127 | } | ||
1128 | if angle_open { | ||
1129 | write!(f, ">")?; | ||
1130 | } | ||
1131 | Ok(()) | ||
1132 | } | ||
1133 | |||
1088 | impl TraitRef { | 1134 | impl TraitRef { |
1089 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { | 1135 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { |
1090 | if f.should_truncate() { | 1136 | if f.should_truncate() { |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 2c2ecee9c..c68c5852b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -10,12 +10,13 @@ use std::sync::Arc; | |||
10 | 10 | ||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | builtin_type::BuiltinType, | 12 | builtin_type::BuiltinType, |
13 | generics::WherePredicate, | 13 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, |
14 | path::{GenericArg, Path, PathSegment, PathSegments}, | 14 | path::{GenericArg, Path, PathSegment, PathSegments}, |
15 | resolver::{HasResolver, Resolver, TypeNs}, | 15 | resolver::{HasResolver, Resolver, TypeNs}, |
16 | type_ref::{TypeBound, TypeRef}, | 16 | type_ref::{TypeBound, TypeRef}, |
17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, | 17 | AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, |
18 | LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 18 | LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, |
19 | VariantId, | ||
19 | }; | 20 | }; |
20 | use ra_arena::map::ArenaMap; | 21 | use ra_arena::map::ArenaMap; |
21 | use ra_db::CrateId; | 22 | use ra_db::CrateId; |
@@ -27,63 +28,158 @@ use crate::{ | |||
27 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, | 28 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, |
28 | variant_data, | 29 | variant_data, |
29 | }, | 30 | }, |
30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | 31 | Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, |
31 | Ty, TypeCtor, TypeWalk, | 32 | TraitEnvironment, TraitRef, Ty, TypeCtor, |
32 | }; | 33 | }; |
33 | 34 | ||
35 | #[derive(Debug)] | ||
36 | pub struct TyLoweringContext<'a, DB: HirDatabase> { | ||
37 | pub db: &'a DB, | ||
38 | pub resolver: &'a Resolver, | ||
39 | /// Note: Conceptually, it's thinkable that we could be in a location where | ||
40 | /// some type params should be represented as placeholders, and others | ||
41 | /// should be converted to variables. I think in practice, this isn't | ||
42 | /// possible currently, so this should be fine for now. | ||
43 | pub type_param_mode: TypeParamLoweringMode, | ||
44 | pub impl_trait_mode: ImplTraitLoweringMode, | ||
45 | pub impl_trait_counter: std::cell::Cell<u16>, | ||
46 | } | ||
47 | |||
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, PartialEq, Eq)] | ||
66 | pub enum ImplTraitLoweringMode { | ||
67 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with | ||
68 | /// anything except itself. This is used in places where values flow 'out', | ||
69 | /// i.e. for arguments of the function we're currently checking, and return | ||
70 | /// types of functions we're calling. | ||
71 | Opaque, | ||
72 | /// `impl Trait` gets lowered into a type variable. Used for argument | ||
73 | /// position impl Trait when inside the respective function, since it allows | ||
74 | /// us to support that without Chalk. | ||
75 | Param, | ||
76 | /// `impl Trait` gets lowered into a variable that can unify with some | ||
77 | /// type. This is used in places where values flow 'in', i.e. for arguments | ||
78 | /// of functions we're calling, and the return type of the function we're | ||
79 | /// currently checking. | ||
80 | Variable, | ||
81 | /// `impl Trait` is disallowed and will be an error. | ||
82 | Disallowed, | ||
83 | } | ||
84 | |||
85 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
86 | pub enum TypeParamLoweringMode { | ||
87 | Placeholder, | ||
88 | Variable, | ||
89 | } | ||
90 | |||
34 | impl Ty { | 91 | impl Ty { |
35 | pub fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 92 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { |
36 | match type_ref { | 93 | match type_ref { |
37 | TypeRef::Never => Ty::simple(TypeCtor::Never), | 94 | TypeRef::Never => Ty::simple(TypeCtor::Never), |
38 | TypeRef::Tuple(inner) => { | 95 | TypeRef::Tuple(inner) => { |
39 | let inner_tys: Arc<[Ty]> = | 96 | let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); |
40 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect(); | ||
41 | Ty::apply( | 97 | Ty::apply( |
42 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | 98 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, |
43 | Substs(inner_tys), | 99 | Substs(inner_tys), |
44 | ) | 100 | ) |
45 | } | 101 | } |
46 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | 102 | TypeRef::Path(path) => Ty::from_hir_path(ctx, path), |
47 | TypeRef::RawPtr(inner, mutability) => { | 103 | TypeRef::RawPtr(inner, mutability) => { |
48 | let inner_ty = Ty::from_hir(db, resolver, inner); | 104 | let inner_ty = Ty::from_hir(ctx, inner); |
49 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) | 105 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) |
50 | } | 106 | } |
51 | TypeRef::Array(inner) => { | 107 | TypeRef::Array(inner) => { |
52 | let inner_ty = Ty::from_hir(db, resolver, inner); | 108 | let inner_ty = Ty::from_hir(ctx, inner); |
53 | Ty::apply_one(TypeCtor::Array, inner_ty) | 109 | Ty::apply_one(TypeCtor::Array, inner_ty) |
54 | } | 110 | } |
55 | TypeRef::Slice(inner) => { | 111 | TypeRef::Slice(inner) => { |
56 | let inner_ty = Ty::from_hir(db, resolver, inner); | 112 | let inner_ty = Ty::from_hir(ctx, inner); |
57 | Ty::apply_one(TypeCtor::Slice, inner_ty) | 113 | Ty::apply_one(TypeCtor::Slice, inner_ty) |
58 | } | 114 | } |
59 | TypeRef::Reference(inner, mutability) => { | 115 | TypeRef::Reference(inner, mutability) => { |
60 | let inner_ty = Ty::from_hir(db, resolver, inner); | 116 | let inner_ty = Ty::from_hir(ctx, inner); |
61 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 117 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
62 | } | 118 | } |
63 | TypeRef::Placeholder => Ty::Unknown, | 119 | TypeRef::Placeholder => Ty::Unknown, |
64 | TypeRef::Fn(params) => { | 120 | TypeRef::Fn(params) => { |
65 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect()); | 121 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); |
66 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) | 122 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) |
67 | } | 123 | } |
68 | TypeRef::DynTrait(bounds) => { | 124 | TypeRef::DynTrait(bounds) => { |
69 | let self_ty = Ty::Bound(0); | 125 | let self_ty = Ty::Bound(0); |
70 | let predicates = bounds | 126 | let predicates = bounds |
71 | .iter() | 127 | .iter() |
72 | .flat_map(|b| { | 128 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) |
73 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
74 | }) | ||
75 | .collect(); | 129 | .collect(); |
76 | Ty::Dyn(predicates) | 130 | Ty::Dyn(predicates) |
77 | } | 131 | } |
78 | TypeRef::ImplTrait(bounds) => { | 132 | TypeRef::ImplTrait(bounds) => { |
79 | let self_ty = Ty::Bound(0); | 133 | match ctx.impl_trait_mode { |
80 | let predicates = bounds | 134 | ImplTraitLoweringMode::Opaque => { |
81 | .iter() | 135 | let self_ty = Ty::Bound(0); |
82 | .flat_map(|b| { | 136 | let predicates = bounds |
83 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | 137 | .iter() |
84 | }) | 138 | .flat_map(|b| { |
85 | .collect(); | 139 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) |
86 | Ty::Opaque(predicates) | 140 | }) |
141 | .collect(); | ||
142 | Ty::Opaque(predicates) | ||
143 | } | ||
144 | ImplTraitLoweringMode::Param => { | ||
145 | let idx = ctx.impl_trait_counter.get(); | ||
146 | ctx.impl_trait_counter.set(idx + 1); | ||
147 | if let Some(def) = ctx.resolver.generic_def() { | ||
148 | let generics = generics(ctx.db, def); | ||
149 | let param = generics | ||
150 | .iter() | ||
151 | .filter(|(_, data)| { | ||
152 | data.provenance == TypeParamProvenance::ArgumentImplTrait | ||
153 | }) | ||
154 | .nth(idx as usize) | ||
155 | .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); | ||
156 | param | ||
157 | } else { | ||
158 | Ty::Unknown | ||
159 | } | ||
160 | } | ||
161 | ImplTraitLoweringMode::Variable => { | ||
162 | let idx = ctx.impl_trait_counter.get(); | ||
163 | ctx.impl_trait_counter.set(idx + 1); | ||
164 | let (parent_params, self_params, list_params, _impl_trait_params) = | ||
165 | if let Some(def) = ctx.resolver.generic_def() { | ||
166 | let generics = generics(ctx.db, def); | ||
167 | generics.provenance_split() | ||
168 | } else { | ||
169 | (0, 0, 0, 0) | ||
170 | }; | ||
171 | Ty::Bound( | ||
172 | idx as u32 | ||
173 | + parent_params as u32 | ||
174 | + self_params as u32 | ||
175 | + list_params as u32, | ||
176 | ) | ||
177 | } | ||
178 | ImplTraitLoweringMode::Disallowed => { | ||
179 | // FIXME: report error | ||
180 | Ty::Unknown | ||
181 | } | ||
182 | } | ||
87 | } | 183 | } |
88 | TypeRef::Error => Ty::Unknown, | 184 | TypeRef::Error => Ty::Unknown, |
89 | } | 185 | } |
@@ -93,10 +189,9 @@ impl Ty { | |||
93 | /// lower the self types of the predicates since that could lead to cycles. | 189 | /// lower the self types of the predicates since that could lead to cycles. |
94 | /// So we just check here if the `type_ref` resolves to a generic param, and which. | 190 | /// So we just check here if the `type_ref` resolves to a generic param, and which. |
95 | fn from_hir_only_param( | 191 | fn from_hir_only_param( |
96 | db: &impl HirDatabase, | 192 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
97 | resolver: &Resolver, | ||
98 | type_ref: &TypeRef, | 193 | type_ref: &TypeRef, |
99 | ) -> Option<u32> { | 194 | ) -> Option<TypeParamId> { |
100 | let path = match type_ref { | 195 | let path = match type_ref { |
101 | TypeRef::Path(path) => path, | 196 | TypeRef::Path(path) => path, |
102 | _ => return None, | 197 | _ => return None, |
@@ -107,29 +202,26 @@ impl Ty { | |||
107 | if path.segments().len() > 1 { | 202 | if path.segments().len() > 1 { |
108 | return None; | 203 | return None; |
109 | } | 204 | } |
110 | let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) { | 205 | let resolution = match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { |
111 | Some((it, None)) => it, | 206 | Some((it, None)) => it, |
112 | _ => return None, | 207 | _ => return None, |
113 | }; | 208 | }; |
114 | if let TypeNs::GenericParam(param_id) = resolution { | 209 | if let TypeNs::GenericParam(param_id) = resolution { |
115 | let generics = generics(db, resolver.generic_def().expect("generics in scope")); | 210 | Some(param_id) |
116 | let idx = generics.param_idx(param_id); | ||
117 | Some(idx) | ||
118 | } else { | 211 | } else { |
119 | None | 212 | None |
120 | } | 213 | } |
121 | } | 214 | } |
122 | 215 | ||
123 | pub(crate) fn from_type_relative_path( | 216 | pub(crate) fn from_type_relative_path( |
124 | db: &impl HirDatabase, | 217 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
125 | resolver: &Resolver, | ||
126 | ty: Ty, | 218 | ty: Ty, |
127 | remaining_segments: PathSegments<'_>, | 219 | remaining_segments: PathSegments<'_>, |
128 | ) -> Ty { | 220 | ) -> Ty { |
129 | if remaining_segments.len() == 1 { | 221 | if remaining_segments.len() == 1 { |
130 | // resolve unselected assoc types | 222 | // resolve unselected assoc types |
131 | let segment = remaining_segments.first().unwrap(); | 223 | let segment = remaining_segments.first().unwrap(); |
132 | Ty::select_associated_type(db, resolver, ty, segment) | 224 | Ty::select_associated_type(ctx, ty, segment) |
133 | } else if remaining_segments.len() > 1 { | 225 | } else if remaining_segments.len() > 1 { |
134 | // FIXME report error (ambiguous associated type) | 226 | // FIXME report error (ambiguous associated type) |
135 | Ty::Unknown | 227 | Ty::Unknown |
@@ -139,20 +231,18 @@ impl Ty { | |||
139 | } | 231 | } |
140 | 232 | ||
141 | pub(crate) fn from_partly_resolved_hir_path( | 233 | pub(crate) fn from_partly_resolved_hir_path( |
142 | db: &impl HirDatabase, | 234 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
143 | resolver: &Resolver, | ||
144 | resolution: TypeNs, | 235 | resolution: TypeNs, |
145 | resolved_segment: PathSegment<'_>, | 236 | resolved_segment: PathSegment<'_>, |
146 | remaining_segments: PathSegments<'_>, | 237 | remaining_segments: PathSegments<'_>, |
147 | ) -> Ty { | 238 | ) -> Ty { |
148 | let ty = match resolution { | 239 | let ty = match resolution { |
149 | TypeNs::TraitId(trait_) => { | 240 | TypeNs::TraitId(trait_) => { |
150 | let trait_ref = | 241 | let trait_ref = TraitRef::from_resolved_path(ctx, trait_, resolved_segment, None); |
151 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); | ||
152 | return if remaining_segments.len() == 1 { | 242 | return if remaining_segments.len() == 1 { |
153 | let segment = remaining_segments.first().unwrap(); | 243 | let segment = remaining_segments.first().unwrap(); |
154 | let associated_ty = associated_type_by_name_including_super_traits( | 244 | let associated_ty = associated_type_by_name_including_super_traits( |
155 | db, | 245 | ctx.db, |
156 | trait_ref.trait_, | 246 | trait_ref.trait_, |
157 | &segment.name, | 247 | &segment.name, |
158 | ); | 248 | ); |
@@ -177,37 +267,55 @@ impl Ty { | |||
177 | }; | 267 | }; |
178 | } | 268 | } |
179 | TypeNs::GenericParam(param_id) => { | 269 | TypeNs::GenericParam(param_id) => { |
180 | let generics = generics(db, resolver.generic_def().expect("generics in scope")); | 270 | let generics = |
181 | let idx = generics.param_idx(param_id); | 271 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); |
182 | // FIXME: maybe return name in resolution? | 272 | match ctx.type_param_mode { |
183 | let name = generics.param_name(param_id); | 273 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), |
184 | Ty::Param { idx, name } | 274 | TypeParamLoweringMode::Variable => { |
275 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
276 | Ty::Bound(idx) | ||
277 | } | ||
278 | } | ||
185 | } | 279 | } |
186 | TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), | 280 | TypeNs::SelfType(impl_id) => { |
187 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), | 281 | let generics = generics(ctx.db, impl_id.into()); |
188 | 282 | let substs = match ctx.type_param_mode { | |
189 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), | 283 | TypeParamLoweringMode::Placeholder => { |
190 | TypeNs::BuiltinType(it) => { | 284 | Substs::type_params_for_generics(&generics) |
191 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | 285 | } |
286 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
287 | }; | ||
288 | ctx.db.impl_self_ty(impl_id).subst(&substs) | ||
192 | } | 289 | } |
193 | TypeNs::TypeAliasId(it) => { | 290 | TypeNs::AdtSelfType(adt) => { |
194 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | 291 | let generics = generics(ctx.db, adt.into()); |
292 | let substs = match ctx.type_param_mode { | ||
293 | TypeParamLoweringMode::Placeholder => { | ||
294 | Substs::type_params_for_generics(&generics) | ||
295 | } | ||
296 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | ||
297 | }; | ||
298 | ctx.db.ty(adt.into()).subst(&substs) | ||
195 | } | 299 | } |
300 | |||
301 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
302 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
303 | TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | ||
196 | // FIXME: report error | 304 | // FIXME: report error |
197 | TypeNs::EnumVariantId(_) => return Ty::Unknown, | 305 | TypeNs::EnumVariantId(_) => return Ty::Unknown, |
198 | }; | 306 | }; |
199 | 307 | ||
200 | Ty::from_type_relative_path(db, resolver, ty, remaining_segments) | 308 | Ty::from_type_relative_path(ctx, ty, remaining_segments) |
201 | } | 309 | } |
202 | 310 | ||
203 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { | 311 | pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path) -> Ty { |
204 | // Resolve the path (in type namespace) | 312 | // Resolve the path (in type namespace) |
205 | if let Some(type_ref) = path.type_anchor() { | 313 | if let Some(type_ref) = path.type_anchor() { |
206 | let ty = Ty::from_hir(db, resolver, &type_ref); | 314 | let ty = Ty::from_hir(ctx, &type_ref); |
207 | return Ty::from_type_relative_path(db, resolver, ty, path.segments()); | 315 | return Ty::from_type_relative_path(ctx, ty, path.segments()); |
208 | } | 316 | } |
209 | let (resolution, remaining_index) = | 317 | let (resolution, remaining_index) = |
210 | match resolver.resolve_path_in_type_ns(db, path.mod_path()) { | 318 | match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { |
211 | Some(it) => it, | 319 | Some(it) => it, |
212 | None => return Ty::Unknown, | 320 | None => return Ty::Unknown, |
213 | }; | 321 | }; |
@@ -218,39 +326,44 @@ impl Ty { | |||
218 | ), | 326 | ), |
219 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), | 327 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), |
220 | }; | 328 | }; |
221 | Ty::from_partly_resolved_hir_path( | 329 | Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) |
222 | db, | ||
223 | resolver, | ||
224 | resolution, | ||
225 | resolved_segment, | ||
226 | remaining_segments, | ||
227 | ) | ||
228 | } | 330 | } |
229 | 331 | ||
230 | fn select_associated_type( | 332 | fn select_associated_type( |
231 | db: &impl HirDatabase, | 333 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
232 | resolver: &Resolver, | ||
233 | self_ty: Ty, | 334 | self_ty: Ty, |
234 | segment: PathSegment<'_>, | 335 | segment: PathSegment<'_>, |
235 | ) -> Ty { | 336 | ) -> Ty { |
236 | let param_idx = match self_ty { | 337 | let def = match ctx.resolver.generic_def() { |
237 | Ty::Param { idx, .. } => idx, | ||
238 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
239 | }; | ||
240 | let def = match resolver.generic_def() { | ||
241 | Some(def) => def, | 338 | Some(def) => def, |
242 | None => return Ty::Unknown, // this can't actually happen | 339 | None => return Ty::Unknown, // this can't actually happen |
243 | }; | 340 | }; |
244 | let predicates = db.generic_predicates_for_param(def.into(), param_idx); | 341 | let param_id = match self_ty { |
245 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { | 342 | Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id, |
246 | GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), | 343 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => { |
344 | let generics = generics(ctx.db, def); | ||
345 | let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) { | ||
346 | id | ||
347 | } else { | ||
348 | return Ty::Unknown; | ||
349 | }; | ||
350 | param_id | ||
351 | } | ||
352 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
353 | }; | ||
354 | let predicates = ctx.db.generic_predicates_for_param(param_id); | ||
355 | let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value { | ||
356 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
247 | _ => None, | 357 | _ => None, |
248 | }); | 358 | }); |
249 | let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)); | 359 | let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); |
250 | for t in traits { | 360 | for t in traits { |
251 | if let Some(associated_ty) = db.trait_data(t).associated_type_by_name(&segment.name) { | 361 | if let Some(associated_ty) = ctx.db.trait_data(t).associated_type_by_name(&segment.name) |
252 | let substs = | 362 | { |
253 | Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); | 363 | let substs = Substs::build_for_def(ctx.db, t) |
364 | .push(self_ty.clone()) | ||
365 | .fill_with_unknown() | ||
366 | .build(); | ||
254 | // FIXME handle type parameters on the segment | 367 | // FIXME handle type parameters on the segment |
255 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); | 368 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); |
256 | } | 369 | } |
@@ -259,8 +372,7 @@ impl Ty { | |||
259 | } | 372 | } |
260 | 373 | ||
261 | fn from_hir_path_inner( | 374 | fn from_hir_path_inner( |
262 | db: &impl HirDatabase, | 375 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
263 | resolver: &Resolver, | ||
264 | segment: PathSegment<'_>, | 376 | segment: PathSegment<'_>, |
265 | typable: TyDefId, | 377 | typable: TyDefId, |
266 | ) -> Ty { | 378 | ) -> Ty { |
@@ -269,15 +381,14 @@ impl Ty { | |||
269 | TyDefId::AdtId(it) => Some(it.into()), | 381 | TyDefId::AdtId(it) => Some(it.into()), |
270 | TyDefId::TypeAliasId(it) => Some(it.into()), | 382 | TyDefId::TypeAliasId(it) => Some(it.into()), |
271 | }; | 383 | }; |
272 | let substs = substs_from_path_segment(db, resolver, segment, generic_def, false); | 384 | let substs = substs_from_path_segment(ctx, segment, generic_def, false); |
273 | db.ty(typable).subst(&substs) | 385 | ctx.db.ty(typable).subst(&substs) |
274 | } | 386 | } |
275 | 387 | ||
276 | /// Collect generic arguments from a path into a `Substs`. See also | 388 | /// Collect generic arguments from a path into a `Substs`. See also |
277 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | 389 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. |
278 | pub(super) fn substs_from_path( | 390 | pub(super) fn substs_from_path( |
279 | db: &impl HirDatabase, | 391 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
280 | resolver: &Resolver, | ||
281 | path: &Path, | 392 | path: &Path, |
282 | // Note that we don't call `db.value_type(resolved)` here, | 393 | // Note that we don't call `db.value_type(resolved)` here, |
283 | // `ValueTyDefId` is just a convenient way to pass generics and | 394 | // `ValueTyDefId` is just a convenient way to pass generics and |
@@ -305,52 +416,49 @@ impl Ty { | |||
305 | (segment, Some(var.parent.into())) | 416 | (segment, Some(var.parent.into())) |
306 | } | 417 | } |
307 | }; | 418 | }; |
308 | substs_from_path_segment(db, resolver, segment, generic_def, false) | 419 | substs_from_path_segment(ctx, segment, generic_def, false) |
309 | } | 420 | } |
310 | } | 421 | } |
311 | 422 | ||
312 | pub(super) fn substs_from_path_segment( | 423 | pub(super) fn substs_from_path_segment( |
313 | db: &impl HirDatabase, | 424 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
314 | resolver: &Resolver, | ||
315 | segment: PathSegment<'_>, | 425 | segment: PathSegment<'_>, |
316 | def_generic: Option<GenericDefId>, | 426 | def_generic: Option<GenericDefId>, |
317 | add_self_param: bool, | 427 | _add_self_param: bool, |
318 | ) -> Substs { | 428 | ) -> Substs { |
319 | let mut substs = Vec::new(); | 429 | let mut substs = Vec::new(); |
320 | let def_generics = def_generic.map(|def| generics(db, def.into())); | 430 | let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); |
321 | 431 | ||
322 | let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split()); | 432 | let (parent_params, self_params, type_params, impl_trait_params) = |
323 | substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); | 433 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); |
324 | if add_self_param { | 434 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
325 | // FIXME this add_self_param argument is kind of a hack: Traits have the | ||
326 | // Self type as an implicit first type parameter, but it can't be | ||
327 | // actually provided in the type arguments | ||
328 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
329 | substs.push(Ty::Unknown); | ||
330 | } | ||
331 | if let Some(generic_args) = &segment.args_and_bindings { | 435 | if let Some(generic_args) = &segment.args_and_bindings { |
436 | if !generic_args.has_self_type { | ||
437 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); | ||
438 | } | ||
439 | let expected_num = | ||
440 | if generic_args.has_self_type { self_params + type_params } else { type_params }; | ||
441 | let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; | ||
332 | // if args are provided, it should be all of them, but we can't rely on that | 442 | // if args are provided, it should be all of them, but we can't rely on that |
333 | let self_param_correction = if add_self_param { 1 } else { 0 }; | 443 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
334 | let child_len = child_len - self_param_correction; | ||
335 | for arg in generic_args.args.iter().take(child_len) { | ||
336 | match arg { | 444 | match arg { |
337 | GenericArg::Type(type_ref) => { | 445 | GenericArg::Type(type_ref) => { |
338 | let ty = Ty::from_hir(db, resolver, type_ref); | 446 | let ty = Ty::from_hir(ctx, type_ref); |
339 | substs.push(ty); | 447 | substs.push(ty); |
340 | } | 448 | } |
341 | } | 449 | } |
342 | } | 450 | } |
343 | } | 451 | } |
452 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
344 | // add placeholders for args that were not provided | 453 | // add placeholders for args that were not provided |
345 | let supplied_params = substs.len(); | 454 | for _ in substs.len()..total_len { |
346 | for _ in supplied_params..total_len { | ||
347 | substs.push(Ty::Unknown); | 455 | substs.push(Ty::Unknown); |
348 | } | 456 | } |
349 | assert_eq!(substs.len(), total_len); | 457 | assert_eq!(substs.len(), total_len); |
350 | 458 | ||
351 | // handle defaults | 459 | // handle defaults |
352 | if let Some(def_generic) = def_generic { | 460 | if let Some(def_generic) = def_generic { |
353 | let default_substs = db.generic_defaults(def_generic.into()); | 461 | let default_substs = ctx.db.generic_defaults(def_generic.into()); |
354 | assert_eq!(substs.len(), default_substs.len()); | 462 | assert_eq!(substs.len(), default_substs.len()); |
355 | 463 | ||
356 | for (i, default_ty) in default_substs.iter().enumerate() { | 464 | for (i, default_ty) in default_substs.iter().enumerate() { |
@@ -365,27 +473,25 @@ pub(super) fn substs_from_path_segment( | |||
365 | 473 | ||
366 | impl TraitRef { | 474 | impl TraitRef { |
367 | fn from_path( | 475 | fn from_path( |
368 | db: &impl HirDatabase, | 476 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
369 | resolver: &Resolver, | ||
370 | path: &Path, | 477 | path: &Path, |
371 | explicit_self_ty: Option<Ty>, | 478 | explicit_self_ty: Option<Ty>, |
372 | ) -> Option<Self> { | 479 | ) -> Option<Self> { |
373 | let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? { | 480 | let resolved = match ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path.mod_path())? { |
374 | TypeNs::TraitId(tr) => tr, | 481 | TypeNs::TraitId(tr) => tr, |
375 | _ => return None, | 482 | _ => return None, |
376 | }; | 483 | }; |
377 | let segment = path.segments().last().expect("path should have at least one segment"); | 484 | let segment = path.segments().last().expect("path should have at least one segment"); |
378 | Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) | 485 | Some(TraitRef::from_resolved_path(ctx, resolved.into(), segment, explicit_self_ty)) |
379 | } | 486 | } |
380 | 487 | ||
381 | pub(crate) fn from_resolved_path( | 488 | pub(crate) fn from_resolved_path( |
382 | db: &impl HirDatabase, | 489 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
383 | resolver: &Resolver, | ||
384 | resolved: TraitId, | 490 | resolved: TraitId, |
385 | segment: PathSegment<'_>, | 491 | segment: PathSegment<'_>, |
386 | explicit_self_ty: Option<Ty>, | 492 | explicit_self_ty: Option<Ty>, |
387 | ) -> Self { | 493 | ) -> Self { |
388 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); | 494 | let mut substs = TraitRef::substs_from_path(ctx, segment, resolved); |
389 | if let Some(self_ty) = explicit_self_ty { | 495 | if let Some(self_ty) = explicit_self_ty { |
390 | make_mut_slice(&mut substs.0)[0] = self_ty; | 496 | make_mut_slice(&mut substs.0)[0] = self_ty; |
391 | } | 497 | } |
@@ -393,8 +499,7 @@ impl TraitRef { | |||
393 | } | 499 | } |
394 | 500 | ||
395 | fn from_hir( | 501 | fn from_hir( |
396 | db: &impl HirDatabase, | 502 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
397 | resolver: &Resolver, | ||
398 | type_ref: &TypeRef, | 503 | type_ref: &TypeRef, |
399 | explicit_self_ty: Option<Ty>, | 504 | explicit_self_ty: Option<Ty>, |
400 | ) -> Option<Self> { | 505 | ) -> Option<Self> { |
@@ -402,28 +507,26 @@ impl TraitRef { | |||
402 | TypeRef::Path(path) => path, | 507 | TypeRef::Path(path) => path, |
403 | _ => return None, | 508 | _ => return None, |
404 | }; | 509 | }; |
405 | TraitRef::from_path(db, resolver, path, explicit_self_ty) | 510 | TraitRef::from_path(ctx, path, explicit_self_ty) |
406 | } | 511 | } |
407 | 512 | ||
408 | fn substs_from_path( | 513 | fn substs_from_path( |
409 | db: &impl HirDatabase, | 514 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
410 | resolver: &Resolver, | ||
411 | segment: PathSegment<'_>, | 515 | segment: PathSegment<'_>, |
412 | resolved: TraitId, | 516 | resolved: TraitId, |
413 | ) -> Substs { | 517 | ) -> Substs { |
414 | let has_self_param = | 518 | let has_self_param = |
415 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); | 519 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); |
416 | substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param) | 520 | substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param) |
417 | } | 521 | } |
418 | 522 | ||
419 | pub(crate) fn from_type_bound( | 523 | pub(crate) fn from_type_bound( |
420 | db: &impl HirDatabase, | 524 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
421 | resolver: &Resolver, | ||
422 | bound: &TypeBound, | 525 | bound: &TypeBound, |
423 | self_ty: Ty, | 526 | self_ty: Ty, |
424 | ) -> Option<TraitRef> { | 527 | ) -> Option<TraitRef> { |
425 | match bound { | 528 | match bound { |
426 | TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)), | 529 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), |
427 | TypeBound::Error => None, | 530 | TypeBound::Error => None, |
428 | } | 531 | } |
429 | } | 532 | } |
@@ -431,33 +534,44 @@ impl TraitRef { | |||
431 | 534 | ||
432 | impl GenericPredicate { | 535 | impl GenericPredicate { |
433 | pub(crate) fn from_where_predicate<'a>( | 536 | pub(crate) fn from_where_predicate<'a>( |
434 | db: &'a impl HirDatabase, | 537 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
435 | resolver: &'a Resolver, | ||
436 | where_predicate: &'a WherePredicate, | 538 | where_predicate: &'a WherePredicate, |
437 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 539 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
438 | let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref); | 540 | let self_ty = match &where_predicate.target { |
439 | GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty) | 541 | WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), |
542 | WherePredicateTarget::TypeParam(param_id) => { | ||
543 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); | ||
544 | let generics = generics(ctx.db, generic_def); | ||
545 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; | ||
546 | match ctx.type_param_mode { | ||
547 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), | ||
548 | TypeParamLoweringMode::Variable => { | ||
549 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
550 | Ty::Bound(idx) | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | }; | ||
555 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) | ||
440 | } | 556 | } |
441 | 557 | ||
442 | pub(crate) fn from_type_bound<'a>( | 558 | pub(crate) fn from_type_bound<'a>( |
443 | db: &'a impl HirDatabase, | 559 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
444 | resolver: &'a Resolver, | ||
445 | bound: &'a TypeBound, | 560 | bound: &'a TypeBound, |
446 | self_ty: Ty, | 561 | self_ty: Ty, |
447 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 562 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
448 | let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty); | 563 | let trait_ref = TraitRef::from_type_bound(ctx, bound, self_ty); |
449 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) | 564 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) |
450 | .chain( | 565 | .chain( |
451 | trait_ref.into_iter().flat_map(move |tr| { | 566 | trait_ref |
452 | assoc_type_bindings_from_type_bound(db, resolver, bound, tr) | 567 | .into_iter() |
453 | }), | 568 | .flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)), |
454 | ) | 569 | ) |
455 | } | 570 | } |
456 | } | 571 | } |
457 | 572 | ||
458 | fn assoc_type_bindings_from_type_bound<'a>( | 573 | fn assoc_type_bindings_from_type_bound<'a>( |
459 | db: &'a impl HirDatabase, | 574 | ctx: &'a TyLoweringContext<'a, impl HirDatabase>, |
460 | resolver: &'a Resolver, | ||
461 | bound: &'a TypeBound, | 575 | bound: &'a TypeBound, |
462 | trait_ref: TraitRef, | 576 | trait_ref: TraitRef, |
463 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 577 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
@@ -471,21 +585,21 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
471 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | 585 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) |
472 | .map(move |(name, type_ref)| { | 586 | .map(move |(name, type_ref)| { |
473 | let associated_ty = | 587 | let associated_ty = |
474 | associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name); | 588 | associated_type_by_name_including_super_traits(ctx.db, trait_ref.trait_, &name); |
475 | let associated_ty = match associated_ty { | 589 | let associated_ty = match associated_ty { |
476 | None => return GenericPredicate::Error, | 590 | None => return GenericPredicate::Error, |
477 | Some(t) => t, | 591 | Some(t) => t, |
478 | }; | 592 | }; |
479 | let projection_ty = | 593 | let projection_ty = |
480 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | 594 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; |
481 | let ty = Ty::from_hir(db, resolver, type_ref); | 595 | let ty = Ty::from_hir(ctx, type_ref); |
482 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; | 596 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; |
483 | GenericPredicate::Projection(projection_predicate) | 597 | GenericPredicate::Projection(projection_predicate) |
484 | }) | 598 | }) |
485 | } | 599 | } |
486 | 600 | ||
487 | /// Build the signature of a callable item (function, struct or enum variant). | 601 | /// Build the signature of a callable item (function, struct or enum variant). |
488 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | 602 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { |
489 | match def { | 603 | match def { |
490 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), | 604 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), |
491 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), | 605 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), |
@@ -497,16 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | |||
497 | pub(crate) fn field_types_query( | 611 | pub(crate) fn field_types_query( |
498 | db: &impl HirDatabase, | 612 | db: &impl HirDatabase, |
499 | variant_id: VariantId, | 613 | variant_id: VariantId, |
500 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { | 614 | ) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> { |
501 | let var_data = variant_data(db, variant_id); | 615 | let var_data = variant_data(db, variant_id); |
502 | let resolver = match variant_id { | 616 | let (resolver, def): (_, GenericDefId) = match variant_id { |
503 | VariantId::StructId(it) => it.resolver(db), | 617 | VariantId::StructId(it) => (it.resolver(db), it.into()), |
504 | VariantId::UnionId(it) => it.resolver(db), | 618 | VariantId::UnionId(it) => (it.resolver(db), it.into()), |
505 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | 619 | VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()), |
506 | }; | 620 | }; |
621 | let generics = generics(db, def); | ||
507 | let mut res = ArenaMap::default(); | 622 | let mut res = ArenaMap::default(); |
623 | let ctx = | ||
624 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
508 | for (field_id, field_data) in var_data.fields().iter() { | 625 | for (field_id, field_data) in var_data.fields().iter() { |
509 | res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref)) | 626 | res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) |
510 | } | 627 | } |
511 | Arc::new(res) | 628 | Arc::new(res) |
512 | } | 629 | } |
@@ -521,32 +638,43 @@ pub(crate) fn field_types_query( | |||
521 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | 638 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. |
522 | pub(crate) fn generic_predicates_for_param_query( | 639 | pub(crate) fn generic_predicates_for_param_query( |
523 | db: &impl HirDatabase, | 640 | db: &impl HirDatabase, |
524 | def: GenericDefId, | 641 | param_id: TypeParamId, |
525 | param_idx: u32, | 642 | ) -> Arc<[Binders<GenericPredicate>]> { |
526 | ) -> Arc<[GenericPredicate]> { | 643 | let resolver = param_id.parent.resolver(db); |
527 | let resolver = def.resolver(db); | 644 | let ctx = |
645 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
646 | let generics = generics(db, param_id.parent); | ||
528 | resolver | 647 | resolver |
529 | .where_predicates_in_scope() | 648 | .where_predicates_in_scope() |
530 | // we have to filter out all other predicates *first*, before attempting to lower them | 649 | // we have to filter out all other predicates *first*, before attempting to lower them |
531 | .filter(|pred| Ty::from_hir_only_param(db, &resolver, &pred.type_ref) == Some(param_idx)) | 650 | .filter(|pred| match &pred.target { |
532 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 651 | WherePredicateTarget::TypeRef(type_ref) => { |
652 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) | ||
653 | } | ||
654 | WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, | ||
655 | }) | ||
656 | .flat_map(|pred| { | ||
657 | GenericPredicate::from_where_predicate(&ctx, pred) | ||
658 | .map(|p| Binders::new(generics.len(), p)) | ||
659 | }) | ||
533 | .collect() | 660 | .collect() |
534 | } | 661 | } |
535 | 662 | ||
536 | pub(crate) fn generic_predicates_for_param_recover( | 663 | pub(crate) fn generic_predicates_for_param_recover( |
537 | _db: &impl HirDatabase, | 664 | _db: &impl HirDatabase, |
538 | _cycle: &[String], | 665 | _cycle: &[String], |
539 | _def: &GenericDefId, | 666 | _param_id: &TypeParamId, |
540 | _param_idx: &u32, | 667 | ) -> Arc<[Binders<GenericPredicate>]> { |
541 | ) -> Arc<[GenericPredicate]> { | ||
542 | Arc::new([]) | 668 | Arc::new([]) |
543 | } | 669 | } |
544 | 670 | ||
545 | impl TraitEnvironment { | 671 | impl TraitEnvironment { |
546 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | 672 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
673 | let ctx = TyLoweringContext::new(db, &resolver) | ||
674 | .with_type_param_mode(TypeParamLoweringMode::Placeholder); | ||
547 | let predicates = resolver | 675 | let predicates = resolver |
548 | .where_predicates_in_scope() | 676 | .where_predicates_in_scope() |
549 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 677 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) |
550 | .collect::<Vec<_>>(); | 678 | .collect::<Vec<_>>(); |
551 | 679 | ||
552 | Arc::new(TraitEnvironment { predicates }) | 680 | Arc::new(TraitEnvironment { predicates }) |
@@ -557,57 +685,74 @@ impl TraitEnvironment { | |||
557 | pub(crate) fn generic_predicates_query( | 685 | pub(crate) fn generic_predicates_query( |
558 | db: &impl HirDatabase, | 686 | db: &impl HirDatabase, |
559 | def: GenericDefId, | 687 | def: GenericDefId, |
560 | ) -> Arc<[GenericPredicate]> { | 688 | ) -> Arc<[Binders<GenericPredicate>]> { |
561 | let resolver = def.resolver(db); | 689 | let resolver = def.resolver(db); |
690 | let ctx = | ||
691 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
692 | let generics = generics(db, def); | ||
562 | resolver | 693 | resolver |
563 | .where_predicates_in_scope() | 694 | .where_predicates_in_scope() |
564 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 695 | .flat_map(|pred| { |
696 | GenericPredicate::from_where_predicate(&ctx, pred) | ||
697 | .map(|p| Binders::new(generics.len(), p)) | ||
698 | }) | ||
565 | .collect() | 699 | .collect() |
566 | } | 700 | } |
567 | 701 | ||
568 | /// Resolve the default type params from generics | 702 | /// Resolve the default type params from generics |
569 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { | 703 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { |
570 | let resolver = def.resolver(db); | 704 | let resolver = def.resolver(db); |
705 | let ctx = TyLoweringContext::new(db, &resolver); | ||
571 | let generic_params = generics(db, def.into()); | 706 | let generic_params = generics(db, def.into()); |
572 | 707 | ||
573 | let defaults = generic_params | 708 | let defaults = generic_params |
574 | .iter() | 709 | .iter() |
575 | .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) | 710 | .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) |
576 | .collect(); | 711 | .collect(); |
577 | 712 | ||
578 | Substs(defaults) | 713 | Substs(defaults) |
579 | } | 714 | } |
580 | 715 | ||
581 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { | 716 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> PolyFnSig { |
582 | let data = db.function_data(def); | 717 | let data = db.function_data(def); |
583 | let resolver = def.resolver(db); | 718 | let resolver = def.resolver(db); |
584 | let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | 719 | let ctx_params = TyLoweringContext::new(db, &resolver) |
585 | let ret = Ty::from_hir(db, &resolver, &data.ret_type); | 720 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) |
586 | FnSig::from_params_and_return(params, ret) | 721 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
722 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); | ||
723 | let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | ||
724 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); | ||
725 | let generics = generics(db, def.into()); | ||
726 | let num_binders = generics.len(); | ||
727 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) | ||
587 | } | 728 | } |
588 | 729 | ||
589 | /// Build the declared type of a function. This should not need to look at the | 730 | /// Build the declared type of a function. This should not need to look at the |
590 | /// function body. | 731 | /// function body. |
591 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { | 732 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Binders<Ty> { |
592 | let generics = generics(db, def.into()); | 733 | let generics = generics(db, def.into()); |
593 | let substs = Substs::identity(&generics); | 734 | let substs = Substs::bound_vars(&generics); |
594 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 735 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
595 | } | 736 | } |
596 | 737 | ||
597 | /// Build the declared type of a const. | 738 | /// Build the declared type of a const. |
598 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { | 739 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders<Ty> { |
599 | let data = db.const_data(def); | 740 | let data = db.const_data(def); |
741 | let generics = generics(db, def.into()); | ||
600 | let resolver = def.resolver(db); | 742 | let resolver = def.resolver(db); |
743 | let ctx = | ||
744 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
601 | 745 | ||
602 | Ty::from_hir(db, &resolver, &data.type_ref) | 746 | Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) |
603 | } | 747 | } |
604 | 748 | ||
605 | /// Build the declared type of a static. | 749 | /// Build the declared type of a static. |
606 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { | 750 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Binders<Ty> { |
607 | let data = db.static_data(def); | 751 | let data = db.static_data(def); |
608 | let resolver = def.resolver(db); | 752 | let resolver = def.resolver(db); |
753 | let ctx = TyLoweringContext::new(db, &resolver); | ||
609 | 754 | ||
610 | Ty::from_hir(db, &resolver, &data.type_ref) | 755 | Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) |
611 | } | 756 | } |
612 | 757 | ||
613 | /// Build the declared type of a static. | 758 | /// Build the declared type of a static. |
@@ -621,68 +766,69 @@ fn type_for_builtin(def: BuiltinType) -> Ty { | |||
621 | }) | 766 | }) |
622 | } | 767 | } |
623 | 768 | ||
624 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { | 769 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFnSig { |
625 | let struct_data = db.struct_data(def.into()); | 770 | let struct_data = db.struct_data(def.into()); |
626 | let fields = struct_data.variant_data.fields(); | 771 | let fields = struct_data.variant_data.fields(); |
627 | let resolver = def.resolver(db); | 772 | let resolver = def.resolver(db); |
628 | let params = fields | 773 | let ctx = |
629 | .iter() | 774 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
630 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 775 | let params = |
631 | .collect::<Vec<_>>(); | 776 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
632 | let ret = type_for_adt(db, def.into()); | 777 | let ret = type_for_adt(db, def.into()); |
633 | FnSig::from_params_and_return(params, ret) | 778 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) |
634 | } | 779 | } |
635 | 780 | ||
636 | /// Build the type of a tuple struct constructor. | 781 | /// Build the type of a tuple struct constructor. |
637 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { | 782 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { |
638 | let struct_data = db.struct_data(def.into()); | 783 | let struct_data = db.struct_data(def.into()); |
639 | if struct_data.variant_data.is_unit() { | 784 | if struct_data.variant_data.is_unit() { |
640 | return type_for_adt(db, def.into()); // Unit struct | 785 | return type_for_adt(db, def.into()); // Unit struct |
641 | } | 786 | } |
642 | let generics = generics(db, def.into()); | 787 | let generics = generics(db, def.into()); |
643 | let substs = Substs::identity(&generics); | 788 | let substs = Substs::bound_vars(&generics); |
644 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 789 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) |
645 | } | 790 | } |
646 | 791 | ||
647 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { | 792 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> PolyFnSig { |
648 | let enum_data = db.enum_data(def.parent); | 793 | let enum_data = db.enum_data(def.parent); |
649 | let var_data = &enum_data.variants[def.local_id]; | 794 | let var_data = &enum_data.variants[def.local_id]; |
650 | let fields = var_data.variant_data.fields(); | 795 | let fields = var_data.variant_data.fields(); |
651 | let resolver = def.parent.resolver(db); | 796 | let resolver = def.parent.resolver(db); |
652 | let params = fields | 797 | let ctx = |
653 | .iter() | 798 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
654 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 799 | let params = |
655 | .collect::<Vec<_>>(); | 800 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
656 | let generics = generics(db, def.parent.into()); | 801 | let ret = type_for_adt(db, def.parent.into()); |
657 | let substs = Substs::identity(&generics); | 802 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) |
658 | let ret = type_for_adt(db, def.parent.into()).subst(&substs); | ||
659 | FnSig::from_params_and_return(params, ret) | ||
660 | } | 803 | } |
661 | 804 | ||
662 | /// Build the type of a tuple enum variant constructor. | 805 | /// Build the type of a tuple enum variant constructor. |
663 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { | 806 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { |
664 | let enum_data = db.enum_data(def.parent); | 807 | let enum_data = db.enum_data(def.parent); |
665 | let var_data = &enum_data.variants[def.local_id].variant_data; | 808 | let var_data = &enum_data.variants[def.local_id].variant_data; |
666 | if var_data.is_unit() { | 809 | if var_data.is_unit() { |
667 | return type_for_adt(db, def.parent.into()); // Unit variant | 810 | return type_for_adt(db, def.parent.into()); // Unit variant |
668 | } | 811 | } |
669 | let generics = generics(db, def.parent.into()); | 812 | let generics = generics(db, def.parent.into()); |
670 | let substs = Substs::identity(&generics); | 813 | let substs = Substs::bound_vars(&generics); |
671 | Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) | 814 | Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)) |
672 | } | 815 | } |
673 | 816 | ||
674 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { | 817 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders<Ty> { |
675 | let generics = generics(db, adt.into()); | 818 | let generics = generics(db, adt.into()); |
676 | Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) | 819 | let substs = Substs::bound_vars(&generics); |
820 | Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) | ||
677 | } | 821 | } |
678 | 822 | ||
679 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { | 823 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
680 | let generics = generics(db, t.into()); | 824 | let generics = generics(db, t.into()); |
681 | let resolver = t.resolver(db); | 825 | let resolver = t.resolver(db); |
826 | let ctx = | ||
827 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
682 | let type_ref = &db.type_alias_data(t).type_ref; | 828 | let type_ref = &db.type_alias_data(t).type_ref; |
683 | let substs = Substs::identity(&generics); | 829 | let substs = Substs::bound_vars(&generics); |
684 | let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 830 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
685 | inner.subst(&substs) | 831 | Binders::new(substs.len(), inner) |
686 | } | 832 | } |
687 | 833 | ||
688 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 834 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
@@ -736,19 +882,24 @@ impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId | |||
736 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 882 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
737 | /// the constructor function `(usize) -> Foo` which lives in the values | 883 | /// the constructor function `(usize) -> Foo` which lives in the values |
738 | /// namespace. | 884 | /// namespace. |
739 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { | 885 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders<Ty> { |
740 | match def { | 886 | match def { |
741 | TyDefId::BuiltinType(it) => type_for_builtin(it), | 887 | TyDefId::BuiltinType(it) => Binders::new(0, type_for_builtin(it)), |
742 | TyDefId::AdtId(it) => type_for_adt(db, it), | 888 | TyDefId::AdtId(it) => type_for_adt(db, it), |
743 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | 889 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), |
744 | } | 890 | } |
745 | } | 891 | } |
746 | 892 | ||
747 | pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { | 893 | pub(crate) fn ty_recover(db: &impl HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders<Ty> { |
748 | Ty::Unknown | 894 | let num_binders = match *def { |
895 | TyDefId::BuiltinType(_) => 0, | ||
896 | TyDefId::AdtId(it) => generics(db, it.into()).len(), | ||
897 | TyDefId::TypeAliasId(it) => generics(db, it.into()).len(), | ||
898 | }; | ||
899 | Binders::new(num_binders, Ty::Unknown) | ||
749 | } | 900 | } |
750 | 901 | ||
751 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | 902 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders<Ty> { |
752 | match def { | 903 | match def { |
753 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 904 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
754 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 905 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), |
@@ -758,24 +909,36 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | |||
758 | } | 909 | } |
759 | } | 910 | } |
760 | 911 | ||
761 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { | 912 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Binders<Ty> { |
762 | let impl_data = db.impl_data(impl_id); | 913 | let impl_data = db.impl_data(impl_id); |
763 | let resolver = impl_id.resolver(db); | 914 | let resolver = impl_id.resolver(db); |
764 | Ty::from_hir(db, &resolver, &impl_data.target_type) | 915 | let generics = generics(db, impl_id.into()); |
916 | let ctx = | ||
917 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
918 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) | ||
765 | } | 919 | } |
766 | 920 | ||
767 | pub(crate) fn impl_self_ty_recover( | 921 | pub(crate) fn impl_self_ty_recover( |
768 | _db: &impl HirDatabase, | 922 | db: &impl HirDatabase, |
769 | _cycle: &[String], | 923 | _cycle: &[String], |
770 | _impl_id: &ImplId, | 924 | impl_id: &ImplId, |
771 | ) -> Ty { | 925 | ) -> Binders<Ty> { |
772 | Ty::Unknown | 926 | let generics = generics(db, (*impl_id).into()); |
927 | Binders::new(generics.len(), Ty::Unknown) | ||
773 | } | 928 | } |
774 | 929 | ||
775 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { | 930 | pub(crate) fn impl_trait_query( |
931 | db: &impl HirDatabase, | ||
932 | impl_id: ImplId, | ||
933 | ) -> Option<Binders<TraitRef>> { | ||
776 | let impl_data = db.impl_data(impl_id); | 934 | let impl_data = db.impl_data(impl_id); |
777 | let resolver = impl_id.resolver(db); | 935 | let resolver = impl_id.resolver(db); |
936 | let ctx = | ||
937 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
778 | let self_ty = db.impl_self_ty(impl_id); | 938 | let self_ty = db.impl_self_ty(impl_id); |
779 | let target_trait = impl_data.target_trait.as_ref()?; | 939 | let target_trait = impl_data.target_trait.as_ref()?; |
780 | TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone())) | 940 | Some(Binders::new( |
941 | self_ty.num_binders, | ||
942 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?, | ||
943 | )) | ||
781 | } | 944 | } |
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs index fe74acf11..0f754eb9c 100644 --- a/crates/ra_hir_ty/src/marks.rs +++ b/crates/ra_hir_ty/src/marks.rs | |||
@@ -6,5 +6,4 @@ test_utils::marks!( | |||
6 | type_var_resolves_to_int_var | 6 | type_var_resolves_to_int_var |
7 | match_ergonomics_ref | 7 | match_ergonomics_ref |
8 | coerce_merge_fail_fallback | 8 | coerce_merge_fail_fallback |
9 | insert_vars_for_impl_trait | ||
10 | ); | 9 | ); |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 5bacbbd7c..5283bff28 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -61,11 +61,11 @@ impl CrateImplBlocks { | |||
61 | for impl_id in module_data.scope.impls() { | 61 | for impl_id in module_data.scope.impls() { |
62 | match db.impl_trait(impl_id) { | 62 | match db.impl_trait(impl_id) { |
63 | Some(tr) => { | 63 | Some(tr) => { |
64 | res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); | 64 | res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id); |
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/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 76a1b46c0..fc5ef36a5 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -75,7 +75,7 @@ fn test2() { | |||
75 | [124; 131) 'loop {}': ! | 75 | [124; 131) 'loop {}': ! |
76 | [129; 131) '{}': () | 76 | [129; 131) '{}': () |
77 | [160; 173) '{ gen() }': *mut [U] | 77 | [160; 173) '{ gen() }': *mut [U] |
78 | [166; 169) 'gen': fn gen<U>() -> *mut [T; _] | 78 | [166; 169) 'gen': fn gen<U>() -> *mut [U; _] |
79 | [166; 171) 'gen()': *mut [U; _] | 79 | [166; 171) 'gen()': *mut [U; _] |
80 | [186; 420) '{ ...rr); }': () | 80 | [186; 420) '{ ...rr); }': () |
81 | [196; 199) 'arr': &[u8; _] | 81 | [196; 199) 'arr': &[u8; _] |
@@ -85,14 +85,14 @@ fn test2() { | |||
85 | [227; 228) 'a': &[u8] | 85 | [227; 228) 'a': &[u8] |
86 | [237; 240) 'arr': &[u8; _] | 86 | [237; 240) 'arr': &[u8; _] |
87 | [250; 251) 'b': u8 | 87 | [250; 251) 'b': u8 |
88 | [254; 255) 'f': fn f<u8>(&[T]) -> T | 88 | [254; 255) 'f': fn f<u8>(&[u8]) -> u8 |
89 | [254; 260) 'f(arr)': u8 | 89 | [254; 260) 'f(arr)': u8 |
90 | [256; 259) 'arr': &[u8; _] | 90 | [256; 259) 'arr': &[u8; _] |
91 | [270; 271) 'c': &[u8] | 91 | [270; 271) 'c': &[u8] |
92 | [280; 287) '{ arr }': &[u8] | 92 | [280; 287) '{ arr }': &[u8] |
93 | [282; 285) 'arr': &[u8; _] | 93 | [282; 285) 'arr': &[u8; _] |
94 | [297; 298) 'd': u8 | 94 | [297; 298) 'd': u8 |
95 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T | 95 | [301; 302) 'g': fn g<u8>(S<&[u8]>) -> u8 |
96 | [301; 316) 'g(S { a: arr })': u8 | 96 | [301; 316) 'g(S { a: arr })': u8 |
97 | [303; 315) 'S { a: arr }': S<&[u8]> | 97 | [303; 315) 'S { a: arr }': S<&[u8]> |
98 | [310; 313) 'arr': &[u8; _] | 98 | [310; 313) 'arr': &[u8; _] |
@@ -164,15 +164,15 @@ fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | |||
164 | [400; 401) 'c': C<[u8; _]> | 164 | [400; 401) 'c': C<[u8; _]> |
165 | [415; 481) '{ ...(c); }': () | 165 | [415; 481) '{ ...(c); }': () |
166 | [425; 426) 'd': A<[{unknown}]> | 166 | [425; 426) 'd': A<[{unknown}]> |
167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> | 167 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> |
168 | [429; 436) 'foo1(a)': A<[{unknown}]> | 168 | [429; 436) 'foo1(a)': A<[{unknown}]> |
169 | [434; 435) 'a': A<[u8; _]> | 169 | [434; 435) 'a': A<[u8; _]> |
170 | [446; 447) 'e': B<[u8]> | 170 | [446; 447) 'e': B<[u8]> |
171 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> | 171 | [450; 454) 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> |
172 | [450; 457) 'foo2(b)': B<[u8]> | 172 | [450; 457) 'foo2(b)': B<[u8]> |
173 | [455; 456) 'b': B<[u8; _]> | 173 | [455; 456) 'b': B<[u8; _]> |
174 | [467; 468) 'f': C<[u8]> | 174 | [467; 468) 'f': C<[u8]> |
175 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> | 175 | [471; 475) 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> |
176 | [471; 478) 'foo3(c)': C<[u8]> | 176 | [471; 478) 'foo3(c)': C<[u8]> |
177 | [476; 477) 'c': C<[u8; _]> | 177 | [476; 477) 'c': C<[u8; _]> |
178 | "### | 178 | "### |
@@ -202,7 +202,7 @@ fn test() { | |||
202 | [64; 123) 'if tru... }': &[i32] | 202 | [64; 123) 'if tru... }': &[i32] |
203 | [67; 71) 'true': bool | 203 | [67; 71) 'true': bool |
204 | [72; 97) '{ ... }': &[i32] | 204 | [72; 97) '{ ... }': &[i32] |
205 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] | 205 | [82; 85) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
206 | [82; 91) 'foo(&[1])': &[i32] | 206 | [82; 91) 'foo(&[1])': &[i32] |
207 | [86; 90) '&[1]': &[i32; _] | 207 | [86; 90) '&[1]': &[i32; _] |
208 | [87; 90) '[1]': [i32; _] | 208 | [87; 90) '[1]': [i32; _] |
@@ -242,7 +242,7 @@ fn test() { | |||
242 | [83; 86) '[1]': [i32; _] | 242 | [83; 86) '[1]': [i32; _] |
243 | [84; 85) '1': i32 | 243 | [84; 85) '1': i32 |
244 | [98; 123) '{ ... }': &[i32] | 244 | [98; 123) '{ ... }': &[i32] |
245 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | 245 | [108; 111) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
246 | [108; 117) 'foo(&[1])': &[i32] | 246 | [108; 117) 'foo(&[1])': &[i32] |
247 | [112; 116) '&[1]': &[i32; _] | 247 | [112; 116) '&[1]': &[i32; _] |
248 | [113; 116) '[1]': [i32; _] | 248 | [113; 116) '[1]': [i32; _] |
@@ -275,7 +275,7 @@ fn test(i: i32) { | |||
275 | [70; 147) 'match ... }': &[i32] | 275 | [70; 147) 'match ... }': &[i32] |
276 | [76; 77) 'i': i32 | 276 | [76; 77) 'i': i32 |
277 | [88; 89) '2': i32 | 277 | [88; 89) '2': i32 |
278 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | 278 | [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
279 | [93; 102) 'foo(&[2])': &[i32] | 279 | [93; 102) 'foo(&[2])': &[i32] |
280 | [97; 101) '&[2]': &[i32; _] | 280 | [97; 101) '&[2]': &[i32; _] |
281 | [98; 101) '[2]': [i32; _] | 281 | [98; 101) '[2]': [i32; _] |
@@ -320,7 +320,7 @@ fn test(i: i32) { | |||
320 | [94; 97) '[1]': [i32; _] | 320 | [94; 97) '[1]': [i32; _] |
321 | [95; 96) '1': i32 | 321 | [95; 96) '1': i32 |
322 | [107; 108) '2': i32 | 322 | [107; 108) '2': i32 |
323 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | 323 | [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
324 | [112; 121) 'foo(&[2])': &[i32] | 324 | [112; 121) 'foo(&[2])': &[i32] |
325 | [116; 120) '&[2]': &[i32; _] | 325 | [116; 120) '&[2]': &[i32; _] |
326 | [117; 120) '[2]': [i32; _] | 326 | [117; 120) '[2]': [i32; _] |
@@ -438,16 +438,16 @@ fn test() { | |||
438 | [43; 45) '*x': T | 438 | [43; 45) '*x': T |
439 | [44; 45) 'x': &T | 439 | [44; 45) 'x': &T |
440 | [58; 127) '{ ...oo); }': () | 440 | [58; 127) '{ ...oo); }': () |
441 | [64; 73) 'takes_ref': fn takes_ref<Foo>(&T) -> T | 441 | [64; 73) 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo |
442 | [64; 79) 'takes_ref(&Foo)': Foo | 442 | [64; 79) 'takes_ref(&Foo)': Foo |
443 | [74; 78) '&Foo': &Foo | 443 | [74; 78) '&Foo': &Foo |
444 | [75; 78) 'Foo': Foo | 444 | [75; 78) 'Foo': Foo |
445 | [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T | 445 | [85; 94) 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo |
446 | [85; 101) 'takes_...&&Foo)': &Foo | 446 | [85; 101) 'takes_...&&Foo)': &Foo |
447 | [95; 100) '&&Foo': &&Foo | 447 | [95; 100) '&&Foo': &&Foo |
448 | [96; 100) '&Foo': &Foo | 448 | [96; 100) '&Foo': &Foo |
449 | [97; 100) 'Foo': Foo | 449 | [97; 100) 'Foo': Foo |
450 | [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T | 450 | [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo |
451 | [107; 124) 'takes_...&&Foo)': &&Foo | 451 | [107; 124) 'takes_...&&Foo)': &&Foo |
452 | [117; 123) '&&&Foo': &&&Foo | 452 | [117; 123) '&&&Foo': &&&Foo |
453 | [118; 123) '&&Foo': &&Foo | 453 | [118; 123) '&&Foo': &&Foo |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index ce9a06fde..1722563aa 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -27,7 +27,7 @@ fn test() { | |||
27 | [66; 73) 'loop {}': ! | 27 | [66; 73) 'loop {}': ! |
28 | [71; 73) '{}': () | 28 | [71; 73) '{}': () |
29 | [133; 160) '{ ...o"); }': () | 29 | [133; 160) '{ ...o"); }': () |
30 | [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T | 30 | [139; 149) '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 |
31 | [139; 157) '<[_]>:..."foo")': u8 | 31 | [139; 157) '<[_]>:..."foo")': u8 |
32 | [150; 156) 'b"foo"': &[u8] | 32 | [150; 156) 'b"foo"': &[u8] |
33 | "### | 33 | "### |
@@ -175,7 +175,7 @@ fn test() { | |||
175 | [98; 101) 'val': T | 175 | [98; 101) 'val': T |
176 | [123; 155) '{ ...32); }': () | 176 | [123; 155) '{ ...32); }': () |
177 | [133; 134) 'a': Gen<u32> | 177 | [133; 134) 'a': Gen<u32> |
178 | [137; 146) 'Gen::make': fn make<u32>(T) -> Gen<T> | 178 | [137; 146) 'Gen::make': fn make<u32>(u32) -> Gen<u32> |
179 | [137; 152) 'Gen::make(0u32)': Gen<u32> | 179 | [137; 152) 'Gen::make(0u32)': Gen<u32> |
180 | [147; 151) '0u32': u32 | 180 | [147; 151) '0u32': u32 |
181 | "### | 181 | "### |
@@ -206,7 +206,7 @@ fn test() { | |||
206 | [95; 98) '{ }': () | 206 | [95; 98) '{ }': () |
207 | [118; 146) '{ ...e(); }': () | 207 | [118; 146) '{ ...e(); }': () |
208 | [128; 129) 'a': Gen<u32> | 208 | [128; 129) 'a': Gen<u32> |
209 | [132; 141) 'Gen::make': fn make<u32>() -> Gen<T> | 209 | [132; 141) 'Gen::make': fn make<u32>() -> Gen<u32> |
210 | [132; 143) 'Gen::make()': Gen<u32> | 210 | [132; 143) 'Gen::make()': Gen<u32> |
211 | "### | 211 | "### |
212 | ); | 212 | ); |
@@ -260,7 +260,7 @@ fn test() { | |||
260 | [91; 94) '{ }': () | 260 | [91; 94) '{ }': () |
261 | [114; 149) '{ ...e(); }': () | 261 | [114; 149) '{ ...e(); }': () |
262 | [124; 125) 'a': Gen<u32> | 262 | [124; 125) 'a': Gen<u32> |
263 | [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<T> | 263 | [128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<u32> |
264 | [128; 146) 'Gen::<...make()': Gen<u32> | 264 | [128; 146) 'Gen::<...make()': Gen<u32> |
265 | "### | 265 | "### |
266 | ); | 266 | ); |
@@ -291,7 +291,7 @@ fn test() { | |||
291 | [117; 120) '{ }': () | 291 | [117; 120) '{ }': () |
292 | [140; 180) '{ ...e(); }': () | 292 | [140; 180) '{ ...e(); }': () |
293 | [150; 151) 'a': Gen<u32, u64> | 293 | [150; 151) 'a': Gen<u32, u64> |
294 | [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, T> | 294 | [154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> |
295 | [154; 177) 'Gen::<...make()': Gen<u32, u64> | 295 | [154; 177) 'Gen::<...make()': Gen<u32, u64> |
296 | "### | 296 | "### |
297 | ); | 297 | ); |
@@ -475,7 +475,7 @@ fn test() { | |||
475 | @r###" | 475 | @r###" |
476 | [33; 37) 'self': &Self | 476 | [33; 37) 'self': &Self |
477 | [102; 127) '{ ...d(); }': () | 477 | [102; 127) '{ ...d(); }': () |
478 | [108; 109) 'S': S<u32>(T) -> S<T> | 478 | [108; 109) 'S': S<u32>(u32) -> S<u32> |
479 | [108; 115) 'S(1u32)': S<u32> | 479 | [108; 115) 'S(1u32)': S<u32> |
480 | [108; 124) 'S(1u32...thod()': u32 | 480 | [108; 124) 'S(1u32...thod()': u32 |
481 | [110; 114) '1u32': u32 | 481 | [110; 114) '1u32': u32 |
@@ -501,13 +501,13 @@ fn test() { | |||
501 | @r###" | 501 | @r###" |
502 | [87; 193) '{ ...t(); }': () | 502 | [87; 193) '{ ...t(); }': () |
503 | [97; 99) 's1': S | 503 | [97; 99) 's1': S |
504 | [105; 121) 'Defaul...efault': fn default<S>() -> Self | 504 | [105; 121) 'Defaul...efault': fn default<S>() -> S |
505 | [105; 123) 'Defaul...ault()': S | 505 | [105; 123) 'Defaul...ault()': S |
506 | [133; 135) 's2': S | 506 | [133; 135) 's2': S |
507 | [138; 148) 'S::default': fn default<S>() -> Self | 507 | [138; 148) 'S::default': fn default<S>() -> S |
508 | [138; 150) 'S::default()': S | 508 | [138; 150) 'S::default()': S |
509 | [160; 162) 's3': S | 509 | [160; 162) 's3': S |
510 | [165; 188) '<S as ...efault': fn default<S>() -> Self | 510 | [165; 188) '<S as ...efault': fn default<S>() -> S |
511 | [165; 190) '<S as ...ault()': S | 511 | [165; 190) '<S as ...ault()': S |
512 | "### | 512 | "### |
513 | ); | 513 | ); |
@@ -533,13 +533,13 @@ fn test() { | |||
533 | @r###" | 533 | @r###" |
534 | [127; 211) '{ ...e(); }': () | 534 | [127; 211) '{ ...e(); }': () |
535 | [137; 138) 'a': u32 | 535 | [137; 138) 'a': u32 |
536 | [141; 148) 'S::make': fn make<S, u32>() -> T | 536 | [141; 148) 'S::make': fn make<S, u32>() -> u32 |
537 | [141; 150) 'S::make()': u32 | 537 | [141; 150) 'S::make()': u32 |
538 | [160; 161) 'b': u64 | 538 | [160; 161) 'b': u64 |
539 | [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T | 539 | [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 |
540 | [164; 180) 'G::<u6...make()': u64 | 540 | [164; 180) 'G::<u6...make()': u64 |
541 | [190; 191) 'c': f64 | 541 | [190; 191) 'c': f64 |
542 | [199; 206) 'G::make': fn make<G<f64>, f64>() -> T | 542 | [199; 206) 'G::make': fn make<G<f64>, f64>() -> f64 |
543 | [199; 208) 'G::make()': f64 | 543 | [199; 208) 'G::make()': f64 |
544 | "### | 544 | "### |
545 | ); | 545 | ); |
@@ -567,19 +567,19 @@ fn test() { | |||
567 | @r###" | 567 | @r###" |
568 | [135; 313) '{ ...e(); }': () | 568 | [135; 313) '{ ...e(); }': () |
569 | [145; 146) 'a': (u32, i64) | 569 | [145; 146) 'a': (u32, i64) |
570 | [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U) | 570 | [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) |
571 | [149; 165) 'S::mak...i64>()': (u32, i64) | 571 | [149; 165) 'S::mak...i64>()': (u32, i64) |
572 | [175; 176) 'b': (u32, i64) | 572 | [175; 176) 'b': (u32, i64) |
573 | [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U) | 573 | [189; 196) 'S::make': fn make<S, u32, i64>() -> (u32, i64) |
574 | [189; 198) 'S::make()': (u32, i64) | 574 | [189; 198) 'S::make()': (u32, i64) |
575 | [208; 209) 'c': (u32, i64) | 575 | [208; 209) 'c': (u32, i64) |
576 | [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U) | 576 | [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
577 | [212; 235) 'G::<u3...i64>()': (u32, i64) | 577 | [212; 235) 'G::<u3...i64>()': (u32, i64) |
578 | [245; 246) 'd': (u32, i64) | 578 | [245; 246) 'd': (u32, i64) |
579 | [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U) | 579 | [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
580 | [259; 275) 'G::mak...i64>()': (u32, i64) | 580 | [259; 275) 'G::mak...i64>()': (u32, i64) |
581 | [285; 286) 'e': (u32, i64) | 581 | [285; 286) 'e': (u32, i64) |
582 | [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U) | 582 | [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) |
583 | [301; 310) 'G::make()': (u32, i64) | 583 | [301; 310) 'G::make()': (u32, i64) |
584 | "### | 584 | "### |
585 | ); | 585 | ); |
@@ -601,7 +601,7 @@ fn test() { | |||
601 | @r###" | 601 | @r###" |
602 | [101; 127) '{ ...e(); }': () | 602 | [101; 127) '{ ...e(); }': () |
603 | [111; 112) 'a': (S<i32>, i64) | 603 | [111; 112) 'a': (S<i32>, i64) |
604 | [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T) | 604 | [115; 122) 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) |
605 | [115; 124) 'S::make()': (S<i32>, i64) | 605 | [115; 124) 'S::make()': (S<i32>, i64) |
606 | "### | 606 | "### |
607 | ); | 607 | ); |
@@ -625,10 +625,10 @@ fn test() { | |||
625 | @r###" | 625 | @r###" |
626 | [131; 203) '{ ...e(); }': () | 626 | [131; 203) '{ ...e(); }': () |
627 | [141; 142) 'a': (S<u64>, i64) | 627 | [141; 142) 'a': (S<u64>, i64) |
628 | [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T) | 628 | [158; 165) 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) |
629 | [158; 167) 'S::make()': (S<u64>, i64) | 629 | [158; 167) 'S::make()': (S<u64>, i64) |
630 | [177; 178) 'b': (S<u32>, i32) | 630 | [177; 178) 'b': (S<u32>, i32) |
631 | [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T) | 631 | [191; 198) 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) |
632 | [191; 200) 'S::make()': (S<u32>, i32) | 632 | [191; 200) 'S::make()': (S<u32>, i32) |
633 | "### | 633 | "### |
634 | ); | 634 | ); |
@@ -651,10 +651,10 @@ fn test() { | |||
651 | @r###" | 651 | @r###" |
652 | [107; 211) '{ ...>(); }': () | 652 | [107; 211) '{ ...>(); }': () |
653 | [117; 118) 'a': (S<u64>, i64, u8) | 653 | [117; 118) 'a': (S<u64>, i64, u8) |
654 | [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U) | 654 | [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
655 | [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8) | 655 | [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8) |
656 | [162; 163) 'b': (S<u64>, i64, u8) | 656 | [162; 163) 'b': (S<u64>, i64, u8) |
657 | [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U) | 657 | [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
658 | [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8) | 658 | [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8) |
659 | "### | 659 | "### |
660 | ); | 660 | ); |
@@ -697,7 +697,7 @@ fn test<U, T: Trait<U>>(t: T) { | |||
697 | [71; 72) 't': T | 697 | [71; 72) 't': T |
698 | [77; 96) '{ ...d(); }': () | 698 | [77; 96) '{ ...d(); }': () |
699 | [83; 84) 't': T | 699 | [83; 84) 't': T |
700 | [83; 93) 't.method()': [missing name] | 700 | [83; 93) 't.method()': U |
701 | "### | 701 | "### |
702 | ); | 702 | ); |
703 | } | 703 | } |
@@ -728,7 +728,7 @@ fn test() { | |||
728 | [157; 158) 'S': S | 728 | [157; 158) 'S': S |
729 | [157; 165) 'S.into()': u64 | 729 | [157; 165) 'S.into()': u64 |
730 | [175; 176) 'z': u64 | 730 | [175; 176) 'z': u64 |
731 | [179; 196) 'Into::...::into': fn into<S, u64>(Self) -> T | 731 | [179; 196) 'Into::...::into': fn into<S, u64>(S) -> u64 |
732 | [179; 199) 'Into::...nto(S)': u64 | 732 | [179; 199) 'Into::...nto(S)': u64 |
733 | [197; 198) 'S': S | 733 | [197; 198) 'S': S |
734 | "### | 734 | "### |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index cb3890b42..e25d6dbc4 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -96,13 +96,13 @@ fn test() { | |||
96 | [38; 42) 'A(n)': A<i32> | 96 | [38; 42) 'A(n)': A<i32> |
97 | [40; 41) 'n': &i32 | 97 | [40; 41) 'n': &i32 |
98 | [45; 50) '&A(1)': &A<i32> | 98 | [45; 50) '&A(1)': &A<i32> |
99 | [46; 47) 'A': A<i32>(T) -> A<T> | 99 | [46; 47) 'A': A<i32>(i32) -> A<i32> |
100 | [46; 50) 'A(1)': A<i32> | 100 | [46; 50) 'A(1)': A<i32> |
101 | [48; 49) '1': i32 | 101 | [48; 49) '1': i32 |
102 | [60; 64) 'A(n)': A<i32> | 102 | [60; 64) 'A(n)': A<i32> |
103 | [62; 63) 'n': &mut i32 | 103 | [62; 63) 'n': &mut i32 |
104 | [67; 76) '&mut A(1)': &mut A<i32> | 104 | [67; 76) '&mut A(1)': &mut A<i32> |
105 | [72; 73) 'A': A<i32>(T) -> A<T> | 105 | [72; 73) 'A': A<i32>(i32) -> A<i32> |
106 | [72; 76) 'A(1)': A<i32> | 106 | [72; 76) 'A(1)': A<i32> |
107 | [74; 75) '1': i32 | 107 | [74; 75) '1': i32 |
108 | "### | 108 | "### |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 02bab6dbe..14c8ed3a9 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -346,7 +346,7 @@ pub fn main_loop() { | |||
346 | @r###" | 346 | @r###" |
347 | [144; 146) '{}': () | 347 | [144; 146) '{}': () |
348 | [169; 198) '{ ...t(); }': () | 348 | [169; 198) '{ ...t(); }': () |
349 | [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H> | 349 | [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> |
350 | [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher> | 350 | [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher> |
351 | "### | 351 | "### |
352 | ); | 352 | ); |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index fdab9c187..3803f5938 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -754,15 +754,15 @@ fn test() { | |||
754 | [289; 295) 'self.0': T | 754 | [289; 295) 'self.0': T |
755 | [315; 353) '{ ...))); }': () | 755 | [315; 353) '{ ...))); }': () |
756 | [325; 326) 't': &i32 | 756 | [325; 326) 't': &i32 |
757 | [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T | 757 | [329; 335) 'A::foo': fn foo<i32>(&A<i32>) -> &i32 |
758 | [329; 350) 'A::foo...42))))': &i32 | 758 | [329; 350) 'A::foo...42))))': &i32 |
759 | [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>> | 759 | [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>> |
760 | [337; 349) '&B(B(A(42)))': &B<B<A<i32>>> | 760 | [337; 349) '&B(B(A(42)))': &B<B<A<i32>>> |
761 | [338; 339) 'B': B<B<A<i32>>>(T) -> B<T> | 761 | [338; 339) 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> |
762 | [338; 349) 'B(B(A(42)))': B<B<A<i32>>> | 762 | [338; 349) 'B(B(A(42)))': B<B<A<i32>>> |
763 | [340; 341) 'B': B<A<i32>>(T) -> B<T> | 763 | [340; 341) 'B': B<A<i32>>(A<i32>) -> B<A<i32>> |
764 | [340; 348) 'B(A(42))': B<A<i32>> | 764 | [340; 348) 'B(A(42))': B<A<i32>> |
765 | [342; 343) 'A': A<i32>(T) -> A<T> | 765 | [342; 343) 'A': A<i32>(i32) -> A<i32> |
766 | [342; 347) 'A(42)': A<i32> | 766 | [342; 347) 'A(42)': A<i32> |
767 | [344; 346) '42': i32 | 767 | [344; 346) '42': i32 |
768 | "### | 768 | "### |
@@ -817,16 +817,16 @@ fn test(a: A<i32>) { | |||
817 | [326; 327) 'a': A<i32> | 817 | [326; 327) 'a': A<i32> |
818 | [337; 383) '{ ...))); }': () | 818 | [337; 383) '{ ...))); }': () |
819 | [347; 348) 't': &i32 | 819 | [347; 348) 't': &i32 |
820 | [351; 352) 'A': A<i32>(*mut T) -> A<T> | 820 | [351; 352) 'A': A<i32>(*mut i32) -> A<i32> |
821 | [351; 365) 'A(0 as *mut _)': A<i32> | 821 | [351; 365) 'A(0 as *mut _)': A<i32> |
822 | [351; 380) 'A(0 as...B(a)))': &i32 | 822 | [351; 380) 'A(0 as...B(a)))': &i32 |
823 | [353; 354) '0': i32 | 823 | [353; 354) '0': i32 |
824 | [353; 364) '0 as *mut _': *mut i32 | 824 | [353; 364) '0 as *mut _': *mut i32 |
825 | [370; 379) '&&B(B(a))': &&B<B<A<i32>>> | 825 | [370; 379) '&&B(B(a))': &&B<B<A<i32>>> |
826 | [371; 379) '&B(B(a))': &B<B<A<i32>>> | 826 | [371; 379) '&B(B(a))': &B<B<A<i32>>> |
827 | [372; 373) 'B': B<B<A<i32>>>(T) -> B<T> | 827 | [372; 373) 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> |
828 | [372; 379) 'B(B(a))': B<B<A<i32>>> | 828 | [372; 379) 'B(B(a))': B<B<A<i32>>> |
829 | [374; 375) 'B': B<A<i32>>(T) -> B<T> | 829 | [374; 375) 'B': B<A<i32>>(A<i32>) -> B<A<i32>> |
830 | [374; 378) 'B(a)': B<A<i32>> | 830 | [374; 378) 'B(a)': B<A<i32>> |
831 | [376; 377) 'a': A<i32> | 831 | [376; 377) 'a': A<i32> |
832 | "### | 832 | "### |
@@ -1169,16 +1169,16 @@ fn test() { | |||
1169 | "#), | 1169 | "#), |
1170 | @r###" | 1170 | @r###" |
1171 | [76; 184) '{ ...one; }': () | 1171 | [76; 184) '{ ...one; }': () |
1172 | [82; 83) 'A': A<i32>(T) -> A<T> | 1172 | [82; 83) 'A': A<i32>(i32) -> A<i32> |
1173 | [82; 87) 'A(42)': A<i32> | 1173 | [82; 87) 'A(42)': A<i32> |
1174 | [84; 86) '42': i32 | 1174 | [84; 86) '42': i32 |
1175 | [93; 94) 'A': A<u128>(T) -> A<T> | 1175 | [93; 94) 'A': A<u128>(u128) -> A<u128> |
1176 | [93; 102) 'A(42u128)': A<u128> | 1176 | [93; 102) 'A(42u128)': A<u128> |
1177 | [95; 101) '42u128': u128 | 1177 | [95; 101) '42u128': u128 |
1178 | [108; 112) 'Some': Some<&str>(T) -> Option<T> | 1178 | [108; 112) 'Some': Some<&str>(&str) -> Option<&str> |
1179 | [108; 117) 'Some("x")': Option<&str> | 1179 | [108; 117) 'Some("x")': Option<&str> |
1180 | [113; 116) '"x"': &str | 1180 | [113; 116) '"x"': &str |
1181 | [123; 135) 'Option::Some': Some<&str>(T) -> Option<T> | 1181 | [123; 135) 'Option::Some': Some<&str>(&str) -> Option<&str> |
1182 | [123; 140) 'Option...e("x")': Option<&str> | 1182 | [123; 140) 'Option...e("x")': Option<&str> |
1183 | [136; 139) '"x"': &str | 1183 | [136; 139) '"x"': &str |
1184 | [146; 150) 'None': Option<{unknown}> | 1184 | [146; 150) 'None': Option<{unknown}> |
@@ -1205,14 +1205,14 @@ fn test() { | |||
1205 | [21; 26) '{ t }': T | 1205 | [21; 26) '{ t }': T |
1206 | [23; 24) 't': T | 1206 | [23; 24) 't': T |
1207 | [38; 98) '{ ...(1); }': () | 1207 | [38; 98) '{ ...(1); }': () |
1208 | [44; 46) 'id': fn id<u32>(T) -> T | 1208 | [44; 46) 'id': fn id<u32>(u32) -> u32 |
1209 | [44; 52) 'id(1u32)': u32 | 1209 | [44; 52) 'id(1u32)': u32 |
1210 | [47; 51) '1u32': u32 | 1210 | [47; 51) '1u32': u32 |
1211 | [58; 68) 'id::<i128>': fn id<i128>(T) -> T | 1211 | [58; 68) 'id::<i128>': fn id<i128>(i128) -> i128 |
1212 | [58; 71) 'id::<i128>(1)': i128 | 1212 | [58; 71) 'id::<i128>(1)': i128 |
1213 | [69; 70) '1': i128 | 1213 | [69; 70) '1': i128 |
1214 | [81; 82) 'x': u64 | 1214 | [81; 82) 'x': u64 |
1215 | [90; 92) 'id': fn id<u64>(T) -> T | 1215 | [90; 92) 'id': fn id<u64>(u64) -> u64 |
1216 | [90; 95) 'id(1)': u64 | 1216 | [90; 95) 'id(1)': u64 |
1217 | [93; 94) '1': u64 | 1217 | [93; 94) '1': u64 |
1218 | "### | 1218 | "### |
@@ -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> { |
@@ -1349,16 +1349,16 @@ fn test() -> i128 { | |||
1349 | [146; 147) 'x': i128 | 1349 | [146; 147) 'x': i128 |
1350 | [150; 151) '1': i128 | 1350 | [150; 151) '1': i128 |
1351 | [162; 163) 'y': i128 | 1351 | [162; 163) 'y': i128 |
1352 | [166; 168) 'id': fn id<i128>(T) -> T | 1352 | [166; 168) 'id': fn id<i128>(i128) -> i128 |
1353 | [166; 171) 'id(x)': i128 | 1353 | [166; 171) 'id(x)': i128 |
1354 | [169; 170) 'x': i128 | 1354 | [169; 170) 'x': i128 |
1355 | [182; 183) 'a': A<i128> | 1355 | [182; 183) 'a': A<i128> |
1356 | [186; 200) 'A { x: id(y) }': A<i128> | 1356 | [186; 200) 'A { x: id(y) }': A<i128> |
1357 | [193; 195) 'id': fn id<i128>(T) -> T | 1357 | [193; 195) 'id': fn id<i128>(i128) -> i128 |
1358 | [193; 198) 'id(y)': i128 | 1358 | [193; 198) 'id(y)': i128 |
1359 | [196; 197) 'y': i128 | 1359 | [196; 197) 'y': i128 |
1360 | [211; 212) 'z': i128 | 1360 | [211; 212) 'z': i128 |
1361 | [215; 217) 'id': fn id<i128>(T) -> T | 1361 | [215; 217) 'id': fn id<i128>(i128) -> i128 |
1362 | [215; 222) 'id(a.x)': i128 | 1362 | [215; 222) 'id(a.x)': i128 |
1363 | [218; 219) 'a': A<i128> | 1363 | [218; 219) 'a': A<i128> |
1364 | [218; 221) 'a.x': i128 | 1364 | [218; 221) 'a.x': i128 |
@@ -1502,14 +1502,14 @@ fn test() { | |||
1502 | [78; 158) '{ ...(1); }': () | 1502 | [78; 158) '{ ...(1); }': () |
1503 | [88; 89) 'y': u32 | 1503 | [88; 89) 'y': u32 |
1504 | [92; 97) '10u32': u32 | 1504 | [92; 97) '10u32': u32 |
1505 | [103; 105) 'id': fn id<u32>(T) -> T | 1505 | [103; 105) 'id': fn id<u32>(u32) -> u32 |
1506 | [103; 108) 'id(y)': u32 | 1506 | [103; 108) 'id(y)': u32 |
1507 | [106; 107) 'y': u32 | 1507 | [106; 107) 'y': u32 |
1508 | [118; 119) 'x': bool | 1508 | [118; 119) 'x': bool |
1509 | [128; 133) 'clone': fn clone<bool>(&T) -> T | 1509 | [128; 133) 'clone': fn clone<bool>(&bool) -> bool |
1510 | [128; 136) 'clone(z)': bool | 1510 | [128; 136) 'clone(z)': bool |
1511 | [134; 135) 'z': &bool | 1511 | [134; 135) 'z': &bool |
1512 | [142; 152) 'id::<i128>': fn id<i128>(T) -> T | 1512 | [142; 152) 'id::<i128>': fn id<i128>(i128) -> i128 |
1513 | [142; 155) 'id::<i128>(1)': i128 | 1513 | [142; 155) 'id::<i128>(1)': i128 |
1514 | [153; 154) '1': i128 | 1514 | [153; 154) '1': i128 |
1515 | "### | 1515 | "### |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index a6ac18f86..17611ddbf 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | 2 | ||
3 | use ra_db::fixture::WithFixture; | 3 | use ra_db::fixture::WithFixture; |
4 | use test_utils::covers; | ||
5 | 4 | ||
6 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | 5 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; |
7 | use crate::test_db::TestDB; | 6 | use crate::test_db::TestDB; |
@@ -261,10 +260,10 @@ fn test() { | |||
261 | [92; 94) '{}': () | 260 | [92; 94) '{}': () |
262 | [105; 144) '{ ...(s); }': () | 261 | [105; 144) '{ ...(s); }': () |
263 | [115; 116) 's': S<u32> | 262 | [115; 116) 's': S<u32> |
264 | [119; 120) 'S': S<u32>(T) -> S<T> | 263 | [119; 120) 'S': S<u32>(u32) -> S<u32> |
265 | [119; 129) 'S(unknown)': S<u32> | 264 | [119; 129) 'S(unknown)': S<u32> |
266 | [121; 128) 'unknown': u32 | 265 | [121; 128) 'unknown': u32 |
267 | [135; 138) 'foo': fn foo<S<u32>>(T) -> () | 266 | [135; 138) 'foo': fn foo<S<u32>>(S<u32>) -> () |
268 | [135; 141) 'foo(s)': () | 267 | [135; 141) 'foo(s)': () |
269 | [139; 140) 's': S<u32> | 268 | [139; 140) 's': S<u32> |
270 | "### | 269 | "### |
@@ -289,11 +288,11 @@ fn test() { | |||
289 | [98; 100) '{}': () | 288 | [98; 100) '{}': () |
290 | [111; 163) '{ ...(s); }': () | 289 | [111; 163) '{ ...(s); }': () |
291 | [121; 122) 's': S<u32> | 290 | [121; 122) 's': S<u32> |
292 | [125; 126) 'S': S<u32>(T) -> S<T> | 291 | [125; 126) 'S': S<u32>(u32) -> S<u32> |
293 | [125; 135) 'S(unknown)': S<u32> | 292 | [125; 135) 'S(unknown)': S<u32> |
294 | [127; 134) 'unknown': u32 | 293 | [127; 134) 'unknown': u32 |
295 | [145; 146) 'x': u32 | 294 | [145; 146) 'x': u32 |
296 | [154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U | 295 | [154; 157) 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32 |
297 | [154; 160) 'foo(s)': u32 | 296 | [154; 160) 'foo(s)': u32 |
298 | [158; 159) 's': S<u32> | 297 | [158; 159) 's': S<u32> |
299 | "### | 298 | "### |
@@ -358,15 +357,15 @@ fn test() { | |||
358 | [221; 223) '{}': () | 357 | [221; 223) '{}': () |
359 | [234; 300) '{ ...(S); }': () | 358 | [234; 300) '{ ...(S); }': () |
360 | [244; 245) 'x': u32 | 359 | [244; 245) 'x': u32 |
361 | [248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item | 360 | [248; 252) 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item |
362 | [248; 255) 'foo1(S)': u32 | 361 | [248; 255) 'foo1(S)': u32 |
363 | [253; 254) 'S': S | 362 | [253; 254) 'S': S |
364 | [265; 266) 'y': u32 | 363 | [265; 266) 'y': u32 |
365 | [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item | 364 | [269; 273) 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item |
366 | [269; 276) 'foo2(S)': u32 | 365 | [269; 276) 'foo2(S)': u32 |
367 | [274; 275) 'S': S | 366 | [274; 275) 'S': S |
368 | [286; 287) 'z': u32 | 367 | [286; 287) 'z': u32 |
369 | [290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item | 368 | [290; 294) 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item |
370 | [290; 297) 'foo3(S)': u32 | 369 | [290; 297) 'foo3(S)': u32 |
371 | [295; 296) 'S': S | 370 | [295; 296) 'S': S |
372 | "### | 371 | "### |
@@ -822,8 +821,7 @@ fn test<T: ApplyL>() { | |||
822 | "#, | 821 | "#, |
823 | ); | 822 | ); |
824 | // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. | 823 | // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. |
825 | // FIXME: fix type parameter names going missing when going through Chalk | 824 | assert_eq!(t, "ApplyL::Out<T>"); |
826 | assert_eq!(t, "ApplyL::Out<[missing name]>"); | ||
827 | } | 825 | } |
828 | 826 | ||
829 | #[test] | 827 | #[test] |
@@ -850,6 +848,197 @@ fn test<T: ApplyL>(t: T) { | |||
850 | } | 848 | } |
851 | 849 | ||
852 | #[test] | 850 | #[test] |
851 | fn argument_impl_trait() { | ||
852 | assert_snapshot!( | ||
853 | infer_with_mismatches(r#" | ||
854 | trait Trait<T> { | ||
855 | fn foo(&self) -> T; | ||
856 | fn foo2(&self) -> i64; | ||
857 | } | ||
858 | fn bar(x: impl Trait<u16>) {} | ||
859 | struct S<T>(T); | ||
860 | impl<T> Trait<T> for S<T> {} | ||
861 | |||
862 | fn test(x: impl Trait<u64>, y: &impl Trait<u32>) { | ||
863 | x; | ||
864 | y; | ||
865 | let z = S(1); | ||
866 | bar(z); | ||
867 | x.foo(); | ||
868 | y.foo(); | ||
869 | z.foo(); | ||
870 | x.foo2(); | ||
871 | y.foo2(); | ||
872 | z.foo2(); | ||
873 | } | ||
874 | "#, true), | ||
875 | @r###" | ||
876 | [30; 34) 'self': &Self | ||
877 | [55; 59) 'self': &Self | ||
878 | [78; 79) 'x': impl Trait<u16> | ||
879 | [98; 100) '{}': () | ||
880 | [155; 156) 'x': impl Trait<u64> | ||
881 | [175; 176) 'y': &impl Trait<u32> | ||
882 | [196; 324) '{ ...2(); }': () | ||
883 | [202; 203) 'x': impl Trait<u64> | ||
884 | [209; 210) 'y': &impl Trait<u32> | ||
885 | [220; 221) 'z': S<u16> | ||
886 | [224; 225) 'S': S<u16>(u16) -> S<u16> | ||
887 | [224; 228) 'S(1)': S<u16> | ||
888 | [226; 227) '1': u16 | ||
889 | [234; 237) 'bar': fn bar(S<u16>) -> () | ||
890 | [234; 240) 'bar(z)': () | ||
891 | [238; 239) 'z': S<u16> | ||
892 | [246; 247) 'x': impl Trait<u64> | ||
893 | [246; 253) 'x.foo()': u64 | ||
894 | [259; 260) 'y': &impl Trait<u32> | ||
895 | [259; 266) 'y.foo()': u32 | ||
896 | [272; 273) 'z': S<u16> | ||
897 | [272; 279) 'z.foo()': u16 | ||
898 | [285; 286) 'x': impl Trait<u64> | ||
899 | [285; 293) 'x.foo2()': i64 | ||
900 | [299; 300) 'y': &impl Trait<u32> | ||
901 | [299; 307) 'y.foo2()': i64 | ||
902 | [313; 314) 'z': S<u16> | ||
903 | [313; 321) 'z.foo2()': i64 | ||
904 | "### | ||
905 | ); | ||
906 | } | ||
907 | |||
908 | #[test] | ||
909 | fn argument_impl_trait_type_args_1() { | ||
910 | assert_snapshot!( | ||
911 | infer_with_mismatches(r#" | ||
912 | trait Trait {} | ||
913 | trait Foo { | ||
914 | // this function has an implicit Self param, an explicit type param, | ||
915 | // and an implicit impl Trait param! | ||
916 | fn bar<T>(x: impl Trait) -> T { loop {} } | ||
917 | } | ||
918 | fn foo<T>(x: impl Trait) -> T { loop {} } | ||
919 | struct S; | ||
920 | impl Trait for S {} | ||
921 | struct F; | ||
922 | impl Foo for F {} | ||
923 | |||
924 | fn test() { | ||
925 | Foo::bar(S); | ||
926 | <F as Foo>::bar(S); | ||
927 | F::bar(S); | ||
928 | Foo::bar::<u32>(S); | ||
929 | <F as Foo>::bar::<u32>(S); | ||
930 | |||
931 | foo(S); | ||
932 | foo::<u32>(S); | ||
933 | foo::<u32, i32>(S); // we should ignore the extraneous i32 | ||
934 | } | ||
935 | "#, true), | ||
936 | @r###" | ||
937 | [156; 157) 'x': impl Trait | ||
938 | [176; 187) '{ loop {} }': T | ||
939 | [178; 185) 'loop {}': ! | ||
940 | [183; 185) '{}': () | ||
941 | [200; 201) 'x': impl Trait | ||
942 | [220; 231) '{ loop {} }': T | ||
943 | [222; 229) 'loop {}': ! | ||
944 | [227; 229) '{}': () | ||
945 | [301; 510) '{ ... i32 }': () | ||
946 | [307; 315) 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} | ||
947 | [307; 318) 'Foo::bar(S)': {unknown} | ||
948 | [316; 317) 'S': S | ||
949 | [324; 339) '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown} | ||
950 | [324; 342) '<F as ...bar(S)': {unknown} | ||
951 | [340; 341) 'S': S | ||
952 | [348; 354) 'F::bar': fn bar<F, {unknown}>(S) -> {unknown} | ||
953 | [348; 357) 'F::bar(S)': {unknown} | ||
954 | [355; 356) 'S': S | ||
955 | [363; 378) 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32 | ||
956 | [363; 381) 'Foo::b...32>(S)': u32 | ||
957 | [379; 380) 'S': S | ||
958 | [387; 409) '<F as ...:<u32>': fn bar<F, u32>(S) -> u32 | ||
959 | [387; 412) '<F as ...32>(S)': u32 | ||
960 | [410; 411) 'S': S | ||
961 | [419; 422) 'foo': fn foo<{unknown}>(S) -> {unknown} | ||
962 | [419; 425) 'foo(S)': {unknown} | ||
963 | [423; 424) 'S': S | ||
964 | [431; 441) 'foo::<u32>': fn foo<u32>(S) -> u32 | ||
965 | [431; 444) 'foo::<u32>(S)': u32 | ||
966 | [442; 443) 'S': S | ||
967 | [450; 465) 'foo::<u32, i32>': fn foo<u32>(S) -> u32 | ||
968 | [450; 468) 'foo::<...32>(S)': u32 | ||
969 | [466; 467) 'S': S | ||
970 | "### | ||
971 | ); | ||
972 | } | ||
973 | |||
974 | #[test] | ||
975 | fn argument_impl_trait_type_args_2() { | ||
976 | assert_snapshot!( | ||
977 | infer_with_mismatches(r#" | ||
978 | trait Trait {} | ||
979 | struct S; | ||
980 | impl Trait for S {} | ||
981 | struct F<T>; | ||
982 | impl<T> F<T> { | ||
983 | fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} } | ||
984 | } | ||
985 | |||
986 | fn test() { | ||
987 | F.foo(S); | ||
988 | F::<u32>.foo(S); | ||
989 | F::<u32>.foo::<i32>(S); | ||
990 | F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored | ||
991 | } | ||
992 | "#, true), | ||
993 | @r###" | ||
994 | [88; 92) 'self': F<T> | ||
995 | [94; 95) 'x': impl Trait | ||
996 | [119; 130) '{ loop {} }': (T, U) | ||
997 | [121; 128) 'loop {}': ! | ||
998 | [126; 128) '{}': () | ||
999 | [144; 284) '{ ...ored }': () | ||
1000 | [150; 151) 'F': F<{unknown}> | ||
1001 | [150; 158) 'F.foo(S)': ({unknown}, {unknown}) | ||
1002 | [156; 157) 'S': S | ||
1003 | [164; 172) 'F::<u32>': F<u32> | ||
1004 | [164; 179) 'F::<u32>.foo(S)': (u32, {unknown}) | ||
1005 | [177; 178) 'S': S | ||
1006 | [185; 193) 'F::<u32>': F<u32> | ||
1007 | [185; 207) 'F::<u3...32>(S)': (u32, i32) | ||
1008 | [205; 206) 'S': S | ||
1009 | [213; 221) 'F::<u32>': F<u32> | ||
1010 | [213; 240) 'F::<u3...32>(S)': (u32, i32) | ||
1011 | [238; 239) 'S': S | ||
1012 | "### | ||
1013 | ); | ||
1014 | } | ||
1015 | |||
1016 | #[test] | ||
1017 | fn argument_impl_trait_to_fn_pointer() { | ||
1018 | assert_snapshot!( | ||
1019 | infer_with_mismatches(r#" | ||
1020 | trait Trait {} | ||
1021 | fn foo(x: impl Trait) { loop {} } | ||
1022 | struct S; | ||
1023 | impl Trait for S {} | ||
1024 | |||
1025 | fn test() { | ||
1026 | let f: fn(S) -> () = foo; | ||
1027 | } | ||
1028 | "#, true), | ||
1029 | @r###" | ||
1030 | [23; 24) 'x': impl Trait | ||
1031 | [38; 49) '{ loop {} }': () | ||
1032 | [40; 47) 'loop {}': ! | ||
1033 | [45; 47) '{}': () | ||
1034 | [91; 124) '{ ...foo; }': () | ||
1035 | [101; 102) 'f': fn(S) -> () | ||
1036 | [118; 121) 'foo': fn foo(S) -> () | ||
1037 | "### | ||
1038 | ); | ||
1039 | } | ||
1040 | |||
1041 | #[test] | ||
853 | #[ignore] | 1042 | #[ignore] |
854 | fn impl_trait() { | 1043 | fn impl_trait() { |
855 | assert_snapshot!( | 1044 | assert_snapshot!( |
@@ -994,29 +1183,17 @@ fn weird_bounds() { | |||
994 | assert_snapshot!( | 1183 | assert_snapshot!( |
995 | infer(r#" | 1184 | infer(r#" |
996 | trait Trait {} | 1185 | trait Trait {} |
997 | fn test() { | 1186 | fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) { |
998 | let a: impl Trait + 'lifetime = foo; | ||
999 | let b: impl 'lifetime = foo; | ||
1000 | let b: impl (Trait) = foo; | ||
1001 | let b: impl ('lifetime) = foo; | ||
1002 | let d: impl ?Sized = foo; | ||
1003 | let e: impl Trait + ?Sized = foo; | ||
1004 | } | 1187 | } |
1005 | "#), | 1188 | "#), |
1006 | @r###" | 1189 | @r###" |
1007 | [26; 237) '{ ...foo; }': () | 1190 | [24; 25) 'a': impl Trait + {error} |
1008 | [36; 37) 'a': impl Trait + {error} | 1191 | [51; 52) 'b': impl {error} |
1009 | [64; 67) 'foo': impl Trait + {error} | 1192 | [70; 71) 'c': impl Trait |
1010 | [77; 78) 'b': impl {error} | 1193 | [87; 88) 'd': impl {error} |
1011 | [97; 100) 'foo': impl {error} | 1194 | [108; 109) 'e': impl {error} |
1012 | [110; 111) 'b': impl Trait | 1195 | [124; 125) 'f': impl Trait + {error} |
1013 | [128; 131) 'foo': impl Trait | 1196 | [148; 151) '{ }': () |
1014 | [141; 142) 'b': impl {error} | ||
1015 | [163; 166) 'foo': impl {error} | ||
1016 | [176; 177) 'd': impl {error} | ||
1017 | [193; 196) 'foo': impl {error} | ||
1018 | [206; 207) 'e': impl Trait + {error} | ||
1019 | [231; 234) 'foo': impl Trait + {error} | ||
1020 | "### | 1197 | "### |
1021 | ); | 1198 | ); |
1022 | } | 1199 | } |
@@ -1078,26 +1255,26 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | |||
1078 | [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type | 1255 | [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type |
1079 | [296; 302) 'get(x)': {unknown} | 1256 | [296; 302) 'get(x)': {unknown} |
1080 | [300; 301) 'x': T | 1257 | [300; 301) 'x': T |
1081 | [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U | 1258 | [308; 312) 'get2': fn get2<{unknown}, T>(T) -> {unknown} |
1082 | [308; 315) 'get2(x)': {unknown} | 1259 | [308; 315) 'get2(x)': {unknown} |
1083 | [313; 314) 'x': T | 1260 | [313; 314) 'x': T |
1084 | [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type | 1261 | [321; 324) 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type |
1085 | [321; 327) 'get(y)': {unknown} | 1262 | [321; 327) 'get(y)': {unknown} |
1086 | [325; 326) 'y': impl Trait<Type = i64> | 1263 | [325; 326) 'y': impl Trait<Type = i64> |
1087 | [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(T) -> U | 1264 | [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> {unknown} |
1088 | [333; 340) 'get2(y)': {unknown} | 1265 | [333; 340) 'get2(y)': {unknown} |
1089 | [338; 339) 'y': impl Trait<Type = i64> | 1266 | [338; 339) 'y': impl Trait<Type = i64> |
1090 | [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type | 1267 | [346; 349) 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type |
1091 | [346; 357) 'get(set(S))': u64 | 1268 | [346; 357) 'get(set(S))': u64 |
1092 | [350; 353) 'set': fn set<S<u64>>(T) -> T | 1269 | [350; 353) 'set': fn set<S<u64>>(S<u64>) -> S<u64> |
1093 | [350; 356) 'set(S)': S<u64> | 1270 | [350; 356) 'set(S)': S<u64> |
1094 | [354; 355) 'S': S<u64> | 1271 | [354; 355) 'S': S<u64> |
1095 | [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U | 1272 | [363; 367) 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 |
1096 | [363; 375) 'get2(set(S))': u64 | 1273 | [363; 375) 'get2(set(S))': u64 |
1097 | [368; 371) 'set': fn set<S<u64>>(T) -> T | 1274 | [368; 371) 'set': fn set<S<u64>>(S<u64>) -> S<u64> |
1098 | [368; 374) 'set(S)': S<u64> | 1275 | [368; 374) 'set(S)': S<u64> |
1099 | [372; 373) 'S': S<u64> | 1276 | [372; 373) 'S': S<u64> |
1100 | [381; 385) 'get2': fn get2<str, S<str>>(T) -> U | 1277 | [381; 385) 'get2': fn get2<str, S<str>>(S<str>) -> str |
1101 | [381; 395) 'get2(S::<str>)': str | 1278 | [381; 395) 'get2(S::<str>)': str |
1102 | [386; 394) 'S::<str>': S<str> | 1279 | [386; 394) 'S::<str>': S<str> |
1103 | "### | 1280 | "### |
@@ -1225,6 +1402,32 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) { | |||
1225 | } | 1402 | } |
1226 | 1403 | ||
1227 | #[test] | 1404 | #[test] |
1405 | fn super_trait_impl_trait_method_resolution() { | ||
1406 | assert_snapshot!( | ||
1407 | infer(r#" | ||
1408 | mod foo { | ||
1409 | trait SuperTrait { | ||
1410 | fn foo(&self) -> u32 {} | ||
1411 | } | ||
1412 | } | ||
1413 | trait Trait1: foo::SuperTrait {} | ||
1414 | |||
1415 | fn test(x: &impl Trait1) { | ||
1416 | x.foo(); | ||
1417 | } | ||
1418 | "#), | ||
1419 | @r###" | ||
1420 | [50; 54) 'self': &Self | ||
1421 | [63; 65) '{}': () | ||
1422 | [116; 117) 'x': &impl Trait1 | ||
1423 | [133; 149) '{ ...o(); }': () | ||
1424 | [139; 140) 'x': &impl Trait1 | ||
1425 | [139; 146) 'x.foo()': u32 | ||
1426 | "### | ||
1427 | ); | ||
1428 | } | ||
1429 | |||
1430 | #[test] | ||
1228 | fn super_trait_cycle() { | 1431 | fn super_trait_cycle() { |
1229 | // This just needs to not crash | 1432 | // This just needs to not crash |
1230 | assert_snapshot!( | 1433 | assert_snapshot!( |
@@ -1270,9 +1473,9 @@ fn test() { | |||
1270 | [157; 160) '{t}': T | 1473 | [157; 160) '{t}': T |
1271 | [158; 159) 't': T | 1474 | [158; 159) 't': T |
1272 | [259; 280) '{ ...S)); }': () | 1475 | [259; 280) '{ ...S)); }': () |
1273 | [265; 269) 'get2': fn get2<u64, S<u64>>(T) -> U | 1476 | [265; 269) 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 |
1274 | [265; 277) 'get2(set(S))': u64 | 1477 | [265; 277) 'get2(set(S))': u64 |
1275 | [270; 273) 'set': fn set<S<u64>>(T) -> T | 1478 | [270; 273) 'set': fn set<S<u64>>(S<u64>) -> S<u64> |
1276 | [270; 276) 'set(S)': S<u64> | 1479 | [270; 276) 'set(S)': S<u64> |
1277 | [274; 275) 'S': S<u64> | 1480 | [274; 275) 'S': S<u64> |
1278 | "### | 1481 | "### |
@@ -1334,7 +1537,7 @@ fn test() { | |||
1334 | [173; 175) '{}': () | 1537 | [173; 175) '{}': () |
1335 | [189; 308) '{ ... 1); }': () | 1538 | [189; 308) '{ ... 1); }': () |
1336 | [199; 200) 'x': Option<u32> | 1539 | [199; 200) 'x': Option<u32> |
1337 | [203; 215) 'Option::Some': Some<u32>(T) -> Option<T> | 1540 | [203; 215) 'Option::Some': Some<u32>(u32) -> Option<u32> |
1338 | [203; 221) 'Option...(1u32)': Option<u32> | 1541 | [203; 221) 'Option...(1u32)': Option<u32> |
1339 | [216; 220) '1u32': u32 | 1542 | [216; 220) '1u32': u32 |
1340 | [227; 228) 'x': Option<u32> | 1543 | [227; 228) 'x': Option<u32> |
@@ -1444,7 +1647,7 @@ fn test() { | |||
1444 | [340; 342) '{}': () | 1647 | [340; 342) '{}': () |
1445 | [356; 515) '{ ... S); }': () | 1648 | [356; 515) '{ ... S); }': () |
1446 | [366; 368) 'x1': u64 | 1649 | [366; 368) 'x1': u64 |
1447 | [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(T, F) -> U | 1650 | [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64 |
1448 | [371; 394) 'foo1(S...hod())': u64 | 1651 | [371; 394) 'foo1(S...hod())': u64 |
1449 | [376; 377) 'S': S | 1652 | [376; 377) 'S': S |
1450 | [379; 393) '|s| s.method()': |S| -> u64 | 1653 | [379; 393) '|s| s.method()': |S| -> u64 |
@@ -1452,7 +1655,7 @@ fn test() { | |||
1452 | [383; 384) 's': S | 1655 | [383; 384) 's': S |
1453 | [383; 393) 's.method()': u64 | 1656 | [383; 393) 's.method()': u64 |
1454 | [404; 406) 'x2': u64 | 1657 | [404; 406) 'x2': u64 |
1455 | [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(F, T) -> U | 1658 | [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64 |
1456 | [409; 432) 'foo2(|...(), S)': u64 | 1659 | [409; 432) 'foo2(|...(), S)': u64 |
1457 | [414; 428) '|s| s.method()': |S| -> u64 | 1660 | [414; 428) '|s| s.method()': |S| -> u64 |
1458 | [415; 416) 's': S | 1661 | [415; 416) 's': S |
@@ -1605,7 +1808,6 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
1605 | 1808 | ||
1606 | #[test] | 1809 | #[test] |
1607 | fn unify_impl_trait() { | 1810 | fn unify_impl_trait() { |
1608 | covers!(insert_vars_for_impl_trait); | ||
1609 | assert_snapshot!( | 1811 | assert_snapshot!( |
1610 | infer_with_mismatches(r#" | 1812 | infer_with_mismatches(r#" |
1611 | trait Trait<T> {} | 1813 | trait Trait<T> {} |
@@ -1637,26 +1839,26 @@ fn test() -> impl Trait<i32> { | |||
1637 | [172; 183) '{ loop {} }': T | 1839 | [172; 183) '{ loop {} }': T |
1638 | [174; 181) 'loop {}': ! | 1840 | [174; 181) 'loop {}': ! |
1639 | [179; 181) '{}': () | 1841 | [179; 181) '{}': () |
1640 | [214; 310) '{ ...t()) }': S<i32> | 1842 | [214; 310) '{ ...t()) }': S<{unknown}> |
1641 | [224; 226) 's1': S<u32> | 1843 | [224; 226) 's1': S<u32> |
1642 | [229; 230) 'S': S<u32>(T) -> S<T> | 1844 | [229; 230) 'S': S<u32>(u32) -> S<u32> |
1643 | [229; 241) 'S(default())': S<u32> | 1845 | [229; 241) 'S(default())': S<u32> |
1644 | [231; 238) 'default': fn default<u32>() -> T | 1846 | [231; 238) 'default': fn default<u32>() -> u32 |
1645 | [231; 240) 'default()': u32 | 1847 | [231; 240) 'default()': u32 |
1646 | [247; 250) 'foo': fn foo(impl Trait<u32>) -> () | 1848 | [247; 250) 'foo': fn foo(S<u32>) -> () |
1647 | [247; 254) 'foo(s1)': () | 1849 | [247; 254) 'foo(s1)': () |
1648 | [251; 253) 's1': S<u32> | 1850 | [251; 253) 's1': S<u32> |
1649 | [264; 265) 'x': i32 | 1851 | [264; 265) 'x': i32 |
1650 | [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T | 1852 | [273; 276) 'bar': fn bar<i32>(S<i32>) -> i32 |
1651 | [273; 290) 'bar(S(...lt()))': i32 | 1853 | [273; 290) 'bar(S(...lt()))': i32 |
1652 | [277; 278) 'S': S<i32>(T) -> S<T> | 1854 | [277; 278) 'S': S<i32>(i32) -> S<i32> |
1653 | [277; 289) 'S(default())': S<i32> | 1855 | [277; 289) 'S(default())': S<i32> |
1654 | [279; 286) 'default': fn default<i32>() -> T | 1856 | [279; 286) 'default': fn default<i32>() -> i32 |
1655 | [279; 288) 'default()': i32 | 1857 | [279; 288) 'default()': i32 |
1656 | [296; 297) 'S': S<i32>(T) -> S<T> | 1858 | [296; 297) 'S': S<{unknown}>({unknown}) -> S<{unknown}> |
1657 | [296; 308) 'S(default())': S<i32> | 1859 | [296; 308) 'S(default())': S<{unknown}> |
1658 | [298; 305) 'default': fn default<i32>() -> T | 1860 | [298; 305) 'default': fn default<{unknown}>() -> {unknown} |
1659 | [298; 307) 'default()': i32 | 1861 | [298; 307) 'default()': {unknown} |
1660 | "### | 1862 | "### |
1661 | ); | 1863 | ); |
1662 | } | 1864 | } |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index fe9cb556c..4974c565b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -14,7 +14,7 @@ use ra_db::{ | |||
14 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 14 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
15 | use crate::{ | 15 | use crate::{ |
16 | db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, | 16 | db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, |
17 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 17 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | 20 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] |
@@ -142,9 +142,13 @@ impl ToChalk for Ty { | |||
142 | let substitution = proj_ty.parameters.to_chalk(db); | 142 | let substitution = proj_ty.parameters.to_chalk(db); |
143 | chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() | 143 | chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() |
144 | } | 144 | } |
145 | Ty::Param { idx, .. } => { | 145 | Ty::Param(id) => { |
146 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } | 146 | let interned_id = db.intern_type_param_id(id); |
147 | .to_ty::<TypeFamily>() | 147 | PlaceholderIndex { |
148 | ui: UniverseIndex::ROOT, | ||
149 | idx: interned_id.as_intern_id().as_usize(), | ||
150 | } | ||
151 | .to_ty::<TypeFamily>() | ||
148 | } | 152 | } |
149 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), | 153 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), |
150 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 154 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
@@ -177,7 +181,10 @@ impl ToChalk for Ty { | |||
177 | }, | 181 | }, |
178 | chalk_ir::TyData::Placeholder(idx) => { | 182 | chalk_ir::TyData::Placeholder(idx) => { |
179 | assert_eq!(idx.ui, UniverseIndex::ROOT); | 183 | assert_eq!(idx.ui, UniverseIndex::ROOT); |
180 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | 184 | let interned_id = crate::db::GlobalTypeParamId::from_intern_id( |
185 | crate::salsa::InternId::from(idx.idx), | ||
186 | ); | ||
187 | Ty::Param(db.lookup_intern_type_param_id(interned_id)) | ||
181 | } | 188 | } |
182 | chalk_ir::TyData::Alias(proj) => { | 189 | chalk_ir::TyData::Alias(proj) => { |
183 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 190 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
@@ -520,7 +527,7 @@ fn convert_where_clauses( | |||
520 | let generic_predicates = db.generic_predicates(def); | 527 | let generic_predicates = db.generic_predicates(def); |
521 | let mut result = Vec::with_capacity(generic_predicates.len()); | 528 | let mut result = Vec::with_capacity(generic_predicates.len()); |
522 | for pred in generic_predicates.iter() { | 529 | for pred in generic_predicates.iter() { |
523 | if pred.is_error() { | 530 | if pred.value.is_error() { |
524 | // skip errored predicates completely | 531 | // skip errored predicates completely |
525 | continue; | 532 | continue; |
526 | } | 533 | } |
@@ -709,12 +716,12 @@ fn impl_block_datum( | |||
709 | let trait_ref = db | 716 | let trait_ref = db |
710 | .impl_trait(impl_id) | 717 | .impl_trait(impl_id) |
711 | // ImplIds for impls where the trait ref can't be resolved should never reach Chalk | 718 | // ImplIds for impls where the trait ref can't be resolved should never reach Chalk |
712 | .expect("invalid impl passed to Chalk"); | 719 | .expect("invalid impl passed to Chalk") |
720 | .value; | ||
713 | let impl_data = db.impl_data(impl_id); | 721 | let impl_data = db.impl_data(impl_id); |
714 | 722 | ||
715 | let generic_params = generics(db, impl_id.into()); | 723 | let generic_params = generics(db, impl_id.into()); |
716 | let bound_vars = Substs::bound_vars(&generic_params); | 724 | let bound_vars = Substs::bound_vars(&generic_params); |
717 | let trait_ref = trait_ref.subst(&bound_vars); | ||
718 | let trait_ = trait_ref.trait_; | 725 | let trait_ = trait_ref.trait_; |
719 | let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { | 726 | let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { |
720 | chalk_rust_ir::ImplType::Local | 727 | chalk_rust_ir::ImplType::Local |
@@ -789,20 +796,18 @@ fn type_alias_associated_ty_value( | |||
789 | _ => panic!("assoc ty value should be in impl"), | 796 | _ => panic!("assoc ty value should be in impl"), |
790 | }; | 797 | }; |
791 | 798 | ||
792 | let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved | 799 | let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved |
793 | 800 | ||
794 | let assoc_ty = db | 801 | let assoc_ty = db |
795 | .trait_data(trait_ref.trait_) | 802 | .trait_data(trait_ref.trait_) |
796 | .associated_type_by_name(&type_alias_data.name) | 803 | .associated_type_by_name(&type_alias_data.name) |
797 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | 804 | .expect("assoc ty value should not exist"); // validated when building the impl data as well |
798 | let generic_params = generics(db, impl_id.into()); | 805 | let ty = db.ty(type_alias.into()); |
799 | let bound_vars = Substs::bound_vars(&generic_params); | 806 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; |
800 | let ty = db.ty(type_alias.into()).subst(&bound_vars); | ||
801 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
802 | let value = chalk_rust_ir::AssociatedTyValue { | 807 | let value = chalk_rust_ir::AssociatedTyValue { |
803 | impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db), | 808 | impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db), |
804 | associated_ty_id: assoc_ty.to_chalk(db), | 809 | associated_ty_id: assoc_ty.to_chalk(db), |
805 | value: make_binders(value_bound, bound_vars.len()), | 810 | value: make_binders(value_bound, ty.num_binders), |
806 | }; | 811 | }; |
807 | Arc::new(value) | 812 | Arc::new(value) |
808 | } | 813 | } |
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 0b1806a84..508ae9046 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -2,10 +2,11 @@ | |||
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 hir_def::generics::WherePredicateTarget; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | adt::VariantData, | 7 | adt::VariantData, |
7 | db::DefDatabase, | 8 | db::DefDatabase, |
8 | generics::{GenericParams, TypeParamData}, | 9 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
9 | path::Path, | 10 | path::Path, |
10 | resolver::{HasResolver, TypeNs}, | 11 | resolver::{HasResolver, TypeNs}, |
11 | type_ref::TypeRef, | 12 | type_ref::TypeRef, |
@@ -19,11 +20,18 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
19 | // lifetime problems, but since there usually shouldn't be more than a | 20 | // lifetime problems, but since there usually shouldn't be more than a |
20 | // few direct traits this should be fine (we could even use some kind of | 21 | // few direct traits this should be fine (we could even use some kind of |
21 | // SmallVec if performance is a concern) | 22 | // SmallVec if performance is a concern) |
22 | db.generic_params(trait_.into()) | 23 | let generic_params = db.generic_params(trait_.into()); |
24 | let trait_self = generic_params.find_trait_self_param(); | ||
25 | generic_params | ||
23 | .where_predicates | 26 | .where_predicates |
24 | .iter() | 27 | .iter() |
25 | .filter_map(|pred| match &pred.type_ref { | 28 | .filter_map(|pred| match &pred.target { |
26 | TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(), | 29 | WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => { |
30 | pred.bound.as_path() | ||
31 | } | ||
32 | WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | ||
33 | pred.bound.as_path() | ||
34 | } | ||
27 | _ => None, | 35 | _ => None, |
28 | }) | 36 | }) |
29 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { | 37 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { |
@@ -95,41 +103,77 @@ pub(crate) struct Generics { | |||
95 | } | 103 | } |
96 | 104 | ||
97 | impl Generics { | 105 | impl Generics { |
98 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { | 106 | pub(crate) fn iter<'a>( |
107 | &'a self, | ||
108 | ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a { | ||
99 | self.parent_generics | 109 | self.parent_generics |
100 | .as_ref() | 110 | .as_ref() |
101 | .into_iter() | 111 | .into_iter() |
102 | .flat_map(|it| it.params.types.iter()) | 112 | .flat_map(|it| { |
103 | .chain(self.params.types.iter()) | 113 | it.params |
104 | .enumerate() | 114 | .types |
105 | .map(|(i, (_local_id, p))| (i as u32, p)) | 115 | .iter() |
116 | .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) | ||
117 | }) | ||
118 | .chain( | ||
119 | self.params | ||
120 | .types | ||
121 | .iter() | ||
122 | .map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)), | ||
123 | ) | ||
106 | } | 124 | } |
107 | 125 | ||
108 | pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { | 126 | pub(crate) fn iter_parent<'a>( |
109 | self.parent_generics | 127 | &'a self, |
110 | .as_ref() | 128 | ) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a { |
111 | .into_iter() | 129 | self.parent_generics.as_ref().into_iter().flat_map(|it| { |
112 | .flat_map(|it| it.params.types.iter()) | 130 | it.params |
113 | .enumerate() | 131 | .types |
114 | .map(|(i, (_local_id, p))| (i as u32, p)) | 132 | .iter() |
133 | .map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)) | ||
134 | }) | ||
115 | } | 135 | } |
116 | 136 | ||
117 | pub(crate) fn len(&self) -> usize { | 137 | pub(crate) fn len(&self) -> usize { |
118 | self.len_split().0 | 138 | self.len_split().0 |
119 | } | 139 | } |
140 | |||
120 | /// (total, parents, child) | 141 | /// (total, parents, child) |
121 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { | 142 | pub(crate) fn len_split(&self) -> (usize, usize, usize) { |
122 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); | 143 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); |
123 | let child = self.params.types.len(); | 144 | let child = self.params.types.len(); |
124 | (parent + child, parent, child) | 145 | (parent + child, parent, child) |
125 | } | 146 | } |
126 | pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { | 147 | |
127 | self.find_param(param).0 | 148 | /// (parent total, self param, type param list, impl trait) |
149 | pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize) { | ||
150 | let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); | ||
151 | let self_params = self | ||
152 | .params | ||
153 | .types | ||
154 | .iter() | ||
155 | .filter(|(_, p)| p.provenance == TypeParamProvenance::TraitSelf) | ||
156 | .count(); | ||
157 | let list_params = self | ||
158 | .params | ||
159 | .types | ||
160 | .iter() | ||
161 | .filter(|(_, p)| p.provenance == TypeParamProvenance::TypeParamList) | ||
162 | .count(); | ||
163 | let impl_trait_params = self | ||
164 | .params | ||
165 | .types | ||
166 | .iter() | ||
167 | .filter(|(_, p)| p.provenance == TypeParamProvenance::ArgumentImplTrait) | ||
168 | .count(); | ||
169 | (parent, self_params, list_params, impl_trait_params) | ||
128 | } | 170 | } |
129 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { | 171 | |
130 | self.find_param(param).1.name.clone() | 172 | pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> { |
173 | Some(self.find_param(param)?.0) | ||
131 | } | 174 | } |
132 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { | 175 | |
176 | fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> { | ||
133 | if param.parent == self.def { | 177 | if param.parent == self.def { |
134 | let (idx, (_local_id, data)) = self | 178 | let (idx, (_local_id, data)) = self |
135 | .params | 179 | .params |
@@ -139,9 +183,10 @@ impl Generics { | |||
139 | .find(|(_, (idx, _))| *idx == param.local_id) | 183 | .find(|(_, (idx, _))| *idx == param.local_id) |
140 | .unwrap(); | 184 | .unwrap(); |
141 | let (_total, parent_len, _child) = self.len_split(); | 185 | let (_total, parent_len, _child) = self.len_split(); |
142 | return ((parent_len + idx) as u32, data); | 186 | Some(((parent_len + idx) as u32, data)) |
187 | } else { | ||
188 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) | ||
143 | } | 189 | } |
144 | self.parent_generics.as_ref().unwrap().find_param(param) | ||
145 | } | 190 | } |
146 | } | 191 | } |
147 | 192 | ||