Skip to content

Commit 9db9cf2

Browse files
Always compute coroutine layout when checking for recursive opaques
1 parent 203e6c1 commit 9db9cf2

11 files changed

+63
-93
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+15-25
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ 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
};
2626
use rustc_session::lint::builtin::UNINHABITED_STATIC;
2727
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2828
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
2929
use rustc_trait_selection::traits;
30-
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
30+
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
3131
use rustc_type_ir::fold::TypeFoldable;
3232
use tracing::{debug, instrument};
3333
use ty::TypingMode;
@@ -258,30 +258,20 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
258258

259259
// First, try to look at any opaque expansion cycles, considering coroutine fields
260260
// (even though these aren't necessarily true errors).
261-
if tcx
262-
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
263-
.is_err()
264-
{
265-
// Look for true opaque expansion cycles, but ignore coroutines.
266-
// This will give us any true errors. Coroutines are only problematic
267-
// if they cause layout computation errors.
268-
if tcx
269-
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
270-
.is_err()
271-
{
272-
let reported = opaque_type_cycle_error(tcx, def_id);
273-
return Err(reported);
274-
}
261+
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
262+
let reported = opaque_type_cycle_error(tcx, def_id);
263+
return Err(reported);
264+
}
275265

276-
// And also look for cycle errors in the layout of coroutines.
277-
if let Err(&LayoutError::Cycle(guar)) =
278-
tcx.layout_of(
279-
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
280-
.as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
281-
)
282-
{
283-
return Err(guar);
284-
}
266+
// And also look for cycle errors in the layout of coroutines behind opaques.
267+
if let Err(&LayoutError::Cycle(guar)) = tcx.layout_of(
268+
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()).as_query_input(Ty::new_opaque(
269+
tcx,
270+
def_id.to_def_id(),
271+
args,
272+
)),
273+
) {
274+
return Err(guar);
285275
}
286276

287277
Ok(())

compiler/rustc_middle/src/ty/util.rs

+2-56
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,6 @@ impl<'tcx> TyCtxt<'tcx> {
776776
self,
777777
def_id: DefId,
778778
args: GenericArgsRef<'tcx>,
779-
inspect_coroutine_fields: InspectCoroutineFields,
780779
) -> Result<Ty<'tcx>, Ty<'tcx>> {
781780
let mut visitor = OpaqueTypeExpander {
782781
seen_opaque_tys: FxHashSet::default(),
@@ -785,9 +784,7 @@ impl<'tcx> TyCtxt<'tcx> {
785784
found_recursion: false,
786785
found_any_recursion: false,
787786
check_recursion: true,
788-
expand_coroutines: true,
789787
tcx: self,
790-
inspect_coroutine_fields,
791788
};
792789

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

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

10481002
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
@@ -1051,19 +1005,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
10511005
}
10521006

10531007
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1054-
let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
1008+
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
10551009
self.expand_opaque_ty(def_id, args).unwrap_or(t)
1056-
} else if t.has_opaque_types() || t.has_coroutines() {
1010+
} else if t.has_opaque_types() {
10571011
t.super_fold_with(self)
10581012
} else {
10591013
t
1060-
};
1061-
if self.expand_coroutines {
1062-
if let ty::CoroutineWitness(def_id, args) = *t.kind() {
1063-
t = self.expand_coroutine(def_id, args).unwrap_or(t);
1064-
}
10651014
}
1066-
t
10671015
}
10681016

10691017
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
@@ -1752,9 +1700,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
17521700
found_recursion: false,
17531701
found_any_recursion: false,
17541702
check_recursion: false,
1755-
expand_coroutines: false,
17561703
tcx,
1757-
inspect_coroutine_fields: InspectCoroutineFields::No,
17581704
};
17591705
val.fold_with(&mut visitor)
17601706
}

tests/ui/force-inlining/deny-async.rs

+2
Original file line numberDiff line numberDiff line change
@@ -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
}

tests/ui/force-inlining/deny-async.stderr

+18-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ LL | pub fn callee() {
99
|
1010
= note: incompatible due to: #[rustc_no_mir_inline]
1111

12+
error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
13+
--> $DIR/deny-async.rs:22:5
14+
|
15+
LL | callee();
16+
| ^^^^^^^^ ...`callee` called here
17+
|
18+
= note: could not be inlined due to: #[rustc_no_mir_inline]
19+
1220
error: `callee_justified` is incompatible with `#[rustc_force_inline]`
1321
--> $DIR/deny-async.rs:16:1
1422
|
@@ -20,5 +28,14 @@ LL | pub fn callee_justified() {
2028
|
2129
= note: incompatible due to: #[rustc_no_mir_inline]
2230

23-
error: aborting due to 2 previous errors
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

tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr

+21-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
2020
| +++++++++++
2121

2222
error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
23-
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
23+
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
2424
|
2525
LL | F: Callback<Self::CallbackArg>,
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
@@ -118,7 +118,7 @@ LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
118118
| +++++++++++
119119

120120
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
121-
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
121+
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
122122
|
123123
LL | F: Callback<Self::CallbackArg>,
124124
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
@@ -133,6 +133,24 @@ help: consider further restricting type parameter `F` with trait `MyFn`
133133
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
134134
| +++++++++++
135135

136-
error: aborting due to 7 previous errors
136+
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
137+
--> $DIR/false-positive-predicate-entailment-error.rs:36:30
138+
|
139+
LL | fn autobatch<F>(self) -> impl Trait
140+
| ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
141+
|
142+
note: required for `F` to implement `Callback<i32>`
143+
--> $DIR/false-positive-predicate-entailment-error.rs:14:21
144+
|
145+
LL | impl<A, F: MyFn<A>> Callback<A> for F {
146+
| ------- ^^^^^^^^^^^ ^
147+
| |
148+
| unsatisfied trait bound introduced here
149+
help: consider further restricting type parameter `F` with trait `MyFn`
150+
|
151+
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
152+
| +++++++++++
153+
154+
error: aborting due to 8 previous errors
137155

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

tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl ChannelSender for Sender {
3838
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
3939
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
4040
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
41+
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
4142
where
4243
F: Callback<Self::CallbackArg>,
4344
//[current]~^ ERROR the trait bound `F: MyFn<i32>` is not satisfied

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
| ^^^^^^^

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
| ^^^^^^^

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 {

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

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)