From a14285ca7e5d0c6d1ce69ae0fd5f1e0b01fdb373 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 30 Jun 2023 19:09:42 +0000 Subject: [PATCH] RPITITs inherit method predicates --- .../src/collect/predicates_of.rs | 16 ++++++++++++++-- .../infer/error_reporting/note_and_explain.rs | 4 +++- compiler/rustc_ty_utils/src/ty.rs | 19 +------------------ .../in-trait/issue-102140.next.stderr | 6 +----- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index cffb9500e9686..1d00dc2a11d5d 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, @@ -95,7 +107,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen 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 7293de4c6c5e5..c9a8f8131dffb 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_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2b391f94a6335..d5ebcda8a6cf8 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 7aa7880e25883..94893c9e7b495 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