about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs19
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs8
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs19
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102140.next.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.current.stderr27
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.next.stderr27
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.rs7
8 files changed, 76 insertions, 41 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index b9e71aaa004..1d00dc2a11d 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -63,7 +63,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     use rustc_hir::*;
 
     match tcx.opt_rpitit_info(def_id.to_def_id()) {
-        Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+        Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
             let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
             let opaque_ty_node = tcx.hir().get(opaque_ty_id);
             let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
@@ -71,6 +71,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             };
 
             let mut predicates = Vec::new();
+
+            // RPITITs should inherit the predicates of their parent. This is
+            // both to ensure that the RPITITs are only instantiated when the
+            // parent predicates would hold, and also so that the param-env
+            // inherits these predicates as assumptions.
+            let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+            predicates.extend(
+                tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
+            );
+
+            // We also install bidirectional outlives predicates for the RPITIT
+            // to keep the duplicates lifetimes from opaque lowering in sync.
             compute_bidirectional_outlives_predicates(
                 tcx,
                 def_id,
@@ -89,12 +101,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
         Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
             let assoc_item = tcx.associated_item(def_id);
-            let trait_assoc_predicates = tcx.predicates_of(assoc_item.trait_item_def_id.unwrap());
+            let trait_assoc_predicates =
+                tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
 
             let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
             let impl_def_id = tcx.parent(fn_def_id);
             let impl_trait_ref_substs =
-                tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
+                tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
 
             let impl_assoc_substs =
                 impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 7293de4c6c5..c9a8f8131df 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -574,7 +574,9 @@ fn foo(&self) -> Self::T { String::new() }
         let Some(hir_id) = body_owner_def_id.as_local() else {
             return false;
         };
-        let hir_id = tcx.hir().local_def_id_to_hir_id(hir_id);
+        let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(hir_id) else {
+            return false;
+        };
         // When `body_owner` is an `impl` or `trait` item, look in its associated types for
         // `expected` and point at it.
         let parent_id = tcx.hir().get_parent_item(hir_id);
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index efe49d687c9..541c19c3561 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1151,10 +1151,10 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
                 ty::AssocItemContainer::ImplContainer => true,
-                // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) always encode RPITITs,
-                // since we need to be able to "project" from an RPITIT associated item
-                // to an opaque when installing the default projection predicates in
-                // default trait methods with RPITITs.
+                // Always encode RPITITs, since we need to be able to project
+                // from an RPITIT associated item to an opaque when installing
+                // the default projection predicates in default trait methods
+                // with RPITITs.
                 ty::AssocItemContainer::TraitContainer => {
                     assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
                 }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 2b391f94a63..d5ebcda8a6c 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -4,8 +4,7 @@ use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
-    self, EarlyBinder, ImplTraitInTraitData, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
-    TypeVisitable, TypeVisitor,
+    self, EarlyBinder, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
 };
 use rustc_session::config::TraitSolver;
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
@@ -120,22 +119,6 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     let ty::InstantiatedPredicates { mut predicates, .. } =
         tcx.predicates_of(def_id).instantiate_identity(tcx);
 
-    // When computing the param_env of an RPITIT, use predicates of the containing function,
-    // *except* for the additional assumption that the RPITIT normalizes to the trait method's
-    // default opaque type. This is needed to properly check the item bounds of the assoc
-    // type hold (`check_type_bounds`), since that method already installs a similar projection
-    // bound, so they will conflict.
-    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
-    // at least be making sure that the generics in RPITITs and their parent fn don't
-    // get out of alignment, or else we do actually need to substitute these predicates.
-    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
-    | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
-    {
-        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
-        // from the parent fn to our assumptions
-        predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
-    }
-
     // Finally, we have to normalize the bounds in the environment, in
     // case they contain any associated type projections. This process
     // can yield errors if the put in illegal associated types, like
diff --git a/tests/ui/impl-trait/in-trait/issue-102140.next.stderr b/tests/ui/impl-trait/in-trait/issue-102140.next.stderr
index 7aa7880e258..94893c9e7b4 100644
--- a/tests/ui/impl-trait/in-trait/issue-102140.next.stderr
+++ b/tests/ui/impl-trait/in-trait/issue-102140.next.stderr
@@ -6,11 +6,7 @@ LL |         MyTrait::foo(&self)
    |         |
    |         required by a bound introduced by this call
    |
-help: consider removing the leading `&`-reference
-   |
-LL -         MyTrait::foo(&self)
-LL +         MyTrait::foo(self)
-   |
+   = help: the trait `MyTrait` is implemented for `Outer`
 
 error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:26:9
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
index 1a70716123c..74c84c012b1 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:13:22
+  --> $DIR/wf-bounds.rs:17:22
    |
 LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,14 +9,14 @@ note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:16:23
+  --> $DIR/wf-bounds.rs:20:23
    |
 LL |     fn nya2() -> impl Wf<[u8]>;
    |                       ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Wf`
-  --> $DIR/wf-bounds.rs:8:10
+  --> $DIR/wf-bounds.rs:10:10
    |
 LL | trait Wf<T> {
    |          ^ required by this bound in `Wf`
@@ -26,7 +26,7 @@ LL | trait Wf<T: ?Sized> {
    |           ++++++++
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:19:44
+  --> $DIR/wf-bounds.rs:23:44
    |
 LL |     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
    |                                            ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -35,6 +35,23 @@ LL |     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/wf-bounds.rs:26:26
+   |
+LL |     fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
+   |                          ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `NeedsDisplay`
+  --> $DIR/wf-bounds.rs:14:24
+   |
+LL | struct NeedsDisplay<T: Display>(T);
+   |                        ^^^^^^^ required by this bound in `NeedsDisplay`
+help: consider restricting type parameter `T`
+   |
+LL |     fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
+   |              +++++++++++++++++++
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
index 1a70716123c..74c84c012b1 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:13:22
+  --> $DIR/wf-bounds.rs:17:22
    |
 LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,14 +9,14 @@ note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:16:23
+  --> $DIR/wf-bounds.rs:20:23
    |
 LL |     fn nya2() -> impl Wf<[u8]>;
    |                       ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Wf`
-  --> $DIR/wf-bounds.rs:8:10
+  --> $DIR/wf-bounds.rs:10:10
    |
 LL | trait Wf<T> {
    |          ^ required by this bound in `Wf`
@@ -26,7 +26,7 @@ LL | trait Wf<T: ?Sized> {
    |           ++++++++
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:19:44
+  --> $DIR/wf-bounds.rs:23:44
    |
 LL |     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
    |                                            ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -35,6 +35,23 @@ LL |     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/wf-bounds.rs:26:26
+   |
+LL |     fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
+   |                          ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `NeedsDisplay`
+  --> $DIR/wf-bounds.rs:14:24
+   |
+LL | struct NeedsDisplay<T: Display>(T);
+   |                        ^^^^^^^ required by this bound in `NeedsDisplay`
+help: consider restricting type parameter `T`
+   |
+LL |     fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
+   |              +++++++++++++++++++
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs
index 1c9590bd853..f8c1e561d5c 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs
@@ -5,10 +5,14 @@
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
+use std::fmt::Display;
+
 trait Wf<T> {
     type Output;
 }
 
+struct NeedsDisplay<T: Display>(T);
+
 trait Uwu {
     fn nya() -> impl Wf<Vec<[u8]>>;
     //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
@@ -18,6 +22,9 @@ trait Uwu {
 
     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
     //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+
+    fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
+    //~^ ERROR `T` doesn't implement `std::fmt::Display`
 }
 
 fn main() {}