Skip to content

Commit

Permalink
fix(generic_const_exprs): Fix predicate inheritance for children of o…
Browse files Browse the repository at this point in the history
…paque types
  • Loading branch information
Neo-Zhixing committed Nov 1, 2022
1 parent 95a3a72 commit 744fa61
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
31 changes: 29 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/test/ui/const-generics/generic_const_exprs/issue-99705.rs
Original file line number Diff line number Diff line change
@@ -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}>{}
}

0 comments on commit 744fa61

Please sign in to comment.