Skip to content

Commit 349a237

Browse files
Take RPITITs inherit the assumed_wf_types of their parent fn
1 parent 03a5725 commit 349a237

File tree

6 files changed

+57
-100
lines changed

6 files changed

+57
-100
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+11-88
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,17 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
284284
};
285285
check_object_unsafe_self_trait_by_name(tcx, trait_item);
286286
check_associated_item(tcx, def_id, span, method_sig);
287+
288+
if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
289+
for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
290+
check_associated_item(
291+
tcx,
292+
assoc_ty_def_id.expect_local(),
293+
tcx.def_span(assoc_ty_def_id),
294+
None,
295+
);
296+
}
297+
}
287298
}
288299

289300
/// Require that the user writes where clauses on GATs for the implicit
@@ -1466,13 +1477,6 @@ fn check_fn_or_method<'tcx>(
14661477

14671478
check_where_clauses(wfcx, span, def_id);
14681479

1469-
check_return_position_impl_trait_in_trait_bounds(
1470-
wfcx,
1471-
def_id,
1472-
sig.output(),
1473-
hir_decl.output.span(),
1474-
);
1475-
14761480
if sig.abi == Abi::RustCall {
14771481
let span = tcx.def_span(def_id);
14781482
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
@@ -1507,87 +1511,6 @@ fn check_fn_or_method<'tcx>(
15071511
}
15081512
}
15091513

1510-
/// Basically `check_associated_type_bounds`, but separated for now and should be
1511-
/// deduplicated when RPITITs get lowered into real associated items.
1512-
#[tracing::instrument(level = "trace", skip(wfcx))]
1513-
fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
1514-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1515-
fn_def_id: LocalDefId,
1516-
fn_output: Ty<'tcx>,
1517-
span: Span,
1518-
) {
1519-
let tcx = wfcx.tcx();
1520-
let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
1521-
return;
1522-
};
1523-
if assoc_item.container != ty::AssocItemContainer::TraitContainer {
1524-
return;
1525-
}
1526-
fn_output.visit_with(&mut ImplTraitInTraitFinder {
1527-
wfcx,
1528-
fn_def_id,
1529-
depth: ty::INNERMOST,
1530-
seen: FxHashSet::default(),
1531-
});
1532-
}
1533-
1534-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
1535-
// strategy, we can't just call `check_associated_item` on the new RPITITs,
1536-
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
1537-
// That's because we need to check that the bounds of the RPITIT hold using
1538-
// the special args that we create during opaque type lowering, otherwise we're
1539-
// getting a bunch of early bound and free regions mixed up... Haven't looked too
1540-
// deep into this, though.
1541-
struct ImplTraitInTraitFinder<'a, 'tcx> {
1542-
wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
1543-
fn_def_id: LocalDefId,
1544-
depth: ty::DebruijnIndex,
1545-
seen: FxHashSet<DefId>,
1546-
}
1547-
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
1548-
type BreakTy = !;
1549-
1550-
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
1551-
let tcx = self.wfcx.tcx();
1552-
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
1553-
&& self.seen.insert(unshifted_opaque_ty.def_id)
1554-
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
1555-
&& let origin = tcx.opaque_type_origin(opaque_def_id)
1556-
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
1557-
&& source == self.fn_def_id
1558-
{
1559-
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
1560-
match re.kind() {
1561-
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
1562-
r => bug!("unexpected region: {r:?}"),
1563-
}
1564-
});
1565-
for (bound, bound_span) in tcx
1566-
.explicit_item_bounds(opaque_ty.def_id)
1567-
.iter_instantiated_copied(tcx, opaque_ty.args)
1568-
{
1569-
let bound = self.wfcx.normalize(bound_span, None, bound);
1570-
self.wfcx.register_obligations(traits::wf::predicate_obligations(
1571-
self.wfcx.infcx,
1572-
self.wfcx.param_env,
1573-
self.wfcx.body_def_id,
1574-
bound.as_predicate(),
1575-
bound_span,
1576-
));
1577-
// Set the debruijn index back to innermost here, since we already eagerly
1578-
// shifted the args that we use to generate these bounds. This is unfortunately
1579-
// subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
1580-
// but that function doesn't actually need to normalize the bound it's visiting
1581-
// (whereas we have to do so here)...
1582-
let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
1583-
bound.visit_with(self);
1584-
self.depth = old_depth;
1585-
}
1586-
}
1587-
ty.super_visit_with(self)
1588-
}
1589-
}
1590-
15911514
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
15921515
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
15931516
of the previous types except `Self`)";

compiler/rustc_ty_utils/src/implied_bounds.rs

