mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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:
@@ -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;
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user