Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d33d5fc

Browse files
committed
fix const generic panic in dyn trait
1 parent 71d49d3 commit d33d5fc

File tree

2 files changed

+66
-36
lines changed

2 files changed

+66
-36
lines changed

crates/hir_ty/src/lower.rs

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -681,23 +681,31 @@ impl<'a> TyLoweringContext<'a> {
681681

682682
let ty_error = GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner);
683683

684-
for eid in def_generics.iter_id().take(parent_params) {
685-
match eid {
686-
Either::Left(_) => substs.push(ty_error.clone()),
687-
Either::Right(x) => {
688-
substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
684+
let mut def_generic_iter = def_generics.iter_id();
685+
686+
for _ in 0..parent_params {
687+
if let Some(eid) = def_generic_iter.next() {
688+
match eid {
689+
Either::Left(_) => substs.push(ty_error.clone()),
690+
Either::Right(x) => {
691+
substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
692+
}
689693
}
690694
}
691695
}
692696

693697
let fill_self_params = || {
694-
substs.extend(
695-
explicit_self_ty
696-
.into_iter()
697-
.map(|x| GenericArgData::Ty(x).intern(Interner))
698-
.chain(iter::repeat(ty_error.clone()))
699-
.take(self_params),
700-
)
698+
for x in explicit_self_ty
699+
.into_iter()
700+
.map(|x| GenericArgData::Ty(x).intern(Interner))
701+
.chain(iter::repeat(ty_error.clone()))
702+
.take(self_params)
703+
{
704+
if let Some(id) = def_generic_iter.next() {
705+
assert!(id.is_left());
706+
substs.push(x);
707+
}
708+
}
701709
};
702710
let mut had_explicit_args = false;
703711

@@ -712,34 +720,37 @@ impl<'a> TyLoweringContext<'a> {
712720
};
713721
let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
714722
// if args are provided, it should be all of them, but we can't rely on that
715-
for (arg, id) in generic_args
723+
for arg in generic_args
716724
.args
717725
.iter()
718726
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
719727
.skip(skip)
720728
.take(expected_num)
721-
.zip(def_generics.iter_id().skip(parent_params + skip))
722729
{
723-
if let Some(x) = generic_arg_to_chalk(
724-
self.db,
725-
id,
726-
arg,
727-
&mut (),
728-
|_, type_ref| self.lower_ty(type_ref),
729-
|_, c, ty| {
730-
const_or_path_to_chalk(
731-
self.db,
732-
&self.resolver,
733-
ty,
734-
c,
735-
self.type_param_mode,
736-
|| self.generics(),
737-
self.in_binders,
738-
)
739-
},
740-
) {
741-
had_explicit_args = true;
742-
substs.push(x);
730+
if let Some(id) = def_generic_iter.next() {
731+
if let Some(x) = generic_arg_to_chalk(
732+
self.db,
733+
id,
734+
arg,
735+
&mut (),
736+
|_, type_ref| self.lower_ty(type_ref),
737+
|_, c, ty| {
738+
const_or_path_to_chalk(
739+
self.db,
740+
&self.resolver,
741+
ty,
742+
c,
743+
self.type_param_mode,
744+
|| self.generics(),
745+
self.in_binders,
746+
)
747+
},
748+
) {
749+
had_explicit_args = true;
750+
substs.push(x);
751+
} else {
752+
never!();
753+
}
743754
}
744755
}
745756
} else {
@@ -757,21 +768,24 @@ impl<'a> TyLoweringContext<'a> {
757768
for default_ty in defaults.iter().skip(substs.len()) {
758769
// each default can depend on the previous parameters
759770
let substs_so_far = Substitution::from_iter(Interner, substs.clone());
760-
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
771+
if let Some(_id) = def_generic_iter.next() {
772+
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
773+
}
761774
}
762775
}
763776
}
764777

765778
// add placeholders for args that were not provided
766779
// FIXME: emit diagnostics in contexts where this is not allowed
767-
for eid in def_generics.iter_id().skip(substs.len()) {
780+
for eid in def_generic_iter {
768781
match eid {
769782
Either::Left(_) => substs.push(ty_error.clone()),
770783
Either::Right(x) => {
771784
substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
772785
}
773786
}
774787
}
788+
// If this assert fails, it means you pushed into subst but didn't call .next() of def_generic_iter
775789
assert_eq!(substs.len(), total_len);
776790

777791
Substitution::from_iter(Interner, substs)

crates/hir_ty/src/tests/regression.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,22 @@ fn regression_11688_3() {
14701470
);
14711471
}
14721472

1473+
#[test]
1474+
fn regression_11688_4() {
1475+
check_types(
1476+
r#"
1477+
trait Bar<const C: usize> {
1478+
fn baz(&self) -> [i32; C];
1479+
}
1480+
1481+
fn foo(x: &dyn Bar<2>) {
1482+
x.baz();
1483+
//^^^^^^^ [i32; 2]
1484+
}
1485+
"#,
1486+
)
1487+
}
1488+
14731489
#[test]
14741490
fn gat_crash_1() {
14751491
cov_mark::check!(ignore_gats);

0 commit comments

Comments
 (0)