8156: Correctly lower TraitRefs with default params r=flodiebold a=Veykril

Fixes #5685

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-03-22 20:39:58 +00:00 committed by GitHub
commit 4b997b8663
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 8 deletions

View file

@ -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<GenericDefId>,
infer_args: bool,
explicit_self_ty: Option<Ty>,
) -> 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<Ty>,
) -> 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<Ty>,
) -> 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(

View file

@ -3324,3 +3324,49 @@ fn f() {
"#]],
)
}
#[test]
fn infer_default_trait_type_parameter() {
check_infer(
r#"
struct A;
trait Op<RHS=Self> {
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
"#]],
)
}