Skip to content

Commit c5949c8

Browse files
committed
Create bidirectional bounds between original and duplicated parameters.
1 parent 49a5aa4 commit c5949c8

File tree

5 files changed

+94
-66
lines changed

5 files changed

+94
-66
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
6161
use rustc_hir::definitions::DefPathData;
6262
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
6363
use rustc_index::vec::{Idx, IndexVec};
64+
use rustc_middle::span_bug;
6465
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
65-
use rustc_middle::{bug, span_bug};
6666
use rustc_session::parse::feature_err;
6767
use rustc_span::hygiene::MacroKind;
6868
use rustc_span::source_map::DesugaringKind;
@@ -1457,17 +1457,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14571457
// frequently opened issues show.
14581458
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
14591459

1460-
let opaque_ty_def_id = match origin {
1461-
hir::OpaqueTyOrigin::TyAlias => self.create_def(
1462-
self.current_hir_id_owner.def_id,
1463-
opaque_ty_node_id,
1464-
DefPathData::ImplTrait,
1465-
),
1466-
hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
1467-
self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
1468-
}
1469-
hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
1470-
};
1460+
let opaque_ty_def_id = self.create_def(
1461+
self.current_hir_id_owner.def_id,
1462+
opaque_ty_node_id,
1463+
DefPathData::ImplTrait,
1464+
);
14711465
debug!(?opaque_ty_def_id);
14721466

14731467
// Contains the new lifetime definitions created for the TAIT (if any).

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,6 @@ fn check_fn_or_method<'tcx>(
15381538

15391539
check_return_position_impl_trait_in_trait_bounds(
15401540
tcx,
1541-
wfcx,
15421541
def_id,
15431542
sig.output(),
15441543
hir_decl.output.span(),
@@ -1574,9 +1573,9 @@ fn check_fn_or_method<'tcx>(
15741573

15751574
/// Basically `check_associated_type_bounds`, but separated for now and should be
15761575
/// deduplicated when RPITITs get lowered into real associated items.
1576+
#[tracing::instrument(level = "trace", skip(tcx))]
15771577
fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15781578
tcx: TyCtxt<'tcx>,
1579-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
15801579
fn_def_id: LocalDefId,
15811580
fn_output: Ty<'tcx>,
15821581
span: Span,
@@ -1590,18 +1589,22 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15901589
&& tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
15911590
&& tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
15921591
{
1593-
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
1594-
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
1595-
let normalized_bound = wfcx.normalize(span, None, bound);
1596-
traits::wf::predicate_obligations(
1597-
wfcx.infcx,
1598-
wfcx.param_env,
1599-
wfcx.body_id,
1600-
normalized_bound,
1601-
bound_span,
1602-
)
1592+
// Create a new context, since we want the opaque's ParamEnv and not the parent's.
1593+
let span = tcx.def_span(proj.item_def_id);
1594+
enter_wf_checking_ctxt(tcx, span, proj.item_def_id.expect_local(), |wfcx| {
1595+
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
1596+
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
1597+
let normalized_bound = wfcx.normalize(span, None, bound);
1598+
traits::wf::predicate_obligations(
1599+
wfcx.infcx,
1600+
wfcx.param_env,
1601+
wfcx.body_id,
1602+
normalized_bound,
1603+
bound_span,
1604+
)
1605+
});
1606+
wfcx.register_obligations(wf_obligations);
16031607
});
1604-
wfcx.register_obligations(wf_obligations);
16051608
}
16061609
}
16071610
}

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,40 +84,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
8484

8585
Node::ImplItem(item) => item.generics,
8686

