aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/lower.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-02-07 15:24:09 +0000
committerFlorian Diebold <[email protected]>2020-02-07 17:28:10 +0000
commit6c70619b0126bc0e40bd9df39dcd6e711cac69c5 (patch)
treec9812b922e3f7ec753ff18e0b17b0f54f18ea737 /crates/ra_hir_ty/src/lower.rs
parentdded90a748737c3661aad043524f2248e324c867 (diff)
Deal better with implicit type parameters and argument lists
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r--crates/ra_hir_ty/src/lower.rs41
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);