diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-22 20:39:58 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-22 20:39:58 +0000 |
commit | 4b997b86633b1c0ca134d89e8236d285422c04e3 (patch) | |
tree | 89544f6e84fec2a981cf60cf05aa2af1ac903cf5 /crates | |
parent | 97fe64a5c7d68a40adf7b88d5cc992f9f3066537 (diff) | |
parent | 0aa4ac362d1a40e4aea98857d22a2cd3884aa215 (diff) |
Merge #8156
8156: Correctly lower TraitRefs with default params r=flodiebold a=Veykril
Fixes #5685
Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/lower.rs | 25 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 46 |
2 files changed, 63 insertions, 8 deletions
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index f60cec649..3153b5b74 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -521,7 +521,7 @@ impl<'a> TyLoweringContext<'a> { | |||
521 | TyDefId::AdtId(it) => Some(it.into()), | 521 | TyDefId::AdtId(it) => Some(it.into()), |
522 | TyDefId::TypeAliasId(it) => Some(it.into()), | 522 | TyDefId::TypeAliasId(it) => Some(it.into()), |
523 | }; | 523 | }; |
524 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args); | 524 | let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); |
525 | self.db.ty(typeable).subst(&substs) | 525 | self.db.ty(typeable).subst(&substs) |
526 | } | 526 | } |
527 | 527 | ||
@@ -558,7 +558,7 @@ impl<'a> TyLoweringContext<'a> { | |||
558 | (segment, Some(var.parent.into())) | 558 | (segment, Some(var.parent.into())) |
559 | } | 559 | } |
560 | }; | 560 | }; |
561 | self.substs_from_path_segment(segment, generic_def, infer_args) | 561 | self.substs_from_path_segment(segment, generic_def, infer_args, None) |
562 | } | 562 | } |
563 | 563 | ||
564 | fn substs_from_path_segment( | 564 | fn substs_from_path_segment( |
@@ -566,6 +566,7 @@ impl<'a> TyLoweringContext<'a> { | |||
566 | segment: PathSegment<'_>, | 566 | segment: PathSegment<'_>, |
567 | def_generic: Option<GenericDefId>, | 567 | def_generic: Option<GenericDefId>, |
568 | infer_args: bool, | 568 | infer_args: bool, |
569 | explicit_self_ty: Option<Ty>, | ||
569 | ) -> Substitution { | 570 | ) -> Substitution { |
570 | let mut substs = Vec::new(); | 571 | let mut substs = Vec::new(); |
571 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); | 572 | let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); |
@@ -576,11 +577,19 @@ impl<'a> TyLoweringContext<'a> { | |||
576 | 577 | ||
577 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); | 578 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); |
578 | 579 | ||
580 | let fill_self_params = || { | ||
581 | substs.extend( | ||
582 | explicit_self_ty | ||
583 | .into_iter() | ||
584 | .chain(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
585 | .take(self_params), | ||
586 | ) | ||
587 | }; | ||
579 | let mut had_explicit_type_args = false; | 588 | let mut had_explicit_type_args = false; |
580 | 589 | ||
581 | if let Some(generic_args) = &segment.args_and_bindings { | 590 | if let Some(generic_args) = &segment.args_and_bindings { |
582 | if !generic_args.has_self_type { | 591 | if !generic_args.has_self_type { |
583 | substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params)); | 592 | fill_self_params(); |
584 | } | 593 | } |
585 | let expected_num = | 594 | let expected_num = |
586 | if generic_args.has_self_type { self_params + type_params } else { type_params }; | 595 | if generic_args.has_self_type { self_params + type_params } else { type_params }; |
@@ -602,6 +611,8 @@ impl<'a> TyLoweringContext<'a> { | |||
602 | GenericArg::Lifetime(_) => {} | 611 | GenericArg::Lifetime(_) => {} |
603 | } | 612 | } |
604 | } | 613 | } |
614 | } else { | ||
615 | fill_self_params(); | ||
605 | } | 616 | } |
606 | 617 | ||
607 | // handle defaults. In expression or pattern path segments without | 618 | // handle defaults. In expression or pattern path segments without |
@@ -650,10 +661,7 @@ impl<'a> TyLoweringContext<'a> { | |||
650 | segment: PathSegment<'_>, | 661 | segment: PathSegment<'_>, |
651 | explicit_self_ty: Option<Ty>, | 662 | explicit_self_ty: Option<Ty>, |
652 | ) -> TraitRef { | 663 | ) -> TraitRef { |
653 | let mut substs = self.trait_ref_substs_from_path(segment, resolved); | 664 | let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); |
654 | if let Some(self_ty) = explicit_self_ty { | ||
655 | substs.0[0] = self_ty; | ||
656 | } | ||
657 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } | 665 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } |
658 | } | 666 | } |
659 | 667 | ||
@@ -673,8 +681,9 @@ impl<'a> TyLoweringContext<'a> { | |||
673 | &self, | 681 | &self, |
674 | segment: PathSegment<'_>, | 682 | segment: PathSegment<'_>, |
675 | resolved: TraitId, | 683 | resolved: TraitId, |
684 | explicit_self_ty: Option<Ty>, | ||
676 | ) -> Substitution { | 685 | ) -> Substitution { |
677 | self.substs_from_path_segment(segment, Some(resolved.into()), false) | 686 | self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) |
678 | } | 687 | } |
679 | 688 | ||
680 | pub(crate) fn lower_where_predicate( | 689 | pub(crate) fn lower_where_predicate( |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 37cd04c6f..45a1958e3 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3324,3 +3324,49 @@ fn f() { | |||
3324 | "#]], | 3324 | "#]], |
3325 | ) | 3325 | ) |
3326 | } | 3326 | } |
3327 | |||
3328 | #[test] | ||
3329 | fn infer_default_trait_type_parameter() { | ||
3330 | check_infer( | ||
3331 | r#" | ||
3332 | struct A; | ||
3333 | |||
3334 | trait Op<RHS=Self> { | ||
3335 | type Output; | ||
3336 | |||
3337 | fn do_op(self, rhs: RHS) -> Self::Output; | ||
3338 | } | ||
3339 | |||
3340 | impl Op for A { | ||
3341 | type Output = bool; | ||
3342 | |||
3343 | fn do_op(self, rhs: Self) -> Self::Output { | ||
3344 | true | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | fn test() { | ||
3349 | let x = A; | ||
3350 | let y = A; | ||
3351 | let r = x.do_op(y); | ||
3352 | } | ||
3353 | "#, | ||
3354 | expect![[r#" | ||
3355 | 63..67 'self': Self | ||
3356 | 69..72 'rhs': RHS | ||
3357 | 153..157 'self': A | ||
3358 | 159..162 'rhs': A | ||
3359 | 186..206 '{ ... }': bool | ||
3360 | 196..200 'true': bool | ||
3361 | 220..277 '{ ...(y); }': () | ||
3362 | 230..231 'x': A | ||
3363 | 234..235 'A': A | ||
3364 | 245..246 'y': A | ||
3365 | 249..250 'A': A | ||
3366 | 260..261 'r': bool | ||
3367 | 264..265 'x': A | ||
3368 | 264..274 'x.do_op(y)': bool | ||
3369 | 272..273 'y': A | ||
3370 | "#]], | ||
3371 | ) | ||
3372 | } | ||