From 0aa4ac362d1a40e4aea98857d22a2cd3884aa215 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 22 Mar 2021 19:13:43 +0100 Subject: Correctly lower TraitRefs with default params --- crates/hir_ty/src/lower.rs | 25 ++++++++++++++------- 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> { TyDefId::AdtId(it) => Some(it.into()), TyDefId::TypeAliasId(it) => Some(it.into()), }; - let substs = self.substs_from_path_segment(segment, generic_def, infer_args); + let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); self.db.ty(typeable).subst(&substs) } @@ -558,7 +558,7 @@ impl<'a> TyLoweringContext<'a> { (segment, Some(var.parent.into())) } }; - self.substs_from_path_segment(segment, generic_def, infer_args) + self.substs_from_path_segment(segment, generic_def, infer_args, None) } fn substs_from_path_segment( @@ -566,6 +566,7 @@ impl<'a> TyLoweringContext<'a> { segment: PathSegment<'_>, def_generic: Option, infer_args: bool, + explicit_self_ty: Option, ) -> Substitution { let mut substs = Vec::new(); let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); @@ -576,11 +577,19 @@ impl<'a> TyLoweringContext<'a> { substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); + let fill_self_params = || { + substs.extend( + explicit_self_ty + .into_iter() + .chain(iter::repeat(TyKind::Unknown.intern(&Interner))) + .take(self_params), + ) + }; let mut had_explicit_type_args = false; if let Some(generic_args) = &segment.args_and_bindings { if !generic_args.has_self_type { - substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params)); + fill_self_params(); } let expected_num = if generic_args.has_self_type { self_params + type_params } else { type_params }; @@ -602,6 +611,8 @@ impl<'a> TyLoweringContext<'a> { GenericArg::Lifetime(_) => {} } } + } else { + fill_self_params(); } // handle defaults. In expression or pattern path segments without @@ -650,10 +661,7 @@ impl<'a> TyLoweringContext<'a> { segment: PathSegment<'_>, explicit_self_ty: Option, ) -> TraitRef { - let mut substs = self.trait_ref_substs_from_path(segment, resolved); - if let Some(self_ty) = explicit_self_ty { - substs.0[0] = self_ty; - } + let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } } @@ -673,8 +681,9 @@ impl<'a> TyLoweringContext<'a> { &self, segment: PathSegment<'_>, resolved: TraitId, + explicit_self_ty: Option, ) -> Substitution { - self.substs_from_path_segment(segment, Some(resolved.into()), false) + self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) } 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() { "#]], ) } + +#[test] +fn infer_default_trait_type_parameter() { + check_infer( + r#" +struct A; + +trait Op { + type Output; + + fn do_op(self, rhs: RHS) -> Self::Output; +} + +impl Op for A { + type Output = bool; + + fn do_op(self, rhs: Self) -> Self::Output { + true + } +} + +fn test() { + let x = A; + let y = A; + let r = x.do_op(y); +} + "#, + expect![[r#" + 63..67 'self': Self + 69..72 'rhs': RHS + 153..157 'self': A + 159..162 'rhs': A + 186..206 '{ ... }': bool + 196..200 'true': bool + 220..277 '{ ...(y); }': () + 230..231 'x': A + 234..235 'A': A + 245..246 'y': A + 249..250 'A': A + 260..261 'r': bool + 264..265 'x': A + 264..274 'x.do_op(y)': bool + 272..273 'y': A + "#]], + ) +} -- cgit v1.2.3