87-
Node::Item(item) => {
88-
match item.kind {
89-
ItemKind::Impl(ref impl_) => {
90-
if impl_.defaultness.is_default() {
91-
is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy);
92-
}
93-
&impl_.generics
94-
}
95-
ItemKind::Fn(.., ref generics, _)
96-
| ItemKind::TyAlias(_, ref generics)
97-
| ItemKind::Enum(_, ref generics)
98-
| ItemKind::Struct(_, ref generics)
99-
| ItemKind::Union(_, ref generics) => *generics,
100-
101-
ItemKind::Trait(_, _, ref generics, ..) => {
102-
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
103-
*generics
104-
}
105-
ItemKind::TraitAlias(ref generics, _) => {
106-
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
107-
*generics
87+
Node::Item(item) => match item.kind {
88+
ItemKind::Impl(ref impl_) => {
89+
if impl_.defaultness.is_default() {
90+
is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy);
10891
}
109-
ItemKind::OpaqueTy(OpaqueTy {
110-
ref generics,
111-
origin: hir::OpaqueTyOrigin::TyAlias,
112-
..
113-
}) => {
114-
// type-alias impl trait
115-
generics
116-
}
117-
118-
_ => NO_GENERICS,
92+
&impl_.generics
11993
}
120-
}
94+
ItemKind::Fn(.., ref generics, _)
95+
| ItemKind::TyAlias(_, ref generics)
96+
| ItemKind::Enum(_, ref generics)
97+
| ItemKind::Struct(_, ref generics)
98+
| ItemKind::Union(_, ref generics) => *generics,
99+
100+
ItemKind::Trait(_, _, ref generics, ..) => {
101+
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
102+
*generics
103+
}
104+
ItemKind::TraitAlias(ref generics, _) => {
105+
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
106+
*generics
107+
}
108+
ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) => generics,
109+
_ => NO_GENERICS,
110+
},
121111

122112
Node::ForeignItem(item) => match item.kind {
123113
ForeignItemKind::Static(..) => NO_GENERICS,
@@ -161,6 +151,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
161151

162152
trace!(?predicates);
163153
trace!(?ast_generics);
154+
trace!(?generics);
164155

165156
// Collect the predicates that were written inline by the user on each
166157
// type parameter (e.g., `<T: Foo>`).
@@ -279,6 +270,54 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
279270
);
280271
}
281272

273+
// Opaque types duplicate some of their generic parameters.
274+
// We create bi-directional Outlives predicates between the original
275+
// and the duplicated parameter, to ensure that they do not get out of sync.
276+
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
277+
let opaque_ty_id = tcx.hir().get_parent_node(hir_id);
278+
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
279+
let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
280+
bug!("unexpected {opaque_ty_node:?}")
281+
};
282+
debug!(?lifetimes);
283+
for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
284+
let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
285+
let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None);
286+
if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
287+
// Only early-bound regions can point to the original generic parameter.
288+
continue;
289+
}
290+
291+
let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
292+
let dup_def = tcx.hir().local_def_id(duplicate.hir_id).to_def_id();
293+
294+
let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
295+
296+
let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
297+
def_id: dup_def,
298+
index: dup_index,
299+
name: duplicate.name.ident().name,
300+
}));
301+
predicates.push((
302+
ty::Binder::dummy(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
303+
orig_region,
304+
dup_region,
305+
)))
306+
.to_predicate(icx.tcx),
307+
duplicate.span,
308+
));
309+
predicates.push((
310+
ty::Binder::dummy(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
311+
dup_region,
312+
orig_region,
313+
)))
314+
.to_predicate(icx.tcx),
315+
duplicate.span,
316+
));
317+
}
318+
debug!(?predicates);
319+
}
320+
282321
ty::GenericPredicates {
283322
parent: generics.parent,
284323
predicates: tcx.arena.alloc_from_iter(predicates),

compiler/rustc_ty_utils/src/ty.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
108108

109109
/// See `ParamEnv` struct definition for details.
110110
fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
111-
// The param_env of an impl Trait type is its defining function's param_env
112-
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
113-
return param_env(tcx, parent.to_def_id());
114-
}
115111
// Compute the bounds on Self and the type parameters.
116-
117112
let ty::InstantiatedPredicates { mut predicates, .. } =
118113
tcx.predicates_of(def_id).instantiate_identity(tcx);
119114

src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ error[E0720]: cannot resolve opaque type
1414
--> $DIR/impl-fn-predefined-lifetimes.rs:4:35
1515
|
1616
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
17-
| ^^^^^^^^^^^^^^^ recursive opaque type
18-
...
19-
LL | |x| x
20-
| ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]`
17+
| ^^^^^^^^^^^^^^^ cannot resolve opaque type
2118

2219
error: aborting due to 2 previous errors
2320

0 commit comments

Comments
 (0)