aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-03-22 18:13:43 +0000
committerLukas Wirth <[email protected]>2021-03-22 18:13:43 +0000
commit0aa4ac362d1a40e4aea98857d22a2cd3884aa215 (patch)
treed5b08bd272f28ad16e7b6a23b3502434c2370e1e /crates/hir_ty
parent94aa3a7b1af7b756139e6c2d8384beb57daa6190 (diff)
Correctly lower TraitRefs with default params
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/lower.rs25
-rw-r--r--crates/hir_ty/src/tests/traits.rs46
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]
3329fn infer_default_trait_type_parameter() {
3330 check_infer(
3331 r#"
3332struct A;
3333
3334trait Op<RHS=Self> {
3335 type Output;
3336
3337 fn do_op(self, rhs: RHS) -> Self::Output;
3338}
3339
3340impl Op for A {
3341 type Output = bool;
3342
3343 fn do_op(self, rhs: Self) -> Self::Output {
3344 true
3345 }
3346}
3347
3348fn 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}