From 4fb10c0ce45673264d5dd428f4d5a4a389a2f1de Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 20 Dec 2022 16:15:55 +0000 Subject: [PATCH 1/8] parse const closures --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast/src/mut_visit.rs | 2 ++ compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/src/expr.rs | 6 ++++++ compiler/rustc_ast_lowering/src/item.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/expr.rs | 2 ++ compiler/rustc_expand/src/build.rs | 1 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_hir/src/intravisit.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 14 ++++++++++---- compiler/rustc_parse/src/parser/expr.rs | 8 +++++++- compiler/rustc_parse/src/parser/mod.rs | 10 ++++++++++ src/tools/rustfmt/src/closures.rs | 19 ++++++++++++++++--- src/tools/rustfmt/src/expr.rs | 1 + tests/ui/parser/recover-quantified-closure.rs | 2 +- .../parser/recover-quantified-closure.stderr | 4 ++-- 16 files changed, 63 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e656fb3740b..7de594719dd 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1307,6 +1307,7 @@ pub fn is_approximately_pattern(&self) -> bool { pub struct Closure { pub binder: ClosureBinder, pub capture_clause: CaptureBy, + pub constness: Const, pub asyncness: Async, pub movability: Movability, pub fn_decl: P, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c572171e8f4..77f342d1eb3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1362,6 +1362,7 @@ pub fn noop_visit_expr( ExprKind::Closure(box Closure { binder, capture_clause: _, + constness, asyncness, movability: _, fn_decl, @@ -1370,6 +1371,7 @@ pub fn noop_visit_expr( fn_arg_span: _, }) => { vis.visit_closure_binder(binder); + visit_constness(constness, vis); vis.visit_asyncness(asyncness); vis.visit_fn_decl(fn_decl); vis.visit_expr(body); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index df7145a722a..e8823eff83a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -836,6 +836,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { binder, capture_clause: _, asyncness: _, + constness: _, movability: _, fn_decl, body, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 14f082be9ba..c3611b2f522 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -209,6 +209,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { ExprKind::Closure(box Closure { binder, capture_clause, + constness, asyncness, movability, fn_decl, @@ -233,6 +234,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { binder, *capture_clause, e.id, + *constness, *movability, fn_decl, body, @@ -651,6 +653,7 @@ pub(super) fn make_async_expr( fn_decl_span: self.lower_span(span), fn_arg_span: None, movability: Some(hir::Movability::Static), + constness: hir::Constness::NotConst, }); hir::ExprKind::Closure(c) @@ -890,6 +893,7 @@ fn lower_expr_closure( binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, + constness: Const, movability: Movability, decl: &FnDecl, body: &Expr, @@ -927,6 +931,7 @@ fn lower_expr_closure( fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), movability: generator_option, + constness: self.lower_constness(constness), }); hir::ExprKind::Closure(c) @@ -1041,6 +1046,7 @@ fn lower_expr_async_closure( fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), movability: None, + constness: hir::Constness::NotConst, }); hir::ExprKind::Closure(c) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ea30bed5ace..065779d0670 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1239,7 +1239,7 @@ fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { } } - fn lower_constness(&mut self, c: Const) -> hir::Constness { + pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness { match c { Const::Yes(_) => hir::Constness::Const, Const::No => hir::Constness::NotConst, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 3b17f6dd627..b125c6407d0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -399,6 +399,7 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline ast::ExprKind::Closure(box ast::Closure { binder, capture_clause, + constness, asyncness, movability, fn_decl, @@ -407,6 +408,7 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline fn_arg_span: _, }) => { self.print_closure_binder(binder); + self.print_constness(*constness); self.print_movability(*movability); self.print_asyncness(*asyncness); self.print_capture_clause(*capture_clause); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 93b3af4ab97..9b16e79d49a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -533,6 +533,7 @@ pub fn lambda(&self, span: Span, ids: Vec, body: P) -> P { pub struct Closure<'hir> { pub def_id: LocalDefId, pub binder: ClosureBinder, + pub constness: Constness, pub capture_clause: CaptureBy, pub bound_generic_params: &'hir [GenericParam<'hir>], pub fn_decl: &'hir FnDecl<'hir>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 6c475b659eb..02641b7cf8f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -742,6 +742,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) fn_decl_span: _, fn_arg_span: _, movability: _, + constness: _, }) => { walk_list!(visitor, visit_generic_param, bound_generic_params); visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3e3af8395a1..f74c551a45b 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1464,6 +1464,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) { } hir::ExprKind::Closure(&hir::Closure { binder, + constness, capture_clause, bound_generic_params, fn_decl, @@ -1474,6 +1475,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) { def_id: _, }) => { self.print_closure_binder(binder, bound_generic_params); + self.print_constness(constness); self.print_capture_clause(capture_clause); self.print_closure_params(fn_decl, body); @@ -2272,10 +2274,7 @@ pub fn print_ty_fn( } pub fn print_fn_header_info(&mut self, header: hir::FnHeader) { - match header.constness { - hir::Constness::NotConst => {} - hir::Constness::Const => self.word_nbsp("const"), - } + self.print_constness(header.constness); match header.asyncness { hir::IsAsync::NotAsync => {} @@ -2292,6 +2291,13 @@ pub fn print_fn_header_info(&mut self, header: hir::FnHeader) { self.word("fn") } + pub fn print_constness(&mut self, s: hir::Constness) { + match s { + hir::Constness::NotConst => {} + hir::Constness::Const => self.word_nbsp("const"), + } + } + pub fn print_unsafety(&mut self, s: hir::Unsafety) { match s { hir::Unsafety::Normal => {} diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f5093fb02a8..dd2b03988c3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1325,7 +1325,10 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { self.parse_array_or_repeat_expr(Delimiter::Bracket) } else if self.check_path() { self.parse_path_start_expr() - } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { + } else if self.check_keyword(kw::Move) + || self.check_keyword(kw::Static) + || self.check_const_closure() + { self.parse_closure_expr() } else if self.eat_keyword(kw::If) { self.parse_if_expr() @@ -2065,6 +2068,8 @@ fn parse_closure_expr(&mut self) -> PResult<'a, P> { ClosureBinder::NotPresent }; + let constness = self.parse_constness(Case::Sensitive); + let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; @@ -2111,6 +2116,7 @@ fn parse_closure_expr(&mut self) -> PResult<'a, P> { ExprKind::Closure(Box::new(ast::Closure { binder, capture_clause, + constness, asyncness, movability, fn_decl, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 49d31981539..2fd2a4e5154 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -736,6 +736,16 @@ fn check_const_arg(&mut self) -> bool { self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) } + fn check_const_closure(&self) -> bool { + self.is_keyword_ahead(0, &[kw::Const]) + && self.look_ahead(1, |t| match &t.kind { + token::Ident(kw::Move | kw::Static | kw::Async, _) + | token::OrOr + | token::BinOp(token::Or) => true, + _ => false, + }) + } + fn check_inline_const(&self, dist: usize) -> bool { self.is_keyword_ahead(dist, &[kw::Const]) && self.look_ahead(dist + 1, |t| match &t.kind { diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 244d4427c56..8fd0fcf8f5c 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -26,6 +26,7 @@ pub(crate) fn rewrite_closure( binder: &ast::ClosureBinder, + constness: ast::Const, capture: ast::CaptureBy, is_async: &ast::Async, movability: ast::Movability, @@ -38,7 +39,7 @@ pub(crate) fn rewrite_closure( debug!("rewrite_closure {:?}", body); let (prefix, extra_offset) = rewrite_closure_fn_decl( - binder, capture, is_async, movability, fn_decl, body, span, context, shape, + binder, constness, capture, is_async, movability, fn_decl, body, span, context, shape, )?; // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; @@ -230,6 +231,7 @@ fn rewrite_closure_block( // Return type is (prefix, extra_offset) fn rewrite_closure_fn_decl( binder: &ast::ClosureBinder, + constness: ast::Const, capture: ast::CaptureBy, asyncness: &ast::Async, movability: ast::Movability, @@ -250,6 +252,12 @@ fn rewrite_closure_fn_decl( ast::ClosureBinder::NotPresent => "".to_owned(), }; + let const_ = if matches!(constness, ast::Const::Yes(_)) { + "const " + } else { + "" + }; + let immovable = if movability == ast::Movability::Static { "static " } else { @@ -264,7 +272,7 @@ fn rewrite_closure_fn_decl( // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. let nested_shape = shape - .shrink_left(binder.len() + immovable.len() + is_async.len() + mover.len())? + .shrink_left(binder.len() + const_.len() + immovable.len() + is_async.len() + mover.len())? .sub_width(4)?; // 1 = | @@ -302,7 +310,10 @@ fn rewrite_closure_fn_decl( .tactic(tactic) .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}{}{}{}|{}|", binder, immovable, is_async, mover, list_str); + let mut prefix = format!( + "{}{}{}{}{}|{}|", + binder, const_, immovable, is_async, mover, list_str + ); if !ret_str.is_empty() { if prefix.contains('\n') { @@ -329,6 +340,7 @@ pub(crate) fn rewrite_last_closure( if let ast::ExprKind::Closure(ref closure) = expr.kind { let ast::Closure { ref binder, + constness, capture_clause, ref asyncness, movability, @@ -349,6 +361,7 @@ pub(crate) fn rewrite_last_closure( }; let (prefix, extra_offset) = rewrite_closure_fn_decl( binder, + constness, capture_clause, asyncness, movability, diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 414e767690b..868ff045ab7 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -205,6 +205,7 @@ pub(crate) fn format_expr( } ast::ExprKind::Closure(ref cl) => closures::rewrite_closure( &cl.binder, + cl.constness, cl.capture_clause, &cl.asyncness, cl.movability, diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs index 10af39b7007..df22f5e065c 100644 --- a/tests/ui/parser/recover-quantified-closure.rs +++ b/tests/ui/parser/recover-quantified-closure.rs @@ -7,6 +7,6 @@ fn main() { enum Foo { Bar } fn foo(x: impl Iterator) { for ::Bar in x {} - //~^ ERROR expected one of `move`, `static`, `|` + //~^ ERROR expected one of `const`, `move`, `static`, `|` //~^^ ERROR `for<...>` binders for closures are experimental } diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr index 39eec80f658..9ec4d2c034d 100644 --- a/tests/ui/parser/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -1,8 +1,8 @@ -error: expected one of `move`, `static`, `|`, or `||`, found `::` +error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::` --> $DIR/recover-quantified-closure.rs:9:14 | LL | for ::Bar in x {} - | ^^ expected one of `move`, `static`, `|`, or `||` + | ^^ expected one of `const`, `move`, `static`, `|`, or `||` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/recover-quantified-closure.rs:2:5 From e7fea8c7e63cd60aa583e6ee761716bef9a7cc1a Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 21 Dec 2022 14:51:02 +0000 Subject: [PATCH 2/8] gate const closures --- compiler/rustc_ast_passes/src/feature_gate.rs | 8 ++++++++ compiler/rustc_feature/src/active.rs | 4 +++- compiler/rustc_span/src/symbol.rs | 1 + .../rfc-2632-const-trait-impl/const_closures/gate.rs | 4 ++++ .../const_closures/gate.stderr | 12 ++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 039338f543c..89ba6f936d1 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -385,6 +385,14 @@ fn visit_expr(&mut self, e: &'a ast::Expr) { ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } + ast::ExprKind::Closure(box ast::Closure { constness: ast::Const::Yes(_), .. }) => { + gate_feature_post!( + &self, + const_closures, + e.span, + "const closures are experimental" + ); + } _ => {} } visit::walk_expr(self, e) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 691c0955cad..d6eda08f662 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -342,7 +342,9 @@ pub fn set(&self, features: &mut Features, span: Span) { (active, collapse_debuginfo, "1.65.0", Some(100758), None), /// Allows `async {}` expressions in const contexts. (active, const_async_blocks, "1.53.0", Some(85368), None), - // Allows limiting the evaluation steps of const expressions + /// Allows `const || {}` closures in const contexts. + (incomplete, const_closures, "CURRENT_RUSTC_VERSION", Some(106003), None), + /// Allows limiting the evaluation steps of const expressions (active, const_eval_limit, "1.43.0", Some(67217), None), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fbb12701d96..706002f79b1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -498,6 +498,7 @@ console, const_allocate, const_async_blocks, + const_closures, const_compare_raw_pointers, const_constructor, const_deallocate, diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs new file mode 100644 index 00000000000..89551121ad2 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs @@ -0,0 +1,4 @@ +fn main() { + (const || {})(); + //~^ ERROR: const closures are experimental +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr new file mode 100644 index 00000000000..94a7fe9e62c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: const closures are experimental + --> $DIR/gate.rs:2:6 + | +LL | (const || {})(); + | ^^^^^^^^^^^ + | + = note: see issue #106003 for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 23718a3cc207c20655c08c828b497dbb52413f50 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 21 Dec 2022 15:47:33 +0000 Subject: [PATCH 3/8] suggest adding const_trait_impl if error because of that --- .../src/transform/check_consts/check.rs | 4 ++++ .../rustc_const_eval/src/transform/check_consts/ops.rs | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 54213d55a2d..fd166e3c938 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -730,6 +730,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location substs, span: *fn_span, from_hir_call: *from_hir_call, + feature: Some(sym::const_trait_impl), }); return; } @@ -802,6 +803,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location substs, span: *fn_span, from_hir_call: *from_hir_call, + feature: None, }); return; } @@ -844,6 +846,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location substs, span: *fn_span, from_hir_call: *from_hir_call, + feature: None, }); return; } @@ -903,6 +906,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location substs, span: *fn_span, from_hir_call: *from_hir_call, + feature: None, }); return; } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index b19d270e610..0cb5d2ff8c7 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -111,6 +111,7 @@ pub struct FnCallNonConst<'tcx> { pub substs: SubstsRef<'tcx>, pub span: Span, pub from_hir_call: bool, + pub feature: Option, } impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { @@ -119,7 +120,7 @@ fn build_error( ccx: &ConstCx<'_, 'tcx>, _: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let FnCallNonConst { caller, callee, substs, span, from_hir_call } = *self; + let FnCallNonConst { caller, callee, substs, span, from_hir_call, feature } = *self; let ConstCx { tcx, param_env, .. } = *ccx; let diag_trait = |err, self_ty: Ty<'_>, trait_id| { @@ -318,6 +319,13 @@ macro_rules! error { ccx.const_kind(), )); + if let Some(feature) = feature && ccx.tcx.sess.is_nightly_build() { + err.help(&format!( + "add `#![feature({})]` to the crate attributes to enable", + feature, + )); + } + if let ConstContext::Static(_) = ccx.const_kind() { err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell"); } From 6e63f7be54d084b3ba31b3706b3a1eb36a98b43f Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 21 Dec 2022 16:32:16 +0000 Subject: [PATCH 4/8] attempt to make a minimal example work --- .../src/const_eval/fn_queries.rs | 1 + compiler/rustc_const_eval/src/lib.rs | 1 + .../src/transform/check_consts/check.rs | 14 ++++++++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 2 ++ compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/traits/select.rs | 4 ++- compiler/rustc_middle/src/ty/mod.rs | 6 +++-- .../src/traits/select/candidate_assembly.rs | 11 +++++--- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 27 ++++++++++--------- .../const_closures/call.rs | 10 +++++++ .../const_closures/gate.rs | 1 + .../const_closures/gate.stderr | 2 +- 13 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index f1674d04f8d..351c701305a 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -41,6 +41,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { }; if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } + hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, _ => { if let Some(fn_kind) = node.fn_kind() { if fn_kind.constness() == hir::Constness::Const { diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 443c01fdb90..46e7b09a55e 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -20,6 +20,7 @@ #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![feature(if_let_guard)] #![feature(is_some_and)] #![recursion_limit = "256"] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index fd166e3c938..38212496ec8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -783,6 +783,20 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location ); return; } + Ok(Some(ImplSource::Closure(data))) => { + if !tcx.is_const_fn_raw(data.closure_def_id) { + self.check_op(ops::FnCallNonConst { + caller, + callee, + substs, + span: *fn_span, + from_hir_call: *from_hir_call, + feature: None, + }); + + return; + } + } Ok(Some(ImplSource::UserDefined(data))) => { let callee_name = tcx.item_name(callee); if let Some(&did) = tcx diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bdc4ae391f0..030328d1e26 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1686,6 +1686,8 @@ fn encode_info_for_closure(&mut self, def_id: LocalDefId) { } ty::Closure(_, substs) => { + let constness = self.tcx.constness(def_id.to_def_id()); + self.tables.constness.set(def_id.to_def_id().index, constness); record!(self.tables.fn_sig[def_id.to_def_id()] <- substs.as_closure().sig()); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 883554f959c..4b09a9b6939 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -485,7 +485,7 @@ pub fn body_const_context(self, def_id: LocalDefId) -> Option { BodyOwnerKind::Static(mt) => ConstContext::Static(mt), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None, - BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(def_id.to_def_id()) => { + BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id.to_def_id()) => { ConstContext::ConstFn } BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => { diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ec69864c951..1cc9fd526b4 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -131,7 +131,9 @@ pub enum SelectionCandidate<'tcx> { /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for an `||` expression. - ClosureCandidate, + ClosureCandidate { + is_const: bool, + }, /// Implementation of a `Generator` trait by one of the anonymous types /// generated for a generator. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fa571d480b6..993e95b3514 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2465,8 +2465,10 @@ pub fn is_object_safe(self, key: DefId) -> bool { #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) - && self.constness(def_id) == hir::Constness::Const + matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure + ) && self.constness(def_id) == hir::Constness::Const } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index c54d901e9b1..a5635ccfec4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -254,18 +254,23 @@ fn assemble_closure_candidates( // touch bound regions, they just capture the in-scope // type/region parameters match *obligation.self_ty().skip_binder().kind() { - ty::Closure(_, closure_substs) => { + ty::Closure(def_id, closure_substs) => { + let is_const = self.tcx().is_const_fn_raw(def_id); debug!(?kind, ?obligation, "assemble_unboxed_candidates"); match self.infcx.closure_kind(closure_substs) { Some(closure_kind) => { debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { - candidates.vec.push(ClosureCandidate); + candidates.vec.push(ClosureCandidate { + is_const, + }); } } None => { debug!("assemble_unboxed_candidates: closure_kind not yet known"); - candidates.vec.push(ClosureCandidate); + candidates.vec.push(ClosureCandidate { + is_const, + }); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 15526b34ed2..a41d10f1043 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -84,7 +84,7 @@ pub(super) fn confirm_candidate( ImplSource::Object(data) } - ClosureCandidate => { + ClosureCandidate { .. } => { let vtable_closure = self.confirm_closure_candidate(obligation)?; ImplSource::Closure(vtable_closure) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3f14491f803..25a294b5401 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1365,15 +1365,18 @@ fn filter_impls( // const param ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {} // const projection - ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {} + ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) // auto trait impl - AutoImplCandidate => {} + | AutoImplCandidate // generator / future, this will raise error in other places // or ignore error with const_async_blocks feature - GeneratorCandidate => {} - FutureCandidate => {} + | GeneratorCandidate + | FutureCandidate // FnDef where the function is const - FnPointerCandidate { is_const: true } => {} + | FnPointerCandidate { is_const: true } + | ConstDestructCandidate(_) + | ClosureCandidate { is_const: true } => {} + FnPointerCandidate { is_const: false } => { if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() { // Trait methods are not seen as const unless the trait is implemented as const. @@ -1382,7 +1385,7 @@ fn filter_impls( continue } } - ConstDestructCandidate(_) => {} + _ => { // reject all other types of candidates continue; @@ -1844,7 +1847,7 @@ fn candidate_should_be_dropped_in_favor_of( ( ParamCandidate(ref cand), ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1863,7 +1866,7 @@ fn candidate_should_be_dropped_in_favor_of( } ( ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1894,7 +1897,7 @@ fn candidate_should_be_dropped_in_favor_of( ( ObjectCandidate(_) | ProjectionCandidate(..), ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1907,7 +1910,7 @@ fn candidate_should_be_dropped_in_favor_of( ( ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1989,7 +1992,7 @@ fn candidate_should_be_dropped_in_favor_of( // Everything else is ambiguous ( ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1999,7 +2002,7 @@ fn candidate_should_be_dropped_in_favor_of( | BuiltinCandidate { has_nested: true } | TraitAliasCandidate, ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs b/src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs new file mode 100644 index 00000000000..5f48c235373 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +pub const _: () = { + assert!((const || true)()); +}; + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs index 89551121ad2..f2cd26c91b6 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs @@ -1,3 +1,4 @@ +// gate-test-const_closures fn main() { (const || {})(); //~^ ERROR: const closures are experimental diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr index 94a7fe9e62c..30edc4127e1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: const closures are experimental - --> $DIR/gate.rs:2:6 + --> $DIR/gate.rs:3:6 | LL | (const || {})(); | ^^^^^^^^^^^ From f6725c0a9833b48d3d8bc463385872b3a5227dad Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 22 Dec 2022 07:19:15 +0000 Subject: [PATCH 5/8] fix fn_sig ice --- .../src/transform/check_consts/check.rs | 2 +- .../src/transform/check_consts/mod.rs | 13 ++++++++++++- .../non-const-op-const-closure-non-const-outer.rs | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 38212496ec8..d4c75cd55ce 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -242,7 +242,7 @@ pub fn check_body(&mut self) { // impl trait is gone in MIR, so check the return type of a const fn by its signature // instead of the type of the return place. self.span = body.local_decls[RETURN_PLACE].source_info.span; - let return_ty = tcx.fn_sig(def_id).output(); + let return_ty = self.ccx.fn_sig().output(); self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 0a90572d39e..b528bc92330 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, PolyFnSig}; use rustc_span::Symbol; pub use self::qualifs::Qualif; @@ -64,6 +64,17 @@ pub fn is_const_stable_const_fn(&self) -> bool { fn is_async(&self) -> bool { self.tcx.asyncness(self.def_id()).is_async() } + + pub fn fn_sig(&self) -> PolyFnSig<'tcx> { + let did = self.def_id().to_def_id(); + if self.tcx.is_closure(did) { + let ty = self.tcx.type_of(did); + let ty::Closure(_, substs) = ty.kind() else { bug!("type_of closure not ty::Closure") }; + substs.as_closure().sig() + } else { + self.tcx.fn_sig(did) + } + } } pub fn rustc_allow_const_fn_unstable( diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs b/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs new file mode 100644 index 00000000000..cd8bb5963ad --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs @@ -0,0 +1,15 @@ +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + //~^ ERROR: cannot call non-const fn +} From b0aa859c2440864bdc6d25d7d40071d91745d342 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 22 Dec 2022 18:15:15 +0000 Subject: [PATCH 6/8] fix fmt and bless --- .../src/transform/check_consts/mod.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 +++- .../src/traits/select/candidate_assembly.rs | 8 ++------ .../non-const-op-const-closure-non-const-outer.stderr | 11 +++++++++++ tests/ui/check-static-values-constraints.stderr | 1 + tests/ui/const-generics/issue-93647.stderr | 1 + tests/ui/consts/const-fn-error.stderr | 2 ++ tests/ui/consts/const-for.stderr | 2 ++ .../consts/invalid-inline-const-in-match-arm.stderr | 1 + tests/ui/consts/issue-28113.stderr | 1 + tests/ui/consts/issue-56164.stderr | 1 + .../ui/consts/issue-68542-closure-in-array-len.stderr | 1 + tests/ui/consts/issue-90870.fixed | 3 +++ tests/ui/consts/issue-90870.rs | 3 +++ tests/ui/consts/issue-90870.stderr | 7 +++++-- tests/ui/never_type/issue-52443.stderr | 2 ++ tests/ui/resolve/issue-39559-2.stderr | 2 ++ .../const_derives/derive-const-non-const-type.stderr | 1 + .../cross-crate.stock.stderr | 1 + .../staged-api-user-crate.stderr | 1 + .../std-impl-gate.stock.stderr | 1 + 21 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index b528bc92330..54868e418c4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir; -use rustc_middle::ty::{self, TyCtxt, PolyFnSig}; +use rustc_middle::ty::{self, PolyFnSig, TyCtxt}; use rustc_span::Symbol; pub use self::qualifs::Qualif; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4b09a9b6939..48bae7a2d4e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -485,7 +485,9 @@ pub fn body_const_context(self, def_id: LocalDefId) -> Option { BodyOwnerKind::Static(mt) => ConstContext::Static(mt), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None, - BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id.to_def_id()) => { + BodyOwnerKind::Fn | BodyOwnerKind::Closure + if self.tcx.is_const_fn_raw(def_id.to_def_id()) => + { ConstContext::ConstFn } BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a5635ccfec4..9a094acfb71 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -261,16 +261,12 @@ fn assemble_closure_candidates( Some(closure_kind) => { debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { - candidates.vec.push(ClosureCandidate { - is_const, - }); + candidates.vec.push(ClosureCandidate { is_const }); } } None => { debug!("assemble_unboxed_candidates: closure_kind not yet known"); - candidates.vec.push(ClosureCandidate { - is_const, - }); + candidates.vec.push(ClosureCandidate { is_const }); } } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr new file mode 100644 index 00000000000..979d7febbca --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/check-static-values-constraints.stderr b/tests/ui/check-static-values-constraints.stderr index b13700a4ea5..49056678448 100644 --- a/tests/ui/check-static-values-constraints.stderr +++ b/tests/ui/check-static-values-constraints.stderr @@ -22,6 +22,7 @@ LL | field2: SafeEnum::Variant4("str".to_string()) | ^^^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error[E0010]: allocations are not allowed in statics diff --git a/tests/ui/const-generics/issue-93647.stderr b/tests/ui/const-generics/issue-93647.stderr index e2048ecd60f..18370eea571 100644 --- a/tests/ui/const-generics/issue-93647.stderr +++ b/tests/ui/const-generics/issue-93647.stderr @@ -6,6 +6,7 @@ LL | (||1usize)() | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index f6b532fb658..f735b3d53ce 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -22,6 +22,7 @@ LL | for i in 0..x { note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions --> $DIR/const-fn-error.rs:5:14 @@ -39,6 +40,7 @@ LL | for i in 0..x { | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to 4 previous errors diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 294ea627d85..3fb9787c0d8 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -7,6 +7,7 @@ LL | for _ in 0..5 {} note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/const-for.rs:5:14 @@ -15,6 +16,7 @@ LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index ab594c921f9..257ecd7f3cf 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -6,6 +6,7 @@ LL | const { (|| {})() } => {} | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/consts/issue-28113.stderr b/tests/ui/consts/issue-28113.stderr index 7ad1f752eb0..1294cc99bf7 100644 --- a/tests/ui/consts/issue-28113.stderr +++ b/tests/ui/consts/issue-28113.stderr @@ -6,6 +6,7 @@ LL | || -> u8 { 5 }() | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/consts/issue-56164.stderr b/tests/ui/consts/issue-56164.stderr index 2579b3e7827..845b23d5d87 100644 --- a/tests/ui/consts/issue-56164.stderr +++ b/tests/ui/consts/issue-56164.stderr @@ -6,6 +6,7 @@ LL | const fn foo() { (||{})() } | = note: closures need an RFC before allowed to be called in constant functions = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: function pointer calls are not allowed in constant functions --> $DIR/issue-56164.rs:5:5 diff --git a/tests/ui/consts/issue-68542-closure-in-array-len.stderr b/tests/ui/consts/issue-68542-closure-in-array-len.stderr index 74fbbc680f7..d23513ed7ff 100644 --- a/tests/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/tests/ui/consts/issue-68542-closure-in-array-len.stderr @@ -6,6 +6,7 @@ LL | a: [(); (|| { 0 })()] | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/consts/issue-90870.fixed b/tests/ui/consts/issue-90870.fixed index 0d28e06e532..df44689efed 100644 --- a/tests/ui/consts/issue-90870.fixed +++ b/tests/ui/consts/issue-90870.fixed @@ -8,12 +8,14 @@ const fn f(a: &u8, b: &u8) -> bool { *a == *b //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` } const fn g(a: &&&&i64, b: &&&&i64) -> bool { ****a == ****b //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` } const fn h(mut a: &[u8], mut b: &[u8]) -> bool { @@ -21,6 +23,7 @@ const fn h(mut a: &[u8], mut b: &[u8]) -> bool { if *l == *r { //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` a = at; b = bt; } else { diff --git a/tests/ui/consts/issue-90870.rs b/tests/ui/consts/issue-90870.rs index c6bfffd2c5c..676ac73c64d 100644 --- a/tests/ui/consts/issue-90870.rs +++ b/tests/ui/consts/issue-90870.rs @@ -8,12 +8,14 @@ const fn f(a: &u8, b: &u8) -> bool { a == b //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` } const fn g(a: &&&&i64, b: &&&&i64) -> bool { a == b //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` } const fn h(mut a: &[u8], mut b: &[u8]) -> bool { @@ -21,6 +23,7 @@ const fn h(mut a: &[u8], mut b: &[u8]) -> bool { if l == r { //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` a = at; b = bt; } else { diff --git a/tests/ui/consts/issue-90870.stderr b/tests/ui/consts/issue-90870.stderr index 478445cfb39..8825efd1449 100644 --- a/tests/ui/consts/issue-90870.stderr +++ b/tests/ui/consts/issue-90870.stderr @@ -5,30 +5,33 @@ LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable help: consider dereferencing here | LL | *a == *b | + + error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:14:5 + --> $DIR/issue-90870.rs:15:5 | LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable help: consider dereferencing here | LL | ****a == ****b | ++++ ++++ error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:21:12 + --> $DIR/issue-90870.rs:23:12 | LL | if l == r { | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable help: consider dereferencing here | LL | if *l == *r { diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index de5c9c56016..33b7a9185d0 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -47,6 +47,7 @@ LL | [(); { for _ in 0usize.. {}; 0}]; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constants --> $DIR/issue-52443.rs:9:21 @@ -64,6 +65,7 @@ LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to 6 previous errors; 1 warning emitted diff --git a/tests/ui/resolve/issue-39559-2.stderr b/tests/ui/resolve/issue-39559-2.stderr index ea27e7bd250..e9d8eb0835b 100644 --- a/tests/ui/resolve/issue-39559-2.stderr +++ b/tests/ui/resolve/issue-39559-2.stderr @@ -5,6 +5,7 @@ LL | let array: [usize; Dim3::dim()] | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error[E0015]: cannot call non-const fn `::dim` in constants --> $DIR/issue-39559-2.rs:16:15 @@ -13,6 +14,7 @@ LL | = [0; Dim3::dim()]; | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr index d463c774e28..96e0c78b9c7 100644 --- a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -7,6 +7,7 @@ LL | pub struct S(A); | ^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr index 086547542bb..22f13a7416e 100644 --- a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -5,6 +5,7 @@ LL | Const.func(); | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr index 61f9840e0d0..d7aa0d95cfc 100644 --- a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr @@ -5,6 +5,7 @@ LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr index 0b450a94742..6a3396401d2 100644 --- a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr @@ -5,6 +5,7 @@ LL | Default::default() | ^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable error: aborting due to previous error From ca1eb4309e7dc169873dfd5c33401f99937e8cc9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 26 Dec 2022 10:48:54 +0000 Subject: [PATCH 7/8] test use in libcore --- library/core/src/cmp.rs | 26 +++++++++++++--------- library/core/src/lib.rs | 1 + tests/ui-fulldeps/pprust-expr-roundtrip.rs | 1 + 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index ebf5baa3c02..a7d6fec7d3d 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1234,17 +1234,23 @@ pub const fn min_by_key K, K: ~const Ord>(v1: T, v2: T F: ~const Destruct, K: ~const Destruct, { - const fn imp K, K: ~const Ord>( - f: &mut F, - (v1, v2): (&T, &T), - ) -> Ordering - where - T: ~const Destruct, - K: ~const Destruct, - { - f(v1).cmp(&f(v2)) + cfg_if! { + if #[cfg(bootstrap)] { + const fn imp K, K: ~const Ord>( + f: &mut F, + (v1, v2): (&T, &T), + ) -> Ordering + where + T: ~const Destruct, + K: ~const Destruct, + { + f(v1).cmp(&f(v2)) + } + min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) + } else { + min_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2))) + } } - min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) } /// Compares and returns the maximum of two values. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 9e0d7cab63e..20b325546e2 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -191,6 +191,7 @@ #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] +#![cfg_attr(not(bootstrap), feature(const_closures))] #![feature(const_fn_floating_point_arithmetic)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 6dbabc8eb34..7a91dcf0dad 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -126,6 +126,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { g(ExprKind::Closure(Box::new(Closure { binder: ClosureBinder::NotPresent, capture_clause: CaptureBy::Value, + constness: Const::No, asyncness: Async::No, movability: Movability::Movable, fn_decl: decl.clone(), From 42a50bac319c0fc4fedf295fb1e606f015c48bb6 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 12 Jan 2023 04:20:00 +0000 Subject: [PATCH 8/8] move to correct test --- .../const_closures => tests/ui/rfc-2632-const-trait-impl}/call.rs | 0 .../const_closures => tests/ui/rfc-2632-const-trait-impl}/gate.rs | 0 .../ui/rfc-2632-const-trait-impl}/gate.stderr | 0 .../non-const-op-const-closure-non-const-outer.rs | 0 .../non-const-op-const-closure-non-const-outer.stderr | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {src/test/ui/rfc-2632-const-trait-impl/const_closures => tests/ui/rfc-2632-const-trait-impl}/call.rs (100%) rename {src/test/ui/rfc-2632-const-trait-impl/const_closures => tests/ui/rfc-2632-const-trait-impl}/gate.rs (100%) rename {src/test/ui/rfc-2632-const-trait-impl/const_closures => tests/ui/rfc-2632-const-trait-impl}/gate.stderr (100%) rename {src/test/ui/rfc-2632-const-trait-impl/const_closures => tests/ui/rfc-2632-const-trait-impl}/non-const-op-const-closure-non-const-outer.rs (100%) rename {src/test/ui/rfc-2632-const-trait-impl/const_closures => tests/ui/rfc-2632-const-trait-impl}/non-const-op-const-closure-non-const-outer.stderr (100%) diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs b/tests/ui/rfc-2632-const-trait-impl/call.rs similarity index 100% rename from src/test/ui/rfc-2632-const-trait-impl/const_closures/call.rs rename to tests/ui/rfc-2632-const-trait-impl/call.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs b/tests/ui/rfc-2632-const-trait-impl/gate.rs similarity index 100% rename from src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.rs rename to tests/ui/rfc-2632-const-trait-impl/gate.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr b/tests/ui/rfc-2632-const-trait-impl/gate.stderr similarity index 100% rename from src/test/ui/rfc-2632-const-trait-impl/const_closures/gate.stderr rename to tests/ui/rfc-2632-const-trait-impl/gate.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs similarity index 100% rename from src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.rs rename to tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr similarity index 100% rename from src/test/ui/rfc-2632-const-trait-impl/const_closures/non-const-op-const-closure-non-const-outer.stderr rename to tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr