Skip to content

Commit 6ff35da

Browse files
authored
Unrolled build for #145338
Rollup merge of #145338 - lcnr:coroutine-witness-yikes, r=compiler-errors actually provide the correct args to coroutine witnesses #145194 accidentally provided all arguments of the closure to the witness, but the witness only takes the generic parameters of the defining scope: https://github.com/rust-lang/rust/blob/216cdb7b22b637cef75b7225c642cb7587192643/compiler/rustc_hir_typeck/src/closure.rs#L164 Fixes #145288
2 parents 16ad385 + 4d84149 commit 6ff35da

File tree

5 files changed

+85
-63
lines changed

5 files changed

+85
-63
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,10 +821,38 @@ impl<'tcx> Ty<'tcx> {
821821
#[inline]
822822
pub fn new_coroutine_witness(
823823
tcx: TyCtxt<'tcx>,
824-
id: DefId,
824+
def_id: DefId,
825825
args: GenericArgsRef<'tcx>,
826826
) -> Ty<'tcx> {
827-
Ty::new(tcx, CoroutineWitness(id, args))
827+
if cfg!(debug_assertions) {
828+
tcx.debug_assert_args_compatible(tcx.typeck_root_def_id(def_id), args);
829+
}
830+
Ty::new(tcx, CoroutineWitness(def_id, args))
831+
}
832+
833+
pub fn new_coroutine_witness_for_coroutine(
834+
tcx: TyCtxt<'tcx>,
835+
def_id: DefId,
836+
coroutine_args: GenericArgsRef<'tcx>,
837+
) -> Ty<'tcx> {
838+
tcx.debug_assert_args_compatible(def_id, coroutine_args);
839+
// HACK: Coroutine witness types are lifetime erased, so they
840+
// never reference any lifetime args from the coroutine. We erase
841+
// the regions here since we may get into situations where a
842+
// coroutine is recursively contained within itself, leading to
843+
// witness types that differ by region args. This means that
844+
// cycle detection in fulfillment will not kick in, which leads
845+
// to unnecessary overflows in async code. See the issue:
846+
// <https://github.com/rust-lang/rust/issues/145151>.
847+
let args =
848+
ty::GenericArgs::for_item(tcx, tcx.typeck_root_def_id(def_id), |def, _| {
849+
match def.kind {
850+
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
851+
ty::GenericParamDefKind::Type { .. }
852+
| ty::GenericParamDefKind::Const { .. } => coroutine_args[def.index as usize],
853+
}
854+
});
855+
Ty::new_coroutine_witness(tcx, def_id, args)
828856
}
829857

830858
// misc
@@ -985,6 +1013,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
9851013
Ty::new_coroutine_witness(interner, def_id, args)
9861014
}
9871015

1016+
fn new_coroutine_witness_for_coroutine(
1017+
interner: TyCtxt<'tcx>,
1018+
def_id: DefId,
1019+
coroutine_args: ty::GenericArgsRef<'tcx>,
1020+
) -> Self {
1021+
Ty::new_coroutine_witness_for_coroutine(interner, def_id, coroutine_args)
1022+
}
1023+
9881024
fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
9891025
Ty::new_ptr(interner, ty, mutbl)
9901026
}

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,10 @@ where
7575
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
7676
}
7777

78-
ty::Coroutine(def_id, args) => {
79-
let coroutine_args = args.as_coroutine();
80-
Ok(ty::Binder::dummy(vec![
81-
coroutine_args.tupled_upvars_ty(),
82-
Ty::new_coroutine_witness(
83-
ecx.cx(),
84-
def_id,
85-
ecx.cx().mk_args(coroutine_args.parent_args().as_slice()),
86-
),
87-
]))
88-
}
78+
ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
79+
args.as_coroutine().tupled_upvars_ty(),
80+
Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
81+
])),
8982

