fix(generic_const_exprs): Fix predicate inheritance for children of opaque types

This commit is contained in:
Zhixing Zhang 2022-10-31 17:01:00 -07:00 committed by Zhixing Zhang
parent 95a3a7277b
commit 744fa610eb
2 changed files with 62 additions and 2 deletions

View File

@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
} else {
if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let parent_def_id = tcx.hir().get_parent_item(hir_id);
if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() {
// In `generics_of` we set the generics' parent to be our parent's parent which means that
// 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>(
// parent of generics returned by `generics_of`
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
let item_def_id = tcx.hir().get_parent_item(hir_id);
// In the above code example we would be calling `explicit_predicates_of(Foo)` here
// and we would be calling `explicit_predicates_of(Foo)` here
return tcx.explicit_predicates_of(parent_def_id);
}
let parent_def_kind = tcx.def_kind(parent_def_id);
if matches!(parent_def_kind, DefKind::OpaqueTy) {
// In `instantiate_identity` we inherit the predicates of our parent.
// However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means
// that we lose out on the predicates of our actual parent if we dont return those predicates here.
//
//
// fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() }
// ^^^^^^^^^^^^^^^^^^^ the def id we are calling
// explicit_predicates_of on
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`.
// However, the anon const cannot inherit predicates from its parent since it's opaque.
//
// To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent.
// In the above example this is `foo::{opaque#0}` or `impl Iterator`
let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id);
// In the above example this is the function `foo`
let item_def_id = tcx.hir().get_parent_item(parent_hir_id);
// In the above code example we would be calling `explicit_predicates_of(foo)` here
return tcx.explicit_predicates_of(item_def_id);
}
}

View File

@ -0,0 +1,33 @@
// check-pass
#![crate_type = "lib"]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
pub trait MyIterator {
type Output;
}
pub trait Foo {
const ABC: usize;
}
pub struct IteratorStruct<const N: usize>{
}
pub struct Bar<const N: usize> {
pub data: [usize; N]
}
impl<const N: usize> MyIterator for IteratorStruct<N> {
type Output = Bar<N>;
}
pub fn test1<T: Foo>() -> impl MyIterator<Output = Bar<{T::ABC}>> where [(); T::ABC]: Sized {
IteratorStruct::<{T::ABC}>{}
}
pub trait Baz<const N: usize>{}
impl<const N: usize> Baz<N> for Bar<N> {}
pub fn test2<T: Foo>() -> impl MyIterator<Output = impl Baz<{ T::ABC }>> where [(); T::ABC]: Sized {
IteratorStruct::<{T::ABC}>{}
}