Skip to content

Commit 0fd4bf1

Browse files
authored
Rollup merge of rust-lang#136073 - compiler-errors:recursive-coro-always, r=oli-obk
Always compute coroutine layout for eagerly emitting recursive layout errors Detect recursive coroutine layouts even if we don't detect opaque type recursion in the new solver. This is for two reasons: 1. It helps us detect (bad) recursive async function calls in the new solver, which due to its approach to normalization causes us to not detect this via a recursive RPIT (since the opaques are more eagerly revealed in the opaque body). * Fixes rust-lang/trait-system-refactor-initiative#137. 2. It helps us detect (bad) recursive async functions behind AFITs. See the AFIT test that changed for the old solver too. 3. It also greatly simplifies the recursive impl trait check, since I can remove some jankness around how it handles coroutines.
2 parents 534d79a + eedfece commit 0fd4bf1

12 files changed

+37
-95
lines changed

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

+4-25
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::span_bug;
1919
use rustc_middle::ty::error::TypeErrorToStringExt;
2020
use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
2121
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
22-
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
22+
use rustc_middle::ty::util::{Discr, IntTypeExt};
2323
use rustc_middle::ty::{
2424
AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
2525
};
@@ -257,30 +257,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
257257

258258
// First, try to look at any opaque expansion cycles, considering coroutine fields
259259
// (even though these aren't necessarily true errors).
260-
if tcx
261-
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
262-
.is_err()
263-
{
264-
// Look for true opaque expansion cycles, but ignore coroutines.
265-
// This will give us any true errors. Coroutines are only problematic
266-
// if they cause layout computation errors.
267-
if tcx
268-
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
269-
.is_err()
270-
{
271-
let reported = opaque_type_cycle_error(tcx, def_id);
272-
return Err(reported);
273-
}
274-
275-
// And also look for cycle errors in the layout of coroutines.
276-
if let Err(&LayoutError::Cycle(guar)) =
277-
tcx.layout_of(
278-
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
279-
.as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
280-
)
281-
{
282-
return Err(guar);
283-
}
260+
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
261+
let reported = opaque_type_cycle_error(tcx, def_id);
262+
return Err(reported);
284263
}
285264

286265
Ok(())

Diff for: compiler/rustc_interface/src/passes.rs

+5
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,11 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
909909
tcx.ensure_ok().check_coroutine_obligations(
910910
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
911911
);
912+
// Eagerly check the unsubstituted layout for cycles.
913+
tcx.ensure().layout_of(
914+
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
915+
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
916+
);
912917
}
913918
});
914919
});

Diff for: compiler/rustc_middle/src/ty/util.rs

+2-56
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,6 @@ impl<'tcx> TyCtxt<'tcx> {
777777
self,
778778
def_id: DefId,
779779
args: GenericArgsRef<'tcx>,
780-
inspect_coroutine_fields: InspectCoroutineFields,
781780
) -> Result<Ty<'tcx>, Ty<'tcx>> {
782781
let mut visitor = OpaqueTypeExpander {
783782
seen_opaque_tys: FxHashSet::default(),
@@ -786,9 +785,7 @@ impl<'tcx> TyCtxt<'tcx> {
786785
found_recursion: false,
787786
found_any_recursion: false,
788787
check_recursion: true,
789-
expand_coroutines: true,
790788
tcx: self,
791-
inspect_coroutine_fields,
792789
};
793790

794791
let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
@@ -965,19 +962,11 @@ struct OpaqueTypeExpander<'tcx> {
965962
primary_def_id: Option<DefId>,
966963
found_recursion: bool,
967964
found_any_recursion: bool,
968-
expand_coroutines: bool,
969965
/// Whether or not to check for recursive opaque types.
970966
/// This is `true` when we're explicitly checking for opaque type
971967
/// recursion, and 'false' otherwise to avoid unnecessary work.
972968
check_recursion: bool,
973969
tcx: TyCtxt<'tcx>,
974-
inspect_coroutine_fields: InspectCoroutineFields,
975-
}
976-
977-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
978-
pub enum InspectCoroutineFields {
979-
No,
980-
Yes,
981970
}
982971

983972
impl<'tcx> OpaqueTypeExpander<'tcx> {
@@ -1009,41 +998,6 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
1009998
None
1010999
}
10111000
}
1012-
1013-
fn expand_coroutine(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
1014-
if self.found_any_recursion {
1015-
return None;
1016-
}
1017-
let args = args.fold_with(self);
1018-
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
1019-
let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
1020-
Some(expanded_ty) => *expanded_ty,
1021-
None => {
1022-
if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) {
1023-
for bty in self.tcx.bound_coroutine_hidden_types(def_id) {
1024-
let hidden_ty = self.tcx.instantiate_bound_regions_with_erased(
1025-
bty.instantiate(self.tcx, args),
1026-
);
1027-
self.fold_ty(hidden_ty);
1028-
}
1029-
}
1030-
let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
1031-
self.expanded_cache.insert((def_id, args), expanded_ty);
1032-
expanded_ty
1033-
}
1034-
};
1035-
if self.check_recursion {
1036-
self.seen_opaque_tys.remove(&def_id);
1037-
}
1038-
Some(expanded_ty)
1039-
} else {
1040-
// If another opaque type that we contain is recursive, then it
1041-
// will report the error, so we don't have to.
1042-
self.found_any_recursion = true;
1043-
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
1044-
None
1045-
}
1046-
}
10471001
}
10481002

