diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 4168e7509..d2df3fe2b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -161,15 +161,19 @@ impl Ty { | |||
161 | ImplTraitLoweringMode::Variable => { | 161 | ImplTraitLoweringMode::Variable => { |
162 | let idx = ctx.impl_trait_counter.get(); | 162 | let idx = ctx.impl_trait_counter.get(); |
163 | ctx.impl_trait_counter.set(idx + 1); | 163 | ctx.impl_trait_counter.set(idx + 1); |
164 | let (self_params, list_params, _impl_trait_params) = | 164 | let (parent_params, self_params, list_params, _impl_trait_params) = |
165 | if let Some(def) = ctx.resolver.generic_def() { | 165 | if let Some(def) = ctx.resolver.generic_def() { |
166 | let generics = generics(ctx.db, def); | 166 | let generics = generics(ctx.db, def); |
167 | generics.provenance_split() | 167 | generics.provenance_split() |
168 | } else { | 168 | } else { |
169 | (0, 0, 0) | 169 | (0, 0, 0, 0) |
170 | }; | 170 | }; |
171 | // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait | 171 | Ty::Bound( |
172 | Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) | 172 | idx as u32 |
173 | + parent_params as u32 | ||
174 | + self_params as u32 | ||
175 | + list_params as u32, | ||
176 | ) | ||
173 | } | 177 | } |
174 | ImplTraitLoweringMode::Disallowed => { | 178 | ImplTraitLoweringMode::Disallowed => { |
175 | // FIXME: report error | 179 | // FIXME: report error |
@@ -420,26 +424,23 @@ pub(super) fn substs_from_path_segment( | |||
420 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | 424 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
421 | segment: PathSegment<'_>, | 425 | segment: PathSegment<'_>, |
422 | def_generic: Option<GenericDefId>, | 426 | def_generic: Option<GenericDefId>, |
423 | add_self_param: bool, | 427 | _add_self_param: bool, |
424 | ) -> Substs { | 428 | ) -> Substs { |
425 | let mut substs = Vec::new(); | 429 | let mut substs = Vec::new(); |
426 | let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); | 430 | let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); |
427 | 431 | ||
428 | 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) = |
429 | substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); | 433 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); |
430 | if add_self_param { | 434 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
431 | // FIXME this add_self_param argument is kind of a hack: Traits have the | ||
432 | // Self type as an implicit first type parameter, but it can't be | ||
433 | // actually provided in the type arguments | ||
434 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
435 | // TODO handle this using type param provenance (if there's a self param, and not one provided, add unknown) | ||
436 | substs.push(Ty::Unknown); | ||
437 | } | ||
438 | 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 }; | ||
439 | // 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 |
440 | let self_param_correction = if add_self_param { 1 } else { 0 }; | 443 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
441 | let child_len = child_len - self_param_correction; | ||
442 | for arg in generic_args.args.iter().take(child_len) { | ||
443 | match arg { | 444 | match arg { |
444 | GenericArg::Type(type_ref) => { | 445 | GenericArg::Type(type_ref) => { |
445 | let ty = Ty::from_hir(ctx, type_ref); | 446 | let ty = Ty::from_hir(ctx, type_ref); |
@@ -448,9 +449,9 @@ pub(super) fn substs_from_path_segment( | |||
448 | } | 449 | } |
449 | } | 450 | } |
450 | } | 451 | } |
452 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
451 | // add placeholders for args that were not provided | 453 | // add placeholders for args that were not provided |
452 | let supplied_params = substs.len(); | 454 | for _ in substs.len()..total_len { |
453 | for _ in supplied_params..total_len { | ||
454 | substs.push(Ty::Unknown); | 455 | substs.push(Ty::Unknown); |
455 | } | 456 | } |
456 | assert_eq!(substs.len(), total_len); | 457 | assert_eq!(substs.len(), total_len); |