about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-03-15 22:55:00 +0000
committerMichael Goulet <michael@errs.io>2023-03-16 01:56:49 +0000
commit0949da8f4e309ac5e5035250bd662dfdbd5c32b4 (patch)
treed4143cf7115dc3a2667551d13f6b56a813052c2c
parentc5c43407603599f4ff2b217cc09be2cc5f39967d (diff)
downloadrust-0949da8f4e309ac5e5035250bd662dfdbd5c32b4.tar.gz
rust-0949da8f4e309ac5e5035250bd662dfdbd5c32b4.zip
Install projection from RPITIT to default trait method opaque correctly
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs36
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs17
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr (renamed from tests/ui/async-await/in-trait/async-default-fn-overridden.stderr)2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-method-constraint.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.rs2
8 files changed, 64 insertions, 19 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 7dce29cc0bb..df0258ff7a3 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
     tcx: TyCtxt<'_>,
     def_id: DefId,
 ) -> &'_ [(ty::Predicate<'_>, Span)] {
-    // If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
-    // generated the synthesized associate type.
-    let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
-        tcx.opt_rpitit_info(def_id)
-    {
-        Some(opaque_def_id)
-    } else {
-        None
-    };
+    match tcx.opt_rpitit_info(def_id) {
+        // RPITIT's bounds are the same as opaque type bounds, but with
+        // a projection self type.
+        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
+            let opaque_ty = item.expect_opaque_ty();
+            return opaque_type_bounds(
+                tcx,
+                opaque_def_id,
+                opaque_ty.bounds,
+                tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
+                item.span,
+            );
+        }
+        // These should have been fed!
+        Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+        None => {}
+    }
 
-    let bounds_def_id = rpitit_info.unwrap_or(def_id);
-    let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     match tcx.hir().get(hir_id) {
         hir::Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => {
             let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            let item_ty = if *in_trait || rpitit_info.is_some() {
+            let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
                 tcx.mk_projection(def_id, substs)
             } else {
                 tcx.mk_opaque(def_id, substs)
             };
-            opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
+            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
         _ => bug!("item_bounds called on {:?}", def_id),
     }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index ad05b68f1b4..df4b8543ba6 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -268,8 +268,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
         if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
-            // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) need to project to the opaque, could
-            // get it via type_of + subst.
             && self.tcx.is_impl_trait_in_trait(alias_ty.def_id)
             && self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
             && self.seen.insert(alias_ty.def_id)
@@ -284,11 +282,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
                     re
                 }
             });
+
+            // If we're lowering to associated item, install the opaque type which is just
+            // the `type_of` of the trait's associated item. If we're using the old lowering
+            // strategy, then just reinterpret the associated type like an opaque :^)
+            let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+                self
+                    .tcx
+                    .type_of(alias_ty.def_id)
+                    .subst(self.tcx, alias_ty.substs)
+            } else {
+                self.tcx.mk_alias(ty::Opaque, alias_ty)
+            };
+
             self.predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
                         projection_ty: alias_ty,
-                        term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
+                        term: default_ty.into(),
                     },
                     self.bound_vars,
                 )
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
index 61a826258d0..2142ee232ca 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/async-default-fn-overridden.rs:4:12
+  --> $DIR/async-default-fn-overridden.rs:6:12
    |
 LL | #![feature(async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
new file mode 100644
index 00000000000..2142ee232ca
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/async-default-fn-overridden.rs:6:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 0fd1a2703db..dd1af93d706 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -1,5 +1,7 @@
 // run-pass
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
index 5e18605aa4c..7bb79911f56 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-method-constraint.rs:5:12
+  --> $DIR/default-method-constraint.rs:7:12
    |
 LL | #![feature(return_position_impl_trait_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
new file mode 100644
index 00000000000..7bb79911f56
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-method-constraint.rs:7:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
index 8c50cc29586..e85fe3c8626 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 // This didn't work in the previous default RPITIT method hack attempt