Skip to content

Commit ebe6e30

Browse files
committed
Auto merge of rust-lang#12054 - HKalbasi:const_generic, r=flodiebold
Fix const generic panic in dyn trait fix rust-lang#12048
2 parents b6b5214 + 785ae4d commit ebe6e30

File tree

2 files changed

+71
-36
lines changed

2 files changed

+71
-36
lines changed

crates/hir_ty/src/lower.rs

+55-36
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,38 @@ 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+
// we just filtered them out
753+
never!("Unexpected lifetime argument");
754+
}
743755
}
744756
}
745757
} else {
@@ -757,21 +769,24 @@ impl<'a> TyLoweringContext<'a> {
757769
for default_ty in defaults.iter().skip(substs.len()) {
758770
// each default can depend on the previous parameters
759771
let substs_so_far = Substitution::from_iter(Interner, substs.clone());
760-
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
772+
if let Some(_id) = def_generic_iter.next() {
773+
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
774+
}
761775
}
762776
}
763777
}
764778

765779
// add placeholders for args that were not provided
766780
// FIXME: emit diagnostics in contexts where this is not allowed
767-
for eid in def_generics.iter_id().skip(substs.len()) {
781+
for eid in def_generic_iter {
768782
match eid {
769783
Either::Left(_) => substs.push(ty_error.clone()),
770784
Either::Right(x) => {
771785
substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
772786
}
773787
}
774788
}
789+
// If this assert fails, it means you pushed into subst but didn't call .next() of def_generic_iter
775790
assert_eq!(substs.len(), total_len);
776791

777792
Substitution::from_iter(Interner, substs)
@@ -1659,6 +1674,10 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
16591674
}
16601675
}
16611676

1677+
/// Checks if the provided generic arg matches its expected kind, then lower them via
1678+
/// provided closures. Use unknown if there was kind mismatch.
1679+
///
1680+
/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
16621681
pub(crate) fn generic_arg_to_chalk<'a, T>(
16631682
db: &dyn HirDatabase,
16641683
kind_id: Either<TypeParamId, ConstParamId>,

crates/hir_ty/src/tests/regression.rs

+16
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)