From 03301f24ab3f7fefafff192b3c468f6af1213e7b Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 17 Oct 2023 10:40:24 +0200 Subject: [PATCH 01/12] std: implement thread parking for xous --- library/std/src/lib.rs | 1 + library/std/src/sys/xous/mod.rs | 1 - library/std/src/sys/xous/thread_parking.rs | 88 ++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 library/std/src/sys/xous/thread_parking.rs diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index aaf20875129c4..fbb2d846e0039 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -336,6 +336,7 @@ #![feature(portable_simd)] #![feature(prelude_2024)] #![feature(ptr_as_uninit)] +#![feature(ptr_from_ref)] #![feature(raw_os_nonzero)] #![feature(round_ties_even)] #![feature(slice_internals)] diff --git a/library/std/src/sys/xous/mod.rs b/library/std/src/sys/xous/mod.rs index 6d5c218d19570..c2550dcfd8315 100644 --- a/library/std/src/sys/xous/mod.rs +++ b/library/std/src/sys/xous/mod.rs @@ -28,7 +28,6 @@ pub mod process; pub mod stdio; pub mod thread; pub mod thread_local_key; -#[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/xous/thread_parking.rs b/library/std/src/sys/xous/thread_parking.rs new file mode 100644 index 0000000000000..3e77ecf0c7342 --- /dev/null +++ b/library/std/src/sys/xous/thread_parking.rs @@ -0,0 +1,88 @@ +use crate::os::xous::ffi::blocking_scalar; +use crate::os::xous::services::{ticktimer_server, TicktimerScalar}; +use crate::pin::Pin; +use crate::ptr; +use crate::sync::atomic::{ + AtomicI8, + Ordering::{Acquire, Release}, +}; +use crate::time::Duration; + +const NOTIFIED: i8 = 1; +const EMPTY: i8 = 0; +const PARKED: i8 = -1; + +pub struct Parker { + state: AtomicI8, +} + +impl Parker { + pub unsafe fn new_in_place(parker: *mut Parker) { + unsafe { parker.write(Parker { state: AtomicI8::new(EMPTY) }) } + } + + fn index(&self) -> usize { + ptr::from_ref(self).addr() + } + + pub unsafe fn park(self: Pin<&Self>) { + // Change NOTIFIED to EMPTY and EMPTY to PARKED. + let state = self.state.fetch_sub(1, Acquire); + if state == NOTIFIED { + return; + } + + // The state was set to PARKED. Wait until the `unpark` wakes us up. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), 0).into(), + ) + .expect("failed to send WaitForCondition command"); + + self.state.swap(EMPTY, Acquire); + } + + pub unsafe fn park_timeout(self: Pin<&Self>, timeout: Duration) { + // Change NOTIFIED to EMPTY and EMPTY to PARKED. + let state = self.state.fetch_sub(1, Acquire); + if state == NOTIFIED { + return; + } + + // A value of zero indicates an indefinite wait. Clamp the number of + // milliseconds to the allowed range. + let millis = usize::max(timeout.as_millis().try_into().unwrap_or(usize::MAX), 1); + + let was_timeout = blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), millis).into(), + ) + .expect("failed to send WaitForCondition command")[0] + != 0; + + let state = self.state.swap(EMPTY, Acquire); + if was_timeout && state == NOTIFIED { + // The state was set to NOTIFIED after we returned from the wait + // but before we reset the state. Therefore, a wakeup is on its + // way, which we need to consume here. + // NOTICE: this is a priority hole. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), 0).into(), + ) + .expect("failed to send WaitForCondition command"); + } + } + + pub fn unpark(self: Pin<&Self>) { + let state = self.state.swap(NOTIFIED, Release); + if state == PARKED { + // The thread is parked, wake it up. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::NotifyCondition(self.index(), 1).into(), + ) + .expect("failed to send NotifyCondition command"); + } + } +} From 2dc6ba27b5bbb4b5aca064d007b8305636422c5d Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 18 Oct 2023 16:21:21 +0200 Subject: [PATCH 02/12] std: send free message when xous thread parker is dropped --- library/std/src/sys/xous/thread_parking.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/xous/thread_parking.rs b/library/std/src/sys/xous/thread_parking.rs index 3e77ecf0c7342..aa39c6d27185f 100644 --- a/library/std/src/sys/xous/thread_parking.rs +++ b/library/std/src/sys/xous/thread_parking.rs @@ -1,4 +1,4 @@ -use crate::os::xous::ffi::blocking_scalar; +use crate::os::xous::ffi::{blocking_scalar, scalar}; use crate::os::xous::services::{ticktimer_server, TicktimerScalar}; use crate::pin::Pin; use crate::ptr; @@ -86,3 +86,9 @@ impl Parker { } } } + +impl Drop for Parker { + fn drop(&mut self) { + scalar(ticktimer_server(), TicktimerScalar::FreeCondition(self.index()).into()).ok(); + } +} From 73042206ddfd2686eae6c9e186ef77ba2c08ddb5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 24 Nov 2023 21:23:45 +0100 Subject: [PATCH 03/12] remove the memcpy-on-equal-ptrs assumption --- library/core/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d44cf299c2780..cc094f643275d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -24,9 +24,8 @@ //! which are generated by Rust codegen backends. Additionally, this library can make explicit //! calls to `strlen`. Their signatures are the same as found in C, but there are extra //! assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if -//! the `n` parameter is 0, the function is assumed to not be UB. Furthermore, for `memcpy`, if -//! source and target pointer are equal, the function is assumed to not be UB. -//! (Note that these are standard assumptions among compilers: +//! the `n` parameter is 0, the function is assumed to not be UB, even if the pointers are NULL or +//! dangling. (Note that making extra assumptions about these functions is common among compilers: //! [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/onlinedocs/gcc/Standards.html#C-Language) do the same.) //! These functions are often provided by the system libc, but can also be provided by the //! [compiler-builtins crate](https://crates.io/crates/compiler_builtins). From e511cc7d49bd04cbe09450454bc573ac00c21a9b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 Nov 2023 22:53:13 +0000 Subject: [PATCH 04/12] Unify TraitRefs and PolyTraitRefs --- compiler/rustc_infer/src/infer/at.rs | 6 +++++- .../rustc_infer/src/infer/error_reporting/mod.rs | 16 +--------------- .../nice_region_error/placeholder_error.rs | 5 ----- compiler/rustc_infer/src/infer/mod.rs | 1 - 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index c32c3aa6d2968..09313cd9738c2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -448,7 +448,11 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)), + values: PolyTraitRefs(ExpectedFound::new( + a_is_expected, + ty::Binder::dummy(a), + ty::Binder::dummy(b), + )), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a2aa99e78e1e9..d66990c348288 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1667,9 +1667,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .report(diag); (false, Mismatch::Fixed("signature")) } - ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { - (false, Mismatch::Fixed("trait")) - } + ValuePairs::PolyTraitRefs(_) => (false, Mismatch::Fixed("trait")), ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => { (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id))) } @@ -2219,18 +2217,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Aliases(exp_found) => self.expected_found_str(exp_found), infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), - infer::TraitRefs(exp_found) => { - let pretty_exp_found = ty::error::ExpectedFound { - expected: exp_found.expected.print_only_trait_path(), - found: exp_found.found.print_only_trait_path(), - }; - match self.expected_found_str(pretty_exp_found) { - Some((expected, found, _, _)) if expected == found => { - self.expected_found_str(exp_found) - } - ret => ret, - } - } infer::PolyTraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index c38e5b8cd09e5..d98ca995d71d4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -197,11 +197,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { value_pairs: &ValuePairs<'tcx>, ) -> Option> { let (expected_args, found_args, trait_def_id) = match value_pairs { - ValuePairs::TraitRefs(ExpectedFound { expected, found }) - if expected.def_id == found.def_id => - { - (expected.args, found.args, expected.def_id) - } ValuePairs::PolyTraitRefs(ExpectedFound { expected, found }) if expected.def_id() == found.def_id() => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d6c7a24476f9e..739eb69929a6c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -384,7 +384,6 @@ pub enum ValuePairs<'tcx> { Regions(ExpectedFound>), Terms(ExpectedFound>), Aliases(ExpectedFound>), - TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), From 0efd2a9d8ff5d2ef1b23545a9f67216b7e183a3d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 09:11:03 +1100 Subject: [PATCH 05/12] Rework `ast::BinOpKind::to_string` and `ast::UnOp::to_string`. - Rename them both `as_str`, which is the typical name for a function that returns a `&str`. (`to_string` is appropriate for functions returning `String` or maybe `Cow<'a, str>`.) - Change `UnOp::as_str` from an associated function (weird!) to a method. - Avoid needless `self` dereferences. --- compiler/rustc_ast/src/ast.rs | 8 ++++---- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 6 +++--- compiler/rustc_parse/src/parser/stmt.rs | 2 +- src/tools/clippy/clippy_lints/src/formatting.rs | 8 ++++---- src/tools/clippy/clippy_lints/src/precedence.rs | 6 +++--- .../clippy_lints/src/suspicious_operation_groupings.rs | 4 ++-- src/tools/clippy/clippy_utils/src/sugg.rs | 2 +- src/tools/rustfmt/src/expr.rs | 2 +- src/tools/rustfmt/src/pairs.rs | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 10776f31c07bf..4fe7a72925f64 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -858,9 +858,9 @@ pub enum BinOpKind { } impl BinOpKind { - pub fn to_string(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { use BinOpKind::*; - match *self { + match self { Add => "+", Sub => "-", Mul => "*", @@ -912,8 +912,8 @@ pub enum UnOp { } impl UnOp { - pub fn to_string(op: UnOp) -> &'static str { - match op { + pub fn as_str(&self) -> &'static str { + match self { UnOp::Deref => "*", UnOp::Not => "!", UnOp::Neg => "-", diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index ed9b68a1d5a9d..45a55e20ca737 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -255,12 +255,12 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(lhs, left_prec); self.space(); - self.word_space(op.node.to_string()); + self.word_space(op.node.as_str()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.word(ast::UnOp::to_string(op)); + self.word(op.as_str()); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -470,7 +470,7 @@ impl<'a> State<'a> { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); self.space(); - self.word(op.node.to_string()); + self.word(op.node.as_str()); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5316dde609605..cf165a50b53aa 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -387,7 +387,7 @@ impl<'a> Parser<'a> { if op.node.lazy() { self.sess.emit_err(errors::InvalidExpressionInLetElse { span: init.span, - operator: op.node.to_string(), + operator: op.node.as_str(), sugg: errors::WrapExpressionInParentheses { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 70892ce608f6e..2ab04682f1d52 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; use clippy_utils::is_span_if; use clippy_utils::source::snippet_opt; -use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; +use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -144,7 +144,7 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { let eq_span = lhs.span.between(rhs.span); if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind { if let Some(eq_snippet) = snippet_opt(cx, eq_span) { - let op = UnOp::to_string(op); + let op = op.as_str(); let eqop_span = lhs.span.between(sub_rhs.span); if eq_snippet.ends_with('=') { span_lint_and_note( @@ -177,11 +177,11 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) { && let unop_operand_span = rhs.span.until(un_rhs.span) && let Some(binop_snippet) = snippet_opt(cx, binop_span) && let Some(unop_operand_snippet) = snippet_opt(cx, unop_operand_span) - && let binop_str = BinOpKind::to_string(&binop.node) + && let binop_str = binop.node.as_str() // no space after BinOp operator and space after UnOp operator && binop_snippet.ends_with(binop_str) && unop_operand_snippet.ends_with(' ') { - let unop_str = UnOp::to_string(op); + let unop_str = op.as_str(); let eqop_span = lhs.span.between(un_rhs.span); span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs index b638e83997a58..52cec43737869 100644 --- a/src/tools/clippy/clippy_lints/src/precedence.rs +++ b/src/tools/clippy/clippy_lints/src/precedence.rs @@ -78,7 +78,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "({}) {} ({})", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); @@ -87,7 +87,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "({}) {} {}", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); @@ -96,7 +96,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "{} {} ({})", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 92de7917871f0..b332309a55274 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -298,7 +298,7 @@ fn replace_left_sugg( ) -> String { format!( "{left_suggestion} {} {}", - binop.op.to_string(), + binop.op.as_str(), snippet_with_applicability(cx, binop.right.span, "..", applicability), ) } @@ -312,7 +312,7 @@ fn replace_right_sugg( format!( "{} {} {right_suggestion}", snippet_with_applicability(cx, binop.left.span, "..", applicability), - binop.op.to_string(), + binop.op.as_str(), ) } diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index db79dd788018e..f143163152e0d 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -382,7 +382,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { | AssocOp::GreaterEqual => { format!( "{lhs} {} {rhs}", - op.to_ast_binop().expect("Those are AST ops").to_string() + op.to_ast_binop().expect("Those are AST ops").as_str() ) }, AssocOp::Assign => format!("{lhs} = {rhs}"), diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index fa941e6146ad4..60e0e007b1d11 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -1933,7 +1933,7 @@ fn rewrite_unary_op( shape: Shape, ) -> Option { // For some reason, an UnOp is not spanned like BinOp! - rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape) + rewrite_unary_prefix(context, op.as_str(), expr, shape) } pub(crate) enum RhsAssignKind<'ast> { diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs index 07c0519373910..bfc2ffed3834e 100644 --- a/src/tools/rustfmt/src/pairs.rs +++ b/src/tools/rustfmt/src/pairs.rs @@ -339,7 +339,7 @@ impl FlattenPair for ast::Expr { if let Some(pop) = stack.pop() { match pop.kind { ast::ExprKind::Binary(op, _, ref rhs) => { - separators.push(op.node.to_string()); + separators.push(op.node.as_str()); node = rhs; } _ => unreachable!(), From 705b484922697b3dfc73ea7cb58dc12cca963ecf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 09:42:25 +1100 Subject: [PATCH 06/12] Rename `BinOpKind::lazy` as `BinOpKind::is_lazy`. To match `BinOpKind::is_comparison` and `hir::BinOpKind::is_lazy`. --- compiler/rustc_ast/src/ast.rs | 3 ++- compiler/rustc_lint/src/unused.rs | 4 ++-- compiler/rustc_parse/src/parser/stmt.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4fe7a72925f64..1e7aac088600c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -881,7 +881,8 @@ impl BinOpKind { Gt => ">", } } - pub fn lazy(&self) -> bool { + + pub fn is_lazy(&self) -> bool { matches!(self, BinOpKind::And | BinOpKind::Or) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b4535c72d6c6f..a7a4709e887a0 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -656,7 +656,7 @@ trait UnusedDelimLint { ) -> bool { if followed_by_else { match inner.kind { - ast::ExprKind::Binary(op, ..) if op.node.lazy() => return true, + ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true, _ if classify::expr_trailing_brace(inner).is_some() => return true, _ => {} } @@ -1016,7 +1016,7 @@ impl UnusedDelimLint for UnusedParens { rustc_span::source_map::Spanned { node, .. }, _, _, - ) if node.lazy())) + ) if node.is_lazy())) { self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index cf165a50b53aa..361f231d4936c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -384,7 +384,7 @@ impl<'a> Parser<'a> { fn check_let_else_init_bool_expr(&self, init: &ast::Expr) { if let ast::ExprKind::Binary(op, ..) = init.kind { - if op.node.lazy() { + if op.node.is_lazy() { self.sess.emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.as_str(), From c751bfa015ab9e99f3c7845cebf04eb543648042 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 26 Nov 2023 14:24:38 +0800 Subject: [PATCH 07/12] Add proper cfgs --- library/alloc/src/alloc.rs | 3 +++ library/alloc/src/collections/mod.rs | 1 + library/alloc/src/rc.rs | 1 + library/alloc/src/sync.rs | 1 + library/alloc/src/vec/mod.rs | 5 +++++ 5 files changed, 11 insertions(+) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 2499f1053d860..1663aa84921c9 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -423,12 +423,14 @@ pub mod __alloc_error_handler { } } +#[cfg(not(no_global_oom_handling))] /// Specialize clones into pre-allocated, uninitialized memory. /// Used by `Box::clone` and `Rc`/`Arc::make_mut`. pub(crate) trait WriteCloneIntoRaw: Sized { unsafe fn write_clone_into_raw(&self, target: *mut Self); } +#[cfg(not(no_global_oom_handling))] impl WriteCloneIntoRaw for T { #[inline] default unsafe fn write_clone_into_raw(&self, target: *mut Self) { @@ -438,6 +440,7 @@ impl WriteCloneIntoRaw for T { } } +#[cfg(not(no_global_oom_handling))] impl WriteCloneIntoRaw for T { #[inline] unsafe fn write_clone_into_raw(&self, target: *mut Self) { diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 3e0b0f735508e..705b81535c279 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -148,6 +148,7 @@ impl Display for TryReserveError { /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] +#[cfg(not(no_global_oom_handling))] trait SpecExtend { /// Extends `self` with the contents of the given iterator. fn spec_extend(&mut self, iter: I); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index dd7876bed7691..98983e670d0f6 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2023,6 +2023,7 @@ impl Rc<[T], A> { } } +#[cfg(not(no_global_oom_handling))] /// Specialization trait used for `From<&[T]>`. trait RcFromSlice { fn from_slice(slice: &[T]) -> Self; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 351e6c1a4b3d2..da0abdc974666 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3503,6 +3503,7 @@ impl FromIterator for Arc<[T]> { } } +#[cfg(not(no_global_oom_handling))] /// Specialization trait used for collecting into `Arc<[T]>`. trait ToArcSlice: Iterator + Sized { fn to_arc_slice(self) -> Arc<[T]>; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ea7d6f6f4a649..bcf4163e39c49 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,6 +58,7 @@ use core::cmp; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; +#[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; @@ -101,6 +102,7 @@ mod into_iter; #[cfg(not(no_global_oom_handling))] use self::is_zero::IsZero; +#[cfg(not(no_global_oom_handling))] mod is_zero; #[cfg(not(no_global_oom_handling))] @@ -2599,6 +2601,7 @@ pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec< ::from_elem(elem, n, alloc) } +#[cfg(not(no_global_oom_handling))] trait ExtendFromWithinSpec { /// # Safety /// @@ -2607,6 +2610,7 @@ trait ExtendFromWithinSpec { unsafe fn spec_extend_from_within(&mut self, src: Range); } +#[cfg(not(no_global_oom_handling))] impl ExtendFromWithinSpec for Vec { default unsafe fn spec_extend_from_within(&mut self, src: Range) { // SAFETY: @@ -2626,6 +2630,7 @@ impl ExtendFromWithinSpec for Vec { } } +#[cfg(not(no_global_oom_handling))] impl ExtendFromWithinSpec for Vec { unsafe fn spec_extend_from_within(&mut self, src: Range) { let count = src.len(); From d9fef774e3ba9e00f0ea143f632f66b1d87afff6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 09:36:09 +1100 Subject: [PATCH 08/12] Remove `hir::BinOp`, `hir::BinOpKind`, and `hir::UnOp`. They're identical to the same-named types from `ast`. I find it silly (and inefficient) to have all this boilerplate code to convert one type to an identical type. There is already a small amount of type sharing between the AST and HIR, e.g. `Attribute`, `MacroDef`. The commit adds a `pub use` to `rustc_hir` so that, for example, `ast::BinOp` can also be referred to as `hir::BinOp`. This is so the many existing `hir`-qualified mentions of these types don't need to change. The commit also moves a couple of operations from the (removed) HIR types to the AST types, e.g. `is_by_value`. --- compiler/rustc_ast/src/ast.rs | 16 ++- compiler/rustc_ast_lowering/src/expr.rs | 26 +--- compiler/rustc_hir/src/hir.rs | 153 +----------------------- 3 files changed, 17 insertions(+), 178 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1e7aac088600c..2b56e9f3a86cc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -817,7 +817,7 @@ pub enum BorrowKind { Raw, } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum BinOpKind { /// The `+` operator (addition) Add, @@ -888,13 +888,18 @@ impl BinOpKind { pub fn is_comparison(&self) -> bool { use BinOpKind::*; - // Note for developers: please keep this as is; + // Note for developers: please keep this match exhaustive; // we want compilation to fail if another variant is added. match *self { Eq | Lt | Le | Ne | Gt | Ge => true, And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false, } } + + /// Returns `true` if the binary operator takes its arguments by value. + pub fn is_by_value(self) -> bool { + !self.is_comparison() + } } pub type BinOp = Spanned; @@ -902,7 +907,7 @@ pub type BinOp = Spanned; /// Unary operator. /// /// Note that `&data` is not an operator, it's an `AddrOf` expression. -#[derive(Clone, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum UnOp { /// The `*` operator for dereferencing Deref, @@ -920,6 +925,11 @@ impl UnOp { UnOp::Neg => "-", } } + + /// Returns `true` if the unary operator takes its argument by value. + pub fn is_by_value(self) -> bool { + matches!(self, Self::Neg | Self::Not) + } } /// A statement diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6f2f9787e7727..1f2b1ab3a243b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -350,30 +350,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { - Spanned { - node: match b.node { - BinOpKind::Add => hir::BinOpKind::Add, - BinOpKind::Sub => hir::BinOpKind::Sub, - BinOpKind::Mul => hir::BinOpKind::Mul, - BinOpKind::Div => hir::BinOpKind::Div, - BinOpKind::Rem => hir::BinOpKind::Rem, - BinOpKind::And => hir::BinOpKind::And, - BinOpKind::Or => hir::BinOpKind::Or, - BinOpKind::BitXor => hir::BinOpKind::BitXor, - BinOpKind::BitAnd => hir::BinOpKind::BitAnd, - BinOpKind::BitOr => hir::BinOpKind::BitOr, - BinOpKind::Shl => hir::BinOpKind::Shl, - BinOpKind::Shr => hir::BinOpKind::Shr, - BinOpKind::Eq => hir::BinOpKind::Eq, - BinOpKind::Lt => hir::BinOpKind::Lt, - BinOpKind::Le => hir::BinOpKind::Le, - BinOpKind::Ne => hir::BinOpKind::Ne, - BinOpKind::Ge => hir::BinOpKind::Ge, - BinOpKind::Gt => hir::BinOpKind::Gt, - }, - span: self.lower_span(b.span), - } + fn lower_binop(&mut self, b: BinOp) -> BinOp { + Spanned { node: b.node, span: self.lower_span(b.span) } } fn lower_legacy_const_generics( diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d2b83d0eb00fa..bd6eba3754782 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -7,8 +7,8 @@ use crate::LangItem; use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; -pub use rustc_ast::{BindingAnnotation, BorrowKind, ByRef, ImplPolarity, IsAuto}; -pub use rustc_ast::{CaptureBy, Movability, Mutability}; +pub use rustc_ast::{BinOp, BinOpKind, BindingAnnotation, BorrowKind, ByRef, CaptureBy}; +pub use rustc_ast::{ImplPolarity, IsAuto, Movability, Mutability, UnOp}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -1174,155 +1174,6 @@ pub enum PatKind<'hir> { Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), } -#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] -pub enum BinOpKind { - /// The `+` operator (addition). - Add, - /// The `-` operator (subtraction). - Sub, - /// The `*` operator (multiplication). - Mul, - /// The `/` operator (division). - Div, - /// The `%` operator (modulus). - Rem, - /// The `&&` operator (logical and). - And, - /// The `||` operator (logical or). - Or, - /// The `^` operator (bitwise xor). - BitXor, - /// The `&` operator (bitwise and). - BitAnd, - /// The `|` operator (bitwise or). - BitOr, - /// The `<<` operator (shift left). - Shl, - /// The `>>` operator (shift right). - Shr, - /// The `==` operator (equality). - Eq, - /// The `<` operator (less than). - Lt, - /// The `<=` operator (less than or equal to). - Le, - /// The `!=` operator (not equal to). - Ne, - /// The `>=` operator (greater than or equal to). - Ge, - /// The `>` operator (greater than). - Gt, -} - -impl BinOpKind { - pub fn as_str(self) -> &'static str { - match self { - BinOpKind::Add => "+", - BinOpKind::Sub => "-", - BinOpKind::Mul => "*", - BinOpKind::Div => "/", - BinOpKind::Rem => "%", - BinOpKind::And => "&&", - BinOpKind::Or => "||", - BinOpKind::BitXor => "^", - BinOpKind::BitAnd => "&", - BinOpKind::BitOr => "|", - BinOpKind::Shl => "<<", - BinOpKind::Shr => ">>", - BinOpKind::Eq => "==", - BinOpKind::Lt => "<", - BinOpKind::Le => "<=", - BinOpKind::Ne => "!=", - BinOpKind::Ge => ">=", - BinOpKind::Gt => ">", - } - } - - pub fn is_lazy(self) -> bool { - matches!(self, BinOpKind::And | BinOpKind::Or) - } - - pub fn is_comparison(self) -> bool { - match self { - BinOpKind::Eq - | BinOpKind::Lt - | BinOpKind::Le - | BinOpKind::Ne - | BinOpKind::Gt - | BinOpKind::Ge => true, - BinOpKind::And - | BinOpKind::Or - | BinOpKind::Add - | BinOpKind::Sub - | BinOpKind::Mul - | BinOpKind::Div - | BinOpKind::Rem - | BinOpKind::BitXor - | BinOpKind::BitAnd - | BinOpKind::BitOr - | BinOpKind::Shl - | BinOpKind::Shr => false, - } - } - - /// Returns `true` if the binary operator takes its arguments by value. - pub fn is_by_value(self) -> bool { - !self.is_comparison() - } -} - -impl Into for BinOpKind { - fn into(self) -> ast::BinOpKind { - match self { - BinOpKind::Add => ast::BinOpKind::Add, - BinOpKind::Sub => ast::BinOpKind::Sub, - BinOpKind::Mul => ast::BinOpKind::Mul, - BinOpKind::Div => ast::BinOpKind::Div, - BinOpKind::Rem => ast::BinOpKind::Rem, - BinOpKind::And => ast::BinOpKind::And, - BinOpKind::Or => ast::BinOpKind::Or, - BinOpKind::BitXor => ast::BinOpKind::BitXor, - BinOpKind::BitAnd => ast::BinOpKind::BitAnd, - BinOpKind::BitOr => ast::BinOpKind::BitOr, - BinOpKind::Shl => ast::BinOpKind::Shl, - BinOpKind::Shr => ast::BinOpKind::Shr, - BinOpKind::Eq => ast::BinOpKind::Eq, - BinOpKind::Lt => ast::BinOpKind::Lt, - BinOpKind::Le => ast::BinOpKind::Le, - BinOpKind::Ne => ast::BinOpKind::Ne, - BinOpKind::Ge => ast::BinOpKind::Ge, - BinOpKind::Gt => ast::BinOpKind::Gt, - } - } -} - -pub type BinOp = Spanned; - -#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] -pub enum UnOp { - /// The `*` operator (dereferencing). - Deref, - /// The `!` operator (logical negation). - Not, - /// The `-` operator (negation). - Neg, -} - -impl UnOp { - pub fn as_str(self) -> &'static str { - match self { - Self::Deref => "*", - Self::Not => "!", - Self::Neg => "-", - } - } - - /// Returns `true` if the unary operator takes its argument by value. - pub fn is_by_value(self) -> bool { - matches!(self, Self::Neg | Self::Not) - } -} - /// A statement. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Stmt<'hir> { From a76d2e1fd13b69b81b05560d727c000df5c44581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 18:35:59 +0000 Subject: [PATCH 09/12] Eagerly return ExprKind::Err on yield/await in wrong coroutine context --- compiler/rustc_ast_lowering/src/expr.rs | 6 +++--- tests/ui/async-await/issue-70594.rs | 3 --- tests/ui/async-await/issues/issue-62009-1.rs | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 180459efef920..b62e647164415 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -778,10 +778,10 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Async(_)) => {} Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { - self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { + return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, - }); + })); } } let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); @@ -1500,7 +1500,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Gen(_)) => {} Some(hir::CoroutineKind::Async(_)) => { - self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }); + return hir::ExprKind::Err(self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span })); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { diff --git a/tests/ui/async-await/issue-70594.rs b/tests/ui/async-await/issue-70594.rs index 9e7c5847b3b2e..4c8209348b37a 100644 --- a/tests/ui/async-await/issue-70594.rs +++ b/tests/ui/async-await/issue-70594.rs @@ -3,9 +3,6 @@ async fn fun() { [1; ().await]; //~^ error: `await` is only allowed inside `async` functions and blocks - //~| error: `.await` is not allowed in a `const` - //~| error: `.await` is not allowed in a `const` - //~| error: `()` is not a future } fn main() {} diff --git a/tests/ui/async-await/issues/issue-62009-1.rs b/tests/ui/async-await/issues/issue-62009-1.rs index 40ccf25712e2b..51d216408d7ee 100644 --- a/tests/ui/async-await/issues/issue-62009-1.rs +++ b/tests/ui/async-await/issues/issue-62009-1.rs @@ -11,5 +11,4 @@ fn main() { //~^ ERROR `await` is only allowed inside `async` functions and blocks (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks - //~| ERROR is not a future } From f2c500bb434427f693cb9f6b02d675673808b6f9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 19:06:23 +0000 Subject: [PATCH 10/12] Fix spans for bad await in inline const --- compiler/rustc_ast_lowering/src/expr.rs | 19 +++++----- compiler/rustc_ast_lowering/src/item.rs | 5 +-- compiler/rustc_ast_lowering/src/lib.rs | 11 ++++-- tests/ui/async-await/issue-70594.stderr | 37 +++---------------- .../async-await/issues/issue-62009-1.stderr | 18 +-------- 5 files changed, 26 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b62e647164415..43b345292c8b3 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -72,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(|this| hir::ConstBlock { + let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { @@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( @@ -941,9 +941,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let (body_id, coroutine_option) = self.with_new_scopes(move |this| { - let prev = this.current_item; - this.current_item = Some(fn_decl_span); + let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); @@ -952,7 +950,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let coroutine_option = this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); - this.current_item = prev; (body_id, coroutine_option) }); @@ -1038,7 +1035,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(|this| { + let body = self.with_new_scopes(fn_decl_span, |this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); @@ -1060,7 +1057,7 @@ impl<'hir> LoweringContext<'_, 'hir> { async_ret_ty, body.span, hir::CoroutineSource::Closure, - |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), ); let hir_id = this.lower_node_id(inner_closure_id); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); @@ -1500,7 +1497,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Gen(_)) => {} Some(hir::CoroutineKind::Async(_)) => { - return hir::ExprKind::Err(self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span })); + return hir::ExprKind::Err( + self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }), + ); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fb75471ede3bc..5c42012c1dfad 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -268,9 +268,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body, .. }) => { - self.with_new_scopes(|this| { - this.current_item = Some(ident.span); - + self.with_new_scopes(ident.span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body // only cares about the input argument patterns in the function @@ -867,7 +865,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ), AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { - self.current_item = Some(i.span); let asyncness = sig.header.asyncness; let body_id = self.lower_maybe_async_body( i.span, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4c7b9b4155fdf..11e980370b863 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -839,7 +839,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { result } - fn with_new_scopes(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + fn with_new_scopes(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T { + let current_item = self.current_item; + self.current_item = Some(scope_span); + let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -851,6 +854,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.is_in_loop_condition = was_in_loop_condition; + self.current_item = current_item; + ret } @@ -1200,7 +1205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(|this| hir::AnonConst { + let ct = self.with_new_scopes(span, |this| hir::AnonConst { def_id, hir_id: this.lower_node_id(node_id), body: this.lower_const_body(path_expr.span, Some(&path_expr)), @@ -2207,7 +2212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(|this| hir::AnonConst { + self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), diff --git a/tests/ui/async-await/issue-70594.stderr b/tests/ui/async-await/issue-70594.stderr index 9866e00bb83a9..aed99ec3f1f08 100644 --- a/tests/ui/async-await/issue-70594.stderr +++ b/tests/ui/async-await/issue-70594.stderr @@ -1,37 +1,12 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-70594.rs:4:12 | -LL | async fn fun() { - | --- this is not `async` LL | [1; ().await]; - | ^^^^^ only allowed inside `async` functions and blocks + | ---^^^^^ + | | | + | | only allowed inside `async` functions and blocks + | this is not `async` -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:9 - | -LL | [1; ().await]; - | ^^^^^^^^ - -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | ^^^^^ - -error[E0277]: `()` is not a future - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - = note: required for `()` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0728, E0744. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr index bb617d09076f0..02933f4f2f233 100644 --- a/tests/ui/async-await/issues/issue-62009-1.stderr +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -24,20 +24,6 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^ only allowed inside `async` functions and blocks -error[E0277]: `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - --> $DIR/issue-62009-1.rs:12:16 - | -LL | (|_| 2333).await; - | -^^^^^ - | || - | |`{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for closure `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` - = note: {closure@$DIR/issue-62009-1.rs:12:6: 12:9} must be a future or must implement `IntoFuture` to be awaited - = note: required for `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0728. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. From 5161b22143bf9a726cfd69d19bef11552d0ed519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 28 Nov 2023 00:00:00 +0000 Subject: [PATCH 11/12] Fix coroutine validation for mixed panic strategy Validation introduced in #113124 allows UnwindAction::Continue and TerminatorKind::Resume to occur only in functions with ABI that can unwind. The function ABI depends on the panic strategy, which can vary across crates. Usually MIR is built and validated in the same crate. The coroutine drop glue thus far was an exception. As a result validation could fail when mixing different panic strategies. Avoid the problem by executing AbortUnwindingCalls along with the validation. --- compiler/rustc_mir_transform/src/coroutine.rs | 10 ---------- compiler/rustc_mir_transform/src/shim.rs | 6 ++++-- tests/ui/coroutine/auxiliary/unwind-aux.rs | 11 +++++++++++ tests/ui/coroutine/unwind-abort-mix.rs | 13 +++++++++++++ 4 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 tests/ui/coroutine/auxiliary/unwind-aux.rs create mode 100644 tests/ui/coroutine/unwind-abort-mix.rs diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 1cb1a9886a09d..d626fed32757d 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -51,7 +51,6 @@ //! Otherwise it drops all the values in scope at the last suspension point. use crate::abort_unwinding_calls; -use crate::add_call_guards; use crate::deref_separator::deref_finder; use crate::errors; use crate::pass_manager as pm; @@ -1168,18 +1167,9 @@ fn create_coroutine_drop_shim<'tcx>( simplify::remove_dead_blocks(&mut body); // Update the body's def to become the drop glue. - // This needs to be updated before the AbortUnwindingCalls pass. let coroutine_instance = body.source.instance; let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None); let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty)); - body.source.instance = drop_instance; - - pm::run_passes_no_validate( - tcx, - &mut body, - &[&abort_unwinding_calls::AbortUnwindingCalls, &add_call_guards::CriticalCallEdges], - None, - ); // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible // filename. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f24a2d07e4949..fba73d5195b76 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -74,11 +74,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); - // Run empty passes to mark phase change and perform validation. pm::run_passes( tcx, &mut body, - &[], + &[ + &abort_unwinding_calls::AbortUnwindingCalls, + &add_call_guards::CriticalCallEdges, + ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); diff --git a/tests/ui/coroutine/auxiliary/unwind-aux.rs b/tests/ui/coroutine/auxiliary/unwind-aux.rs new file mode 100644 index 0000000000000..215d676911633 --- /dev/null +++ b/tests/ui/coroutine/auxiliary/unwind-aux.rs @@ -0,0 +1,11 @@ +// compile-flags: -Cpanic=unwind --crate-type=lib +// no-prefer-dynamic +// edition:2021 + +#![feature(coroutines)] +pub fn run(a: T) { + let _ = move || { + drop(a); + yield; + }; +} diff --git a/tests/ui/coroutine/unwind-abort-mix.rs b/tests/ui/coroutine/unwind-abort-mix.rs new file mode 100644 index 0000000000000..869b3e4f43347 --- /dev/null +++ b/tests/ui/coroutine/unwind-abort-mix.rs @@ -0,0 +1,13 @@ +// Ensure that coroutine drop glue is valid when mixing different panic +// strategies. Regression test for #116953. +// +// no-prefer-dynamic +// build-pass +// aux-build:unwind-aux.rs +// compile-flags: -Cpanic=abort +// needs-unwind +extern crate unwind_aux; + +pub fn main() { + unwind_aux::run(String::new()); +} From dd5abb50cc08a212d23be1fb8482ae166e9bc738 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 20:40:38 +0000 Subject: [PATCH 12/12] Yeet E0744 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + compiler/rustc_error_codes/src/error_codes/E0744.md | 4 +++- compiler/rustc_passes/src/check_const.rs | 9 ++++----- compiler/rustc_passes/src/errors.rs | 9 --------- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 6680e8875c3e3..1028d43f9c5ba 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -653,3 +653,4 @@ E0795: include_str!("./error_codes/E0795.md"), // E0721, // `await` keyword // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. +// E0744, // merged into E0728 diff --git a/compiler/rustc_error_codes/src/error_codes/E0744.md b/compiler/rustc_error_codes/src/error_codes/E0744.md index 9a8ef3b840dff..e56c45db1766e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0744.md +++ b/compiler/rustc_error_codes/src/error_codes/E0744.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An unsupported expression was used inside a const context. Erroneous code example: -```compile_fail,edition2018,E0744 +```ignore (removed error code) const _: i32 = { async { 0 }.await }; diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index de96746e215c1..76c7467346d37 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; -use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks}; +use crate::errors::SkippingConstChecks; /// An expression that is not *always* legal in a const context. #[derive(Clone, Copy)] @@ -138,11 +138,10 @@ impl<'tcx> CheckConstVisitor<'tcx> { match missing_gates.as_slice() { [] => { - tcx.sess.emit_err(ExprNotAllowedInContext { + span_bug!( span, - expr: expr.name(), - context: const_kind.keyword_name(), - }); + "we should not have reached this point, since `.await` is denied earlier" + ); } [missing_primary, ref missing_secondary @ ..] => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 411c9410195f1..5812744532280 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1005,15 +1005,6 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> { pub prev_declared: &'b str, } -#[derive(Diagnostic)] -#[diag(passes_expr_not_allowed_in_context, code = "E0744")] -pub struct ExprNotAllowedInContext<'a> { - #[primary_span] - pub span: Span, - pub expr: String, - pub context: &'a str, -} - pub struct BreakNonLoop<'a> { pub span: Span, pub head: Option,