Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
mut constness: Const,
constness: Const,
movability: Movability,
decl: &FnDecl,
body: &Expr,
Expand All @@ -1062,18 +1062,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
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;
Expand Down
24 changes: 4 additions & 20 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::mem;

use rustc_abi::ExternAbi;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
Expand Down Expand Up @@ -378,7 +376,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
body.as_deref(),
attrs,
contract.as_deref(),
header.constness,
);

let itctx = ImplTraitContext::Universal;
Expand Down Expand Up @@ -1068,7 +1065,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(body),
attrs,
contract.as_deref(),
sig.header.constness,
);
let (generics, sig) = self.lower_method_sig(
generics,
Expand Down Expand Up @@ -1262,7 +1258,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
body.as_deref(),
attrs,
contract.as_deref(),
sig.header.constness,
);
let (generics, sig) = self.lower_method_sig(
generics,
Expand Down Expand Up @@ -1391,13 +1386,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
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
}

Expand All @@ -1416,13 +1409,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
&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)));

Expand All @@ -1440,20 +1429,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
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 {
self.lower_body(|this| {
(
&[],
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")),
},
)
Expand All @@ -1472,13 +1457,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
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 {
Expand All @@ -1503,7 +1487,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
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| {
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -193,7 +192,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
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,
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_middle/src/hir/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,17 +319,7 @@ impl<'tcx> TyCtxt<'tcx> {
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,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_target/src/spec/base/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions src/ci/docker/scripts/rfl-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions tests/ui/consts/const-closure-in-trait-impl.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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

Loading