Auto merge of #118433 - matthiaskrgr:rollup-fi9lrwg, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #116839 (Implement thread parking for xous)
 - #118265 (remove the memcpy-on-equal-ptrs assumption)
 - #118269 (Unify `TraitRefs` and `PolyTraitRefs` in `ValuePairs`)
 - #118394 (Remove HIR opkinds)
 - #118398 (Add proper cfgs in std)
 - #118419 (Eagerly return `ExprKind::Err` on `yield`/`await` in wrong coroutine context)
 - #118422 (Fix coroutine validation for mixed panic strategy)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-11-29 08:51:01 +00:00
commit ec1f21cb04
39 changed files with 220 additions and 325 deletions

View File

@ -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,
@ -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 => "*",
@ -881,19 +881,25 @@ pub fn to_string(&self) -> &'static str {
Gt => ">",
}
}
pub fn lazy(&self) -> bool {
pub fn is_lazy(&self) -> bool {
matches!(self, BinOpKind::And | BinOpKind::Or)
}
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<BinOpKind>;
@ -901,7 +907,7 @@ pub fn is_comparison(&self) -> bool {
/// 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,
@ -912,13 +918,18 @@ 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 => "-",
}
}
/// 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

View File

@ -72,7 +72,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'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 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'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 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'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(
@ -350,30 +350,8 @@ fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
}
}
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(
@ -781,10 +759,10 @@ fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKin
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);
@ -944,9 +922,7 @@ fn lower_expr_closure(
) -> 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);
@ -955,7 +931,6 @@ fn lower_expr_closure(
});
let coroutine_option =
this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
this.current_item = prev;
(body_id, coroutine_option)
});
@ -1041,7 +1016,7 @@ fn lower_expr_async_closure(
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 });
@ -1063,7 +1038,7 @@ fn lower_expr_async_closure(
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);
@ -1503,7 +1478,9 @@ fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::Expr
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 {

View File

@ -202,9 +202,7 @@ fn lower_item_kind(
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<Output = T>` here because lower_body
// only cares about the input argument patterns in the function
@ -837,7 +835,6 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'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,

View File

@ -878,7 +878,10 @@ fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -
result
}
fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
fn with_new_scopes<T>(&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;
@ -890,6 +893,8 @@ fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
self.is_in_loop_condition = was_in_loop_condition;
self.current_item = current_item;
ret
}
@ -1239,7 +1244,7 @@ fn lower_generic_arg(
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)),
@ -2246,7 +2251,7 @@ fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
}
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)),

View File

@ -255,12 +255,12 @@ fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr
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 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline
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);
}

View File

@ -653,3 +653,4 @@
// E0721, // `await` keyword
// E0723, // unstable feature in `const` context
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
// E0744, // merged into E0728

View File

@ -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
};

View File

@ -7,8 +7,8 @@
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<ast::BinOpKind> 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<BinOpKind>;
#[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> {

View File

@ -448,7 +448,11 @@ fn to_trace(
) -> 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),
)),
}
}
}

View File

@ -1667,9 +1667,7 @@ enum Mismatch<'a> {
.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 @@ fn values_str(
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(),

View File

@ -197,11 +197,6 @@ fn try_report_trait_placeholder_mismatch(
value_pairs: &ValuePairs<'tcx>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
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() =>
{

View File

@ -384,7 +384,6 @@ pub enum ValuePairs<'tcx> {
Regions(ExpectedFound<ty::Region<'tcx>>),
Terms(ExpectedFound<ty::Term<'tcx>>),
Aliases(ExpectedFound<ty::AliasTy<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),

View File

@ -656,7 +656,7 @@ fn is_expr_delims_necessary(
) -> 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 @@ fn check_unused_delims_expr(
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)
}

View File

@ -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.

View File

@ -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)),
);

View File

@ -384,10 +384,10 @@ fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
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.to_string(),
operator: op.node.as_str(),
sugg: errors::WrapExpressionInParentheses {
left: init.span.shrink_to_lo(),
right: init.span.shrink_to_hi(),

View File

@ -17,7 +17,7 @@
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 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
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 @ ..] => {

View File

@ -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<Span>,

View File

@ -423,12 +423,14 @@ pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
}
}
#[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<T: Clone> WriteCloneIntoRaw for T {
#[inline]
default unsafe fn write_clone_into_raw(&self, target: *mut Self) {
@ -438,6 +440,7 @@ impl<T: Clone> WriteCloneIntoRaw for T {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy> WriteCloneIntoRaw for T {
#[inline]
unsafe fn write_clone_into_raw(&self, target: *mut Self) {

View File

@ -148,6 +148,7 @@ fn fmt(
/// An intermediate trait for specialization of `Extend`.
#[doc(hidden)]
#[cfg(not(no_global_oom_handling))]
trait SpecExtend<I: IntoIterator> {
/// Extends `self` with the contents of the given iterator.
fn spec_extend(&mut self, iter: I);

View File

@ -2023,6 +2023,7 @@ unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcBox<[T]> {
}
}
#[cfg(not(no_global_oom_handling))]
/// Specialization trait used for `From<&[T]>`.
trait RcFromSlice<T> {
fn from_slice(slice: &[T]) -> Self;

View File

@ -3503,6 +3503,7 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
/// Specialization trait used for collecting into `Arc<[T]>`.
trait ToArcSlice<T>: Iterator<Item = T> + Sized {
fn to_arc_slice(self) -> Arc<[T]>;

View File

@ -58,6 +58,7 @@
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 @@
#[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<T: Clone, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<
<T as SpecFromElem>::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<usize>);
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
default unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
// SAFETY:
@ -2626,6 +2630,7 @@ impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
let count = src.len();

View File

@ -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).

View File

@ -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)]

View File

@ -28,7 +28,6 @@
pub mod stdio;
pub mod thread;
pub mod thread_local_key;
#[path = "../unsupported/thread_parking.rs"]
pub mod thread_parking;
pub mod time;

View File

@ -0,0 +1,94 @@
use crate::os::xous::ffi::{blocking_scalar, 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");
}
}
}
impl Drop for Parker {
fn drop(&mut self) {
scalar(ticktimer_server(), TicktimerScalar::FreeCondition(self.index()).into()).ok();
}
}

View File

@ -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,

View File

@ -78,7 +78,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
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 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
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 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
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);

View File

@ -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(),
)
}

View File

@ -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}"),

View File

@ -1933,7 +1933,7 @@ fn rewrite_unary_op(
shape: Shape,
) -> Option<String> {
// 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> {

View File

@ -339,7 +339,7 @@ fn flatten(
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!(),

View File

@ -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() {}

View File

@ -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: aborting due to 1 previous error
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
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`.

View File

@ -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
}

View File

@ -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 3 previous errors
error: aborting due to 4 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`.

View File

@ -0,0 +1,11 @@
// compile-flags: -Cpanic=unwind --crate-type=lib
// no-prefer-dynamic
// edition:2021
#![feature(coroutines)]
pub fn run<T>(a: T) {
let _ = move || {
drop(a);
yield;
};
}

View File

@ -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());
}