about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-11-02 22:06:26 +0100
committerGitHub <noreply@github.com>2022-11-02 22:06:26 +0100
commit214d6b6836413bbfe9132f7aff3d91ae67bc62ba (patch)
treecf6d81f856d3cd4779dffd35eed075402f69238b
parentedf0182213a9e30982eb34f3925ddc4cf5ed3471 (diff)
parent744fa610eb6bd476b875dd2d6f8be5b7b9f1b77c (diff)
Rollup merge of #99801 - Neo-Zhixing:fix/generic_const_exprs_parent_opaque_predicates, r=oli-obk
fix(generic_const_exprs): Fix predicate inheritance for children of opaque types

Fixes #99705

We currently have a special case to perform predicate inheritance when the const item is in the generics. I think we're also going to need this for opaque return types. When evaluating the predicates applied to the associated item, it'll inherit from its parent, the opaque type, which will never have predicates applied. This PR bypass the opaque typed parent and inherit predicates directly from the function itself.
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs31
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-99705.rs33
2 files changed, 62 insertions, 2 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 2e84e1d0160..5d1ca1cbd23 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -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);
             }
         }
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs b/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs
new file mode 100644
index 00000000000..75b57b621bb
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-99705.rs
@@ -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}>{}
+}