Skip to content

Commit 3384f19

Browse files
committed
Auto merge of #153841 - matthiaskrgr:rollup-ihwBtPg, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #153376 (Replace `visit_waiters` with `abstracted_waiters_of`) - #153818 (Reimplement const closures) - #153774 (Fix std doctest build for SGX target.) - #153786 (Remove `value_from_cycle_error` specializations)
2 parents a0e206b + 5bdbc6b commit 3384f19

File tree

48 files changed

+283
-388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+283
-388
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
230230
e.id,
231231
expr_hir_id,
232232
*coroutine_kind,
233+
*constness,
233234
fn_decl,
234235
body,
235236
*fn_decl_span,
@@ -1060,7 +1061,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10601061
binder: &ClosureBinder,
10611062
capture_clause: CaptureBy,
10621063
closure_id: NodeId,
1063-
constness: Const,
1064+
mut constness: Const,
10641065
movability: Movability,
10651066
decl: &FnDecl,
10661067
body: &Expr,
@@ -1070,11 +1071,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
10701071
let closure_def_id = self.local_def_id(closure_id);
10711072
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
10721073

1074+
if let Const::Yes(span) = constness {
1075+
if !self.is_in_const_context {
1076+
self.dcx().span_err(span, "cannot use `const` closures outside of const contexts");
1077+
constness = Const::No;
1078+
}
1079+
}
1080+
10731081
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
10741082
let mut coroutine_kind = find_attr!(attrs, Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable));
10751083

10761084
// FIXME(contracts): Support contracts on closures?
1077-
let body_id = this.lower_fn_body(decl, None, |this| {
1085+
let body_id = this.lower_fn_body(decl, None, constness, |this| {
10781086
this.coroutine_kind = coroutine_kind;
10791087
let e = this.lower_expr_mut(body);
10801088
coroutine_kind = this.coroutine_kind;
@@ -1157,6 +1165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11571165
closure_id: NodeId,
11581166
closure_hir_id: HirId,
11591167
coroutine_kind: CoroutineKind,
1168+
constness: Const,
11601169
decl: &FnDecl,
11611170
body: &Expr,
11621171
fn_decl_span: Span,
@@ -1203,6 +1212,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
12031212
let fn_decl =
12041213
self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
12051214

1215+
if let Const::Yes(span) = constness {
1216+
self.dcx().span_err(span, "const coroutines are not supported");
1217+
}
1218+
12061219
let c = self.arena.alloc(hir::Closure {
12071220
def_id: closure_def_id,
12081221
binder: binder_clause,
@@ -1216,7 +1229,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12161229
// knows that a `FnDecl` output type like `-> &str` actually means
12171230
// "coroutine that returns &str", rather than directly returning a `&str`.
12181231
kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring),
1219-
constness: hir::Constness::NotConst,
1232+
constness: self.lower_constness(constness),
12201233
});
12211234
hir::ExprKind::Closure(c)
12221235
}

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::mem;
2+
13
use rustc_abi::ExternAbi;
24
use rustc_ast::visit::AssocCtxt;
35
use rustc_ast::*;
@@ -345,6 +347,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
345347
body.as_deref(),
346348
attrs,
347349
contract.as_deref(),
350+
header.constness,
348351
);
349352

350353
let itctx = ImplTraitContext::Universal;
@@ -1024,6 +1027,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10241027
Some(body),
10251028
attrs,
10261029
contract.as_deref(),
1030+
sig.header.constness,
10271031
);
10281032
let (generics, sig) = self.lower_method_sig(
10291033
generics,
@@ -1217,6 +1221,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12171221
body.as_deref(),
12181222
attrs,
12191223
contract.as_deref(),
1224+
sig.header.constness,
12201225
);
12211226
let (generics, sig) = self.lower_method_sig(
12221227
generics,
@@ -1346,11 +1351,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
13461351
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
13471352
) -> hir::BodyId {
13481353
let prev_coroutine_kind = self.coroutine_kind.take();
1354+
let prev_is_in_const_context = mem::take(&mut self.is_in_const_context);
13491355
let task_context = self.task_context.take();
13501356
let (parameters, result) = f(self);
13511357
let body_id = self.record_body(parameters, result);
13521358
self.task_context = task_context;
13531359
self.coroutine_kind = prev_coroutine_kind;
1360+
self.is_in_const_context = prev_is_in_const_context;
13541361
body_id
13551362
}
13561363