+37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use rustc_data_structures::fx::FxHashMap;
12
use rustc_hir as hir;
23
use rustc_hir::def::DefKind;
34
use rustc_hir::def_id::LocalDefId;
5+
use rustc_middle::middle::resolve_bound_vars as rbv;
46
use rustc_middle::query::Providers;
57
use rustc_middle::ty::{self, Ty, TyCtxt};
68
use rustc_span::Span;
@@ -42,6 +44,41 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
4244
let mut impl_spans = impl_spans(tcx, def_id);
4345
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
4446
}
47+
DefKind::AssocTy if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = tcx.opt_rpitit_info(def_id.to_def_id()) => {
48+
let hir::OpaqueTy { lifetime_mapping, .. } =
49+
*tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty();
50+
let mut mapping = FxHashMap::default();
51+
let generics = tcx.generics_of(def_id);
52+
for &(lifetime, new_early_bound_def_id) in lifetime_mapping {
53+
if let Some(rbv::ResolvedArg::LateBound(_, _, def_id)) =
54+
tcx.named_bound_var(lifetime.hir_id)
55+
{
56+
let name = tcx.hir().name(lifetime.hir_id);
57+
let index = generics
58+
.param_def_id_to_index(tcx, new_early_bound_def_id.to_def_id())
59+
.unwrap();
60+
mapping.insert(
61+
ty::Region::new_free(
62+
tcx,
63+
fn_def_id,
64+
ty::BoundRegionKind::BrNamed(def_id, name),
65+
),
66+
ty::Region::new_early_bound(
67+
tcx,
68+
ty::EarlyBoundRegion {
69+
def_id: new_early_bound_def_id.to_def_id(),
70+
index,
71+
name,
72+
},
73+
),
74+
);
75+
}
76+
}
77+
let a = tcx.fold_regions(tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), |re, _| {
78+
if let Some(re) = mapping.get(&re) { *re } else { re }
79+
});
80+
tcx.arena.alloc_from_iter(a)
81+
}
4582
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
4683
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
4784
DefKind::TyAlias => ty::List::empty(),

compiler/rustc_ty_utils/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(assert_matches)]
99
#![feature(iterator_try_collect)]
1010
#![feature(let_chains)]
11+
#![feature(if_let_guard)]
1112
#![feature(never_type)]
1213
#![feature(box_patterns)]
1314
#![recursion_limit = "256"]

tests/ui/async-await/in-trait/async-generics-and-bounds.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0311]: the parameter type `U` may not live long enough
44
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
55
| ^^^^^^^
66
|
7-
note: the parameter type `U` must be valid for the anonymous lifetime defined here...
7+
note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
88
--> $DIR/async-generics-and-bounds.rs:12:18
99
|
1010
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
11-
| ^^^^^
11+
| ^
1212
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
1313
--> $DIR/async-generics-and-bounds.rs:12:28
1414
|
@@ -21,11 +21,11 @@ error[E0311]: the parameter type `T` may not live long enough
2121
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
2222
| ^^^^^^^
2323
|
24-
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
24+
note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
2525
--> $DIR/async-generics-and-bounds.rs:12:18
2626
|
2727
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
28-
| ^^^^^
28+
| ^
2929
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
3030
--> $DIR/async-generics-and-bounds.rs:12:28
3131
|

tests/ui/async-await/in-trait/async-generics.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0311]: the parameter type `U` may not live long enough
44
LL | async fn foo(&self) -> &(T, U);
55
| ^^^^^^^
66
|
7-
note: the parameter type `U` must be valid for the anonymous lifetime defined here...
7+
note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
88
--> $DIR/async-generics.rs:9:18
99
|
1010
LL | async fn foo(&self) -> &(T, U);
11-
| ^^^^^
11+
| ^
1212
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
1313
--> $DIR/async-generics.rs:9:28
1414
|
@@ -21,11 +21,11 @@ error[E0311]: the parameter type `T` may not live long enough
2121
LL | async fn foo(&self) -> &(T, U);
2222
| ^^^^^^^
2323
|
24-
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
24+
note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
2525
--> $DIR/async-generics.rs:9:18
2626
|
2727
LL | async fn foo(&self) -> &(T, U);
28-
| ^^^^^
28+
| ^
2929
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
3030
--> $DIR/async-generics.rs:9:28
3131
|

tests/ui/impl-trait/in-trait/wf-bounds.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ note: required by a bound in `NeedsDisplay`
4747
|
4848
LL | struct NeedsDisplay<T: Display>(T);
4949
| ^^^^^^^ required by this bound in `NeedsDisplay`
50-
help: consider restricting type parameter `T`
51-
|
52-
LL | fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
53-
| +++++++++++++++++++
5450

5551
error: aborting due to 4 previous errors
5652

0 commit comments

Comments
 (0)