Auto merge of #155863 - jhpratt:rollup-6wWyVPM, r=jhpratt

Rollup of 3 pull requests

Successful merges:

 - rust-lang/rust#155772 (Check closure's constness validity in the constness query)
 - rust-lang/rust#155833 (CI: rfl: move job forward to Linux v7.0)
 - rust-lang/rust#155839 (Remove unnecessary requires_lto: false for eBPF)
This commit is contained in:
bors
2026-04-27 07:49:26 +00:00
13 changed files with 57 additions and 50 deletions
+2 -9
View File
@@ -1052,7 +1052,7 @@ fn lower_expr_closure(
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
mut constness: Const,
constness: Const,
movability: Movability,
decl: &FnDecl,
body: &Expr,
@@ -1062,18 +1062,11 @@ fn lower_expr_closure(
let closure_def_id = self.local_def_id(closure_id);
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
if let Const::Yes(span) = constness {
if !self.is_in_const_context {
self.dcx().span_err(span, "cannot use `const` closures outside of const contexts");
constness = Const::No;
}
}
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
let mut coroutine_kind = find_attr!(attrs, Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable));
// FIXME(contracts): Support contracts on closures?
let body_id = this.lower_fn_body(decl, None, constness, |this| {
let body_id = this.lower_fn_body(decl, None, |this| {
this.coroutine_kind = coroutine_kind;
let e = this.lower_expr_mut(body);
coroutine_kind = this.coroutine_kind;
+4 -20
View File
@@ -1,5 +1,3 @@
use std::mem;
use rustc_abi::ExternAbi;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
@@ -378,7 +376,6 @@ fn lower_item_kind(
body.as_deref(),
attrs,
contract.as_deref(),
header.constness,
);
let itctx = ImplTraitContext::Universal;
@@ -1068,7 +1065,6 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
Some(body),
attrs,
contract.as_deref(),
sig.header.constness,
);
let (generics, sig) = self.lower_method_sig(
generics,
@@ -1262,7 +1258,6 @@ fn lower_impl_item(
body.as_deref(),
attrs,
contract.as_deref(),
sig.header.constness,
);
let (generics, sig) = self.lower_method_sig(
generics,
@@ -1391,13 +1386,11 @@ pub(super) fn lower_body(
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
) -> hir::BodyId {
let prev_coroutine_kind = self.coroutine_kind.take();
let prev_is_in_const_context = mem::take(&mut self.is_in_const_context);
let task_context = self.task_context.take();
let (parameters, result) = f(self);
let body_id = self.record_body(parameters, result);
self.task_context = task_context;
self.coroutine_kind = prev_coroutine_kind;
self.is_in_const_context = prev_is_in_const_context;
body_id
}
@@ -1416,13 +1409,9 @@ pub(super) fn lower_fn_body(
&mut self,
decl: &FnDecl,
contract: Option<&FnContract>,
constness: Const,
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::BodyId {
self.lower_body(|this| {
if let Const::Yes(_) = constness {
this.is_in_const_context = true;
}
let params =
this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
@@ -1440,9 +1429,8 @@ fn lower_fn_body_block(
decl: &FnDecl,
body: &Block,
contract: Option<&FnContract>,
constness: Const,
) -> hir::BodyId {
self.lower_fn_body(decl, contract, constness, |this| this.lower_block_expr(body))
self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))
}
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
@@ -1450,10 +1438,7 @@ pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hi
(
&[],
match expr {
Some(expr) => {
this.is_in_const_context = true;
this.lower_expr_mut(expr)
}
Some(expr) => this.lower_expr_mut(expr),
None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
},
)
@@ -1472,13 +1457,12 @@ fn lower_maybe_coroutine_body(
body: Option<&Block>,
attrs: &'hir [hir::Attribute],
contract: Option<&FnContract>,
constness: Const,
) -> hir::BodyId {
let Some(body) = body else {
// Functions without a body are an error, except if this is an intrinsic. For those we
// create a fake body so that the entire rest of the compiler doesn't have to deal with
// this as a special case.
return self.lower_fn_body(decl, contract, constness, |this| {
return self.lower_fn_body(decl, contract, |this| {
if find_attr!(attrs, RustcIntrinsic) || this.tcx.is_sdylib_interface_build() {
let span = this.lower_span(span);
let empty_block = hir::Block {
@@ -1503,7 +1487,7 @@ fn lower_maybe_coroutine_body(
};
let Some(coroutine_kind) = coroutine_kind else {
// Typical case: not a coroutine.
return self.lower_fn_body_block(decl, body, contract, constness);
return self.lower_fn_body_block(decl, body, contract);
};
// FIXME(contracts): Support contracts on async fn.
self.lower_body(|this| {
-2
View File
@@ -124,7 +124,6 @@ struct LoweringContext<'a, 'hir> {
loop_scope: Option<HirId>,
is_in_loop_condition: bool,
is_in_dyn_type: bool,
is_in_const_context: bool,
current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId,
@@ -193,7 +192,6 @@ fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>) -> Self {
loop_scope: None,
is_in_loop_condition: false,
is_in_dyn_type: false,
is_in_const_context: false,
coroutine_kind: None,
task_context: None,
current_item: None,
@@ -16,7 +16,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
// Foreign functions cannot be evaluated at compile-time.
Constness::NotConst
}
Node::Expr(e) if let ExprKind::Closure(c) = e.kind => c.constness,
Node::Expr(e) if let ExprKind::Closure(c) = e.kind => {
if let Constness::Const = c.constness && tcx.hir_body_const_context(tcx.local_parent(def_id)).is_none() {
tcx.dcx().span_err(tcx.def_span(def_id), "cannot use `const` closures outside of const contexts");
return Constness::NotConst;
}
c.constness
},
// FIXME(fee1-dead): extract this one out and rename this query to `fn_constness` so we don't need `is_const_fn` anymore.
Node::Item(i) if let ItemKind::Impl(impl_) = i.kind => impl_.constness,
Node::Item(Item { kind: ItemKind::Fn { sig, .. }, .. }) => sig.header.constness,
+1 -11
View File
@@ -319,17 +319,7 @@ pub fn hir_body_const_context(self, local_def_id: LocalDefId) -> Option<ConstCon
BodyOwnerKind::Fn if self.is_constructor(def_id) => return None,
// Const closures use their parent's const context
BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
return Some(
self.hir_body_const_context(self.local_parent(local_def_id)).unwrap_or_else(
|| {
assert!(
self.dcx().has_errors().is_some(),
"`const` closure with no enclosing const context",
);
ConstContext::ConstFn
},
),
);
return self.hir_body_const_context(self.local_parent(local_def_id));
}
BodyOwnerKind::Fn if self.is_const_fn(def_id) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
@@ -18,7 +18,6 @@ pub(crate) fn opts(endian: Endian) -> TargetOptions {
// BPF_PROG_LOAD and not all BPF libraries do that yet
merge_functions: MergeFunctions::Disabled,
obj_is_bitcode: true,
requires_lto: false,
singlethread: true,
// When targeting the `v3` cpu in llvm, 32-bit atomics are also supported.
// But making this value change based on the target cpu can be mostly confusing
+1 -3
View File
@@ -2,9 +2,7 @@
set -euo pipefail
# https://github.com/rust-lang/rust/pull/151534
# https://github.com/rust-lang/rust/pull/149389
LINUX_VERSION=167ea5357eb7c3a39200627a36dfbfe249576192
LINUX_VERSION=v7.0
# Build rustc, rustdoc, cargo, clippy-driver and rustfmt
../x.py build --stage 2 library rustdoc clippy rustfmt
@@ -0,0 +1,25 @@
//@ check-pass
#![feature(const_closures, const_destruct, const_trait_impl)]
use std::marker::Destruct;
use std::num::NonZero;
const trait T {
fn a(&mut self, f: impl [const] Fn() + [const] Destruct);
fn b(&mut self);
}
struct S;
impl const T for S {
fn a(&mut self, f: impl [const] Fn() + [const] Destruct) {
f()
}
fn b(&mut self) {
self.a(const || {});
}
}
fn main() {}
@@ -11,6 +11,7 @@ impl<T: Foo> Foo for &mut T {
const fn test() -> impl [const] Fn() {
//~^ ERROR functions in trait impls cannot be declared const
const move || {}
//~^ ERROR: cannot use `const` closures outside of const contexts
}
}
@@ -14,6 +14,12 @@ help: ... and declare the impl to be const instead
LL | impl<T: Foo> const Foo for &mut T {
| +++++
error: aborting due to 1 previous error
error: cannot use `const` closures outside of const contexts
--> $DIR/const-closure-in-non-const-trait-impl-method.rs:13:9
|
LL | const move || {}
| ^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0379`.
@@ -6,6 +6,7 @@ trait Tr {
const fn test() {
//~^ ERROR functions in traits cannot be declared const
(const || {})()
//~^ ERROR cannot use `const` closures outside of const contexts
}
}
@@ -7,6 +7,12 @@ LL | const fn test() {
| functions in traits cannot be const
| help: remove the `const`
error: aborting due to 1 previous error
error: cannot use `const` closures outside of const contexts
--> $DIR/const-closure-in-non-const-trait-method.rs:8:10
|
LL | (const || {})()
| ^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0379`.
@@ -2,7 +2,7 @@ error: cannot use `const` closures outside of const contexts
--> $DIR/non-const-op-const-closure-non-const-outer.rs:14:6
|
LL | (const || { (()).foo() })();
| ^^^^^
| ^^^^^^^^
error: aborting due to 1 previous error