Skip to content

Commit 3b49ad3

Browse files
authored
Rollup merge of #109545 - compiler-errors:rpitit-wf, r=eholk
Deeply check well-formedness of return-position `impl Trait` in trait Walk the bounds of RPITITs to see if we find any more RPITITs 😸
2 parents 8c83058 + b605d07 commit 3b49ad3

File tree

4 files changed

+108
-44
lines changed

4 files changed

+108
-44
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/wfcheck.rs

+72-33
Original file line numberDiff line numberDiff line change
@@ -1544,42 +1544,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15441544
span: Span,
15451545
) {
15461546
let tcx = wfcx.tcx();
1547-
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
1548-
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
1549-
{
1550-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
1551-
// strategy, we can't just call `check_associated_item` on the new RPITITs,
1552-
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
1553-
// That's because we need to check that the bounds of the RPITIT hold using
1554-
// the special substs that we create during opaque type lowering, otherwise we're
1555-
// getting a bunch of early bound and free regions mixed up... Haven't looked too
1556-
// deep into this, though.
1557-
for arg in fn_output.walk() {
1558-
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1559-
// RPITITs are always eagerly normalized into opaques, so always look for an
1560-
// opaque here.
1561-
&& let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
1562-
&& let Some(opaque_def_id) = opaque_ty.def_id.as_local()
1563-
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
1564-
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
1565-
&& source == fn_def_id
1547+
let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
1548+
return;
1549+
};
1550+
if assoc_item.container != ty::AssocItemContainer::TraitContainer {
1551+
return;
1552+
}
1553+
fn_output.visit_with(&mut ImplTraitInTraitFinder {
1554+
wfcx,
1555+
fn_def_id,
1556+
depth: ty::INNERMOST,
1557+
seen: FxHashSet::default(),
1558+
});
1559+
}
1560+
1561+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
1562+
// strategy, we can't just call `check_associated_item` on the new RPITITs,
1563+
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
1564+
// That's because we need to check that the bounds of the RPITIT hold using
1565+
// the special substs that we create during opaque type lowering, otherwise we're
1566+
// getting a bunch of early bound and free regions mixed up... Haven't looked too
1567+
// deep into this, though.
1568+
struct ImplTraitInTraitFinder<'a, 'tcx> {
1569+
wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
1570+
fn_def_id: LocalDefId,
1571+
depth: ty::DebruijnIndex,
1572+
seen: FxHashSet<DefId>,
1573+
}
1574+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
1575+
type BreakTy = !;
1576+
1577+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
1578+
let tcx = self.wfcx.tcx();
1579+
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
1580+
&& self.seen.insert(unshifted_opaque_ty.def_id)
1581+
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
1582+
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
1583+
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
1584+
&& source == self.fn_def_id
1585+
{
1586+
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
1587+
if let ty::ReLateBound(index, bv) = re.kind() {
1588+
if depth != ty::INNERMOST {
1589+
return tcx.mk_re_error_with_message(
1590+
DUMMY_SP,
1591+
"we shouldn't walk non-predicate binders with `impl Trait`...",
1592+
);
1593+
}
1594+
tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
1595+
} else {
1596+
re
1597+
}
1598+
});
1599+
for (bound, bound_span) in tcx
1600+
.bound_explicit_item_bounds(opaque_ty.def_id)
1601+
.subst_iter_copied(tcx, opaque_ty.substs)
15661602
{
1567-
let span = tcx.def_span(opaque_ty.def_id);
1568-
let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
1569-
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
1570-
let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
1571-
let normalized_bound = wfcx.normalize(span, None, bound);
1572-
traits::wf::predicate_obligations(
1573-
wfcx.infcx,
1574-
wfcx.param_env,
1575-
wfcx.body_def_id,
1576-
normalized_bound,
1577-
bound_span,
1578-
)
1579-
});
1580-
wfcx.register_obligations(wf_obligations);
1603+
let bound = self.wfcx.normalize(bound_span, None, bound);
1604+
self.wfcx.register_obligations(traits::wf::predicate_obligations(
1605+
self.wfcx.infcx,
1606+
self.wfcx.param_env,
1607+
self.wfcx.body_def_id,
1608+
bound,
1609+
bound_span,
1610+
));
1611+
// Set the debruijn index back to innermost here, since we already eagerly
1612+
// shifted the substs that we use to generate these bounds. This is unfortunately
1613+
// subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
1614+
// but that function doesn't actually need to normalize the bound it's visiting
1615+
// (whereas we have to do so here)...
1616+
let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
1617+
bound.visit_with(self);
1618+
self.depth = old_depth;
15811619
}
15821620
}
1621+
ty.super_visit_with(self)
15831622
}
15841623
}
15851624

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
2-
--> $DIR/wf-bounds.rs:11:22
2+
--> $DIR/wf-bounds.rs:13:22
33
|
44
LL | fn nya() -> impl Wf<Vec<[u8]>>;
55
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +9,7 @@ note: required by a bound in `Vec`
99
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
1010

