fix const generic panic in dyn trait

This commit is contained in:
hkalbasi 2022-04-22 01:35:28 +04:30
parent 71d49d31bb
commit d33d5fca1d
2 changed files with 66 additions and 36 deletions

View file

@ -681,23 +681,31 @@ impl<'a> TyLoweringContext<'a> {
let ty_error = GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner); let ty_error = GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner);
for eid in def_generics.iter_id().take(parent_params) { let mut def_generic_iter = def_generics.iter_id();
match eid {
Either::Left(_) => substs.push(ty_error.clone()), for _ in 0..parent_params {
Either::Right(x) => { if let Some(eid) = def_generic_iter.next() {
substs.push(unknown_const_as_generic(self.db.const_param_ty(x))) match eid {
Either::Left(_) => substs.push(ty_error.clone()),
Either::Right(x) => {
substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
}
} }
} }
} }
let fill_self_params = || { let fill_self_params = || {
substs.extend( for x in explicit_self_ty
explicit_self_ty .into_iter()
.into_iter() .map(|x| GenericArgData::Ty(x).intern(Interner))
.map(|x| GenericArgData::Ty(x).intern(Interner)) .chain(iter::repeat(ty_error.clone()))
.chain(iter::repeat(ty_error.clone())) .take(self_params)
.take(self_params), {
) if let Some(id) = def_generic_iter.next() {
assert!(id.is_left());
substs.push(x);
}
}
}; };
let mut had_explicit_args = false; let mut had_explicit_args = false;
@ -712,34 +720,37 @@ impl<'a> TyLoweringContext<'a> {
}; };
let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
// if args are provided, it should be all of them, but we can't rely on that // if args are provided, it should be all of them, but we can't rely on that
for (arg, id) in generic_args for arg in generic_args
.args .args
.iter() .iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) .filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.skip(skip) .skip(skip)
.take(expected_num) .take(expected_num)
.zip(def_generics.iter_id().skip(parent_params + skip))
{ {
if let Some(x) = generic_arg_to_chalk( if let Some(id) = def_generic_iter.next() {
self.db, if let Some(x) = generic_arg_to_chalk(
id, self.db,
arg, id,
&mut (), arg,
|_, type_ref| self.lower_ty(type_ref), &mut (),
|_, c, ty| { |_, type_ref| self.lower_ty(type_ref),
const_or_path_to_chalk( |_, c, ty| {
self.db, const_or_path_to_chalk(
&self.resolver, self.db,
ty, &self.resolver,
c, ty,
self.type_param_mode, c,
|| self.generics(), self.type_param_mode,
self.in_binders, || self.generics(),
) self.in_binders,
}, )
) { },
had_explicit_args = true; ) {
substs.push(x); had_explicit_args = true;
substs.push(x);
} else {
never!();
}
} }
} }
} else { } else {
@ -757,14 +768,16 @@ impl<'a> TyLoweringContext<'a> {
for default_ty in defaults.iter().skip(substs.len()) { for default_ty in defaults.iter().skip(substs.len()) {
// each default can depend on the previous parameters // each default can depend on the previous parameters
let substs_so_far = Substitution::from_iter(Interner, substs.clone()); let substs_so_far = Substitution::from_iter(Interner, substs.clone());
substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); if let Some(_id) = def_generic_iter.next() {
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
}
} }
} }
} }
// add placeholders for args that were not provided // add placeholders for args that were not provided
// FIXME: emit diagnostics in contexts where this is not allowed // FIXME: emit diagnostics in contexts where this is not allowed
for eid in def_generics.iter_id().skip(substs.len()) { for eid in def_generic_iter {
match eid { match eid {
Either::Left(_) => substs.push(ty_error.clone()), Either::Left(_) => substs.push(ty_error.clone()),
Either::Right(x) => { Either::Right(x) => {
@ -772,6 +785,7 @@ impl<'a> TyLoweringContext<'a> {
} }
} }
} }
// If this assert fails, it means you pushed into subst but didn't call .next() of def_generic_iter
assert_eq!(substs.len(), total_len); assert_eq!(substs.len(), total_len);
Substitution::from_iter(Interner, substs) Substitution::from_iter(Interner, substs)

View file

@ -1470,6 +1470,22 @@ fn regression_11688_3() {
); );
} }
#[test]
fn regression_11688_4() {
check_types(
r#"
trait Bar<const C: usize> {
fn baz(&self) -> [i32; C];
}
fn foo(x: &dyn Bar<2>) {
x.baz();
//^^^^^^^ [i32; 2]
}
"#,
)
}
#[test] #[test]
fn gat_crash_1() { fn gat_crash_1() {
cov_mark::check!(ignore_gats); cov_mark::check!(ignore_gats);