@@ -1369,9 +1376,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
13691376
&mut self,
13701377
decl: &FnDecl,
13711378
contract: Option<&FnContract>,
1379+
constness: Const,
13721380
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
13731381
) -> hir::BodyId {
13741382
self.lower_body(|this| {
1383+
if let Const::Yes(_) = constness {
1384+
this.is_in_const_context = true;
1385+
}
13751386
let params =
13761387
this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
13771388

@@ -1389,16 +1400,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
13891400
decl: &FnDecl,
13901401
body: &Block,
13911402
contract: Option<&FnContract>,
1403+
constness: Const,
13921404
) -> hir::BodyId {
1393-
self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))
1405+
self.lower_fn_body(decl, contract, constness, |this| this.lower_block_expr(body))
13941406
}
13951407

13961408
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
13971409
self.lower_body(|this| {
13981410
(
13991411
&[],
14001412
match expr {
1401-
Some(expr) => this.lower_expr_mut(expr),
1413+
Some(expr) => {
1414+
this.is_in_const_context = true;
1415+
this.lower_expr_mut(expr)
1416+
}
14021417
None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
14031418
},
14041419
)
@@ -1417,12 +1432,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
14171432
body: Option<&Block>,
14181433
attrs: &'hir [hir::Attribute],
14191434
contract: Option<&FnContract>,
1435+
constness: Const,
14201436
) -> hir::BodyId {
14211437
let Some(body) = body else {
14221438
// Functions without a body are an error, except if this is an intrinsic. For those we
14231439
// create a fake body so that the entire rest of the compiler doesn't have to deal with
14241440
// this as a special case.
1425-
return self.lower_fn_body(decl, contract, |this| {
1441+
return self.lower_fn_body(decl, contract, constness, |this| {
14261442
if find_attr!(attrs, RustcIntrinsic) || this.tcx.is_sdylib_interface_build() {
14271443
let span = this.lower_span(span);
14281444
let empty_block = hir::Block {
@@ -1447,7 +1463,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14471463
};
14481464
let Some(coroutine_kind) = coroutine_kind else {
14491465
// Typical case: not a coroutine.
1450-
return self.lower_fn_body_block(decl, body, contract);
1466+
return self.lower_fn_body_block(decl, body, contract, constness);
14511467
};
14521468
// FIXME(contracts): Support contracts on async fn.
14531469
self.lower_body(|this| {

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct LoweringContext<'a, 'hir> {
129129
loop_scope: Option<HirId>,
130130
is_in_loop_condition: bool,
131131
is_in_dyn_type: bool,
132+
is_in_const_context: bool,
132133

133134
current_hir_id_owner: hir::OwnerId,
134135
item_local_id_counter: hir::ItemLocalId,
@@ -190,6 +191,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
190191
loop_scope: None,
191192
is_in_loop_condition: false,
192193
is_in_dyn_type: false,
194+
is_in_const_context: false,
193195
coroutine_kind: None,
194196
task_context: None,
195197
current_item: None,

compiler/rustc_feature/src/unstable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ declare_features! (
431431
/// Allows defining and calling c-variadic functions in const contexts.
432432
(unstable, const_c_variadic, "1.95.0", Some(151787)),
433433
/// Allows `const || {}` closures in const contexts.
434-
(incomplete, const_closures, "1.68.0", Some(106003)),
434+
(unstable, const_closures, "1.68.0", Some(106003)),
435435
/// Allows using `[const] Destruct` bounds and calling drop impls in const contexts.
436436
(unstable, const_destruct, "1.85.0", Some(133214)),
437437
/// Allows `for _ in _` loops in const contexts.

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,9 @@ pub(super) fn const_conditions<'tcx>(
10691069
},
10701070
// N.B. Tuple ctors are unconditionally constant.
10711071
Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1072+
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_), .. }) => {
1073+
(hir::Generics::empty(), None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
1074+
}
10721075
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
10731076
};
10741077

compiler/rustc_middle/src/hir/map.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,16 +310,18 @@ impl<'tcx> TyCtxt<'tcx> {
310310
/// This should only be used for determining the context of a body, a return
311311
/// value of `Some` does not always suggest that the owner of the body is `const`,
312312
/// just that it has to be checked as if it were.
313-
pub fn hir_body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
314-
let def_id = def_id.into();
313+
pub fn hir_body_const_context(self, local_def_id: LocalDefId) -> Option<ConstContext> {
314+
let def_id = local_def_id.into();
315315
let ccx = match self.hir_body_owner_kind(def_id) {
316316
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
317317
BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability),
318318

319319
BodyOwnerKind::Fn if self.is_constructor(def_id) => return None,
320-
BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
321-
ConstContext::ConstFn
320+
// Const closures use their parent's const context
321+
BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
322+
return self.hir_body_const_context(self.local_parent(local_def_id));
322323
}
324+
BodyOwnerKind::Fn if self.is_const_fn(def_id) => ConstContext::ConstFn,
323325
BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
324326
};
325327

compiler/rustc_middle/src/query/job.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl<'tcx> QueryJob<'tcx> {
6565

6666
#[derive(Debug)]
6767
pub struct QueryWaiter<'tcx> {
68-
pub query: Option<QueryJobId>,
68+
pub parent: Option<QueryJobId>,
6969
pub condvar: Condvar,
7070
pub span: Span,
7171
pub cycle: Mutex<Option<CycleError<'tcx>>>,
@@ -94,8 +94,12 @@ impl<'tcx> QueryLatch<'tcx> {
9494
return Ok(()); // already complete
9595
};
9696

97-
let waiter =
98-
Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
97+
let waiter = Arc::new(QueryWaiter {
98+
parent: query,
99+
span,
100+
cycle: Mutex::new(None),
101+
condvar: Condvar::new(),
102+
});
99103

100104
// We push the waiter on to the `waiters` list. It can be accessed inside
101105
// the `wait` call below, by 1) the `set` method or 2) by deadlock detection.

compiler/rustc_middle/src/ty/context/impl_interner.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
402402
self.is_conditionally_const(def_id)
403403
}
404404

405+
fn closure_is_const(self, def_id: DefId) -> bool {
406+
debug_assert_matches!(self.def_kind(def_id), DefKind::Closure);
407+
self.constness(def_id) == hir::Constness::Const
408+
}
409+
405410
fn alias_has_const_conditions(self, def_id: DefId) -> bool {
406411
debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy);
407412
self.is_conditionally_const(def_id)

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,11 +2118,7 @@ impl<'tcx> TyCtxt<'tcx> {
21182118
// FIXME(const_trait_impl): ATPITs could be conditionally const?
21192119
hir::OpaqueTyOrigin::TyAlias { .. } => false,
21202120
},
2121-
DefKind::Closure => {
2122-
// Closures and RPITs will eventually have const conditions
2123-
// for `[const]` bounds.
2124-
false
2125-
}
2121+
DefKind::Closure => self.constness(def_id) == hir::Constness::Const,
21262122
DefKind::Ctor(_, CtorKind::Const)
21272123
| DefKind::Mod
21282124
| DefKind::Struct

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,11 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
661661
///
662662
/// Doing so on all calls to `extract_tupled_inputs_and_output_from_callable`
663663
/// would be wasteful.
664+
#[instrument(level = "trace", skip(cx), ret)]
664665
pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
665666
cx: I,
666667
self_ty: I::Ty,
667-
) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::FunctionId, I::GenericArgs), NoSolution> {
668+
) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
668669
match self_ty.kind() {
669670
ty::FnDef(def_id, args) => {
670671
let sig = cx.fn_sig(def_id);
@@ -675,7 +676,7 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
675676
Ok((
676677
sig.instantiate(cx, args)
677678
.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
678-
def_id,
679+
def_id.into(),
679680
args,
680681
))
681682
} else {
@@ -686,9 +687,19 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
686687
ty::FnPtr(..) => {
687688
return Err(NoSolution);
688689
}
689-
// `Closure`s are not const for now.
690-
ty::Closure(..) => {
691-
return Err(NoSolution);
690+
ty::Closure(def, args) => {
691+
if cx.closure_is_const(def) {
692+
let closure_args = args.as_closure();
693+
Ok((
694+
closure_args
695+
.sig()
696+
.map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
697+
def.into(),
698+
args,
699+
))
700+
} else {
701+
return Err(NoSolution);
702+
}
692703
}
693704
// `CoroutineClosure`s are not const for now.
694705
ty::CoroutineClosure(..) => {

0 commit comments

Comments
 (0)