9083
ty::CoroutineWitness(def_id, args) => Ok(ecx
9184
.cx()
@@ -251,14 +244,9 @@ where
251244
Movability::Static => Err(NoSolution),
252245
Movability::Movable => {
253246
if ecx.cx().features().coroutine_clone() {
254-
let coroutine = args.as_coroutine();
255247
Ok(ty::Binder::dummy(vec![
256-
coroutine.tupled_upvars_ty(),
257-
Ty::new_coroutine_witness(
258-
ecx.cx(),
259-
def_id,
260-
ecx.cx().mk_args(coroutine.parent_args().as_slice()),
261-
),
248+
args.as_coroutine().tupled_upvars_ty(),
249+
Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
262250
]))
263251
} else {
264252
Err(NoSolution)

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
55
use std::assert_matches::assert_matches;
66
use std::cell::{Cell, RefCell};
7+
use std::cmp;
78
use std::fmt::{self, Display};
89
use std::ops::ControlFlow;
9-
use std::{cmp, iter};
1010

1111
use hir::def::DefKind;
1212
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -2185,32 +2185,23 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
21852185
ty::Binder::dummy(vec![ty])
21862186
}
21872187

2188-
ty::Coroutine(coroutine_def_id, args) => {
2189-
match self.tcx().coroutine_movability(coroutine_def_id) {
2190-
hir::Movability::Static => {
2191-
unreachable!("tried to assemble `Sized` for static coroutine")
2192-
}
2193-
hir::Movability::Movable => {
2194-
if self.tcx().features().coroutine_clone() {
2195-
ty::Binder::dummy(
2196-
args.as_coroutine()
2197-
.upvar_tys()
2198-
.iter()
2199-
.chain([Ty::new_coroutine_witness(
2200-
self.tcx(),
2201-
coroutine_def_id,
2202-
self.tcx().mk_args(args.as_coroutine().parent_args()),
2203-
)])
2204-
.collect::<Vec<_>>(),
2205-
)
2206-
} else {
2207-
unreachable!(
2208-
"tried to assemble `Sized` for coroutine without enabled feature"
2209-
)
2210-
}
2188+
ty::Coroutine(def_id, args) => match self.tcx().coroutine_movability(def_id) {
2189+
hir::Movability::Static => {
2190+
unreachable!("tried to assemble `Clone` for static coroutine")
2191+
}
2192+
hir::Movability::Movable => {
2193+
if self.tcx().features().coroutine_clone() {
2194+
ty::Binder::dummy(vec![
2195+
args.as_coroutine().tupled_upvars_ty(),
2196+
Ty::new_coroutine_witness_for_coroutine(self.tcx(), def_id, args),
2197+
])
2198+
} else {
2199+
unreachable!(
2200+
"tried to assemble `Clone` for coroutine without enabled feature"
2201+
)
22112202
}
22122203
}
2213-
}
2204+
},
22142205

22152206
ty::CoroutineWitness(def_id, args) => self
22162207
.infcx
@@ -2334,25 +2325,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
23342325
ty::Coroutine(def_id, args) => {
23352326
let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
23362327
let tcx = self.tcx();
2337-
let witness = Ty::new_coroutine_witness(
2338-
tcx,
2339-
def_id,
2340-
ty::GenericArgs::for_item(tcx, def_id, |def, _| match def.kind {
2341-
// HACK: Coroutine witnesse types are lifetime erased, so they
2342-
// never reference any lifetime args from the coroutine. We erase
2343-
// the regions here since we may get into situations where a
2344-
// coroutine is recursively contained within itself, leading to
2345-
// witness types that differ by region args. This means that
2346-
// cycle detection in fulfillment will not kick in, which leads
2347-
// to unnecessary overflows in async code. See the issue:
2348-
// <https://github.com/rust-lang/rust/issues/145151>.
2349-
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
2350-
ty::GenericParamDefKind::Type { .. }
2351-
| ty::GenericParamDefKind::Const { .. } => args[def.index as usize],
2352-
}),
2353-
);
2328+
let witness = Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args);
23542329
ty::Binder::dummy(AutoImplConstituents {
2355-
types: [ty].into_iter().chain(iter::once(witness)).collect(),
2330+
types: vec![ty, witness],
23562331
assumptions: vec![],
23572332
})
23582333
}

compiler/rustc_type_ir/src/inherent.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ pub trait Ty<I: Interner<Ty = Self>>:
9191

9292
fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
9393

94+
fn new_coroutine_witness_for_coroutine(
95+
interner: I,
96+
def_id: I::DefId,
97+
coroutine_args: I::GenericArgs,
98+
) -> Self;
99+
94100
fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
95101

96102
fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Regression test for #145288. This is the same issue as #145151
2+
// which we fixed in #145194. However in that PR we accidentally created
3+
// a `CoroutineWitness` which referenced all generic arguments of the
4+
// coroutine, including upvars and the signature.
5+
6+
//@ edition: 2024
7+
//@ check-pass
8+
9+
async fn process<'a>(x: &'a u32) {
10+
Box::pin(process(x)).await;
11+
}
12+
13+
fn require_send(_: impl Send) {}
14+
15+
fn main() {
16+
require_send(process(&1));
17+
}

0 commit comments

Comments
 (0)