1111
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
12-
--> $DIR/wf-bounds.rs:14:23
12+
--> $DIR/wf-bounds.rs:16:23
1313
|
1414
LL | fn nya2() -> impl Wf<[u8]>;
1515
| ^^^^^^^^ doesn't have a size known at compile-time
@@ -18,13 +18,23 @@ LL | fn nya2() -> impl Wf<[u8]>;
1818
note: required by a bound in `Wf`
1919
--> $DIR/wf-bounds.rs:8:10
2020
|
21-
LL | trait Wf<T> {}
21+
LL | trait Wf<T> {
2222
| ^ required by this bound in `Wf`
2323
help: consider relaxing the implicit `Sized` restriction
2424
|
25-
LL | trait Wf<T: ?Sized> {}
25+
LL | trait Wf<T: ?Sized> {
2626
| ++++++++
2727

28-
error: aborting due to 2 previous errors
28+
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
29+
--> $DIR/wf-bounds.rs:19:44
30+
|
31+
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
32+
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
33+
|
34+
= help: the trait `Sized` is not implemented for `[u8]`
35+
note: required by a bound in `Vec`
36+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
37+
38+
error: aborting due to 3 previous errors
2939

3040
For more information about this error, try `rustc --explain E0277`.

Diff for: tests/ui/impl-trait/in-trait/wf-bounds.next.stderr

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
2-
--> $DIR/wf-bounds.rs:11:22
2+
--> $DIR/wf-bounds.rs:13:22
33
|
44
LL | fn nya() -> impl Wf<Vec<[u8]>>;
55
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +9,7 @@ note: required by a bound in `Vec`
99
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
1010

1111
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
12-
--> $DIR/wf-bounds.rs:14:23
12+
--> $DIR/wf-bounds.rs:16:23
1313
|
1414
LL | fn nya2() -> impl Wf<[u8]>;
1515
| ^^^^^^^^ doesn't have a size known at compile-time
@@ -18,13 +18,23 @@ LL | fn nya2() -> impl Wf<[u8]>;
1818
note: required by a bound in `Wf`
1919
--> $DIR/wf-bounds.rs:8:10
2020
|
21-
LL | trait Wf<T> {}
21+
LL | trait Wf<T> {
2222
| ^ required by this bound in `Wf`
2323
help: consider relaxing the implicit `Sized` restriction
2424
|
25-
LL | trait Wf<T: ?Sized> {}
25+
LL | trait Wf<T: ?Sized> {
2626
| ++++++++
2727

28-
error: aborting due to 2 previous errors
28+
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
29+
--> $DIR/wf-bounds.rs:19:44
30+
|
31+
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
32+
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
33+
|
34+
= help: the trait `Sized` is not implemented for `[u8]`
35+
note: required by a bound in `Vec`
36+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
37+
38+
error: aborting due to 3 previous errors
2939

3040
For more information about this error, try `rustc --explain E0277`.

Diff for: tests/ui/impl-trait/in-trait/wf-bounds.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
#![feature(return_position_impl_trait_in_trait)]
66
#![allow(incomplete_features)]
77

8-
trait Wf<T> {}
8+
trait Wf<T> {
9+
type Output;
10+
}
911

1012
trait Uwu {
1113
fn nya() -> impl Wf<Vec<[u8]>>;
1214
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
1315

1416
fn nya2() -> impl Wf<[u8]>;
1517
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
18+
19+
fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
20+
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
1621
}
1722

1823
fn main() {}

0 commit comments

Comments
 (0)