Skip to content

Commit a14285c

Browse files
RPITITs inherit method predicates
1 parent 982f025 commit a14285c

File tree

4 files changed

+19
-26
lines changed

4 files changed

+19
-26
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,26 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
6363
use rustc_hir::*;
6464

6565
match tcx.opt_rpitit_info(def_id.to_def_id()) {
66-
Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
66+
Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
6767
let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
6868
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
6969
let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
7070
bug!("unexpected {opaque_ty_node:?}")
7171
};
7272

7373
let mut predicates = Vec::new();
74+
75+
// RPITITs should inherit the predicates of their parent. This is
76+
// both to ensure that the RPITITs are only instantiated when the
77+
// parent predicates would hold, and also so that the param-env
78+
// inherits these predicates as assumptions.
79+
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
80+
predicates.extend(
81+
tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
82+
);
83+
84+
// We also install bidirectional outlives predicates for the RPITIT
85+
// to keep the duplicates lifetimes from opaque lowering in sync.
7486
compute_bidirectional_outlives_predicates(
7587
tcx,
7688
def_id,
@@ -95,7 +107,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
95107
let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
96108
let impl_def_id = tcx.parent(fn_def_id);
97109
let impl_trait_ref_substs =
98-
tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
110+
tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
99111

100112
let impl_assoc_substs =
101113
impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,9 @@ fn foo(&self) -> Self::T { String::new() }
574574
let Some(hir_id) = body_owner_def_id.as_local() else {
575575
return false;
576576
};
577-
let hir_id = tcx.hir().local_def_id_to_hir_id(hir_id);
577+
let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(hir_id) else {
578+
return false;
579+
};
578580
// When `body_owner` is an `impl` or `trait` item, look in its associated types for
579581
// `expected` and point at it.
580582
let parent_id = tcx.hir().get_parent_item(hir_id);

compiler/rustc_ty_utils/src/ty.rs

+1-18
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use rustc_hir::def::DefKind;
44
use rustc_index::bit_set::BitSet;
55
use rustc_middle::query::Providers;
66
use rustc_middle::ty::{
7-
self, EarlyBinder, ImplTraitInTraitData, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
8-
TypeVisitable, TypeVisitor,
7+
self, EarlyBinder, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
98
};
109
use rustc_session::config::TraitSolver;
1110
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
@@ -120,22 +119,6 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
120119
let ty::InstantiatedPredicates { mut predicates, .. } =
121120
tcx.predicates_of(def_id).instantiate_identity(tcx);
122121

123-
// When computing the param_env of an RPITIT, use predicates of the containing function,
124-
// *except* for the additional assumption that the RPITIT normalizes to the trait method's
125-
// default opaque type. This is needed to properly check the item bounds of the assoc
126-
// type hold (`check_type_bounds`), since that method already installs a similar projection
127-
// bound, so they will conflict.
128-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
129-
// at least be making sure that the generics in RPITITs and their parent fn don't
130-
// get out of alignment, or else we do actually need to substitute these predicates.
131-
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
132-
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
133-
{
134-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
135-
// from the parent fn to our assumptions
136-
predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
137-
}
138-
139122
// Finally, we have to normalize the bounds in the environment, in
140123
// case they contain any associated type projections. This process
141124
// can yield errors if the put in illegal associated types, like

tests/ui/impl-trait/in-trait/issue-102140.next.stderr

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ LL | MyTrait::foo(&self)
66
| |
77
| required by a bound introduced by this call
88
|
9-
help: consider removing the leading `&`-reference
10-
|
11-
LL - MyTrait::foo(&self)
12-
LL + MyTrait::foo(self)
13-
|
9+
= help: the trait `MyTrait` is implemented for `Outer`
1410

1511
error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
1612
--> $DIR/issue-102140.rs:26:9

0 commit comments

Comments
 (0)