10491003
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
@@ -1052,19 +1006,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
10521006
}
10531007

10541008
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1055-
let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
1009+
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
10561010
self.expand_opaque_ty(def_id, args).unwrap_or(t)
1057-
} else if t.has_opaque_types() || t.has_coroutines() {
1011+
} else if t.has_opaque_types() {
10581012
t.super_fold_with(self)
10591013
} else {
10601014
t
1061-
};
1062-
if self.expand_coroutines {
1063-
if let ty::CoroutineWitness(def_id, args) = *t.kind() {
1064-
t = self.expand_coroutine(def_id, args).unwrap_or(t);
1065-
}
10661015
}
1067-
t
10681016
}
10691017

10701018
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
@@ -1753,9 +1701,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
17531701
found_recursion: false,
17541702
found_any_recursion: false,
17551703
check_recursion: false,
1756-
expand_coroutines: false,
17571704
tcx,
1758-
inspect_coroutine_fields: InspectCoroutineFields::No,
17591705
};
17601706
val.fold_with(&mut visitor)
17611707
}

Diff for: tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//@ edition: 2021
22

3-
// Test doesn't fail until monomorphization time, unfortunately.
4-
//@ build-fail
5-
63
fn main() {
74
let _ = async {
85
A.first().await.second().await;

Diff for: tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in an async fn requires boxing
2-
--> $DIR/indirect-recursion-issue-112047.rs:34:5
2+
--> $DIR/indirect-recursion-issue-112047.rs:31:5
33
|
44
LL | async fn second(self) {
55
| ^^^^^^^^^^^^^^^^^^^^^

Diff for: tests/ui/force-inlining/deny-async.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//@ check-fail
21
//@ compile-flags: --crate-type=lib
32
//@ edition: 2021
3+
44
#![allow(internal_features)]
55
#![feature(rustc_attrs)]
66

@@ -20,5 +20,7 @@ pub fn callee_justified() {
2020

2121
async fn async_caller() {
2222
callee();
23+
//~^ ERROR `callee` could not be inlined
2324
callee_justified();
25+
//~^ ERROR `callee_justified` could not be inlined
2426
}

Diff for: tests/ui/force-inlining/deny-async.stderr

+18-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,22 @@ LL | pub fn callee_justified() {
2020
|
2121
= note: incompatible due to: #[rustc_no_mir_inline]
2222

23-
error: aborting due to 2 previous errors
23+
error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
24+
--> $DIR/deny-async.rs:22:5
25+
|
26+
LL | callee();
27+
| ^^^^^^^^ ...`callee` called here
28+
|
29+
= note: could not be inlined due to: #[rustc_no_mir_inline]
30+
31+
error: `callee_justified` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
32+
--> $DIR/deny-async.rs:24:5
33+
|
34+
LL | callee_justified();
35+
| ^^^^^^^^^^^^^^^^^^ ...`callee_justified` called here
36+
|
37+
= note: could not be inlined due to: #[rustc_no_mir_inline]
38+
= note: `callee_justified` is required to be inlined to: the test requires it
39+
40+
error: aborting due to 4 previous errors
2441

Diff for: tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in a coroutine requires boxing
2-
--> $DIR/recursive-coroutine-indirect.rs:11:18
2+
--> $DIR/recursive-coroutine-indirect.rs:8:18
33
|
44
LL | #[coroutine] move || {
55
| ^^^^^^^

Diff for: tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in a coroutine requires boxing
2-
--> $DIR/recursive-coroutine-indirect.rs:11:18
2+
--> $DIR/recursive-coroutine-indirect.rs:8:18
33
|
44
LL | #[coroutine] move || {
55
| ^^^^^^^

Diff for: tests/ui/impl-trait/recursive-coroutine-indirect.rs

-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
//@ ignore-compare-mode-next-solver (explicit revisions)
33
//@[next] compile-flags: -Znext-solver
44

5-
//@[next] build-fail
6-
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
7-
85
#![feature(coroutines)]
96
#![allow(unconditional_recursion)]
107
fn coroutine_hold() -> impl Sized {

Diff for: tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
//@ edition: 2021
2-
//@ build-fail
32

43
#![feature(impl_trait_in_assoc_type)]
54

Diff for: tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0733]: recursion in an async block requires boxing
2-
--> $DIR/indirect-recursion-issue-112047.rs:22:9
2+
--> $DIR/indirect-recursion-issue-112047.rs:21:9
33
|
44
LL | async move { recur(self).await; }
55
| ^^^^^^^^^^ ----------------- recursive call here
66
|
77
note: which leads to this async fn
8-
--> $DIR/indirect-recursion-issue-112047.rs:14:1
8+
--> $DIR/indirect-recursion-issue-112047.rs:13:1
99
|
1010
LL | async fn recur(t: impl Recur) {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)