mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-16 07:03:57 +00:00
fix const generic panic in dyn trait
This commit is contained in:
parent
71d49d31bb
commit
d33d5fca1d
2 changed files with 66 additions and 36 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue