Skip to content

Commit 744fa61

Browse files
committed
fix(generic_const_exprs): Fix predicate inheritance for children of opaque types
1 parent 95a3a72 commit 744fa61

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
427427
} else {
428428
if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
429429
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
430+
let parent_def_id = tcx.hir().get_parent_item(hir_id);
431+
430432
if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() {
431433
// In `generics_of` we set the generics' parent to be our parent's parent which means that
432434
// we lose out on the predicates of our actual parent if we dont return those predicates here.
@@ -439,8 +441,33 @@ pub(super) fn explicit_predicates_of<'tcx>(
439441
// parent of generics returned by `generics_of`
440442
//
441443
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
442-
let item_def_id = tcx.hir().get_parent_item(hir_id);
443-
// In the above code example we would be calling `explicit_predicates_of(Foo)` here
444+
// and we would be calling `explicit_predicates_of(Foo)` here
445+
return tcx.explicit_predicates_of(parent_def_id);
446+
}
447+
448+
let parent_def_kind = tcx.def_kind(parent_def_id);
449+
if matches!(parent_def_kind, DefKind::OpaqueTy) {
450+
// In `instantiate_identity` we inherit the predicates of our parent.
451+
// However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means
452+
// that we lose out on the predicates of our actual parent if we dont return those predicates here.
453+
//
454+
//
455+
// fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() }
456+
// ^^^^^^^^^^^^^^^^^^^ the def id we are calling
457+
// explicit_predicates_of on
458+
//
459+
// In the above code we want the anon const to have predicates in its param env for `T: Trait`.
460+
// However, the anon const cannot inherit predicates from its parent since it's opaque.
461+
//
462+
// To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent.
463+
464+
// In the above example this is `foo::{opaque#0}` or `impl Iterator`
465+
let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id);
466+
467+
// In the above example this is the function `foo`
468+
let item_def_id = tcx.hir().get_parent_item(parent_hir_id);
469+
470+
// In the above code example we would be calling `explicit_predicates_of(foo)` here
444471
return tcx.explicit_predicates_of(item_def_id);
445472
}
446473
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// check-pass
2+
#![crate_type = "lib"]
3+
#![feature(generic_const_exprs)]
4+
#![allow(incomplete_features)]
5+
pub trait MyIterator {
6+
type Output;
7+
}
8+
9+
pub trait Foo {
10+
const ABC: usize;
11+
}
12+
13+
pub struct IteratorStruct<const N: usize>{
14+
15+
}
16+
17+
pub struct Bar<const N: usize> {
18+
pub data: [usize; N]
19+
}
20+
21+
impl<const N: usize> MyIterator for IteratorStruct<N> {
22+
type Output = Bar<N>;
23+
}
24+
25+
pub fn test1<T: Foo>() -> impl MyIterator<Output = Bar<{T::ABC}>> where [(); T::ABC]: Sized {
26+
IteratorStruct::<{T::ABC}>{}
27+
}
28+
29+
pub trait Baz<const N: usize>{}
30+
impl<const N: usize> Baz<N> for Bar<N> {}
31+
pub fn test2<T: Foo>() -> impl MyIterator<Output = impl Baz<{ T::ABC }>> where [(); T::ABC]: Sized {
32+
IteratorStruct::<{T::ABC}>{}
33+
}

0 commit comments

Comments
 (0)