diff --git a/Cargo.lock b/Cargo.lock index c427f6a92a0f0..36327880641af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,7 +848,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1261,7 +1261,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1388,7 +1388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2166,7 +2166,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2515,9 +2515,9 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f1541610994bba178cb36757e102d06a52a2d9612aa6d34c64b3b377c5d943" +checksum = "245c950e30794ed20f72ff60c85ae1cddb0ba54fda4623017a678943f98f636c" [[package]] name = "minimal-lexical" @@ -2653,7 +2653,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5085,7 +5085,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5517,7 +5517,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5536,7 +5536,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6514,7 +6514,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index fb0736a90cd8c..e8779d6ee6869 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1,4 +1,5 @@ use std::fmt::{self, Write}; +use std::num::NonZero; use std::ops::Deref; use std::range::{RangeFrom, RangeInclusive, RangeToInclusive}; use std::{cmp, iter}; @@ -9,8 +10,8 @@ use rustc_index::bit_set::BitMatrix; use tracing::{debug, trace}; use crate::{ - AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer, - LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size, + AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, + IndexVec, Integer, LayoutData, Niche, NumScalableVectors, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange, }; @@ -127,7 +128,7 @@ pub enum LayoutCalculatorError { ZeroLengthSimdType, /// The length of an SIMD type exceeds the maximum number of lanes - OversizedSimdType { max_lanes: u64 }, + OversizedSimdType { max_lanes: usize }, /// An element type of an SIMD type isn't a primitive NonPrimitiveSimdType(F), @@ -495,7 +496,7 @@ impl LayoutCalculator { }, }; - let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else { + let Some(union_field_count) = NonZero::new(only_variant.len()) else { return Err(LayoutCalculatorError::EmptyUnion); }; @@ -1476,19 +1477,17 @@ where F: AsRef> + fmt::Debug, { let elt = element.as_ref(); - if count == 0 { - return Err(LayoutCalculatorError::ZeroLengthSimdType); - } else if count > crate::MAX_SIMD_LANES { - return Err(LayoutCalculatorError::OversizedSimdType { max_lanes: crate::MAX_SIMD_LANES }); - } + let count = BackendLaneCount::new(count)?; let BackendRepr::Scalar(element) = elt.backend_repr else { return Err(LayoutCalculatorError::NonPrimitiveSimdType(element)); }; // Compute the size and alignment of the vector - let size = - elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; + let size = elt + .size + .checked_mul(count.as_u64(), dl) + .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; let (repr, size, align) = match kind { SimdVectorKind::Scalable(number_of_vectors) => ( BackendRepr::SimdScalableVector { element, count, number_of_vectors }, @@ -1521,6 +1520,6 @@ where align: AbiAlign::new(align), max_repr_align: None, unadjusted_abi_align: elt.align.abi, - randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count)), + randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count.as_u64())), }) } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index d978920fb638d..e0e9ecaa49c63 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -40,7 +40,7 @@ use std::cmp::min; use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; -use std::num::{NonZeroUsize, ParseIntError}; +use std::num::{NonZero, ParseIntError}; use std::ops::{Add, AddAssign, Deref, Mul, Sub}; use std::range::RangeInclusive; use std::str::FromStr; @@ -244,7 +244,42 @@ impl ReprOptions { /// This value is selected based on backend support: /// * LLVM does not appear to have a vector width limit. /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. -pub const MAX_SIMD_LANES: u64 = 1 << 0xF; +pub const MAX_SIMD_LANES: u16 = 1 << 0xF; + +/// The number of lanes in a [`BackendRepr::SimdVector`], `1..=`[`MAX_SIMD_LANES`]. +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash))] +pub struct BackendLaneCount(NonZero); + +impl BackendLaneCount { + pub fn new(count: u64) -> Result> { + let Ok(count @ ..=MAX_SIMD_LANES) = u16::try_from(count) else { + return Err(LayoutCalculatorError::OversizedSimdType { + max_lanes: crate::MAX_SIMD_LANES.into(), + }); + }; + if let Some(count) = NonZero::new(count) { + Ok(BackendLaneCount(count)) + } else { + Err(LayoutCalculatorError::ZeroLengthSimdType) + } + } + + #[inline] + pub fn is_power_of_two(self) -> bool { + self.0.is_power_of_two() + } + + #[inline] + pub fn as_u64(self) -> u64 { + self.0.get().into() + } + + #[inline] + pub fn as_u32(self) -> u32 { + self.0.get().into() + } +} /// How pointers are represented in a given address space #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -1611,7 +1646,7 @@ pub enum FieldsShape { Primitive, /// All fields start at no offset. The `usize` is the field count. - Union(NonZeroUsize), + Union(NonZero), /// Array/vector-like placement, with all fields of identical types. Array { stride: Size, count: u64 }, @@ -1770,12 +1805,12 @@ pub enum BackendRepr { }, SimdScalableVector { element: Scalar, - count: u64, + count: BackendLaneCount, number_of_vectors: NumScalableVectors, }, SimdVector { element: Scalar, - count: u64, + count: BackendLaneCount, }, // FIXME: I sometimes use memory, sometimes use an IR aggregate! Memory { @@ -2260,7 +2295,7 @@ impl LayoutData { } /// Returns the elements count of a scalable vector. - pub fn scalable_vector_element_count(&self) -> Option { + pub fn scalable_vector_element_count(&self) -> Option { match self.backend_repr { BackendRepr::SimdScalableVector { count, .. } => Some(count), _ => None, diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index f603e8604e646..efa2a008e65ae 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -8,10 +8,7 @@ pub use TokenKind::*; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::edition::Edition; use rustc_span::symbol::IdentPrintMode; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym}; -#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint. -#[allow(hidden_glob_reexports)] -use rustc_span::{Ident, Symbol}; +use rustc_span::{self as sp, DUMMY_SP, ErrorGuaranteed, Span, Symbol, kw, sym}; use crate::ast; use crate::util::case::Case; @@ -506,7 +503,7 @@ pub enum TokenKind { /// This identifier (and its span) is the identifier passed to the /// declarative macro. The span in the surrounding `Token` is the span of /// the `ident` metavariable in the macro's RHS. - NtIdent(Ident, IdentIsRaw), + NtIdent(sp::Ident, IdentIsRaw), /// Lifetime identifier token. /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. @@ -517,7 +514,7 @@ pub enum TokenKind { /// This identifier (and its span) is the lifetime passed to the /// declarative macro. The span in the surrounding `Token` is the span of /// the `lifetime` metavariable in the macro's RHS. - NtLifetime(Ident, IdentIsRaw), + NtLifetime(sp::Ident, IdentIsRaw), /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) @@ -637,7 +634,7 @@ impl Token { } /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary. - pub fn from_ast_ident(ident: Ident) -> Self { + pub fn from_ast_ident(ident: sp::Ident) -> Self { Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span) } @@ -845,10 +842,10 @@ impl Token { /// Returns an identifier if this token is an identifier. #[inline] - pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> { + pub fn ident(&self) -> Option<(sp::Ident, IdentIsRaw)> { // We avoid using `Token::uninterpolate` here because it's slow. match self.kind { - Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)), + Ident(name, is_raw) => Some((sp::Ident::new(name, self.span), is_raw)), NtIdent(ident, is_raw) => Some((ident, is_raw)), _ => None, } @@ -856,10 +853,10 @@ impl Token { /// Returns a lifetime identifier if this token is a lifetime. #[inline] - pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> { + pub fn lifetime(&self) -> Option<(sp::Ident, IdentIsRaw)> { // We avoid using `Token::uninterpolate` here because it's slow. match self.kind { - Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)), + Lifetime(name, is_raw) => Some((sp::Ident::new(name, self.span), is_raw)), NtLifetime(ident, is_raw) => Some((ident, is_raw)), _ => None, } @@ -934,32 +931,32 @@ impl Token { } pub fn is_path_segment_keyword(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_path_segment_keyword) + self.is_non_raw_ident_where(sp::Ident::is_path_segment_keyword) } /// Returns true for reserved identifiers used internally for elided lifetimes, /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_special) + self.is_non_raw_ident_where(sp::Ident::is_special) } /// Returns `true` if the token is a keyword used in the language. pub fn is_used_keyword(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_used_keyword) + self.is_non_raw_ident_where(sp::Ident::is_used_keyword) } /// Returns `true` if the token is a keyword reserved for possible future use. pub fn is_unused_keyword(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_unused_keyword) + self.is_non_raw_ident_where(sp::Ident::is_unused_keyword) } /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_reserved) + self.is_non_raw_ident_where(sp::Ident::is_reserved) } pub fn is_non_reserved_ident(&self) -> bool { - self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id)) + self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !sp::Ident::is_reserved(id)) } /// Returns `true` if the token is the identifier `true` or `false`. @@ -980,7 +977,7 @@ impl Token { } /// Returns `true` if the token is a non-raw identifier for which `pred` holds. - pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { + pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(sp::Ident) -> bool) -> bool { match self.ident() { Some((id, IdentIsRaw::No)) => pred(id), _ => false, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3b0c90264e32d..64c0be27a2daa 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -10,14 +10,13 @@ use std::borrow::Cow; use std::sync::Arc; use rustc_ast::attr::AttrIdGenerator; -use rustc_ast::token::{self, CommentKind, Delimiter, DocFragmentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{Comment, CommentStyle}; use rustc_ast::{ self as ast, AttrArgs, AttrKind, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg, GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, - InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, SelfKind, Term, attr, + InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, SelfKind, Term, attr, token as tk, }; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; @@ -327,18 +326,14 @@ fn print_crate_inner<'a>( /// E.g. `ident` + `where` would merge into `identwhere`. fn idents_would_merge(tt1: &TokenTree, tt2: &TokenTree) -> bool { fn is_ident_like(tt: &TokenTree) -> bool { - matches!( - tt, - TokenTree::Token(Token { kind: token::Ident(..) | token::NtIdent(..), .. }, _,) - ) + matches!(tt, TokenTree::Token(tk::Token { kind: tk::Ident(..) | tk::NtIdent(..), .. }, _,)) } is_ident_like(tt1) && is_ident_like(tt2) } fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { - use Delimiter::*; use TokenTree::{Delimited as Del, Token as Tok}; - use token::*; + use tk::Delimiter::{Bracket, Parenthesis}; fn is_punct(tt: &TokenTree) -> bool { matches!(tt, TokenTree::Token(tok, _) if tok.is_punct()) @@ -349,58 +344,64 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { // this match. match (tt1, tt2) { // No space after line doc comments. - (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false, + (Tok(tk::Token { kind: tk::DocComment(tk::CommentKind::Line, ..), .. }, _), _) => false, // `.` + NON-PUNCT: `x.y`, `tup.0` - (Tok(Token { kind: Dot, .. }, _), tt2) if !is_punct(tt2) => false, + (Tok(tk::Token { kind: tk::Dot, .. }, _), tt2) if !is_punct(tt2) => false, // `$` + IDENT: `$e` - (Tok(Token { kind: Dollar, .. }, _), Tok(Token { kind: Ident(..), .. }, _)) => false, + ( + Tok(tk::Token { kind: tk::Dollar, .. }, _), + Tok(tk::Token { kind: tk::Ident(..), .. }, _), + ) => false, // NON-PUNCT + `,`: `foo,` // NON-PUNCT + `;`: `x = 3;`, `[T; 3]` // NON-PUNCT + `.`: `x.y`, `tup.0` - (tt1, Tok(Token { kind: Comma | Semi | Dot, .. }, _)) if !is_punct(tt1) => false, + (tt1, Tok(tk::Token { kind: tk::Comma | tk::Semi | tk::Dot, .. }, _)) if !is_punct(tt1) => { + false + } // IDENT + `!`: `println!()`, but `if !x { ... }` needs a space after the `if` - (Tok(Token { kind: Ident(sym, is_raw), span }, _), Tok(Token { kind: Bang, .. }, _)) - if !Ident::new(*sym, *span).is_reserved() || matches!(is_raw, IdentIsRaw::Yes) => - { + ( + Tok(tk::Token { kind: tk::Ident(sym, is_raw), span }, _), + Tok(tk::Token { kind: tk::Bang, .. }, _), + ) if !Ident::new(*sym, *span).is_reserved() || matches!(is_raw, tk::IdentIsRaw::Yes) => { false } // IDENT|`fn`|`Self`|`pub` + `(`: `f(3)`, `fn(x: u8)`, `Self()`, `pub(crate)`, // but `let (a, b) = (1, 2)` needs a space after the `let` - (Tok(Token { kind: Ident(sym, is_raw), span }, _), Del(_, _, Parenthesis, _)) + (Tok(tk::Token { kind: tk::Ident(sym, is_raw), span }, _), Del(_, _, Parenthesis, _)) if !Ident::new(*sym, *span).is_reserved() || *sym == kw::Fn || *sym == kw::SelfUpper || *sym == kw::Pub - || matches!(is_raw, IdentIsRaw::Yes) => + || matches!(is_raw, tk::IdentIsRaw::Yes) => { false } // `#` + `[`: `#[attr]` - (Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false, + (Tok(tk::Token { kind: tk::Pound, .. }, _), Del(_, _, Bracket, _)) => false, _ => true, } } pub fn doc_comment_to_string( - fragment_kind: DocFragmentKind, + fragment_kind: tk::DocFragmentKind, attr_style: ast::AttrStyle, data: Symbol, ) -> String { match fragment_kind { - DocFragmentKind::Sugared(comment_kind) => match (comment_kind, attr_style) { - (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{data}"), - (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{data}"), - (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{data}*/"), - (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{data}*/"), + tk::DocFragmentKind::Sugared(comment_kind) => match (comment_kind, attr_style) { + (tk::CommentKind::Line, ast::AttrStyle::Outer) => format!("///{data}"), + (tk::CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{data}"), + (tk::CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{data}*/"), + (tk::CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{data}*/"), }, - DocFragmentKind::Raw(_) => { + tk::DocFragmentKind::Raw(_) => { format!( "#{}[doc = {:?}]", if attr_style == ast::AttrStyle::Inner { "!" } else { "" }, @@ -410,24 +411,24 @@ pub fn doc_comment_to_string( } } -fn literal_to_string(lit: token::Lit) -> String { - let token::Lit { kind, symbol, suffix } = lit; +fn literal_to_string(lit: tk::Lit) -> String { + let tk::Lit { kind, symbol, suffix } = lit; let mut out = match kind { - token::Byte => format!("b'{symbol}'"), - token::Char => format!("'{symbol}'"), - token::Str => format!("\"{symbol}\""), - token::StrRaw(n) => { + tk::Byte => format!("b'{symbol}'"), + tk::Char => format!("'{symbol}'"), + tk::Str => format!("\"{symbol}\""), + tk::StrRaw(n) => { format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) } - token::ByteStr => format!("b\"{symbol}\""), - token::ByteStrRaw(n) => { + tk::ByteStr => format!("b\"{symbol}\""), + tk::ByteStrRaw(n) => { format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) } - token::CStr => format!("c\"{symbol}\""), - token::CStrRaw(n) => { + tk::CStr => format!("c\"{symbol}\""), + tk::CStrRaw(n) => { format!("cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize)) } - token::Integer | token::Float | token::Bool | token::Err(_) => symbol.to_string(), + tk::Integer | tk::Float | tk::Bool | tk::Err(_) => symbol.to_string(), }; if let Some(suffix) = suffix { @@ -688,7 +689,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere ast::AttrKind::Synthetic(..) => unreachable!(), // due to early return above ast::AttrKind::DocComment(comment_kind, data) => { self.word(doc_comment_to_string( - DocFragmentKind::Sugared(*comment_kind), + tk::DocFragmentKind::Sugared(*comment_kind), attr.style, *data, )); @@ -751,21 +752,21 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere // Emit hygiene annotations for identity-bearing tokens, // matching how print_ident() and print_lifetime() call ann_post(). match token.kind { - token::Ident(name, _) => { + tk::Ident(name, _) => { self.ann_post(Ident::new(name, token.span)); } - token::NtIdent(ident, _) => { + tk::NtIdent(ident, _) => { self.ann_post(ident); } - token::Lifetime(name, _) => { + tk::Lifetime(name, _) => { self.ann_post(Ident::new(name, token.span)); } - token::NtLifetime(ident, _) => { + tk::NtLifetime(ident, _) => { self.ann_post(ident); } _ => {} } - if let token::DocComment(..) = token.kind { + if let tk::DocComment(..) = token.kind { self.hardbreak() } *spacing @@ -807,7 +808,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere // `,` is better printed as `x,` than `x ,`. (Even if the original source // code was `x ,`.) // - // Finally, we must be careful about changing the output. Token pretty + // Finally, we must be careful about changing the output. tk::Token pretty // printing is used by `stringify!` and `impl Display for // proc_macro::TokenStream`, and some programs rely on the output having a // particular form, even though they shouldn't. In particular, some proc @@ -839,13 +840,13 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere header: Option>, has_bang: bool, ident: Option, - delim: Delimiter, + delim: tk::Delimiter, open_spacing: Option, tts: &TokenStream, convert_dollar_crate: bool, span: Span, ) { - let cb = (delim == Delimiter::Brace).then(|| self.cbox(INDENT_UNIT)); + let cb = (delim == tk::Delimiter::Brace).then(|| self.cbox(INDENT_UNIT)); match header { Some(MacHeader::Path(path)) => self.print_path(path, false, 0), Some(MacHeader::Keyword(kw)) => self.word(kw), @@ -859,7 +860,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.print_ident(ident); } match delim { - Delimiter::Brace => { + tk::Delimiter::Brace => { if header.is_some() || has_bang || ident.is_some() { self.nbsp(); } @@ -1004,105 +1005,109 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } /// Print the token kind precisely, without converting `$crate` into its respective crate name. - fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> { + fn token_kind_to_string(&self, tok: &tk::TokenKind) -> Cow<'static, str> { self.token_kind_to_string_ext(tok, None) } fn token_kind_to_string_ext( &self, - tok: &TokenKind, + tok: &tk::TokenKind, convert_dollar_crate: Option, ) -> Cow<'static, str> { match *tok { - token::Eq => "=".into(), - token::Lt => "<".into(), - token::Le => "<=".into(), - token::EqEq => "==".into(), - token::Ne => "!=".into(), - token::Ge => ">=".into(), - token::Gt => ">".into(), - token::Bang => "!".into(), - token::Tilde => "~".into(), - token::OrOr => "||".into(), - token::AndAnd => "&&".into(), - token::Plus => "+".into(), - token::Minus => "-".into(), - token::Star => "*".into(), - token::Slash => "/".into(), - token::Percent => "%".into(), - token::Caret => "^".into(), - token::And => "&".into(), - token::Or => "|".into(), - token::Shl => "<<".into(), - token::Shr => ">>".into(), - token::PlusEq => "+=".into(), - token::MinusEq => "-=".into(), - token::StarEq => "*=".into(), - token::SlashEq => "/=".into(), - token::PercentEq => "%=".into(), - token::CaretEq => "^=".into(), - token::AndEq => "&=".into(), - token::OrEq => "|=".into(), - token::ShlEq => "<<=".into(), - token::ShrEq => ">>=".into(), + tk::Eq => "=".into(), + tk::Lt => "<".into(), + tk::Le => "<=".into(), + tk::EqEq => "==".into(), + tk::Ne => "!=".into(), + tk::Ge => ">=".into(), + tk::Gt => ">".into(), + tk::Bang => "!".into(), + tk::Tilde => "~".into(), + tk::OrOr => "||".into(), + tk::AndAnd => "&&".into(), + tk::Plus => "+".into(), + tk::Minus => "-".into(), + tk::Star => "*".into(), + tk::Slash => "/".into(), + tk::Percent => "%".into(), + tk::Caret => "^".into(), + tk::And => "&".into(), + tk::Or => "|".into(), + tk::Shl => "<<".into(), + tk::Shr => ">>".into(), + tk::PlusEq => "+=".into(), + tk::MinusEq => "-=".into(), + tk::StarEq => "*=".into(), + tk::SlashEq => "/=".into(), + tk::PercentEq => "%=".into(), + tk::CaretEq => "^=".into(), + tk::AndEq => "&=".into(), + tk::OrEq => "|=".into(), + tk::ShlEq => "<<=".into(), + tk::ShrEq => ">>=".into(), /* Structural symbols */ - token::At => "@".into(), - token::Dot => ".".into(), - token::DotDot => "..".into(), - token::DotDotDot => "...".into(), - token::DotDotEq => "..=".into(), - token::Comma => ",".into(), - token::Semi => ";".into(), - token::Colon => ":".into(), - token::PathSep => "::".into(), - token::RArrow => "->".into(), - token::LArrow => "<-".into(), - token::FatArrow => "=>".into(), - token::OpenParen => "(".into(), - token::CloseParen => ")".into(), - token::OpenBracket => "[".into(), - token::CloseBracket => "]".into(), - token::OpenBrace => "{".into(), - token::CloseBrace => "}".into(), - token::OpenInvisible(_) | token::CloseInvisible(_) => "".into(), - token::Pound => "#".into(), - token::Dollar => "$".into(), - token::Question => "?".into(), - token::SingleQuote => "'".into(), + tk::At => "@".into(), + tk::Dot => ".".into(), + tk::DotDot => "..".into(), + tk::DotDotDot => "...".into(), + tk::DotDotEq => "..=".into(), + tk::Comma => ",".into(), + tk::Semi => ";".into(), + tk::Colon => ":".into(), + tk::PathSep => "::".into(), + tk::RArrow => "->".into(), + tk::LArrow => "<-".into(), + tk::FatArrow => "=>".into(), + tk::OpenParen => "(".into(), + tk::CloseParen => ")".into(), + tk::OpenBracket => "[".into(), + tk::CloseBracket => "]".into(), + tk::OpenBrace => "{".into(), + tk::CloseBrace => "}".into(), + tk::OpenInvisible(_) | tk::CloseInvisible(_) => "".into(), + tk::Pound => "#".into(), + tk::Dollar => "$".into(), + tk::Question => "?".into(), + tk::SingleQuote => "'".into(), /* Literals */ - token::Literal(lit) => literal_to_string(lit).into(), + tk::Literal(lit) => literal_to_string(lit).into(), /* Name components */ - token::Ident(name, is_raw) => { + tk::Ident(name, is_raw) => { IdentPrinter::new(name, is_raw.to_print_mode_ident(), convert_dollar_crate) .to_string() .into() } - token::NtIdent(ident, is_raw) => { + tk::NtIdent(ident, is_raw) => { IdentPrinter::for_ast_ident(ident, is_raw.to_print_mode_ident()).to_string().into() } - token::Lifetime(name, is_raw) | token::NtLifetime(Ident { name, .. }, is_raw) => { + tk::Lifetime(name, is_raw) | tk::NtLifetime(Ident { name, .. }, is_raw) => { IdentPrinter::new(name, is_raw.to_print_mode_lifetime(), None).to_string().into() } /* Other */ - token::DocComment(comment_kind, attr_style, data) => { - doc_comment_to_string(DocFragmentKind::Sugared(comment_kind), attr_style, data) + tk::DocComment(comment_kind, attr_style, data) => { + doc_comment_to_string(tk::DocFragmentKind::Sugared(comment_kind), attr_style, data) .into() } - token::Eof => "".into(), + tk::Eof => "".into(), } } /// Print the token precisely, without converting `$crate` into its respective crate name. - fn token_to_string(&self, token: &Token) -> Cow<'static, str> { + fn token_to_string(&self, token: &tk::Token) -> Cow<'static, str> { self.token_to_string_ext(token, false) } - fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> Cow<'static, str> { + fn token_to_string_ext( + &self, + token: &tk::Token, + convert_dollar_crate: bool, + ) -> Cow<'static, str> { let convert_dollar_crate = convert_dollar_crate.then_some(token.span); self.token_kind_to_string_ext(&token.kind, convert_dollar_crate) } @@ -2333,7 +2338,7 @@ impl<'a> State<'a> { self.print_token_literal(lit.as_token_lit(), lit.span) } - fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { + fn print_token_literal(&mut self, token_lit: tk::Lit, span: Span) { self.maybe_print_comment(span.lo()); self.word(token_lit.to_string()) } diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 930f87e697c04..bc8b4a71697e1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -1,12 +1,14 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_feature::AttributeStability; use rustc_hir::attrs::{CrateType, WindowsSubsystemKind}; -use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES; +use rustc_session::lint::builtin::{DUPLICATE_TOOLS, UNKNOWN_CRATE_TYPES}; use rustc_span::Symbol; use rustc_span::edit_distance::find_best_match_for_name_with_substrings; use super::prelude::*; -use crate::diagnostics::{ToolReserved, UnknownCrateTypes, UnknownCrateTypesSuggestion}; +use crate::diagnostics::{ + DuplicateTool, ToolReserved, UnknownCrateTypes, UnknownCrateTypesSuggestion, +}; pub(crate) struct CrateNameParser; @@ -352,6 +354,10 @@ fn parse_register_tool( cx.adcx().expected_identifier(path.span()); continue; }; + if !ident.name.can_be_raw() { + cx.adcx().expected_identifier(path.span()); + continue; + } if ident.name == sym::rustc { cx.should_emit @@ -359,8 +365,18 @@ fn parse_register_tool( continue; } + let mut lint_emitted = false; for tools in tools.iter_mut() { - tools.insert(ident); + if let Some(old_ident) = tools.replace(ident) + && !lint_emitted + { + lint_emitted = true; + cx.emit_lint( + DUPLICATE_TOOLS, + DuplicateTool { span: ident.span, tool: ident, old_ident_span: old_ident.span }, + ident.span, + ); + } } } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index dda8b9913afc4..171c34232411b 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -823,6 +823,16 @@ pub(crate) struct UnknownExternLangItem { pub lang_item: Symbol, } +#[derive(Diagnostic)] +#[diag("duplicate tool `{$tool}` registered")] +pub(crate) struct DuplicateTool { + #[primary_span] + pub(crate) span: Span, + pub(crate) tool: Ident, + #[label("already registered here")] + pub(crate) old_ident_span: Span, +} + #[derive(Diagnostic)] #[diag("tool `{$tool}` is reserved and cannot be registered")] pub(crate) struct ToolReserved { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 3a8adc261e976..874b5c44afbd8 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -60,7 +60,7 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx _ => unreachable!(), }; - scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()).unwrap() + scalar_to_clif_type(tcx, element).by(count.as_u32()).unwrap() } fn simd_for_each_lane<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index c89ba0e3de9fe..440ae9c4b812e 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -132,9 +132,7 @@ impl<'tcx> CValue<'tcx> { let clif_ty = match layout.backend_repr { BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), BackendRepr::SimdVector { element, count } => { - scalar_to_clif_type(fx.tcx, element) - .by(u32::try_from(count).unwrap()) - .unwrap() + scalar_to_clif_type(fx.tcx, element).by(count.as_u32()).unwrap() } _ => unreachable!("{:?}", layout.ty), }; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index f2ce7bca1e338..c6c32236ab49f 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -73,7 +73,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( else { element }; - return cx.context.new_vector_type(element, count); + return cx.context.new_vector_type(element, count.as_u64()); } BackendRepr::ScalarPair { .. } => { return cx.type_struct( diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 1efab9b7c496d..d2dfa9a45de8b 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1119,8 +1119,9 @@ fn llvm_fixup_input<'ll, 'tcx>( BackendRepr::SimdVector { element, count }, ) if layout.size.bytes() == 8 => { let elem_ty = llvm_asm_scalar_type(bx.cx, element); - let vec_ty = bx.cx.type_vector(elem_ty, count); - let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect(); + let count = count.as_u32(); + let vec_ty = bx.cx.type_vector(elem_ty, u64::from(count)); + let indices: Vec<_> = (0..count * 2).map(|x| bx.const_u32(x)).collect(); bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s)) @@ -1165,8 +1166,11 @@ fn llvm_fixup_input<'ll, 'tcx>( | X86InlineAsmRegClass::ymm_reg | X86InlineAsmRegClass::zmm_reg, ), - BackendRepr::SimdVector { element, count: count @ (8 | 16) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 8 | 16 = count + && element.primitive() == Primitive::Float(Float::F16) => + { bx.bitcast(value, bx.type_vector(bx.type_i16(), count)) } ( @@ -1202,8 +1206,11 @@ fn llvm_fixup_input<'ll, 'tcx>( | ArmInlineAsmRegClass::qreg_low4 | ArmInlineAsmRegClass::qreg_low8, ), - BackendRepr::SimdVector { element, count: count @ (4 | 8) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 4 | 8 = count + && element.primitive() == Primitive::Float(Float::F16) => + { bx.bitcast(value, bx.type_vector(bx.type_i16(), count)) } (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) @@ -1291,6 +1298,7 @@ fn llvm_fixup_output<'ll, 'tcx>( BackendRepr::SimdVector { element, count }, ) if layout.size.bytes() == 8 => { let elem_ty = llvm_asm_scalar_type(bx.cx, element); + let count = count.as_u64(); let vec_ty = bx.cx.type_vector(elem_ty, count * 2); let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect(); bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) @@ -1333,8 +1341,11 @@ fn llvm_fixup_output<'ll, 'tcx>( | X86InlineAsmRegClass::ymm_reg | X86InlineAsmRegClass::zmm_reg, ), - BackendRepr::SimdVector { element, count: count @ (8 | 16) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 8 | 16 = count + && element.primitive() == Primitive::Float(Float::F16) => + { bx.bitcast(value, bx.type_vector(bx.type_f16(), count)) } ( @@ -1370,8 +1381,11 @@ fn llvm_fixup_output<'ll, 'tcx>( | ArmInlineAsmRegClass::qreg_low4 | ArmInlineAsmRegClass::qreg_low8, ), - BackendRepr::SimdVector { element, count: count @ (4 | 8) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 4 | 8 = count + && element.primitive() == Primitive::Float(Float::F16) => + { bx.bitcast(value, bx.type_vector(bx.type_f16(), count)) } (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) @@ -1445,7 +1459,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( BackendRepr::SimdVector { element, count }, ) if layout.size.bytes() == 8 => { let elem_ty = llvm_asm_scalar_type(cx, element); - cx.type_vector(elem_ty, count * 2) + cx.type_vector(elem_ty, count.as_u64() * 2) } (X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s)) if s.primitive() == Primitive::Float(Float::F64) => @@ -1482,8 +1496,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>( | X86InlineAsmRegClass::ymm_reg | X86InlineAsmRegClass::zmm_reg, ), - BackendRepr::SimdVector { element, count: count @ (8 | 16) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 8 | 16 = count + && element.primitive() == Primitive::Float(Float::F16) => + { cx.type_vector(cx.type_i16(), count) } ( @@ -1519,8 +1536,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>( | ArmInlineAsmRegClass::qreg_low4 | ArmInlineAsmRegClass::qreg_low8, ), - BackendRepr::SimdVector { element, count: count @ (4 | 8) }, - ) if element.primitive() == Primitive::Float(Float::F16) => { + BackendRepr::SimdVector { element, count }, + ) if let count = count.as_u64() + && let 4 | 8 = count + && element.primitive() == Primitive::Float(Float::F16) => + { cx.type_vector(cx.type_i16(), count) } (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index c422515c1a64b..22d43f22e24a4 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -64,8 +64,8 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { llvm::LLVMIntTypeInContext(self.llcx(), num_bits as c_uint) } - pub(crate) fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type { - unsafe { llvm::LLVMVectorType(ty, len as c_uint) } + pub(crate) fn type_vector(&self, ty: &'ll Type, count: u64) -> &'ll Type { + unsafe { llvm::LLVMVectorType(ty, count as c_uint) } } pub(crate) fn type_scalable_vector(&self, ty: &'ll Type, count: u64) -> &'ll Type { diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 0caf7e761bdb1..68b4b6234b231 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -22,7 +22,7 @@ fn uncached_llvm_type<'a, 'tcx>( BackendRepr::Scalar(_) => bug!("handled elsewhere"), BackendRepr::SimdVector { element, count } => { let element = layout.scalar_llvm_type_at(cx, element); - return cx.type_vector(element, count); + return cx.type_vector(element, count.as_u64()); } BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => { let element = if element.is_bool() { @@ -31,7 +31,7 @@ fn uncached_llvm_type<'a, 'tcx>( layout.scalar_llvm_type_at(cx, *element) }; - let vector_type = cx.type_scalable_vector(element, count); + let vector_type = cx.type_scalable_vector(element, count.as_u64()); return match number_of_vectors.0 { 1 => vector_type, 2 => cx.type_struct(&[vector_type, vector_type], false), diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index 680f0b44d70dd..397fb423e8da3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -2,19 +2,24 @@ //! //! We attempt to retag every argument and return value of a function, and every rvalue //! of an assignment. The first step to retagging is to generate a [`RetagPlan`], which -//! describes which pointers within the place or operand can be retagged. +//! describes which pointers within the place or operand can be retagged. Then, we traverse +//! the [`RetagPlan`] to emit the calls. use rustc_abi::{FieldIdx, FieldsShape, Size, VariantIdx, Variants}; use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::range_set::RangeSet; +use rustc_middle::mir::interpret::Allocation; use rustc_middle::mir::{Rvalue, WithRetag}; -use rustc_middle::ty; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout}; +use rustc_middle::ty::{self, Ty}; use crate::mir::FunctionCx; use crate::mir::operand::{OperandRef, OperandRefBuilder, OperandValue}; use crate::mir::place::PlaceRef; -use crate::traits::{BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods}; +use crate::traits::{ + BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, StaticCodegenMethods, +}; use crate::{RetagFlags, RetagInfo}; pub(crate) fn rvalue_needs_retag(rvalue: &Rvalue<'_>) -> bool { @@ -167,27 +172,62 @@ impl<'a, 'tcx, V> RetagPlan { is_fn_entry: bool, ) -> Option> { let tcx = bx.tcx(); + let retag_opts = tcx.sess.opts.unstable_opts.codegen_emit_retag.unwrap_or_default(); let pointee_ty = pointee_layout.ty; let is_mutable = matches!(ptr_kind, Some(Mutability::Mut) | None); - let is_unpin = pointee_ty.is_unpin(tcx, bx.typing_env()); - let is_freeze = pointee_ty.is_freeze(tcx, bx.typing_env()); + let is_unpin = UnsafePinnedRanges::excludes(bx, pointee_ty); + let is_freeze = UnsafeCellRanges::excludes(bx, pointee_ty); let is_box = ptr_kind.is_none(); // `&mut !Unpin` is not protected let is_protected = is_fn_entry && (!is_mutable || is_unpin); + let pin_ranges = UnsafePinnedRanges::collect(bx, pointee_layout, retag_opts.no_precise_pin); + + if is_mutable { + // Everything is `UnsafePinned` if the collected ranges + // cover the entire size of the layout. + let all_pinned = matches!( + pin_ranges.as_slice(), + [(Size::ZERO, size)] if *size == pointee_layout.size, + ); + + // Otherwise, if we can't find any `UnsafePinned`, + // the type is still might be `!Unpin` or `!UnsafeUnpin`, + // so we should include the entire range. + let implicitly_pinned = pin_ranges.is_empty() && !is_unpin; + + if all_pinned || implicitly_pinned { + return None; + } + } + if is_mutable && !is_unpin { return None; } - let im_layout = bx.const_null(bx.type_ptr()); - let pin_layout = bx.const_null(bx.type_ptr()); + let im_ranges = UnsafeCellRanges::collect(bx, pointee_layout, retag_opts.no_precise_im); + let all_im = matches!( + im_ranges.as_slice(), + [(Size::ZERO, size)] if *size == pointee_layout.size, + ); + + let pin_layout = Self::alloc_ranges(bx, pin_ranges); + + // If the entire type is covered by `UnsafeCell`, then we can + // defer to checking if the type is `Freeze` via `RetagFlags`, + // to avoid allocating a global array. + let im_layout = + if all_im { bx.const_null(bx.type_ptr()) } else { Self::alloc_ranges(bx, im_ranges) }; let mut flags = RetagFlags::empty(); flags.set(RetagFlags::IS_PROTECTED, is_protected); flags.set(RetagFlags::IS_MUTABLE, is_mutable); + // Even though we have a list of interior mutable ranges, + // we still need a separate flag for `Freeze` types, for when + // we retag interior mutable ZSTs. flags.set(RetagFlags::IS_FREEZE, is_freeze); flags.set(RetagFlags::IS_BOX, is_box); @@ -198,6 +238,137 @@ impl<'a, 'tcx, V> RetagPlan { flags, })) } + + /// Creates a pointer to a global static allocation containing adjacent pairs of `u64` bytes, + /// which indicate the offset and width of a range within the layout of a type. Returns a null + /// pointer if the list of ranges is empty. + fn alloc_ranges>( + bx: &mut Bx, + ranges: Vec<(Size, Size)>, + ) -> Bx::Value { + let tcx = bx.tcx(); + let data_layout = &tcx.data_layout; + + if ranges.is_empty() { + return bx.const_null(bx.type_ptr()); + } + + let mut bytes: Vec = vec![]; + for (start, end) in ranges.iter() { + bytes.extend_from_slice(&start.bytes().to_ne_bytes()); + bytes.extend_from_slice(&end.bytes().to_ne_bytes()); + } + + let intptr_ty = data_layout.ptr_sized_integer(); + let align = intptr_ty.align(data_layout).abi; + + let alloc = Allocation::from_bytes(&bytes, align, Mutability::Not, ()); + let const_alloc = tcx.mk_const_alloc(alloc); + + // Different IDs are produced, but identical range lists + // will resolve to the same allocation. + let alloc_id = tcx.reserve_and_set_memory_alloc(const_alloc); + let global_alloc = tcx.global_alloc(alloc_id); + let global_mem = global_alloc.unwrap_memory(); + + bx.cx().static_addr_of(global_mem, None) + } +} + +/// A visitor trait for collecting the ranges within a layout that satisfy a given predicate. +trait PerByteTracking<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { + /// Indicates that we can exclude the range of bytes that contains this type. + /// This tells us that [`PerByteTracking::contains`] is false for every + /// field or variant without having to recurse any further into the layout of the type. + fn excludes(bx: &mut Bx, ty: Ty<'tcx>) -> bool; + + /// Indicates that we should include the range containing this type. + fn contains(bx: &mut Bx, ty: Ty<'tcx>) -> bool; + + /// Traverses through the layout of a type to find each range satisfying + /// the predicate. + /// + /// If `imprecise` is true, then the entire size of the type will be included, + /// even if only one of its fields satisfies the predicate. + fn visit_layout( + bx: &mut Bx, + offset: Size, + ranges: &mut RangeSet, + layout: TyAndLayout<'tcx>, + imprecise: bool, + ) { + if layout.is_zst() { + return; + } + + if Self::excludes(bx, layout.ty) { + return; + } + + if imprecise { + return ranges.add_range(offset, layout.size); + } + + let union_or_primitive = + matches!(layout.fields, FieldsShape::Union(..) | FieldsShape::Primitive); + let has_multiple_variants = matches!(layout.variants, Variants::Multiple { .. }); + + if Self::contains(bx, layout.ty) || union_or_primitive || has_multiple_variants { + ranges.add_range(offset, layout.size); + } else { + // We know at this point that we have an array or an arbitrary layout. + for ix in layout.fields.index_by_increasing_offset() { + // We need to find the offset for this field relative + // to the entire type, not just the current aggregate + // that we are visiting here. + let field_offset = layout.fields.offset(ix); + let layout_offset = field_offset + offset; + + let field = layout.field(bx, ix); + Self::visit_layout(bx, layout_offset, ranges, field, imprecise); + } + } + } + /// Collects the ranges within a type that satisfy the given predicate. + fn collect(bx: &mut Bx, layout: TyAndLayout<'tcx>, imprecise: bool) -> Vec<(Size, Size)> { + let mut ranges = RangeSet::::new(); + Self::visit_layout(bx, Size::ZERO, &mut ranges, layout, imprecise); + ranges.0 + } +} + +/// Collects the ranges within a type that are covered by `UnsafeCell`. +struct UnsafeCellRanges; + +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> PerByteTracking<'a, 'tcx, Bx> for UnsafeCellRanges { + fn excludes(bx: &mut Bx, ty: Ty<'tcx>) -> bool { + ty.is_freeze(bx.tcx(), bx.cx().typing_env()) + } + + fn contains(bx: &mut Bx, ty: Ty<'tcx>) -> bool { + let tcx = bx.tcx(); + match ty.kind() { + ty::Adt(adt, _) => Some(adt.did()) == tcx.lang_items().unsafe_cell_type(), + _ => false, + } + } +} + +/// Collects the ranges within a type that are covered by `UnsafePinned`. +struct UnsafePinnedRanges; + +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> PerByteTracking<'a, 'tcx, Bx> for UnsafePinnedRanges { + fn excludes(bx: &mut Bx, ty: Ty<'tcx>) -> bool { + ty.is_unpin(bx.tcx(), bx.typing_env()) && ty.is_unsafe_unpin(bx.tcx(), bx.typing_env()) + } + + fn contains(bx: &mut Bx, ty: Ty<'tcx>) -> bool { + let tcx = bx.tcx(); + match ty.kind() { + ty::Adt(adt, _) => Some(adt.did()) == tcx.lang_items().unsafe_pinned_type(), + _ => false, + } + } } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 23f95c2797f2e..5b6bc54897dab 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -2,6 +2,7 @@ //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE //! and miri. +mod atomic; mod simd; use std::assert_matches; @@ -20,9 +21,9 @@ use tracing::trace; use super::memory::MemoryKind; use super::util::ensure_monomorphic_enough; use super::{ - AllocId, CheckInAllocMsg, ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Pointer, - PointerArithmetic, Projectable, Provenance, Scalar, err_ub_format, err_unsup_format, interp_ok, - throw_inval, throw_ub, throw_ub_format, + AllocId, AtomicRmwOp, CheckInAllocMsg, ImmTy, Immediate, InterpCx, InterpResult, Machine, OpTy, + PlaceTy, Pointer, PointerArithmetic, Projectable, Provenance, Scalar, err_ub_format, + err_unsup_format, interp_ok, throw_inval, throw_ub, throw_ub_format, }; use crate::interpret::{MPlaceTy, Writeable}; @@ -177,6 +178,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let instance_args = instance.args; let intrinsic_name = self.tcx.item_name(instance.def_id()); + if intrinsic_name.as_str().starts_with("atomic_") { + return self.eval_atomic_intrinsic(intrinsic_name, instance_args, args, dest, ret); + } if intrinsic_name.as_str().starts_with("simd_") { return self.eval_simd_intrinsic(intrinsic_name, instance_args, args, dest, ret); } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs new file mode 100644 index 0000000000000..32967addafe12 --- /dev/null +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs @@ -0,0 +1,131 @@ +use rustc_middle::mir::BinOp; +use rustc_middle::{mir, span_bug, ty}; +use rustc_span::{Symbol, sym}; +use tracing::trace; + +use super::{ + AtomicRmwOp, Immediate, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Scalar, interp_ok, +}; + +impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { + /// Returns `true` if emulation happened. + /// Here we implement the intrinsics that are common to all CTFE instances; individual machines can add their own + /// intrinsic handling. + pub fn eval_atomic_intrinsic( + &mut self, + intrinsic_name: Symbol, + generic_args: ty::GenericArgsRef<'tcx>, + args: &[OpTy<'tcx, M::Provenance>], + dest: &PlaceTy<'tcx, M::Provenance>, + ret: Option, + ) -> InterpResult<'tcx, bool> { + let get_ord_at = |i: usize| { + let ordering = generic_args.const_at(i).to_value(); + ordering.to_branch()[0].to_value().to_leaf().to_atomic_ordering() + }; + + match intrinsic_name { + sym::atomic_load => { + let ord = get_ord_at(1); + let [ptr] = args else { span_bug!(self.cur_span(), "invalid `atomic_load` call") }; + + let place = self.deref_pointer(ptr)?; + let val = M::atomic_load(self, &place, ord)?; + self.write_scalar(val, dest)?; + } + sym::atomic_store => { + let ord = get_ord_at(1); + let [ptr, val] = args else { + span_bug!(self.cur_span(), "invalid `atomic_store` call") + }; + + let place = self.deref_pointer(ptr)?; + let val = self.read_immediate(val)?; + M::atomic_store(self, &place, &val, ord)?; + } + sym::atomic_or + | sym::atomic_xor + | sym::atomic_and + | sym::atomic_nand + | sym::atomic_xadd + | sym::atomic_xsub + | sym::atomic_min + | sym::atomic_umin + | sym::atomic_max + | sym::atomic_umax + | sym::atomic_xchg => { + let num_ty_generics = match intrinsic_name { + sym::atomic_min + | sym::atomic_umin + | sym::atomic_max + | sym::atomic_umax + | sym::atomic_xchg => 1, + _ => 2, + }; + let ord = get_ord_at(num_ty_generics); + let [ptr, operand] = args else { + span_bug!(self.cur_span(), "invalid `{intrinsic_name}` call") + }; + + let place = self.deref_pointer(ptr)?; + let operand = self.read_immediate(operand)?; + + let op = match intrinsic_name { + sym::atomic_or => AtomicRmwOp::MirOp { op: BinOp::BitOr, neg: false }, + sym::atomic_xor => AtomicRmwOp::MirOp { op: BinOp::BitXor, neg: false }, + sym::atomic_and => AtomicRmwOp::MirOp { op: BinOp::BitAnd, neg: false }, + sym::atomic_nand => AtomicRmwOp::MirOp { op: BinOp::BitAnd, neg: true }, + sym::atomic_xadd => AtomicRmwOp::MirOp { op: BinOp::Add, neg: false }, + sym::atomic_xsub => AtomicRmwOp::MirOp { op: BinOp::Sub, neg: false }, + sym::atomic_min => AtomicRmwOp::Min, + sym::atomic_umin => AtomicRmwOp::Min, + sym::atomic_max => AtomicRmwOp::Max, + sym::atomic_umax => AtomicRmwOp::Max, + sym::atomic_xchg => AtomicRmwOp::Swap, + _ => unreachable!(), + }; + + let res = M::atomic_rmw(self, &place, op, &operand, ord)?; + self.write_scalar(res, dest)?; + } + sym::atomic_cxchg | sym::atomic_cxchgweak => { + let success_ord = get_ord_at(1); + let failure_ord = get_ord_at(2); + let [ptr, expected_old, new] = args else { + span_bug!(self.cur_span(), "invalid `{intrinsic_name}` call") + }; + + let place = self.deref_pointer(ptr)?; + let expected_old = self.read_immediate(expected_old)?; + let new = self.read_immediate(new)?; + + let (actual_old, success) = M::atomic_compare_exchange( + self, + &place, + &expected_old, + &new, + /* can_fail_spuriously */ intrinsic_name == sym::atomic_cxchgweak, + success_ord, + failure_ord, + )?; + let res = Immediate::ScalarPair(actual_old, Scalar::from_bool(success)); + self.write_immediate(res, dest)?; + } + sym::atomic_fence | sym::atomic_singlethreadfence => { + let ord = get_ord_at(0); + let [] = args else { + span_bug!(self.cur_span(), "invalid `{intrinsic_name}` call") + }; + + M::atomic_fence(self, ord, intrinsic_name == sym::atomic_singlethreadfence)?; + } + + // Unsupported intrinsic: skip the return_to_block below. + _ => return interp_ok(false), + } + + trace!("{:?}", self.dump_place(&dest.clone().into())); + self.return_to_block(ret)?; + interp_ok(true) + } +} diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 40251cbc8155b..0528fee35031c 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -9,16 +9,17 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::Ty; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{AtomicOrdering, Ty}; use rustc_middle::{mir, ty}; use rustc_span::def_id::DefId; use rustc_target::callconv::FnAbi; use super::{ - AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation, - CtfeProvenance, EnteredTraceSpan, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, - MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, interp_ok, throw_unsup, + AllocBytes, AllocId, AllocKind, AllocRange, Allocation, AtomicRmwOp, CTFE_ALLOC_SALT, + ConstAllocation, CtfeProvenance, EnteredTraceSpan, FnArg, Frame, ImmTy, InterpCx, InterpResult, + MPlaceTy, MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, Scalar, + interp_ok, throw_unsup, }; /// Data returned by [`Machine::after_stack_pop`], and consumed by @@ -281,8 +282,6 @@ pub trait Machine<'tcx>: Sized { ) -> InterpResult<'tcx>; /// Called for all binary operations where the LHS has pointer type. - /// - /// Returns a (value, overflowed) pair if the operation succeeded fn binary_ptr_op( ecx: &InterpCx<'tcx, Self>, bin_op: mir::BinOp, @@ -315,7 +314,46 @@ pub trait Machine<'tcx>: Sized { } /// Determines whether the `fmuladd` intrinsics fuse the multiply-add or use separate operations. - fn float_fuse_mul_add(_ecx: &InterpCx<'tcx, Self>) -> bool; + fn float_fuse_mul_add(ecx: &InterpCx<'tcx, Self>) -> bool; + + fn atomic_load( + ecx: &InterpCx<'tcx, Self>, + place: &MPlaceTy<'tcx, Self::Provenance>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx, Scalar>; + + fn atomic_store( + ecx: &mut InterpCx<'tcx, Self>, + place: &MPlaceTy<'tcx, Self::Provenance>, + val: &ImmTy<'tcx, Self::Provenance>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx>; + + /// Returns the old value. + fn atomic_rmw( + ecx: &mut InterpCx<'tcx, Self>, + place: &MPlaceTy<'tcx, Self::Provenance>, + op: AtomicRmwOp, + operand: &ImmTy<'tcx, Self::Provenance>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx, Scalar>; + + /// Returns a pair of the old value and a boolean indicating whether the update happened. + fn atomic_compare_exchange( + ecx: &mut InterpCx<'tcx, Self>, + place: &MPlaceTy<'tcx, Self::Provenance>, + expected_old: &ImmTy<'tcx, Self::Provenance>, + new: &ImmTy<'tcx, Self::Provenance>, + can_fail_spuriously: bool, + success_ordering: AtomicOrdering, + failure_ordering: AtomicOrdering, + ) -> InterpResult<'tcx, (Scalar, bool)>; + + fn atomic_fence( + ecx: &InterpCx<'tcx, Self>, + ordering: AtomicOrdering, + singlethread: bool, + ) -> InterpResult<'tcx>; /// Called before a basic block terminator is executed. #[inline] @@ -708,6 +746,70 @@ pub macro compile_time_machine(<$tcx: lifetime>) { true } + #[inline(always)] + fn atomic_load( + ecx: &InterpCx<$tcx, Self>, + place: &MPlaceTy<$tcx, Self::Provenance>, + _ordering: AtomicOrdering, + ) -> InterpResult<$tcx, Scalar> { + // Compile-time machines are single-threaded so this is like a regular load. + ecx.read_scalar(place) + } + + #[inline(always)] + fn atomic_store( + ecx: &mut InterpCx<$tcx, Self>, + place: &MPlaceTy<$tcx, Self::Provenance>, + val: &ImmTy<$tcx, Self::Provenance>, + _ordering: AtomicOrdering, + ) -> InterpResult<$tcx> { + // Compile-time machines are single-threaded so this is like a regular store. + ecx.write_scalar(val.to_scalar(), place) + } + + fn atomic_rmw( + ecx: &mut InterpCx<$tcx, Self>, + place: &MPlaceTy<$tcx, Self::Provenance>, + op: AtomicRmwOp, + operand: &ImmTy<$tcx, Self::Provenance>, + _ordering: AtomicOrdering, + ) -> InterpResult<$tcx, Scalar> { + // Compile-time machines are single-threaded so we ignore the ordering. + let old_val = ecx.read_immediate(place)?; + let new_val = ecx.atomic_rmw_op(op, &old_val, operand)?; + ecx.write_immediate(*new_val, place)?; + interp_ok(old_val.to_scalar()) + } + + fn atomic_compare_exchange( + ecx: &mut InterpCx<$tcx, Self>, + place: &MPlaceTy<$tcx, Self::Provenance>, + expected_old: &ImmTy<$tcx, Self::Provenance>, + new: &ImmTy<$tcx, Self::Provenance>, + _can_fail_spuriously: bool, + _success_ordering: AtomicOrdering, + _failure_ordering: AtomicOrdering, + ) -> InterpResult<$tcx, (Scalar, bool)> { + // Compile-time machines are single-threaded so we ignore the ordering. + // They are also deterministic so we do not fail spuriously. + let actual_old = ecx.read_immediate(place)?; + let eq = ecx.binary_op(mir::BinOp::Eq, &actual_old, expected_old)?.to_scalar().to_bool()?; + if eq { + ecx.write_immediate(**new, place)?; + } + interp_ok((actual_old.to_scalar(), eq)) + } + + #[inline(always)] + fn atomic_fence( + _ecx: &InterpCx<$tcx, Self>, + _ordering: AtomicOrdering, + _singlethread: bool, + ) -> InterpResult<$tcx> { + // Compile-time machines are single-threaded so this is a NOP. + interp_ok(()) + } + #[inline(always)] fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index d52c1f9306444..6e66599fc15c8 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -35,6 +35,7 @@ pub use self::machine::{ pub use self::memory::{AllocInfo, AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; use self::operand::Operand; pub use self::operand::{ImmTy, Immediate, OpTy}; +pub use self::operator::AtomicRmwOp; pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable}; use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index ca8c096d3ab41..95e513cc97b4e 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -10,6 +10,19 @@ use tracing::trace; use super::{ImmTy, InterpCx, Machine, MemPlaceMeta, interp_ok, throw_ub}; +/// Describes an atomic RMW operation. +pub enum AtomicRmwOp { + MirOp { + op: mir::BinOp, + /// Indicates whether the result of the operation should be negated (`UnOp::Not`, must be a + /// boolean/integer-typed operation). + neg: bool, + }, + Max, + Min, + Swap, +} + impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn three_way_compare(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> { let res = Ord::cmp(&lhs, &rhs); @@ -504,4 +517,27 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } + + pub fn atomic_rmw_op( + &self, + op: AtomicRmwOp, + left: &ImmTy<'tcx, M::Provenance>, + right: &ImmTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { + interp_ok(match op { + AtomicRmwOp::MirOp { op, neg } => { + let val = self.binary_op(op, &left, right)?; + if neg { self.unary_op(mir::UnOp::Not, &val)? } else { val } + } + AtomicRmwOp::Max => { + let lt = self.binary_op(mir::BinOp::Lt, &left, right)?.to_scalar().to_bool()?; + if lt { right } else { &left }.clone() + } + AtomicRmwOp::Min => { + let lt = self.binary_op(mir::BinOp::Lt, &left, right)?.to_scalar().to_bool()?; + if lt { &left } else { right }.clone() + } + AtomicRmwOp::Swap => right.clone(), + }) + } } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 1b505ae1b9781..adb0d8bb88c06 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -124,7 +124,7 @@ fn check_validity_requirement_lax<'tcx>( BackendRepr::ScalarPair { a: s1, b: s2, b_offset: _ } => { scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2) } - BackendRepr::SimdVector { element: s, count } => count == 0 || scalar_allows_raw_init(s), + BackendRepr::SimdVector { element: s, count: _ } => scalar_allows_raw_init(s), BackendRepr::Memory { .. } => true, // Fields are checked below. BackendRepr::SimdScalableVector { element, .. } => scalar_allows_raw_init(element), }; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index ca418a4473465..94927b41bbb90 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -25,6 +25,7 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(nonzero_internals)] #![feature(pattern_type_macro)] #![feature(pattern_types)] #![feature(ptr_alignment_type)] diff --git a/compiler/rustc_data_structures/src/stable_hash.rs b/compiler/rustc_data_structures/src/stable_hash.rs index 9634472cf283c..26090fdb26754 100644 --- a/compiler/rustc_data_structures/src/stable_hash.rs +++ b/compiler/rustc_data_structures/src/stable_hash.rs @@ -238,14 +238,7 @@ impl StableHash for PhantomData { fn stable_hash(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {} } -impl StableHash for NonZero { - #[inline] - fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { - self.get().stable_hash(hcx, hasher) - } -} - -impl StableHash for NonZero { +impl StableHash for NonZero { #[inline] fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { self.get().stable_hash(hcx, hasher) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5367de7a1cc82..7b52a5600ae2a 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -1,8 +1,7 @@ use std::ops::{Bound, Range}; -use ast::token::IdentIsRaw; use rustc_ast as ast; -use rustc_ast::token; +use rustc_ast::token as tk; use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream}; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; @@ -31,65 +30,65 @@ trait ToInternal { fn to_internal(self) -> T; } -impl FromInternal for Delimiter { - fn from_internal(delim: token::Delimiter) -> Delimiter { +impl FromInternal for Delimiter { + fn from_internal(delim: tk::Delimiter) -> Delimiter { match delim { - token::Delimiter::Parenthesis => Delimiter::Parenthesis, - token::Delimiter::Brace => Delimiter::Brace, - token::Delimiter::Bracket => Delimiter::Bracket, - token::Delimiter::Invisible(_) => Delimiter::None, + tk::Delimiter::Parenthesis => Delimiter::Parenthesis, + tk::Delimiter::Brace => Delimiter::Brace, + tk::Delimiter::Bracket => Delimiter::Bracket, + tk::Delimiter::Invisible(_) => Delimiter::None, } } } -impl ToInternal for Delimiter { - fn to_internal(self) -> token::Delimiter { +impl ToInternal for Delimiter { + fn to_internal(self) -> tk::Delimiter { match self { - Delimiter::Parenthesis => token::Delimiter::Parenthesis, - Delimiter::Brace => token::Delimiter::Brace, - Delimiter::Bracket => token::Delimiter::Bracket, - Delimiter::None => token::Delimiter::Invisible(token::InvisibleOrigin::ProcMacro), + Delimiter::Parenthesis => tk::Delimiter::Parenthesis, + Delimiter::Brace => tk::Delimiter::Brace, + Delimiter::Bracket => tk::Delimiter::Bracket, + Delimiter::None => tk::Delimiter::Invisible(tk::InvisibleOrigin::ProcMacro), } } } -impl FromInternal for LitKind { - fn from_internal(kind: token::LitKind) -> Self { +impl FromInternal for LitKind { + fn from_internal(kind: tk::LitKind) -> Self { match kind { - token::Byte => LitKind::Byte, - token::Char => LitKind::Char, - token::Integer => LitKind::Integer, - token::Float => LitKind::Float, - token::Str => LitKind::Str, - token::StrRaw(n) => LitKind::StrRaw(n), - token::ByteStr => LitKind::ByteStr, - token::ByteStrRaw(n) => LitKind::ByteStrRaw(n), - token::CStr => LitKind::CStr, - token::CStrRaw(n) => LitKind::CStrRaw(n), - token::Err(_guar) => { + tk::Byte => LitKind::Byte, + tk::Char => LitKind::Char, + tk::Integer => LitKind::Integer, + tk::Float => LitKind::Float, + tk::Str => LitKind::Str, + tk::StrRaw(n) => LitKind::StrRaw(n), + tk::ByteStr => LitKind::ByteStr, + tk::ByteStrRaw(n) => LitKind::ByteStrRaw(n), + tk::CStr => LitKind::CStr, + tk::CStrRaw(n) => LitKind::CStrRaw(n), + tk::Err(_guar) => { // This is the only place a `rustc_proc_macro::bridge::LitKind::ErrWithGuar` // is constructed. Note that an `ErrorGuaranteed` is available, // as required. See the comment in `to_internal`. LitKind::ErrWithGuar } - token::Bool => unreachable!(), + tk::Bool => unreachable!(), } } } -impl ToInternal for LitKind { - fn to_internal(self) -> token::LitKind { +impl ToInternal for LitKind { + fn to_internal(self) -> tk::LitKind { match self { - LitKind::Byte => token::Byte, - LitKind::Char => token::Char, - LitKind::Integer => token::Integer, - LitKind::Float => token::Float, - LitKind::Str => token::Str, - LitKind::StrRaw(n) => token::StrRaw(n), - LitKind::ByteStr => token::ByteStr, - LitKind::ByteStrRaw(n) => token::ByteStrRaw(n), - LitKind::CStr => token::CStr, - LitKind::CStrRaw(n) => token::CStrRaw(n), + LitKind::Byte => tk::Byte, + LitKind::Char => tk::Char, + LitKind::Integer => tk::Integer, + LitKind::Float => tk::Float, + LitKind::Str => tk::Str, + LitKind::StrRaw(n) => tk::StrRaw(n), + LitKind::ByteStr => tk::ByteStr, + LitKind::ByteStrRaw(n) => tk::ByteStrRaw(n), + LitKind::CStr => tk::CStr, + LitKind::CStrRaw(n) => tk::CStrRaw(n), LitKind::ErrWithGuar => { // This is annoying but valid. `LitKind::ErrWithGuar` would // have an `ErrorGuaranteed` except that type isn't available @@ -98,7 +97,7 @@ impl ToInternal for LitKind { // which would be expensive. #[allow(deprecated)] let guar = ErrorGuaranteed::unchecked_error_guaranteed(); - token::Err(guar) + tk::Err(guar) } } } @@ -106,24 +105,22 @@ impl ToInternal for LitKind { impl FromInternal for Vec> { fn from_internal(stream: TokenStream) -> Self { - use rustc_ast::token::*; - // Estimate the capacity as `stream.len()` rounded up to the next power // of two to limit the number of required reallocations. let mut trees = Vec::with_capacity(stream.len().next_power_of_two()); for tree in stream.iter() { - let (Token { kind, span }, joint) = match tree.clone() { + let (tk::Token { kind, span }, joint) = match tree.clone() { tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => { // In `mk_delimited` we avoid nesting invisible delimited // of the same `MetaVarKind`. Here we do the same but // ignore the `MetaVarKind` because it is discarded when we // convert it to a `Group`. - while let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim + while let tk::Delimiter::Invisible(tk::InvisibleOrigin::MetaVar(_)) = delim && stream.len() == 1 && let tree = stream.get(0).unwrap() && let tokenstream::TokenTree::Delimited(_, _, delim2, stream2) = tree - && let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim2 + && let tk::Delimiter::Invisible(tk::InvisibleOrigin::MetaVar(_)) = delim2 { delim = *delim2; stream = stream2.clone(); @@ -183,79 +180,79 @@ impl FromInternal for Vec> { }; match kind { - Eq => op("="), - Lt => op("<"), - Le => op("<="), - EqEq => op("=="), - Ne => op("!="), - Ge => op(">="), - Gt => op(">"), - AndAnd => op("&&"), - OrOr => op("||"), - Bang => op("!"), - Tilde => op("~"), - Plus => op("+"), - Minus => op("-"), - Star => op("*"), - Slash => op("/"), - Percent => op("%"), - Caret => op("^"), - And => op("&"), - Or => op("|"), - Shl => op("<<"), - Shr => op(">>"), - PlusEq => op("+="), - MinusEq => op("-="), - StarEq => op("*="), - SlashEq => op("/="), - PercentEq => op("%="), - CaretEq => op("^="), - AndEq => op("&="), - OrEq => op("|="), - ShlEq => op("<<="), - ShrEq => op(">>="), - At => op("@"), - Dot => op("."), - DotDot => op(".."), - DotDotDot => op("..."), - DotDotEq => op("..="), - Comma => op(","), - Semi => op(";"), - Colon => op(":"), - PathSep => op("::"), - RArrow => op("->"), - LArrow => op("<-"), - FatArrow => op("=>"), - Pound => op("#"), - Dollar => op("$"), - Question => op("?"), - SingleQuote => op("'"), - - Ident(sym, is_raw) => trees.push(TokenTree::Ident(Ident { + tk::Eq => op("="), + tk::Lt => op("<"), + tk::Le => op("<="), + tk::EqEq => op("=="), + tk::Ne => op("!="), + tk::Ge => op(">="), + tk::Gt => op(">"), + tk::AndAnd => op("&&"), + tk::OrOr => op("||"), + tk::Bang => op("!"), + tk::Tilde => op("~"), + tk::Plus => op("+"), + tk::Minus => op("-"), + tk::Star => op("*"), + tk::Slash => op("/"), + tk::Percent => op("%"), + tk::Caret => op("^"), + tk::And => op("&"), + tk::Or => op("|"), + tk::Shl => op("<<"), + tk::Shr => op(">>"), + tk::PlusEq => op("+="), + tk::MinusEq => op("-="), + tk::StarEq => op("*="), + tk::SlashEq => op("/="), + tk::PercentEq => op("%="), + tk::CaretEq => op("^="), + tk::AndEq => op("&="), + tk::OrEq => op("|="), + tk::ShlEq => op("<<="), + tk::ShrEq => op(">>="), + tk::At => op("@"), + tk::Dot => op("."), + tk::DotDot => op(".."), + tk::DotDotDot => op("..."), + tk::DotDotEq => op("..="), + tk::Comma => op(","), + tk::Semi => op(";"), + tk::Colon => op(":"), + tk::PathSep => op("::"), + tk::RArrow => op("->"), + tk::LArrow => op("<-"), + tk::FatArrow => op("=>"), + tk::Pound => op("#"), + tk::Dollar => op("$"), + tk::Question => op("?"), + tk::SingleQuote => op("'"), + + tk::Ident(sym, is_raw) => trees.push(TokenTree::Ident(Ident { sym, - is_raw: matches!(is_raw, IdentIsRaw::Yes), + is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), span, })), - NtIdent(ident, is_raw) => trees.push(TokenTree::Ident(Ident { + tk::NtIdent(ident, is_raw) => trees.push(TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(is_raw, IdentIsRaw::Yes), + is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), span: ident.span, })), - Lifetime(name, is_raw) => { + tk::Lifetime(name, is_raw) => { let ident = rustc_span::Ident::new(name, span).without_first_quote(); trees.extend([ TokenTree::Punct(Punct { ch: b'\'', joint: true, span }), TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(is_raw, IdentIsRaw::Yes), + is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), span, }), ]); } - NtLifetime(ident, is_raw) => { + tk::NtLifetime(ident, is_raw) => { let stream = - TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span); + TokenStream::token_alone(tk::Lifetime(ident.name, is_raw), ident.span); trees.push(TokenTree::Group(Group { delimiter: rustc_proc_macro::Delimiter::None, stream: Some(stream), @@ -263,7 +260,7 @@ impl FromInternal for Vec> { })) } - Literal(token::Lit { kind, symbol, suffix }) => { + tk::Literal(tk::Lit { kind, symbol, suffix }) => { trees.push(TokenTree::Literal(self::Literal { kind: FromInternal::from_internal(kind), symbol, @@ -271,15 +268,15 @@ impl FromInternal for Vec> { span, })); } - DocComment(_, attr_style, data) => { + tk::DocComment(_, attr_style, data) => { let mut escaped = String::new(); for ch in data.as_str().chars() { escaped.extend(ch.escape_debug()); } let stream = [ - Ident(sym::doc, IdentIsRaw::No), - Eq, - TokenKind::lit(token::Str, Symbol::intern(&escaped), None), + tk::Ident(sym::doc, tk::IdentIsRaw::No), + tk::Eq, + tk::TokenKind::lit(tk::Str, Symbol::intern(&escaped), None), ] .into_iter() .map(|kind| tokenstream::TokenTree::token_alone(kind, span)) @@ -295,8 +292,15 @@ impl FromInternal for Vec> { })); } - OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket - | OpenInvisible(_) | CloseInvisible(_) | Eof => unreachable!(), + tk::OpenParen + | tk::CloseParen + | tk::OpenBrace + | tk::CloseBrace + | tk::OpenBracket + | tk::CloseBracket + | tk::OpenInvisible(_) + | tk::CloseInvisible(_) + | tk::Eof => unreachable!(), } } trees @@ -308,8 +312,6 @@ impl ToInternal> for (TokenTree, &mut Rustc<'_, '_>) { fn to_internal(self) -> SmallVec<[tokenstream::TokenTree; 2]> { - use rustc_ast::token::*; - // The code below is conservative, using `token_alone`/`Spacing::Alone` // in most places. It's hard in general to do better when working at // the token level. When the resulting code is pretty-printed by @@ -319,31 +321,31 @@ impl ToInternal> match tree { TokenTree::Punct(Punct { ch, joint, span }) => { let kind = match ch { - b'=' => Eq, - b'<' => Lt, - b'>' => Gt, - b'!' => Bang, - b'~' => Tilde, - b'+' => Plus, - b'-' => Minus, - b'*' => Star, - b'/' => Slash, - b'%' => Percent, - b'^' => Caret, - b'&' => And, - b'|' => Or, - b'@' => At, - b'.' => Dot, - b',' => Comma, - b';' => Semi, - b':' => Colon, - b'#' => Pound, - b'$' => Dollar, - b'?' => Question, - b'\'' => SingleQuote, + b'=' => tk::Eq, + b'<' => tk::Lt, + b'>' => tk::Gt, + b'!' => tk::Bang, + b'~' => tk::Tilde, + b'+' => tk::Plus, + b'-' => tk::Minus, + b'*' => tk::Star, + b'/' => tk::Slash, + b'%' => tk::Percent, + b'^' => tk::Caret, + b'&' => tk::And, + b'|' => tk::Or, + b'@' => tk::At, + b'.' => tk::Dot, + b',' => tk::Comma, + b';' => tk::Semi, + b':' => tk::Colon, + b'#' => tk::Pound, + b'$' => tk::Dollar, + b'?' => tk::Question, + b'\'' => tk::SingleQuote, _ => unreachable!(), }; - // We never produce `token::Spacing::JointHidden` here, which + // We never produce `tk::Spacing::JointHidden` here, which // means the pretty-printing of code produced by proc macros is // ugly, with lots of whitespace between tokens. This is // unavoidable because `proc_macro::Spacing` only applies to @@ -364,7 +366,7 @@ impl ToInternal> } TokenTree::Ident(self::Ident { sym, is_raw, span }) => { rustc.psess().symbol_gallery.insert(sym, span); - smallvec![tokenstream::TokenTree::token_alone(Ident(sym, is_raw.into()), span)] + smallvec![tokenstream::TokenTree::token_alone(tk::Ident(sym, is_raw.into()), span)] } TokenTree::Literal(self::Literal { kind: self::LitKind::Integer, @@ -373,8 +375,8 @@ impl ToInternal> span, }) if let Some(symbol) = symbol.as_str().strip_prefix('-') => { let symbol = Symbol::intern(symbol); - let integer = TokenKind::lit(token::Integer, symbol, suffix); - let a = tokenstream::TokenTree::token_joint_hidden(Minus, span); + let integer = tk::TokenKind::lit(tk::Integer, symbol, suffix); + let a = tokenstream::TokenTree::token_joint_hidden(tk::Minus, span); let b = tokenstream::TokenTree::token_alone(integer, span); smallvec![a, b] } @@ -385,14 +387,14 @@ impl ToInternal> span, }) if let Some(symbol) = symbol.as_str().strip_prefix('-') => { let symbol = Symbol::intern(symbol); - let float = TokenKind::lit(token::Float, symbol, suffix); - let a = tokenstream::TokenTree::token_joint_hidden(Minus, span); + let float = tk::TokenKind::lit(tk::Float, symbol, suffix); + let a = tokenstream::TokenTree::token_joint_hidden(tk::Minus, span); let b = tokenstream::TokenTree::token_alone(float, span); smallvec![a, b] } TokenTree::Literal(self::Literal { kind, symbol, suffix, span }) => { smallvec![tokenstream::TokenTree::token_alone( - TokenKind::lit(kind.to_internal(), symbol, suffix), + tk::TokenKind::lit(kind.to_internal(), symbol, suffix), span, )] } @@ -500,7 +502,7 @@ impl server::Server for Rustc<'_, '_> { let minus_present = parser.eat(exp!(Minus)); let lit_span = parser.token.span.data(); - let token::Literal(mut lit) = parser.token.kind else { + let tk::Literal(mut lit) = parser.token.kind else { return Err("not a literal".to_string()); }; @@ -519,26 +521,26 @@ impl server::Server for Rustc<'_, '_> { // Check literal is a kind we allow to be negated in a proc macro token. match lit.kind { - token::LitKind::Bool - | token::LitKind::Byte - | token::LitKind::Char - | token::LitKind::Str - | token::LitKind::StrRaw(_) - | token::LitKind::ByteStr - | token::LitKind::ByteStrRaw(_) - | token::LitKind::CStr - | token::LitKind::CStrRaw(_) - | token::LitKind::Err(_) => { + tk::LitKind::Bool + | tk::LitKind::Byte + | tk::LitKind::Char + | tk::LitKind::Str + | tk::LitKind::StrRaw(_) + | tk::LitKind::ByteStr + | tk::LitKind::ByteStrRaw(_) + | tk::LitKind::CStr + | tk::LitKind::CStrRaw(_) + | tk::LitKind::Err(_) => { return Err("non-numeric literal may not be negated".to_string()); } - token::LitKind::Integer | token::LitKind::Float => {} + tk::LitKind::Integer | tk::LitKind::Float => {} } // Synthesize a new symbol that includes the minus sign. let symbol = Symbol::intern(&s[..1 + lit.symbol.as_str().len()]); - lit = token::Lit::new(lit.kind, symbol, lit.suffix); + lit = tk::Lit::new(lit.kind, symbol, lit.suffix); } - let token::Lit { kind, symbol, suffix } = lit; + let tk::Lit { kind, symbol, suffix } = lit; Ok(Literal { kind: FromInternal::from_internal(kind), symbol, @@ -592,7 +594,7 @@ impl server::Server for Rustc<'_, '_> { let expr = try { let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr")); let expr = p.parse_expr()?; - if p.token != token::Eof { + if p.token != tk::Eof { p.unexpected()?; } expr @@ -613,31 +615,28 @@ impl server::Server for Rustc<'_, '_> { // We don't use `TokenStream::from_ast` as the tokenstream currently cannot // be recovered in the general case. match &expr.kind { - ast::ExprKind::Lit(token_lit) if token_lit.kind == token::Bool => { + ast::ExprKind::Lit(token_lit) if token_lit.kind == tk::Bool => { Ok(tokenstream::TokenStream::token_alone( - token::Ident(token_lit.symbol, IdentIsRaw::No), + tk::Ident(token_lit.symbol, tk::IdentIsRaw::No), expr.span, )) } ast::ExprKind::Lit(token_lit) => { - Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span)) + Ok(tokenstream::TokenStream::token_alone(tk::Literal(*token_lit), expr.span)) } ast::ExprKind::IncludedBytes(byte_sym) => { - let lit = token::Lit::new( - token::ByteStr, - escape_byte_str_symbol(byte_sym.as_byte_str()), - None, - ); - Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span)) + let lit = + tk::Lit::new(tk::ByteStr, escape_byte_str_symbol(byte_sym.as_byte_str()), None); + Ok(tokenstream::TokenStream::token_alone(tk::TokenKind::Literal(lit), expr.span)) } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { ast::ExprKind::Lit(token_lit) => match token_lit { - token::Lit { kind: token::Integer | token::Float, .. } => { + tk::Lit { kind: tk::Integer | tk::Float, .. } => { Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. - tokenstream::TokenTree::token_joint_hidden(token::Minus, e.span), - tokenstream::TokenTree::token_alone(token::Literal(*token_lit), e.span), + tokenstream::TokenTree::token_joint_hidden(tk::Minus, e.span), + tokenstream::TokenTree::token_alone(tk::Literal(*token_lit), e.span), ])) } _ => Err(()), diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1b2e496d6a23c..be821e2044a5b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,7 +1,7 @@ use std::cell::LazyCell; use std::ops::ControlFlow; -use rustc_abi::{ExternAbi, FieldIdx, ScalableElt}; +use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan}; @@ -17,7 +17,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; +use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::util::Discr; use rustc_middle::ty::{ AdtDef, BottomUpFolder, FnSig, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable, @@ -1487,7 +1487,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { if len == 0 { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; - } else if len > MAX_SIMD_LANES { + } else if len > MAX_SIMD_LANES.into() { struct_span_code_err!( tcx.dcx(), sp, diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 96ede89664fea..b2255c8d9679a 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -234,7 +234,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { type Error = !; fn typeck_results(&self) -> Self::TypeckResults<'_> { - self.0.maybe_typeck_results().expect("expected typeck results") + self.0.typeck_results() } fn structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index e32f04308b3d6..638c4a12b9fb1 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -3,7 +3,6 @@ //! See for an //! overview of how lints are implemented. -use std::cell::Cell; use std::slice; use rustc_abi as abi; @@ -484,11 +483,8 @@ pub struct LateContext<'tcx> { /// Current body, or `None` if outside a body. pub enclosing_body: Option, - /// Type-checking results for the current body. Access using the `typeck_results` - /// and `maybe_typeck_results` methods, which handle querying the typeck results on demand. - // FIXME(eddyb) move all the code accessing internal fields like this, - // to this module, to avoid exposing it to lint logic. - pub(super) cached_typeck_results: Cell>>, + /// Type-checking results for the current body. + pub typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, /// Parameter environment for the item we are in. pub param_env: ty::ParamEnv<'tcx>, @@ -663,24 +659,13 @@ impl<'tcx> LateContext<'tcx> { self.tcx.type_is_use_cloned_modulo_regions(self.typing_env(), ty) } - /// Gets the type-checking results for the current body, - /// or `None` if outside a body. - pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { - self.cached_typeck_results.get().or_else(|| { - self.enclosing_body.map(|body| { - let typeck_results = self.tcx.typeck_body(body); - self.cached_typeck_results.set(Some(typeck_results)); - typeck_results - }) - }) - } - /// Gets the type-checking results for the current body. /// As this will ICE if called outside bodies, only call when working with /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[inline] #[track_caller] pub fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> { - self.maybe_typeck_results().expect("`LateContext::typeck_results` called outside of body") + self.typeck_results.expect("`LateContext::typeck_results` called outside of body") } /// Returns the final resolution of a `QPath`, or `Res::Err` if unavailable. @@ -690,7 +675,7 @@ impl<'tcx> LateContext<'tcx> { match *qpath { hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) => self - .maybe_typeck_results() + .typeck_results .filter(|typeck_results| typeck_results.hir_owner == id.owner) .or_else(|| { self.tcx diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 227bff83cabbf..05975187b3180 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -4,7 +4,6 @@ //! borrow checking, etc.). These lints have full type information available. use std::any::Any; -use std::cell::Cell; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::par_join; @@ -37,6 +36,12 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { context: LateContext<'tcx>, pass: T, + + /// Rustdoc parses functions which are behind failing `#[cfg]` checks and may not pass + /// type checking. See: + /// Inlined from the session variables to avoid the indirection and cache pressure in the + /// lint visitor. + actually_rustdoc: bool, } impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> { @@ -89,23 +94,18 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_enclosing_body = self.context.enclosing_body.replace(body_id); - let old_cached_typeck_results = self.context.cached_typeck_results.get(); + let old_typeck_results = self.context.typeck_results; - // HACK(eddyb) avoid trashing `cached_typeck_results` when we're - // nested in `visit_fn`, which may have already resulted in them - // being queried. - if old_enclosing_body != Some(body_id) { - self.context.cached_typeck_results.set(None); + // The body and typeck results are also set in `visit_fn`. + // Only fetch the results if this is for a new body. + if old_enclosing_body != Some(body_id) && !self.actually_rustdoc { + self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id)); } let body = self.context.tcx.hir_body(body_id); self.visit_body(body); self.context.enclosing_body = old_enclosing_body; - - // See HACK comment above. - if old_enclosing_body != Some(body_id) { - self.context.cached_typeck_results.set(old_cached_typeck_results); - } + self.context.typeck_results = old_typeck_results; } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { @@ -123,7 +123,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let generics = self.context.generics.take(); self.context.generics = it.kind.generics(); - let old_cached_typeck_results = self.context.cached_typeck_results.take(); + let old_typeck_results = self.context.typeck_results.take(); let old_enclosing_body = self.context.enclosing_body.take(); self.with_lint_attrs(it.hir_id(), |cx| { cx.with_param_env(it.owner_id, |cx| { @@ -133,7 +133,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas }); }); self.context.enclosing_body = old_enclosing_body; - self.context.cached_typeck_results.set(old_cached_typeck_results); + self.context.typeck_results = old_typeck_results; self.context.generics = generics; } @@ -189,12 +189,15 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas // Wrap in typeck results here, not just in visit_nested_body, // in order for `check_fn` to be able to use them. let old_enclosing_body = self.context.enclosing_body.replace(body_id); - let old_cached_typeck_results = self.context.cached_typeck_results.take(); + let old_typeck_results = self.context.typeck_results; + if !self.actually_rustdoc { + self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id)); + } let body = self.context.tcx.hir_body(body_id); lint_callback!(self, check_fn, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, id); self.context.enclosing_body = old_enclosing_body; - self.context.cached_typeck_results.set(old_cached_typeck_results); + self.context.typeck_results = old_typeck_results; } fn visit_variant_data(&mut self, s: &'tcx hir::VariantData<'tcx>) { @@ -340,7 +343,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( let context = LateContext { tcx, enclosing_body: None, - cached_typeck_results: Cell::new(None), + typeck_results: None, param_env: ty::ParamEnv::empty(), effective_visibilities: tcx.effective_visibilities(()), last_node_with_lint_attrs: tcx.local_def_id_to_hir_id(mod_id), @@ -379,7 +382,11 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( context: LateContext<'tcx>, pass: T, ) { - let mut cx = LateContextAndPass { context, pass }; + let mut cx = LateContextAndPass::<'tcx, T> { + context, + pass, + actually_rustdoc: tcx.sess.opts.actually_rustdoc, + }; let (module, _span, hir_id) = tcx.hir_get_module(mod_id); @@ -414,7 +421,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { let context = LateContext { tcx, enclosing_body: None, - cached_typeck_results: Cell::new(None), + typeck_results: None, param_env: ty::ParamEnv::empty(), effective_visibilities: tcx.effective_visibilities(()), last_node_with_lint_attrs: hir::CRATE_HIR_ID, @@ -423,7 +430,8 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { }; let pass = RuntimeCombinedLateLintPass { passes }; - let mut cx = LateContextAndPass { context, pass }; + let mut cx = + LateContextAndPass { context, pass, actually_rustdoc: tcx.sess.opts.actually_rustdoc }; // Visit the whole crate. cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| { diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs index ed015908ae54a..61c4a95c995b4 100644 --- a/compiler/rustc_lint/src/unit_bindings.rs +++ b/compiler/rustc_lint/src/unit_bindings.rs @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitBindings { // - explicitly wrote `let pat = ();` // - explicitly wrote `let () = init;`. if !local.span.from_expansion() - && let Some(tyck_results) = cx.maybe_typeck_results() + && let Some(tyck_results) = cx.typeck_results && let Some(init) = local.init && let init_ty = tyck_results.expr_ty(init) && let local_ty = tyck_results.node_type(local.hir_id) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 186bfa36bb815..da2220cf7a5fd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -44,6 +44,7 @@ pub mod hardwired { DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_FEATURES, DUPLICATE_MACRO_ATTRIBUTES, + DUPLICATE_TOOLS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_BUILTIN_CFGS_IN_FLAGS, EXPORTED_PRIVATE_DEPENDENCIES, @@ -5742,3 +5743,29 @@ declare_lint! { report_in_deps: false, }; } + +declare_lint! { + /// The `duplicate_tools` lint detects duplicate tools found in crate-level + /// [`register_tool` attributes] (including `register_attribute_tool` or `register_lint_tool`). + /// + /// [`register_tool` attributes]: https://doc.rust-lang.org/nightly/unstable-book/language-features/register-tool.html + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![feature(register_tool)] + /// #![register_tool(foo)] + /// #![register_tool(foo)] + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Enabling a tool more than once is a no-op. + /// To avoid this warning, remove the second `register_tool()` attribute. + pub DUPLICATE_TOOLS, + Deny, + "duplicate tools found in crate-level `#[register_tools]` directives", + @feature_gate = register_tool; +} diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 6f7bd5224cefe..983b4afefdb5f 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -826,6 +826,7 @@ bidirectional_lang_item_map! { // tidy-alphabetical-start DynMetadata, Option, + OwnedBox, Poll, // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 85c658e10d41d..d798cf02f1e49 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -196,8 +196,6 @@ pub const WIDE_PTR_ADDR: usize = 0; /// - For a slice, this is the length. pub const WIDE_PTR_EXTRA: usize = 1; -pub const MAX_SIMD_LANES: u64 = rustc_abi::MAX_SIMD_LANES; - /// Used in `check_validity_requirement` to indicate the kind of initialization /// that is checked to be valid #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, StableHash)] @@ -239,7 +237,7 @@ pub enum SimdLayoutError { ZeroLength, /// The vector has more lanes than supported or permitted by /// #\[rustc_simd_monomorphize_lane_limit\]. - TooManyLanes(u64), + TooManyLanes(Limit), } #[derive(Copy, Clone, Debug, StableHash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index c200e57e69cb3..07fb153b8da58 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -11,6 +11,7 @@ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; +use rustc_mir_dataflow::DropFlagState; use rustc_span::{DUMMY_SP, dummy_spanned}; use tracing::{debug, instrument}; @@ -107,11 +108,10 @@ pub(crate) trait DropElaborator<'a, 'tcx>: fmt::Debug { /// Returns the drop flag of `path` as a MIR `Operand` (or `None` if `path` has no drop flag). fn get_drop_flag(&mut self, path: Self::Path) -> Option>; - /// Modifies the MIR patch so that the drop flag of `path` (if any) is cleared at `location`. + /// Return the drop flag of `path`, if any. /// - /// If `mode` is deep, drop flags of all child paths should also be cleared by inserting - /// additional statements. - fn clear_drop_flag(&mut self, location: Location, path: Self::Path, mode: DropFlagMode); + /// If `mode` is deep, drop flags of all child paths should be returned. + fn drop_flags_for(&mut self, path: Self::Path, mode: DropFlagMode) -> Vec>; // Subpaths @@ -1568,10 +1568,20 @@ where // bother setting it. return succ; } - let block = self.new_block(unwind, TerminatorKind::Goto { target: succ }); - let block_start = Location { block, statement_index: 0 }; - self.elaborator.clear_drop_flag(block_start, self.path, mode); - block + let flags = self.elaborator.drop_flags_for(self.path, mode); + let statements: Vec<_> = flags + .into_iter() + .map(|flag| { + self.assign( + flag, + Rvalue::Use(self.constant_bool(DropFlagState::Absent.value()), WithRetag::Yes), + ) + }) + .collect(); + if statements.is_empty() { + return succ; + } + self.new_block_with_statements(unwind, statements, TerminatorKind::Goto { target: succ }) } #[instrument(level = "debug", skip(self), ret)] @@ -1666,6 +1676,14 @@ where })) } + fn constant_bool(&self, val: bool) -> Operand<'tcx> { + Operand::Constant(Box::new(ConstOperand { + span: self.source_info.span, + user_ty: None, + const_: Const::from_bool(self.tcx(), val), + })) + } + fn assign(&self, lhs: Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> { Statement::new(self.source_info, StatementKind::Assign(Box::new((lhs, rhs)))) } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 83dd9db5f1367..84c9c044ae6a6 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -189,17 +189,23 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { } } - fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) { + fn drop_flags_for(&mut self, path: Self::Path, mode: DropFlagMode) -> Vec> { + let mut flags = vec![]; match mode { DropFlagMode::Shallow => { - self.set_drop_flag(loc, path, DropFlagState::Absent); + if let Some(flag) = self.drop_flags[path] { + flags.push(flag.into()); + } } DropFlagMode::Deep => { on_all_children_bits(self.move_data(), path, |child| { - self.set_drop_flag(loc, child, DropFlagState::Absent) + if let Some(flag) = self.drop_flags[child] { + flags.push(flag.into()); + } }); } } + flags } fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index da158bd6a44d9..3311e82edf37f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -460,7 +460,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { None } - fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {} + fn drop_flags_for(&mut self, _path: Self::Path, _mode: DropFlagMode) -> Vec> { + Vec::new() + } fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option { None diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 22fe960f0790d..e37e69a617bbd 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -3,6 +3,7 @@ use std::ops::ControlFlow; use derive_where::derive_where; use rustc_type_ir::inherent::*; +use rustc_type_ir::lang_items::SolverAdtLangItem; use rustc_type_ir::{ self as ty, InferCtxtLike, Interner, Region, TrivialTypeTraversalImpls, TypeVisitable, TypeVisitableExt, TypeVisitor, @@ -407,12 +408,17 @@ where } // For fundamental types, we just look inside of them. + // Certain lang items (currently, `Box`) have special behaviour here + // and so are special cased. ty::Ref(_, ty, _) => ty.visit_with(self), ty::Adt(def, args) => { if self.def_id_is_local(def.def_id()) { ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } else if def.is_fundamental() { - args.visit_with(self) + match self.infcx.cx().as_adt_lang_item(def.def_id()) { + Some(SolverAdtLangItem::OwnedBox) => args.type_at(0).visit_with(self), + Some(..) | None => args.visit_with(self) + } } else { self.found_non_local_ty(ty) } diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 238eebd73a0fa..371604b88ef2b 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -1843,7 +1843,7 @@ pub(crate) struct AttributeOnEmptyType { } #[derive(Diagnostic)] -#[diag("patterns aren't allowed in methods without bodies", code = E0642)] +#[diag("patterns aren't allowed in {$target}", code = E0642)] pub(crate) struct PatternMethodParamWithoutBody { #[primary_span] #[suggestion( @@ -1853,6 +1853,7 @@ pub(crate) struct PatternMethodParamWithoutBody { style = "verbose" )] pub span: Span, + pub target: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 1c99c2c2dae1e..6176784b3bbe3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2385,12 +2385,22 @@ impl<'a> Parser<'a> { } #[cold] - pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box, Box)> { + pub(super) fn recover_arg_parse( + &mut self, + context: FnContext, + ) -> PResult<'a, (Box, Box)> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; - - self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span }); + self.dcx().emit_err(PatternMethodParamWithoutBody { + span: pat.span, + target: match context { + FnContext::Trait => "methods without bodies", + FnContext::FunctionPtrType => "function pointer types", + FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"), + FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"), + }, + }); // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID }); diff --git a/compiler/rustc_parse/src/parser/function.rs b/compiler/rustc_parse/src/parser/function.rs index c7eb84f553614..1523aba4be9ab 100644 --- a/compiler/rustc_parse/src/parser/function.rs +++ b/compiler/rustc_parse/src/parser/function.rs @@ -101,6 +101,8 @@ pub(crate) struct FnParseMode { pub(crate) enum FnContext { /// Free context. Free, + /// A Function Pointer Type `fn(..)`. + FunctionPtrType, /// A Trait context. Trait, /// An Impl block. @@ -818,7 +820,7 @@ impl<'a> Parser<'a> { // Recover from attempting to parse the argument as a type without pattern. err.cancel(); this.restore_snapshot(parser_snapshot_before_ty); - this.recover_arg_parse()? + this.recover_arg_parse(fn_parse_mode.context)? } Err(err) => return Err(err), } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b975e01796b89..98593c3c303c2 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -882,7 +882,7 @@ impl<'a> Parser<'a> { } let mode = crate::parser::FnParseMode { req_name: |_, _| false, - context: FnContext::Free, + context: FnContext::FunctionPtrType, req_body: false, }; let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?; diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index bbc7435a6c596..31104ce897ffb 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -261,6 +261,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::NumScalableVectors { } } +impl<'tcx> Stable<'tcx> for rustc_abi::BackendLaneCount { + type T = u64; + + fn stable<'cx>( + &self, + _tables: &mut Tables<'cx, BridgeTys>, + _cx: &CompilerCtxt<'cx, BridgeTys>, + ) -> Self::T { + self.as_u64() + } +} + impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { type T = ValueAbi; @@ -278,13 +290,14 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { b_offset: second_offset.stable(tables, cx), } } - rustc_abi::BackendRepr::SimdVector { element, count } => { - ValueAbi::Vector { element: element.stable(tables, cx), count } - } + rustc_abi::BackendRepr::SimdVector { element, count } => ValueAbi::Vector { + element: element.stable(tables, cx), + count: count.stable(tables, cx), + }, rustc_abi::BackendRepr::SimdScalableVector { element, count, number_of_vectors } => { ValueAbi::ScalableVector { element: element.stable(tables, cx), - count, + count: count.stable(tables, cx), number_of_vectors: number_of_vectors.stable(tables, cx), } } diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index f4c7e5519536b..8b383cc3cbc04 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -7,6 +7,7 @@ #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(nonzero_internals)] #![feature(sized_hierarchy)] // tidy-alphabetical-end diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 1cb09e8a1ee2e..4213d0a4650e9 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -5,7 +5,7 @@ use std::cell::{Cell, RefCell}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}; use std::hash::{BuildHasher, Hash}; use std::marker::{PhantomData, PointeeSized}; -use std::num::NonZero; +use std::num::{NonZero, ZeroablePrimitive}; use std::path; use std::rc::Rc; use std::sync::Arc; @@ -241,15 +241,15 @@ impl Decodable for ! { } } -impl Encodable for NonZero { +impl, S: Encoder> Encodable for NonZero { fn encode(&self, s: &mut S) { - s.emit_u32(self.get()); + self.get().encode(s) } } -impl Decodable for NonZero { +impl, D: Decoder> Decodable for NonZero { fn decode(d: &mut D) -> Self { - NonZero::new(d.read_u32()).unwrap() + NonZero::new(T::decode(d)).unwrap() } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 60f4ca6a8759c..32e7a9535a830 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2460,10 +2460,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; err.span_help(span, msg); } else { + // When more than 5 tuples implement the same trait, the output might be very verbose + // Instead of displaying each of these, we sort the candidates by arity in ascending + // order, then we compute the min and the max arity, ensuring that the arities are + // consecutive (by step of one). If these conditions are met, then the output is shown + // as a range of tuples [tuple_min_arity:tuple_max_arity] + let mut tuple_min_arity = usize::MAX; + let mut tuple_max_arity = 0_usize; + let mut last_arity = None; + let mut all_types_tuples_cont_arity = true; + candidates.sort_by(|(c1, _), (c2, _)| { + if let ty::Tuple(tys1) = c1.self_ty().kind() + && let ty::Tuple(tys2) = c2.self_ty().kind() + { + tys1.len().cmp(&tys2.len()) + } else { + std::cmp::Ordering::Equal + } + }); let candidate_names: Vec = candidates .iter() .map(|(c, _)| { if all_traits_equal { + if all_types_tuples_cont_arity + && let ty::Tuple(tys) = c.self_ty().kind() + && last_arity.map_or(1, |a: usize| a.abs_diff(tys.len())) == 1 + { + last_arity = Some(tys.len()); + if tys.len() > tuple_max_arity { + tuple_max_arity = tys.len(); + } + if tys.len() < tuple_min_arity { + tuple_min_arity = tys.len(); + } + } else { + all_types_tuples_cont_arity = false; + } format!( "\n {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()) @@ -2484,6 +2516,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } }) .collect(); + + let details = if all_traits_equal && all_types_tuples_cont_arity { + if tuple_min_arity == 0 { + format!("up to tuples of arity {tuple_max_arity}") + } else { + format!( + "for tuples of arity {tuple_min_arity} up to and including {tuple_max_arity}" + ) + } + } else { + String::new() + }; + let (candidate_names, end) = if all_traits_equal && all_types_tuples_cont_arity { + ( + vec![ + // (T₁, T₂, …, Tₙ) + format!("\n (T\u{2081}, T\u{2082}, …, T\u{2099}) {details}"), + ], + 1, + ) + } else { + (candidate_names, end) + }; let msg = if all_types_equal { format!( "`{}` implements trait `{}`", diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 350c2cb24876e..9e9aed008bf31 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -9,6 +9,7 @@ use rustc_abi::{ LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; +use rustc_data_structures::Limit; use rustc_hashes::Hash64; use rustc_hir as hir; use rustc_hir::find_attr; @@ -156,7 +157,7 @@ fn map_error<'tcx>( } LayoutCalculatorError::OversizedSimdType { max_lanes } => { // Can't be caught in typeck if the array length is generic. - LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) } + LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(Limit(max_lanes)) } } LayoutCalculatorError::NonPrimitiveSimdType(field) => { // This error isn't caught in typeck, e.g., if @@ -678,9 +679,7 @@ fn layout_of_uncached<'tcx>( return Err(map_error( &cx, ty, - rustc_abi::LayoutCalculatorError::OversizedSimdType { - max_lanes: limit.0 as u64, - }, + rustc_abi::LayoutCalculatorError::OversizedSimdType { max_lanes: limit.0 }, )); } } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index d426593c8d519..7188047140982 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -276,7 +276,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou // Currently, vectors must always be aligned to at least their elements: assert!(align >= element_align); // And the size has to be element * count plus alignment padding, of course - assert!(size == (element_size * count).align_to(align)); + assert!(size == (element_size * count.as_u64()).align_to(align)); } BackendRepr::Memory { .. } | BackendRepr::SimdScalableVector { .. } => {} // Nothing to check. } diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index 1671128e67a3a..0bc901e07ea96 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -21,6 +21,7 @@ pub enum SolverAdtLangItem { // tidy-alphabetical-start DynMetadata, Option, + OwnedBox, Poll, // tidy-alphabetical-end } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f2dd2444e2392..ffd02e2f4f6e5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -294,7 +294,11 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { // Previously, layout was calculated on the expression // `&*(ptr as *const RcInner)`, but this created a misaligned // reference (see #54908). - Layout::new::>().extend(layout).unwrap().0.pad_to_align() + Layout::new::>() + .extend(layout) + .unwrap_or_else(|_| panic!("capacity overflow")) + .0 + .pad_to_align() } /// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9c6b43ba6c8ee..4f86d6c596050 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -406,7 +406,11 @@ fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { // Previously, layout was calculated on the expression // `&*(ptr as *const ArcInner)`, but this created a misaligned // reference (see #54908). - Layout::new::>().extend(layout).unwrap().0.pad_to_align() + Layout::new::>() + .extend(layout) + .unwrap_or_else(|_| panic!("capacity overflow")) + .0 + .pad_to_align() } unsafe impl Send for ArcInner {} diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs index 0a7f9e82a9c4b..3cec3c962ab06 100644 --- a/library/alloctests/tests/arc.rs +++ b/library/alloctests/tests/arc.rs @@ -390,3 +390,9 @@ fn issue_155746_make_mut_panic_safety() { assert_eq!(*arc, [[1]]); assert_eq!(Arc::strong_count(&arc), 1); // if this is 0, we have a UAF! } + +#[test] +#[should_panic = "capacity overflow"] +fn new_uninit_slice_capacity_overflow() { + let _ = Arc::<[u8]>::new_uninit_slice(isize::MAX as usize); +} diff --git a/library/alloctests/tests/rc.rs b/library/alloctests/tests/rc.rs index 698585e94f8a6..0009d6fbc7058 100644 --- a/library/alloctests/tests/rc.rs +++ b/library/alloctests/tests/rc.rs @@ -967,3 +967,11 @@ fn issue_158875_make_mut_dont_leak_allocator() { assert_eq!(Rc::strong_count(&alloc), 1); // if this is >1, we have a memory leak! } + +#[test] +#[should_panic = "capacity overflow"] +fn new_uninit_slice_capacity_overflow() { + // header + payload layout exceeds isize::MAX -> "capacity overflow", not + // an unwrapped LayoutError. Regression test for #136797. + let _ = Rc::<[u8]>::new_uninit_slice(isize::MAX as usize); +} diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 9a5768317d45c..b30c449104ad5 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -581,3 +581,55 @@ mod proc_macro_attribute {} /// /// [the `link_section` attribute]: ../reference/abi.html#the-link_section-attribute mod link_section_attribute {} + +#[doc(attribute = "non_exhaustive")] +// +/// Indicates that a type might have more fields or variants added in the future. +/// +/// Placing `#[non_exhaustive]` on a struct or enum tells code in other crates not to assume +/// the definition is complete. This lets a library add new fields or variants without breaking +/// existing code. +/// +/// On an enum, code outside the defining crate must include a wildcard arm when matching: +/// +/// ```rust,ignore (cross-crate effect only) +/// // in crate `errors`: +/// #[non_exhaustive] +/// pub enum ConnectionError { +/// Refused, +/// Timeout, +/// } +/// +/// // in another crate: +/// use errors::ConnectionError; +/// +/// match error { +/// ConnectionError::Refused => println!("connection refused"), +/// ConnectionError::Timeout => println!("timed out"), +/// _ => println!("other error"), // required because of #[non_exhaustive] +/// } +/// ``` +/// +/// On a struct, code outside the defining crate cannot construct instances using struct literal +/// syntax: +/// +/// ```rust,ignore (cross-crate effect only) +/// // in crate `config`: +/// #[non_exhaustive] +/// pub struct Config { +/// pub width: u32, +/// pub height: u32, +/// } +/// +/// // in another crate: +/// use config::Config; +/// +/// let c = Config { width: 800, height: 600 }; // ERROR: cannot construct +/// ``` +/// +/// Inside the defining crate, exhaustive matching and direct construction are still allowed. +/// +/// For more information, see the Reference on [the `non_exhaustive` attribute]. +/// +/// [the `non_exhaustive` attribute]: ../reference/attributes/type_system.html#the-non_exhaustive-attribute +mod non_exhaustive_attribute {} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7210d850c864a..87963bcce8ebb 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -95,7 +95,7 @@ pub enum AtomicOrdering { /// For example, [`AtomicBool::compare_exchange`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_cxchg< +pub const unsafe fn atomic_cxchg< T: Copy, const ORD_SUCC: AtomicOrdering, const ORD_FAIL: AtomicOrdering, @@ -113,7 +113,7 @@ pub unsafe fn atomic_cxchg< /// For example, [`AtomicBool::compare_exchange_weak`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_cxchgweak< +pub const unsafe fn atomic_cxchgweak< T: Copy, const ORD_SUCC: AtomicOrdering, const ORD_FAIL: AtomicOrdering, @@ -130,7 +130,7 @@ pub unsafe fn atomic_cxchgweak< /// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_load(src: *const T) -> T; +pub const unsafe fn atomic_load(src: *const T) -> T; /// Stores the value at the specified memory location. /// `T` must be an integer or pointer type. @@ -139,7 +139,7 @@ pub unsafe fn atomic_load(src: *const T) -> /// [`atomic`] types via the `store` method. For example, [`AtomicBool::store`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_store(dst: *mut T, val: T); +pub const unsafe fn atomic_store(dst: *mut T, val: T); /// Stores the value at the specified memory location, returning the old value. /// `T` must be an integer or pointer type. @@ -148,7 +148,7 @@ pub unsafe fn atomic_store(dst: *mut T, val: /// [`atomic`] types via the `swap` method. For example, [`AtomicBool::swap`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xchg(dst: *mut T, src: T) -> T; +pub const unsafe fn atomic_xchg(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -158,7 +158,10 @@ pub unsafe fn atomic_xchg(dst: *mut T, src: /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xadd(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_xadd( + dst: *mut T, + src: U, +) -> T; /// Subtract from the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -168,7 +171,10 @@ pub unsafe fn atomic_xadd(dst: *mut /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xsub(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_xsub( + dst: *mut T, + src: U, +) -> T; /// Bitwise and with the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -178,7 +184,10 @@ pub unsafe fn atomic_xsub(dst: *mut /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_and(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_and( + dst: *mut T, + src: U, +) -> T; /// Bitwise nand with the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -188,7 +197,10 @@ pub unsafe fn atomic_and(dst: *mut /// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_nand(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_nand( + dst: *mut T, + src: U, +) -> T; /// Bitwise or with the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -198,7 +210,10 @@ pub unsafe fn atomic_nand(dst: *mut /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_or(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_or( + dst: *mut T, + src: U, +) -> T; /// Bitwise xor with the current value, returning the previous value. /// `T` must be an integer or pointer type. @@ -208,7 +223,10 @@ pub unsafe fn atomic_or(dst: *mut T /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_xor(dst: *mut T, src: U) -> T; +pub const unsafe fn atomic_xor( + dst: *mut T, + src: U, +) -> T; /// Maximum with the current value using a signed comparison. /// `T` must be a signed integer type. @@ -217,7 +235,7 @@ pub unsafe fn atomic_xor(dst: *mut /// [`atomic`] signed integer types via the `fetch_max` method. For example, [`AtomicI32::fetch_max`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_max(dst: *mut T, src: T) -> T; +pub const unsafe fn atomic_max(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// `T` must be a signed integer type. @@ -226,7 +244,7 @@ pub unsafe fn atomic_max(dst: *mut T, src: T /// [`atomic`] signed integer types via the `fetch_min` method. For example, [`AtomicI32::fetch_min`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_min(dst: *mut T, src: T) -> T; +pub const unsafe fn atomic_min(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. @@ -235,7 +253,7 @@ pub unsafe fn atomic_min(dst: *mut T, src: T /// [`atomic`] unsigned integer types via the `fetch_min` method. For example, [`AtomicU32::fetch_min`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_umin(dst: *mut T, src: T) -> T; +pub const unsafe fn atomic_umin(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. @@ -244,7 +262,7 @@ pub unsafe fn atomic_umin(dst: *mut T, src: /// [`atomic`] unsigned integer types via the `fetch_max` method. For example, [`AtomicU32::fetch_max`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_umax(dst: *mut T, src: T) -> T; +pub const unsafe fn atomic_umax(dst: *mut T, src: T) -> T; /// An atomic fence. /// @@ -252,7 +270,7 @@ pub unsafe fn atomic_umax(dst: *mut T, src: /// [`atomic::fence`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_fence(); +pub const unsafe fn atomic_fence(); /// An atomic fence for synchronization within a single thread. /// @@ -260,7 +278,7 @@ pub unsafe fn atomic_fence(); /// [`atomic::compiler_fence`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn atomic_singlethreadfence(); +pub const unsafe fn atomic_singlethreadfence(); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// for the given address if supported; otherwise, it is a no-op. diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index c6fbe52ee887b..78222a638c60c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -146,7 +146,7 @@ mod prim_bool {} /// /// ```ignore (hypothetical-example) /// loop { -/// let (client, request) = get_request().expect("disconnected"); +/// let (client, request) = get_request().expect("server should stay connected"); /// let response = request.process(); /// response.send(client); /// } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 867b4d1a8eb88..b257cd8c82a0e 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -114,14 +114,15 @@ //! //! You might instead, if you don't want to handle the error, simply //! assert success with [`expect`]. This will panic if the -//! write fails, providing a marginally useful message indicating why: +//! write fails, providing a message explaining why the write was expected +//! to succeed: //! //! ```no_run //! use std::fs::File; //! use std::io::prelude::*; //! //! let mut file = File::create("valuable_data.txt").unwrap(); -//! file.write_all(b"important message").expect("failed to write message"); +//! file.write_all(b"important message").expect("writing to the file should succeed"); //! ``` //! //! You might also simply assert success: @@ -978,7 +979,7 @@ impl Result { /// .parse::() /// .inspect(|x| println!("original: {x}")) /// .map(|x| x.pow(3)) - /// .expect("failed to parse number"); + /// .expect("literal `4` should parse as a `u8`"); /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1a767d8092bda..71502f8d918e7 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -622,7 +622,8 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - pub fn get_mut(&mut self) -> &mut bool { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut(&mut self) -> &mut bool { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.as_ptr() } } @@ -642,7 +643,8 @@ impl AtomicBool { #[inline] #[cfg(target_has_atomic_primitive_alignment = "8")] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut(v: &mut bool) -> &mut Self { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut(v: &mut bool) -> &mut Self { // SAFETY: the mutable reference guarantees unique ownership, and // alignment of both `bool` and `Self` is 1. unsafe { &mut *(v as *mut bool as *mut Self) } @@ -676,7 +678,8 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn get_mut_slice(this: &mut [Self]) -> &mut [bool] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool] { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *(this as *mut [Self] as *mut [bool]) } } @@ -700,7 +703,8 @@ impl AtomicBool { #[inline] #[cfg(target_has_atomic_primitive_alignment = "8")] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut_slice(v: &mut [bool]) -> &mut [Self] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self] { // SAFETY: the mutable reference guarantees unique ownership, and // alignment of both `bool` and `Self` is 1. unsafe { &mut *(v as *mut [bool] as *mut [Self]) } @@ -750,8 +754,9 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn load(&self, order: Ordering) -> bool { + pub const fn load(&self, order: Ordering) -> bool { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get().cast::(), order) != 0 } @@ -778,9 +783,10 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn store(&self, val: bool, order: Ordering) { + pub const fn store(&self, val: bool, order: Ordering) { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { @@ -810,10 +816,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn swap(&self, val: bool, order: Ordering) -> bool { + pub const fn swap(&self, val: bool, order: Ordering) -> bool { if EMULATE_ATOMIC_BOOL { if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) } } else { @@ -874,6 +881,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[deprecated( since = "1.50.0", note = "Use `compare_exchange` or `compare_exchange_weak` instead" @@ -881,7 +889,7 @@ impl AtomicBool { #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { + pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, Err(x) => x, @@ -939,11 +947,12 @@ impl AtomicBool { /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_exchange( + pub const fn compare_exchange( &self, current: bool, new: bool, @@ -1041,11 +1050,12 @@ impl AtomicBool { /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_exchange_weak( + pub const fn compare_exchange_weak( &self, current: bool, new: bool, @@ -1105,10 +1115,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { + pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.v.get().cast::(), val as u8, order) != 0 } } @@ -1148,10 +1159,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { + pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done // with an 8-bit integer internally, which would set the upper 7 bits. @@ -1201,10 +1213,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { + pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.v.get().cast::(), val as u8, order) != 0 } } @@ -1243,10 +1256,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { + pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.v.get().cast::(), val as u8, order) != 0 } } @@ -1281,10 +1295,11 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_not(&self, order: Ordering) -> bool { + pub const fn fetch_not(&self, order: Ordering) -> bool { self.fetch_xor(true, order) } @@ -1585,7 +1600,8 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - pub fn get_mut(&mut self) -> &mut *mut T { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut(&mut self) -> &mut *mut T { // SAFETY: // `Atomic` is essentially a transparent wrapper around `T`. unsafe { &mut *self.as_ptr() } @@ -1610,7 +1626,8 @@ impl AtomicPtr { #[inline] #[cfg(target_has_atomic_primitive_alignment = "ptr")] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut(v: &mut *mut T) -> &mut Self { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut(v: &mut *mut T) -> &mut Self { let [] = [(); align_of::>() - align_of::<*mut ()>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -1653,7 +1670,8 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *(this as *mut [Self] as *mut [*mut T]) } } @@ -1687,7 +1705,8 @@ impl AtomicPtr { #[inline] #[cfg(target_has_atomic_primitive_alignment = "ptr")] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] { // SAFETY: // - the mutable reference guarantees unique ownership. // - the alignment of `*mut T` and `Self` is the same on all platforms @@ -1739,8 +1758,9 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn load(&self, order: Ordering) -> *mut T { + pub const fn load(&self, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_load(self.as_ptr(), order) } } @@ -1768,9 +1788,10 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn store(&self, ptr: *mut T, order: Ordering) { + pub const fn store(&self, ptr: *mut T, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.as_ptr(), ptr, order); @@ -1801,10 +1822,11 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { + pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.as_ptr(), ptr, order) } } @@ -2724,7 +2746,8 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable_access] - pub fn get_mut(&mut self) -> &mut $int_type { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut(&mut self) -> &mut $int_type { // SAFETY: // `Atomic` is essentially a transparent wrapper around `T`. unsafe { &mut *self.as_ptr() } @@ -2755,7 +2778,8 @@ macro_rules! atomic_int { #[inline] #[cfg(any($cfg_align, doc))] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut(v: &mut $int_type) -> &mut Self { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut(v: &mut $int_type) -> &mut Self { let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -2795,7 +2819,8 @@ macro_rules! atomic_int { /// ``` #[inline] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *(this as *mut [Self] as *mut [$int_type]) } } @@ -2830,7 +2855,8 @@ macro_rules! atomic_int { #[inline] #[cfg(any($cfg_align, doc))] #[stable(feature = "atomic_from_mut", since = "1.98.0")] - pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] { + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] + pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] { let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -2883,8 +2909,9 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub fn load(&self, order: Ordering) -> $int_type { + pub const fn load(&self, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_load(self.as_ptr(), order) } } @@ -2911,9 +2938,10 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn store(&self, val: $int_type, order: Ordering) { + pub const fn store(&self, val: $int_type, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.as_ptr(), val, order); } } @@ -2940,10 +2968,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.as_ptr(), val, order) } } @@ -3002,6 +3031,7 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[deprecated( since = "1.50.0", note = "Use `compare_exchange` or `compare_exchange_weak` instead") @@ -3009,7 +3039,7 @@ macro_rules! atomic_int { #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_and_swap(&self, + pub const fn compare_and_swap(&self, current: $int_type, new: $int_type, order: Ordering) -> $int_type { @@ -3076,10 +3106,11 @@ macro_rules! atomic_int { /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap #[inline] #[$stable_cxchg] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_exchange(&self, + pub const fn compare_exchange(&self, current: $int_type, new: $int_type, success: Ordering, @@ -3141,10 +3172,11 @@ macro_rules! atomic_int { /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap #[inline] #[$stable_cxchg] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn compare_exchange_weak(&self, + pub const fn compare_exchange_weak(&self, current: $int_type, new: $int_type, success: Ordering, @@ -3179,10 +3211,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_add(self.as_ptr(), val, order) } } @@ -3211,10 +3244,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_sub(self.as_ptr(), val, order) } } @@ -3246,10 +3280,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.as_ptr(), val, order) } } @@ -3281,10 +3316,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable_nand] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_nand(self.as_ptr(), val, order) } } @@ -3316,10 +3352,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.as_ptr(), val, order) } } @@ -3351,10 +3388,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.as_ptr(), val, order) } } @@ -3554,10 +3592,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { $max_fn(self.as_ptr(), val, order) } } @@ -3603,10 +3642,11 @@ macro_rules! atomic_int { /// ``` #[inline] #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[cfg(any($cfg_cas, doc))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] - pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { $min_fn(self.as_ptr(), val, order) } } @@ -3918,7 +3958,7 @@ atomic_int_ptr_sized! { #[inline] #[cfg(target_has_atomic)] -fn strongest_failure_ordering(order: Ordering) -> Ordering { +const fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, Relaxed => Relaxed, @@ -3930,7 +3970,8 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { // SAFETY: the caller must uphold the safety contract for `atomic_store`. unsafe { match order { @@ -3945,7 +3986,8 @@ unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_load`. unsafe { match order { @@ -3961,7 +4003,8 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_swap`. unsafe { match order { @@ -3978,7 +4021,8 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_add(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_add(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_add`. unsafe { match order { @@ -3995,7 +4039,8 @@ unsafe fn atomic_add(dst: *mut T, val: U, order: Ordering) -> #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_sub(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_sub(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_sub`. unsafe { match order { @@ -4014,7 +4059,8 @@ unsafe fn atomic_sub(dst: *mut T, val: U, order: Ordering) -> #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[unstable(feature = "core_intrinsics", issue = "none")] #[doc(hidden)] -pub unsafe fn atomic_compare_exchange( +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +pub const unsafe fn atomic_compare_exchange( dst: *mut T, old: T, new: T, @@ -4079,7 +4125,8 @@ pub unsafe fn atomic_compare_exchange( #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_compare_exchange_weak( +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_compare_exchange_weak( dst: *mut T, old: T, new: T, @@ -4144,7 +4191,8 @@ unsafe fn atomic_compare_exchange_weak( #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_and(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_and(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_and` unsafe { match order { @@ -4160,7 +4208,8 @@ unsafe fn atomic_and(dst: *mut T, val: U, order: Ordering) -> #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_nand(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_nand(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_nand` unsafe { match order { @@ -4176,7 +4225,8 @@ unsafe fn atomic_nand(dst: *mut T, val: U, order: Ordering) -> #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_or(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_or(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_or` unsafe { match order { @@ -4192,7 +4242,8 @@ unsafe fn atomic_or(dst: *mut T, val: U, order: Ordering) -> T #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_xor(dst: *mut T, val: U, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_xor(dst: *mut T, val: U, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_xor` unsafe { match order { @@ -4209,7 +4260,8 @@ unsafe fn atomic_xor(dst: *mut T, val: U, order: Ordering) -> #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_max` unsafe { match order { @@ -4226,7 +4278,8 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_min` unsafe { match order { @@ -4243,7 +4296,8 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_umax` unsafe { match order { @@ -4260,7 +4314,8 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] +const unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_umin` unsafe { match order { @@ -4427,10 +4482,11 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[rustc_diagnostic_item = "fence"] #[doc(alias = "atomic_thread_fence")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn fence(order: Ordering) { +pub const fn fence(order: Ordering) { // SAFETY: using an atomic fence is safe. unsafe { match order { @@ -4511,10 +4567,11 @@ pub fn fence(order: Ordering) { /// ``` #[inline] #[stable(feature = "compiler_fences", since = "1.21.0")] +#[rustc_const_unstable(feature = "const_atomic", issue = "160078")] #[rustc_diagnostic_item = "compiler_fence"] #[doc(alias = "atomic_signal_fence")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub fn compiler_fence(order: Ordering) { +pub const fn compiler_fence(order: Ordering) { // SAFETY: using an atomic fence is safe. unsafe { match order { diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 084a8ea8ffcff..1fcc29bf92d93 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,7 @@ askama = { version = "0.16.0", default-features = false, features = ["alloc", "c base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.15" -minifier = { version = "0.3.5", default-features = false } +minifier = { version = "0.4.0", default-features = false } proc-macro2 = "1.0.103" pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] } regex = "1" @@ -37,7 +37,7 @@ features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] [build-dependencies] sha2 = "0.10.8" -minifier = { version = "0.3.2", default-features = false } +minifier = { version = "0.4.0", default-features = false } [dev-dependencies] expect-test = "1.4.0" diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs index 3b887f7d022ec..2a93a2cc28c2e 100644 --- a/src/librustdoc/build.rs +++ b/src/librustdoc/build.rs @@ -57,7 +57,7 @@ fn main() { let minified: String = if path.ends_with(".css") { minifier::css::minify(str::from_utf8(&data_bytes).unwrap()).unwrap().to_string() } else { - minifier::js::minify(str::from_utf8(&data_bytes).unwrap()).to_string() + minifier::js::minify(str::from_utf8(&data_bytes).unwrap()).unwrap().to_string() }; std::fs::write(&minified_path, minified.as_bytes()).expect("write to out_dir"); } else { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index ce191aaf445d5..c4984d527a863 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1174,8 +1174,6 @@ impl LinkCollector<'_, '_> { } /// This is the entry point for resolving an intra-doc link. - /// - /// FIXME(jynelson): this is way too many arguments fn resolve_link( &mut self, dox: &str, diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index f3952b2687a56..c2dd6e681b002 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -78,7 +78,7 @@ fn check_raw_ptr<'tcx>( fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option { if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_, _))) = ( &arg.pat.kind, - cx.maybe_typeck_results() + cx.typeck_results .map(|typeck_results| typeck_results.pat_ty(arg.pat).kind()), ) { Some(id) diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index bf2c7a007644c..03a48bc08612a 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -303,7 +303,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { Self { cx, - maybe_typeck_results: cx.maybe_typeck_results(), + maybe_typeck_results: cx.typeck_results, target, suggestions: BTreeMap::new(), } diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 039da4cc4757a..d8bff9e9f1703 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -174,7 +174,7 @@ impl PassByRefOrValue { && size <= self.ref_min_size && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind { - if let Some(typeck) = cx.maybe_typeck_results() + if let Some(typeck) = cx.typeck_results // Don't lint if a raw pointer is created. // TODO: Limit the check only to raw pointers to the argument (or part of the argument) // which escape the current function. diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7c3fa51228bc9..e9695668d75c1 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { pub fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, - maybe_typeck_results: cx.maybe_typeck_results().map(|x| (x, x)), + maybe_typeck_results: cx.typeck_results.map(|x| (x, x)), allow_side_effects: true, expr_fallback: None, path_check: PathCheck::default(), @@ -1140,7 +1140,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, - maybe_typeck_results: cx.maybe_typeck_results(), + maybe_typeck_results: cx.typeck_results, s: FxHasher::default(), path_check: PathCheck::default(), } diff --git a/src/tools/clippy/clippy_utils/src/res.rs b/src/tools/clippy/clippy_utils/src/res.rs index 23afb25f1bbfe..59571a929887a 100644 --- a/src/tools/clippy/clippy_utils/src/res.rs +++ b/src/tools/clippy/clippy_utils/src/res.rs @@ -72,7 +72,7 @@ impl<'tcx> MaybeTypeckRes<'tcx> for LateContext<'tcx> { #[inline] #[cfg_attr(debug_assertions, track_caller)] fn typeck_res(&self) -> Option<&TypeckResults<'tcx>> { - if let Some(typeck) = self.maybe_typeck_results() { + if let Some(typeck) = self.typeck_results { Some(typeck) } else { // It's possible to get the `TypeckResults` for any other body, but diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index ac3c76df6086f..a62a1a594ea78 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -41,7 +41,7 @@ pub use type_certainty::expr_type_is_certain; /// Lower a [`hir::Ty`] to a [`rustc_middle::ty::Ty`]. pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - cx.maybe_typeck_results() + cx.typeck_results .filter(|results| results.hir_owner == hir_ty.hir_id.owner) .and_then(|results| results.node_type_opt(hir_ty.hir_id)) .unwrap_or_else(|| lower_ty(cx.tcx, hir_ty)) @@ -532,7 +532,7 @@ fn is_uninit_value_valid_for_layout<'tcx>(cx: &LateContext<'tcx>, layout: TyAndL match layout.layout.backend_repr { BackendRepr::Scalar(s) => s.is_uninit_valid(), BackendRepr::ScalarPair { a, b, .. } => a.is_uninit_valid() && b.is_uninit_valid(), - BackendRepr::SimdVector { element, count } => count == 0 || element.is_uninit_valid(), + BackendRepr::SimdVector { element, count: _ } => element.is_uninit_valid(), BackendRepr::SimdScalableVector { element, .. } => element.is_uninit_valid(), // Here validity is determined by the structural fields instead. BackendRepr::Memory { .. } => match &layout.layout.variants { diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 1cdfb1d21b8cb..b3192174a07fb 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -51,14 +51,13 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::{Idx, IndexVec}; use rustc_log::tracing; use rustc_middle::mir; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{AtomicOrdering, Ty}; use rustc_span::Span; use super::vector_clock::{VClock, VTimestamp, VectorIdx}; use super::weak_memory::EvalContextExt as _; use crate::concurrency::GlobalDataRaceHandler; use crate::diagnostics::RacingOp; -use crate::intrinsics::AtomicRmwOp; use crate::*; pub type AllocState = VClockAlloc; @@ -73,6 +72,19 @@ pub enum AtomicRwOrd { SeqCst, } +impl AtomicRwOrd { + pub fn from(ordering: AtomicOrdering) -> Self { + use AtomicRwOrd::*; + match ordering { + AtomicOrdering::Relaxed => Relaxed, + AtomicOrdering::Release => Release, + AtomicOrdering::Acquire => Acquire, + AtomicOrdering::AcqRel => AcqRel, + AtomicOrdering::SeqCst => SeqCst, + } + } +} + /// Valid atomic read orderings, subset of atomic::Ordering. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum AtomicReadOrd { @@ -81,6 +93,18 @@ pub enum AtomicReadOrd { SeqCst, } +impl AtomicReadOrd { + pub fn from(ordering: AtomicOrdering) -> Self { + use AtomicReadOrd::*; + match ordering { + AtomicOrdering::Relaxed => Relaxed, + AtomicOrdering::Acquire => Acquire, + AtomicOrdering::SeqCst => SeqCst, + _ => panic!("invalid atomic read ordering: {ordering:?}"), + } + } +} + /// Valid atomic write orderings, subset of atomic::Ordering. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum AtomicWriteOrd { @@ -89,6 +113,18 @@ pub enum AtomicWriteOrd { SeqCst, } +impl AtomicWriteOrd { + pub fn from(ordering: AtomicOrdering) -> Self { + use AtomicWriteOrd::*; + match ordering { + AtomicOrdering::Relaxed => Relaxed, + AtomicOrdering::Release => Release, + AtomicOrdering::SeqCst => SeqCst, + _ => panic!("invalid atomic write ordering: {ordering:?}"), + } + } +} + /// Valid atomic fence orderings, subset of atomic::Ordering. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum AtomicFenceOrd { @@ -98,6 +134,19 @@ pub enum AtomicFenceOrd { SeqCst, } +impl AtomicFenceOrd { + pub fn from(ordering: AtomicOrdering) -> Self { + use AtomicFenceOrd::*; + match ordering { + AtomicOrdering::Acquire => Acquire, + AtomicOrdering::Release => Release, + AtomicOrdering::SeqCst => SeqCst, + AtomicOrdering::AcqRel => AcqRel, + _ => panic!("invalid atomic fence ordering: {ordering:?}"), + } + } +} + /// The current set of vector clocks describing the state /// of a thread, contains the happens-before clock and /// additional metadata to model atomic fence operations. @@ -789,13 +838,13 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { } /// Perform an atomic RMW operation on a memory location. - fn atomic_rmw_op_immediate( + fn atomic_rmw( &mut self, place: &MPlaceTy<'tcx>, rhs: &ImmTy<'tcx>, atomic_op: AtomicRmwOp, ord: AtomicRwOrd, - ) -> InterpResult<'tcx, ImmTy<'tcx>> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.atomic_access_check(place, AtomicAccessType::Rmw)?; @@ -803,7 +852,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // Inform GenMC about the atomic rmw operation. if let Some(genmc_ctx) = this.machine.data_race.as_genmc_ref() { - let (old_val, new_val) = genmc_ctx.atomic_rmw_op( + let (old_val, new_val) = genmc_ctx.atomic_rmw( this, place.ptr().addr(), place.layout.size, @@ -816,69 +865,17 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { if let Some(new_val) = new_val { this.allow_data_races_mut(|this| this.write_scalar(new_val, place))?; } - return interp_ok(ImmTy::from_scalar(old_val, old.layout)); + return interp_ok(old_val); } trace!("atomic_rmw({:?}, {} bytes)", place.ptr(), place.layout.size.bytes()); - let val = match atomic_op { - AtomicRmwOp::MirOp { op, neg } => { - let val = this.binary_op(op, &old, rhs)?; - if neg { this.unary_op(mir::UnOp::Not, &val)? } else { val } - } - AtomicRmwOp::Max => { - let lt = this.binary_op(mir::BinOp::Lt, &old, rhs)?.to_scalar().to_bool()?; - if lt { rhs } else { &old }.clone() - } - AtomicRmwOp::Min => { - let lt = this.binary_op(mir::BinOp::Lt, &old, rhs)?.to_scalar().to_bool()?; - if lt { &old } else { rhs }.clone() - } - }; + let val = this.atomic_rmw_op(atomic_op, &old, rhs)?; this.allow_data_races_mut(|this| this.write_immediate(*val, place))?; this.validate_atomic_rmw(place, ord)?; this.buffered_atomic_rmw(val.to_scalar(), place, ord, old.to_scalar())?; - interp_ok(old) - } - - /// Perform an atomic exchange with a memory place and a new - /// scalar value, the old value is returned. - fn atomic_exchange_scalar( - &mut self, - place: &MPlaceTy<'tcx>, - new: Scalar, - atomic: AtomicRwOrd, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - this.atomic_access_check(place, AtomicAccessType::Rmw)?; - - let old = this.allow_data_races_mut(|this| this.read_scalar(place))?; - - // Inform GenMC about the atomic atomic exchange. - if let Some(genmc_ctx) = this.machine.data_race.as_genmc_ref() { - let (old_val, new_val) = genmc_ctx.atomic_exchange( - this, - place.ptr().addr(), - place.layout.size, - new, - atomic, - old, - )?; - // The store might be the latest store in coherence order (determined by GenMC). - // If it is, we need to update the value in Miri's memory: - if let Some(new_val) = new_val { - this.allow_data_races_mut(|this| this.write_scalar(new_val, place))?; - } - return interp_ok(old_val); - } - - trace!("atomic_exchange_scalar({:?}, {} bytes)", place.ptr(), place.layout.size.bytes()); - - this.allow_data_races_mut(|this| this.write_scalar(new, place))?; - this.validate_atomic_rmw(place, atomic)?; - this.buffered_atomic_rmw(new, place, atomic, old)?; - interp_ok(old) + interp_ok(old.to_scalar()) } /// Perform an atomic compare and exchange at a given memory location. @@ -887,7 +884,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { /// then we treat it as a "compare_exchange_weak" operation, and /// some portion of the time fail even when the values are actually /// identical. - fn atomic_compare_exchange_scalar( + fn atomic_compare_exchange( &mut self, place: &MPlaceTy<'tcx>, expect_old: &ImmTy<'tcx>, @@ -895,7 +892,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { success: AtomicRwOrd, fail: AtomicReadOrd, can_fail_spuriously: bool, - ) -> InterpResult<'tcx, Immediate> { + ) -> InterpResult<'tcx, (Scalar, bool)> { let this = self.eval_context_mut(); this.atomic_access_check(place, AtomicAccessType::Rmw)?; @@ -920,7 +917,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { if let Some(new_value) = new_value { this.allow_data_races_mut(|this| this.write_scalar(new_value, place))?; } - return interp_ok(Immediate::ScalarPair(old_value, Scalar::from_bool(cmpxchg_success))); + return interp_ok((old_value, cmpxchg_success)); } // `binary_op` will bail if either of them is not a scalar. @@ -934,7 +931,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { } else { true }; - let res = Immediate::ScalarPair(old.to_scalar(), Scalar::from_bool(cmpxchg_success)); + let res = (old.to_scalar(), cmpxchg_success); trace!( "atomic_compare_exchange_scalar({:?}, {} bytes, success = {})", @@ -964,10 +961,10 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { } /// Update the data-race detector for an atomic fence on the current thread. - fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); + fn atomic_fence(&self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); let machine = &this.machine; - match &this.machine.data_race { + match &machine.data_race { GlobalDataRaceHandler::None => interp_ok(()), GlobalDataRaceHandler::Vclocks(data_race) => data_race.atomic_fence(machine, atomic), GlobalDataRaceHandler::Genmc(genmc_ctx) => genmc_ctx.atomic_fence(machine, atomic), diff --git a/src/tools/miri/src/concurrency/genmc/dummy.rs b/src/tools/miri/src/concurrency/genmc/dummy.rs index d643bda28c34e..0ab369f25770a 100644 --- a/src/tools/miri/src/concurrency/genmc/dummy.rs +++ b/src/tools/miri/src/concurrency/genmc/dummy.rs @@ -3,10 +3,9 @@ use rustc_const_eval::interpret::{AllocId, InterpCx, InterpResult}; pub use self::intercept::EvalContextExt as GenmcEvalContextExt; pub use self::run::run_genmc_mode; -use crate::intrinsics::AtomicRmwOp; use crate::{ - AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, MemoryKind, MiriMachine, OpTy, - Scalar, ThreadId, ThreadManager, VisitProvenance, VisitWith, + AtomicFenceOrd, AtomicReadOrd, AtomicRmwOp, AtomicRwOrd, AtomicWriteOrd, MemoryKind, + MiriMachine, OpTy, Scalar, ThreadId, ThreadManager, VisitProvenance, VisitWith, }; #[derive(Clone, Copy, Debug)] @@ -106,7 +105,7 @@ impl GenmcCtx { unreachable!() } - pub(crate) fn atomic_rmw_op<'tcx>( + pub(crate) fn atomic_rmw<'tcx>( &self, _ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, _address: Size, @@ -120,18 +119,6 @@ impl GenmcCtx { unreachable!() } - pub(crate) fn atomic_exchange<'tcx>( - &self, - _ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, - _address: Size, - _size: Size, - _rhs_scalar: Scalar, - _ordering: AtomicRwOrd, - _old_value: Scalar, - ) -> InterpResult<'tcx, (Scalar, Option)> { - unreachable!() - } - pub(crate) fn atomic_compare_exchange<'tcx>( &self, _ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, diff --git a/src/tools/miri/src/concurrency/genmc/helper.rs b/src/tools/miri/src/concurrency/genmc/helper.rs index e20f001185198..1870a8e4e2f3a 100644 --- a/src/tools/miri/src/concurrency/genmc/helper.rs +++ b/src/tools/miri/src/concurrency/genmc/helper.rs @@ -7,7 +7,6 @@ use rustc_middle::{mir, throw_ub_format}; use super::GenmcScalar; use crate::alloc_addresses::EvalContextExt as _; -use crate::intrinsics::AtomicRmwOp; use crate::*; /// Maximum size memory access in bytes that GenMC supports. @@ -177,6 +176,7 @@ pub(super) fn to_genmc_rmw_op(atomic_op: AtomicRmwOp, is_signed: bool) -> RMWBin (AtomicRmwOp::Max, true) => RMWBinOp::Max, (AtomicRmwOp::Min, false) => RMWBinOp::UMin, (AtomicRmwOp::Max, false) => RMWBinOp::UMax, + (AtomicRmwOp::Swap, _is_signed) => RMWBinOp::Xchg, (AtomicRmwOp::MirOp { op, neg }, _is_signed) => match (op, neg) { (mir::BinOp::Add, false) => RMWBinOp::Add, diff --git a/src/tools/miri/src/concurrency/genmc/mod.rs b/src/tools/miri/src/concurrency/genmc/mod.rs index e3a76363df7e8..dfd7d4b52678d 100644 --- a/src/tools/miri/src/concurrency/genmc/mod.rs +++ b/src/tools/miri/src/concurrency/genmc/mod.rs @@ -20,7 +20,6 @@ use self::helper::{ use self::run::GenmcMode; use self::thread_id_map::ThreadIdMap; use crate::diagnostics::SpanDedupDiagnostic; -use crate::intrinsics::AtomicRmwOp; use crate::*; mod config; @@ -325,7 +324,7 @@ impl GenmcCtx { /// Returns `(old_val, Option)`. `new_val` might not be the latest write in coherence order, which is indicated by `None`. /// /// `old_value` is the value that a non-atomic load would read here, or `None` if the memory is uninitialized. - pub(crate) fn atomic_rmw_op<'tcx>( + pub(crate) fn atomic_rmw<'tcx>( &self, ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, address: Size, @@ -347,29 +346,6 @@ impl GenmcCtx { ) } - /// Returns `(old_val, Option)`. `new_val` might not be the latest write in coherence order, which is indicated by `None`. - /// - /// `old_value` is the value that a non-atomic load would read here, or `None` if the memory is uninitialized. - pub(crate) fn atomic_exchange<'tcx>( - &self, - ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, - address: Size, - size: Size, - rhs_scalar: Scalar, - ordering: AtomicRwOrd, - old_value: Scalar, - ) -> InterpResult<'tcx, (Scalar, Option)> { - self.handle_atomic_rmw_op( - ecx, - address, - size, - ordering, - /* genmc_rmw_op */ RMWBinOp::Xchg, - scalar_to_genmc_scalar(ecx, self, rhs_scalar)?, - scalar_to_genmc_scalar(ecx, self, old_value)?, - ) - } - /// Inform GenMC about an atomic compare-exchange operation. /// /// Returns the old value read by the compare exchange, optionally the value that Miri should write back to its memory, and whether the compare-exchange was a success or not. diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index de2e0d8e23924..dda3306d0208d 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -353,17 +353,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // There's no sync object there yet. Create one, and try a CAS for uninit_val to init_val. let meta_obj = new_meta_obj(this)?; - let (old_init, success) = this - .atomic_compare_exchange_scalar( - &init_field, - &ImmTy::from_scalar(Scalar::from_u8(uninit_val), this.machine.layouts.u8), - Scalar::from_u8(init_val), - AtomicRwOrd::Relaxed, - AtomicReadOrd::Relaxed, - /* can_fail_spuriously */ false, - )? - .to_scalar_pair(); - if !success.to_bool()? { + let (old_init, success) = this.atomic_compare_exchange( + &init_field, + &ImmTy::from_scalar(Scalar::from_u8(uninit_val), this.machine.layouts.u8), + Scalar::from_u8(init_val), + AtomicRwOrd::Relaxed, + AtomicReadOrd::Relaxed, + /* can_fail_spuriously */ false, + )?; + if !success { // This can happen for the macOS lock if it is already marked as initialized. assert_eq!( old_init.to_u8()?, diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs deleted file mode 100644 index 481b6716c70c7..0000000000000 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ /dev/null @@ -1,347 +0,0 @@ -use rustc_middle::mir::BinOp; -use rustc_middle::ty::AtomicOrdering; -use rustc_middle::{mir, ty}; - -use super::check_intrinsic_arg_count; -use crate::*; - -pub enum AtomicRmwOp { - MirOp { - op: mir::BinOp, - /// Indicates whether the result of the operation should be negated (`UnOp::Not`, must be a - /// boolean-typed operation). - neg: bool, - }, - Max, - Min, -} - -impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Calls the atomic intrinsic `intrinsic`; the `atomic_` prefix has already been removed. - /// Returns `Ok(true)` if the intrinsic was handled. - fn emulate_atomic_intrinsic( - &mut self, - intrinsic_name: &str, - generic_args: ty::GenericArgsRef<'tcx>, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - ) -> InterpResult<'tcx, EmulateItemResult> { - let this = self.eval_context_mut(); - - let get_ord_at = |i: usize| { - let ordering = generic_args.const_at(i).to_value(); - ordering.to_branch()[0].to_value().to_leaf().to_atomic_ordering() - }; - - fn read_ord(ord: AtomicOrdering) -> AtomicReadOrd { - match ord { - AtomicOrdering::SeqCst => AtomicReadOrd::SeqCst, - AtomicOrdering::Acquire => AtomicReadOrd::Acquire, - AtomicOrdering::Relaxed => AtomicReadOrd::Relaxed, - _ => panic!("invalid read ordering `{ord:?}`"), - } - } - - fn write_ord(ord: AtomicOrdering) -> AtomicWriteOrd { - match ord { - AtomicOrdering::SeqCst => AtomicWriteOrd::SeqCst, - AtomicOrdering::Release => AtomicWriteOrd::Release, - AtomicOrdering::Relaxed => AtomicWriteOrd::Relaxed, - _ => panic!("invalid write ordering `{ord:?}`"), - } - } - - fn rw_ord(ord: AtomicOrdering) -> AtomicRwOrd { - match ord { - AtomicOrdering::SeqCst => AtomicRwOrd::SeqCst, - AtomicOrdering::AcqRel => AtomicRwOrd::AcqRel, - AtomicOrdering::Acquire => AtomicRwOrd::Acquire, - AtomicOrdering::Release => AtomicRwOrd::Release, - AtomicOrdering::Relaxed => AtomicRwOrd::Relaxed, - } - } - - fn fence_ord(ord: AtomicOrdering) -> AtomicFenceOrd { - match ord { - AtomicOrdering::SeqCst => AtomicFenceOrd::SeqCst, - AtomicOrdering::AcqRel => AtomicFenceOrd::AcqRel, - AtomicOrdering::Acquire => AtomicFenceOrd::Acquire, - AtomicOrdering::Release => AtomicFenceOrd::Release, - _ => panic!("invalid fence ordering `{ord:?}`"), - } - } - - match intrinsic_name { - "load" => { - let ord = get_ord_at(1); - this.atomic_load(args, dest, read_ord(ord))?; - } - - "store" => { - let ord = get_ord_at(1); - this.atomic_store(args, write_ord(ord))? - } - - "fence" => { - let ord = get_ord_at(0); - this.atomic_fence_intrinsic(args, fence_ord(ord))? - } - "singlethreadfence" => { - let ord = get_ord_at(0); - this.compiler_fence_intrinsic(args, fence_ord(ord))?; - } - - "xchg" => { - let ord = get_ord_at(1); - this.atomic_exchange(args, dest, rw_ord(ord))?; - } - "cxchg" => { - let ord1 = get_ord_at(1); - let ord2 = get_ord_at(2); - this.atomic_compare_exchange(args, dest, rw_ord(ord1), read_ord(ord2))?; - } - "cxchgweak" => { - let ord1 = get_ord_at(1); - let ord2 = get_ord_at(2); - this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1), read_ord(ord2))?; - } - - "or" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::BitOr, neg: false }, - rw_ord(ord), - )?; - } - "xor" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::BitXor, neg: false }, - rw_ord(ord), - )?; - } - "and" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::BitAnd, neg: false }, - rw_ord(ord), - )?; - } - "nand" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::BitAnd, neg: true }, - rw_ord(ord), - )?; - } - "xadd" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::Add, neg: false }, - rw_ord(ord), - )?; - } - "xsub" => { - let ord = get_ord_at(2); - this.atomic_rmw_op( - args, - dest, - AtomicRmwOp::MirOp { op: BinOp::Sub, neg: false }, - rw_ord(ord), - )?; - } - "min" => { - let ord = get_ord_at(1); - // Later we will use the type to indicate signed vs unsigned, - // so make sure it matches the intrinsic name. - assert!(matches!(args[1].layout.ty.kind(), ty::Int(_))); - this.atomic_rmw_op(args, dest, AtomicRmwOp::Min, rw_ord(ord))?; - } - "umin" => { - let ord = get_ord_at(1); - // Later we will use the type to indicate signed vs unsigned, - // so make sure it matches the intrinsic name. - assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_))); - this.atomic_rmw_op(args, dest, AtomicRmwOp::Min, rw_ord(ord))?; - } - "max" => { - let ord = get_ord_at(1); - // Later we will use the type to indicate signed vs unsigned, - // so make sure it matches the intrinsic name. - assert!(matches!(args[1].layout.ty.kind(), ty::Int(_))); - this.atomic_rmw_op(args, dest, AtomicRmwOp::Max, rw_ord(ord))?; - } - "umax" => { - let ord = get_ord_at(1); - // Later we will use the type to indicate signed vs unsigned, - // so make sure it matches the intrinsic name. - assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_))); - this.atomic_rmw_op(args, dest, AtomicRmwOp::Max, rw_ord(ord))?; - } - - _ => return interp_ok(EmulateItemResult::NotSupported), - } - interp_ok(EmulateItemResult::NeedsReturn) - } -} - -impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {} -trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { - fn atomic_load( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - atomic: AtomicReadOrd, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let [place] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - - // Perform atomic load. - let val = this.read_scalar_atomic(&place, atomic)?; - // Perform regular store. - this.write_scalar(val, dest)?; - interp_ok(()) - } - - fn atomic_store(&mut self, args: &[OpTy<'tcx>], atomic: AtomicWriteOrd) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let [place, val] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - - // Perform regular load. - let val = this.read_scalar(val)?; - // Perform atomic store. - this.write_scalar_atomic(val, &place, atomic)?; - interp_ok(()) - } - - fn compiler_fence_intrinsic( - &mut self, - args: &[OpTy<'tcx>], - atomic: AtomicFenceOrd, - ) -> InterpResult<'tcx> { - let [] = check_intrinsic_arg_count(args)?; - let _ = atomic; - // FIXME, FIXME(GenMC): compiler fences are currently ignored (also ignored in GenMC mode) - interp_ok(()) - } - - fn atomic_fence_intrinsic( - &mut self, - args: &[OpTy<'tcx>], - atomic: AtomicFenceOrd, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let [] = check_intrinsic_arg_count(args)?; - this.atomic_fence(atomic)?; - interp_ok(()) - } - - fn atomic_rmw_op( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - atomic_op: AtomicRmwOp, - ord: AtomicRwOrd, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let [place, rhs] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - let rhs = this.read_immediate(rhs)?; - - // The LHS can be a pointer, the RHS must be an integer. - if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr()) - || !rhs.layout.ty.is_integral() - { - span_bug!( - this.cur_span(), - "atomic arithmetic operations only work on integer and raw pointer types", - ); - } - - let old = this.atomic_rmw_op_immediate(&place, &rhs, atomic_op, ord)?; - this.write_immediate(*old, dest)?; // old value is returned - interp_ok(()) - } - - fn atomic_exchange( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - atomic: AtomicRwOrd, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let [place, new] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - let new = this.read_scalar(new)?; - - let old = this.atomic_exchange_scalar(&place, new, atomic)?; - this.write_scalar(old, dest)?; // old value is returned - interp_ok(()) - } - - fn atomic_compare_exchange_impl( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - success: AtomicRwOrd, - fail: AtomicReadOrd, - can_fail_spuriously: bool, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let [place, expect_old, new] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - let expect_old = this.read_immediate(expect_old)?; // read as immediate for the sake of `binary_op()` - let new = this.read_scalar(new)?; - - let old = this.atomic_compare_exchange_scalar( - &place, - &expect_old, - new, - success, - fail, - can_fail_spuriously, - )?; - - // Return old value. - this.write_immediate(old, dest)?; - interp_ok(()) - } - - fn atomic_compare_exchange( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - success: AtomicRwOrd, - fail: AtomicReadOrd, - ) -> InterpResult<'tcx> { - self.atomic_compare_exchange_impl(args, dest, success, fail, false) - } - - fn atomic_compare_exchange_weak( - &mut self, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, - success: AtomicRwOrd, - fail: AtomicReadOrd, - ) -> InterpResult<'tcx> { - self.atomic_compare_exchange_impl(args, dest, success, fail, true) - } -} diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 858e035a8c1f7..0f55009db790b 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -1,14 +1,11 @@ #![warn(clippy::arithmetic_side_effects)] mod aarch64; -mod atomic; mod loongarch; mod math; mod simd; mod x86; -pub use self::atomic::AtomicRmwOp; - #[rustfmt::skip] // prevent `use` reordering use rand::RngExt; use rustc_abi::{Endian, Size}; @@ -16,7 +13,6 @@ use rustc_middle::{mir, ty}; use rustc_span::{Symbol, sym}; use rustc_target::spec::Arch; -use self::atomic::EvalContextExt as _; use self::math::EvalContextExt as _; use self::simd::EvalContextExt as _; use crate::*; @@ -97,9 +93,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); - if let Some(name) = intrinsic_name.strip_prefix("atomic_") { - return this.emulate_atomic_intrinsic(name, generic_args, args, dest); - } if let Some(name) = intrinsic_name.strip_prefix("simd_") { return this.emulate_simd_intrinsic(name, args, dest); } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 2156efa9179f4..f476614992041 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -25,7 +25,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ HasTyCtxt, HasTypingEnv, LayoutCx, LayoutError, LayoutOf, TyAndLayout, }; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{Span, SpanData, Symbol}; @@ -1346,6 +1346,64 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.binary_ptr_op(bin_op, left, right) } + fn atomic_load( + ecx: &MiriInterpCx<'tcx>, + place: &MPlaceTy<'tcx>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx, Scalar> { + ecx.read_scalar_atomic(place, AtomicReadOrd::from(ordering)) + } + + fn atomic_store( + ecx: &mut MiriInterpCx<'tcx>, + place: &MPlaceTy<'tcx>, + val: &ImmTy<'tcx>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx> { + ecx.write_scalar_atomic(val.to_scalar(), place, AtomicWriteOrd::from(ordering)) + } + + fn atomic_rmw( + ecx: &mut MiriInterpCx<'tcx>, + place: &MPlaceTy<'tcx>, + op: AtomicRmwOp, + operand: &ImmTy<'tcx>, + ordering: AtomicOrdering, + ) -> InterpResult<'tcx, Scalar> { + ecx.atomic_rmw(place, operand, op, AtomicRwOrd::from(ordering)) + } + + fn atomic_compare_exchange( + ecx: &mut MiriInterpCx<'tcx>, + place: &MPlaceTy<'tcx>, + expected_old: &ImmTy<'tcx>, + new: &ImmTy<'tcx>, + can_fail_spuriously: bool, + success_ordering: AtomicOrdering, + failure_ordering: AtomicOrdering, + ) -> InterpResult<'tcx, (Scalar, bool)> { + ecx.atomic_compare_exchange( + place, + expected_old, + new.to_scalar(), + AtomicRwOrd::from(success_ordering), + AtomicReadOrd::from(failure_ordering), + can_fail_spuriously, + ) + } + + fn atomic_fence( + ecx: &MiriInterpCx<'tcx>, + ordering: AtomicOrdering, + singlethread: bool, + ) -> InterpResult<'tcx> { + if singlethread { + // We don't support signal handlers or interrupts so this is a NOP. + return interp_ok(()); + } + ecx.atomic_fence(AtomicFenceOrd::from(ordering)) + } + #[inline(always)] fn generate_nan, F2: Float>( ecx: &InterpCx<'tcx, Self>, diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index 0b7fff69d8ce2..458d3bd09fb50 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -7,7 +7,7 @@ #![allow(static_mut_refs)] use std::sync::atomic::Ordering::*; -use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize, compiler_fence, fence}; +use std::sync::atomic::*; fn main() { atomic_bool(); @@ -27,13 +27,13 @@ fn atomic_bool() { assert_eq!(*ATOMIC.get_mut(), false); ATOMIC.store(true, SeqCst); assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_or(false, SeqCst); + assert_eq!(ATOMIC.fetch_or(false, SeqCst), true); assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_and(false, SeqCst); + assert_eq!(ATOMIC.fetch_and(false, SeqCst), true); assert_eq!(*ATOMIC.get_mut(), false); - ATOMIC.fetch_nand(true, SeqCst); + assert_eq!(ATOMIC.fetch_nand(true, SeqCst), false); assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_xor(true, SeqCst); + assert_eq!(ATOMIC.fetch_xor(true, SeqCst), true); assert_eq!(*ATOMIC.get_mut(), false); } } @@ -124,6 +124,19 @@ fn atomic_u64() { assert_eq!(ATOMIC.fetch_min(0x1000, SeqCst), 0x1000); assert_eq!(ATOMIC.fetch_min(0x100, SeqCst), 0x1000); assert_eq!(ATOMIC.fetch_min(0x10, SeqCst), 0x100); + + assert_eq!(ATOMIC.swap(1, SeqCst), 0x10); + assert_eq!(ATOMIC.load(Relaxed), 1); + + let atomic_signed = AtomicI64::new(0); + assert_eq!(atomic_signed.fetch_min(-1, SeqCst), 0); + assert_eq!(atomic_signed.load(SeqCst), -1); + assert_eq!(atomic_signed.fetch_min(1, SeqCst), -1); + assert_eq!(atomic_signed.load(SeqCst), -1); + assert_eq!(atomic_signed.fetch_max(1, SeqCst), -1); + assert_eq!(atomic_signed.load(SeqCst), 1); + assert_eq!(atomic_signed.fetch_max(-1, SeqCst), 1); + assert_eq!(atomic_signed.load(SeqCst), 1); } fn atomic_fences() { diff --git a/tests/mir-opt/box_partial_move.maybe_move.ElaborateDrops.diff b/tests/mir-opt/box_partial_move.maybe_move.ElaborateDrops.diff index f090795e88656..a22ea0b2c5789 100644 --- a/tests/mir-opt/box_partial_move.maybe_move.ElaborateDrops.diff +++ b/tests/mir-opt/box_partial_move.maybe_move.ElaborateDrops.diff @@ -44,7 +44,7 @@ bb4: { StorageDead(_3); - drop(_2) -> [return: bb5, unwind continue]; -+ goto -> bb14; ++ goto -> bb13; } bb5: { @@ -61,34 +61,30 @@ + } + + bb8: { -+ goto -> bb5; -+ } -+ -+ bb9: { + _6 = &mut _2; -+ _7 = as Drop>::drop(move _6) -> [return: bb8, unwind: bb7]; ++ _7 = as Drop>::drop(move _6) -> [return: bb5, unwind: bb7]; + } + -+ bb10 (cleanup): { ++ bb9 (cleanup): { + _8 = &mut _2; + _9 = as Drop>::drop(move _8) -> [return: bb7, unwind terminate(cleanup)]; + } + ++ bb10: { ++ goto -> bb12; ++ } ++ + bb11: { -+ goto -> bb13; ++ drop((*_10)) -> [return: bb8, unwind: bb9]; + } + + bb12: { -+ drop((*_10)) -> [return: bb9, unwind: bb10]; ++ switchInt(copy _5) -> [0: bb8, otherwise: bb11]; + } + + bb13: { -+ switchInt(copy _5) -> [0: bb9, otherwise: bb12]; -+ } -+ -+ bb14: { + _10 = copy ((_2.0: std::ptr::Unique).0: std::ptr::NonNull) as *const std::string::String (Transmute); -+ goto -> bb11; ++ goto -> bb10; } } diff --git a/tests/mir-opt/building/fallible_struct_drop.build.ElaborateDrops.diff b/tests/mir-opt/building/fallible_struct_drop.build.ElaborateDrops.diff index d2a4f5025bd45..b0db5ea383919 100644 --- a/tests/mir-opt/building/fallible_struct_drop.build.ElaborateDrops.diff +++ b/tests/mir-opt/building/fallible_struct_drop.build.ElaborateDrops.diff @@ -404,34 +404,34 @@ bb37: { StorageDead(_2); - drop(_44) -> [return: bb38, unwind: bb78]; -+ goto -> bb93; ++ goto -> bb38; } bb38: { StorageDead(_44); - drop(_34) -> [return: bb39, unwind: bb83]; -+ goto -> bb94; ++ goto -> bb39; } bb39: { + _53 = const false; StorageDead(_34); - drop(_24) -> [return: bb40, unwind: bb87]; -+ goto -> bb95; ++ goto -> bb40; } bb40: { + _54 = const false; StorageDead(_24); - drop(_14) -> [return: bb41, unwind: bb90]; -+ goto -> bb96; ++ goto -> bb41; } bb41: { + _55 = const false; StorageDead(_14); - drop(_4) -> [return: bb42, unwind continue]; -+ goto -> bb97; ++ goto -> bb42; } bb42: { @@ -459,7 +459,7 @@ StorageDead(_3); StorageDead(_2); - drop(_44) -> [return: bb47, unwind: bb78]; -+ goto -> bb98; ++ goto -> bb47; } bb47: { @@ -485,7 +485,7 @@ bb51: { - drop(_34) -> [return: bb52, unwind: bb83]; -+ goto -> bb99; ++ goto -> bb52; } bb52: { @@ -507,7 +507,7 @@ bb55: { - drop(_24) -> [return: bb56, unwind: bb87]; -+ goto -> bb100; ++ goto -> bb56; } bb56: { @@ -524,7 +524,7 @@ bb58: { - drop(_14) -> [return: bb59, unwind: bb90]; -+ goto -> bb101; ++ goto -> bb59; } bb59: { @@ -535,7 +535,7 @@ bb60: { - drop(_4) -> [return: bb61, unwind continue]; -+ goto -> bb102; ++ goto -> bb61; } bb61: { @@ -681,46 +681,6 @@ bb92 (cleanup): { resume; -+ } -+ -+ bb93: { -+ goto -> bb38; -+ } -+ -+ bb94: { -+ goto -> bb39; -+ } -+ -+ bb95: { -+ goto -> bb40; -+ } -+ -+ bb96: { -+ goto -> bb41; -+ } -+ -+ bb97: { -+ goto -> bb42; -+ } -+ -+ bb98: { -+ goto -> bb47; -+ } -+ -+ bb99: { -+ goto -> bb52; -+ } -+ -+ bb100: { -+ goto -> bb56; -+ } -+ -+ bb101: { -+ goto -> bb59; -+ } -+ -+ bb102: { -+ goto -> bb61; } } diff --git a/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff index 0d89336d64092..b28018182ec37 100644 --- a/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff @@ -30,7 +30,7 @@ + _6 = std::future::ResumeTy(move _7); + _5 = copy (_1.0: &mut {async fn body of a()}); + _4 = discriminant((*_5)); -+ switchInt(move _4) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _4) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -42,20 +42,16 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + _3 = const (); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff index a97366e7cb53f..aaf739ff26eb9 100644 --- a/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff @@ -86,7 +86,7 @@ + _40 = std::future::ResumeTy(move _41); + _39 = copy (_1.0: &mut {async fn body of b()}); + _38 = discriminant((*_39)); -+ switchInt(move _38) -> [0: bb47, 1: bb46, 2: bb45, 3: bb43, 4: bb44, otherwise: bb7]; ++ switchInt(move _38) -> [0: bb46, 1: bb45, 2: bb44, 3: bb42, 4: bb43, otherwise: bb7]; } bb1: { @@ -309,7 +309,7 @@ bb23: { StorageDead(_21); - drop(_1) -> [return: bb24, unwind: bb50]; -+ goto -> bb41; ++ goto -> bb24; } bb24: { @@ -486,14 +486,10 @@ - bb50 (cleanup): { + bb40 (cleanup): { -+ goto -> bb42; -+ } -+ -+ bb41: { -+ goto -> bb24; ++ goto -> bb41; + } + -+ bb42 (cleanup): { ++ bb41 (cleanup): { + discriminant((*_39)) = 2; resume; } @@ -501,7 +497,7 @@ - bb51 (cleanup): { - StorageDead(_23); - goto -> bb52; -+ bb43: { ++ bb42: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_19); @@ -513,7 +509,7 @@ - bb52 (cleanup): { - StorageDead(_21); - goto -> bb55; -+ bb44: { ++ bb43: { + StorageLive(_21); + StorageLive(_35); + StorageLive(_36); @@ -524,21 +520,21 @@ - bb53 (cleanup): { - StorageDead(_6); - goto -> bb54; -+ bb45: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb45, unwind continue]; ++ bb44: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb44, unwind continue]; } - bb54 (cleanup): { - StorageDead(_4); - StorageDead(_3); - goto -> bb55; -+ bb46: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb46, unwind continue]; ++ bb45: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb45, unwind continue]; } - bb55 (cleanup): { - drop(_1) -> [return: bb50, unwind terminate(cleanup)]; -+ bb47: { ++ bb46: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir index d0a63ff192e77..0041816abd0ff 100644 --- a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir @@ -55,7 +55,7 @@ yields () bb0: { _3 = move (_1.0: &mut AsyncEnum); - goto -> bb65; + goto -> bb64; } bb1: { @@ -66,189 +66,189 @@ yields () resume; } - bb3: { - goto -> bb1; - } - - bb4 (cleanup): { + bb3 (cleanup): { drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } - bb5 (cleanup): { + bb4 (cleanup): { drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } - bb6: { + bb5: { StorageDead(_4); goto -> bb1; } - bb7 (cleanup): { + bb6 (cleanup): { StorageDead(_4); goto -> bb2; } - bb8: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + bb7: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; } - bb9: { + bb8: { _2 = move _5; StorageDead(_5); - goto -> bb8; + goto -> bb7; } - bb10: { + bb9: { _2 = move _5; StorageDead(_5); - goto -> bb16; + goto -> bb15; } - bb11: { + bb10: { StorageLive(_5); - _5 = yield(const ()) -> [resume: bb9, drop: bb10]; + _5 = yield(const ()) -> [resume: bb8, drop: bb9]; } - bb12: { + bb11: { unreachable; } - bb13: { + bb12: { _7 = discriminant(_6); - switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12]; + switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; } - bb14: { - _6 = as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7]; + bb13: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; } - bb15: { + bb14: { _10 = move _2; - _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7]; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; } - bb16: { + bb15: { _11 = &mut _4; - _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb15, unwind: bb7]; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; } - bb17: { + bb16: { StorageLive(_4); - _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7]; + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb15, unwind: bb6]; } - bb18: { + bb17: { _13 = &mut (((*_3) as A).0: AsyncInt); - _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2]; + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb16, unwind: bb2]; } - bb19: { + bb18: { StorageDead(_14); - goto -> bb3; + goto -> bb1; } - bb20: { + bb19: { StorageDead(_14); goto -> bb1; } - bb21 (cleanup): { + bb20 (cleanup): { StorageDead(_14); goto -> bb2; } + bb21: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb21, unwind: bb20]; + } + bb22: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb22, unwind: bb21]; + _2 = move _15; + StorageDead(_15); + goto -> bb21; } bb23: { _2 = move _15; StorageDead(_15); - goto -> bb22; + goto -> bb28; } bb24: { - _2 = move _15; - StorageDead(_15); - goto -> bb29; + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb22, drop: bb23]; } bb25: { - StorageLive(_15); - _15 = yield(const ()) -> [resume: bb23, drop: bb24]; + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb19, 1: bb24, otherwise: bb11]; } bb26: { - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb20, 1: bb25, otherwise: bb12]; + _16 = as Future>::poll(move _18, move _19) -> [return: bb25, unwind: bb20]; } bb27: { - _16 = as Future>::poll(move _18, move _19) -> [return: bb26, unwind: bb21]; + _20 = move _2; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb26, unwind: bb20]; } bb28: { - _20 = move _2; - _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb27, unwind: bb21]; + _21 = &mut _14; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb27, unwind: bb20]; } bb29: { - _21 = &mut _14; - _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb28, unwind: bb21]; + _2 = move _22; + StorageDead(_22); + goto -> bb35; } bb30: { _2 = move _22; StorageDead(_22); - goto -> bb36; + goto -> bb28; } bb31: { - _2 = move _22; - StorageDead(_22); - goto -> bb29; + StorageLive(_22); + _22 = yield(const ()) -> [resume: bb29, drop: bb30]; } bb32: { - StorageLive(_22); - _22 = yield(const ()) -> [resume: bb30, drop: bb31]; + _24 = discriminant(_23); + switchInt(move _24) -> [0: bb18, 1: bb31, otherwise: bb11]; } bb33: { - _24 = discriminant(_23); - switchInt(move _24) -> [0: bb19, 1: bb32, otherwise: bb12]; + _23 = as Future>::poll(move _25, move _26) -> [return: bb32, unwind: bb20]; } bb34: { - _23 = as Future>::poll(move _25, move _26) -> [return: bb33, unwind: bb21]; + _27 = move _2; + _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb33, unwind: bb20]; } bb35: { - _27 = move _2; - _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb34, unwind: bb21]; + _28 = &mut _14; + _25 = Pin::<&mut impl Future>::new_unchecked(move _28) -> [return: bb34, unwind: bb20]; } bb36: { - _28 = &mut _14; - _25 = Pin::<&mut impl Future>::new_unchecked(move _28) -> [return: bb35, unwind: bb21]; + StorageLive(_14); + _14 = async_drop_in_place::(copy (_29.0: &mut AsyncInt)) -> [return: bb35, unwind: bb20]; } bb37: { - StorageLive(_14); - _14 = async_drop_in_place::(copy (_29.0: &mut AsyncInt)) -> [return: bb36, unwind: bb21]; + _30 = &mut (((*_3) as A).0: AsyncInt); + _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb36, unwind: bb2]; } - bb38: { - _30 = &mut (((*_3) as A).0: AsyncInt); - _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb37, unwind: bb2]; + bb38 (cleanup): { + drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } bb39 (cleanup): { drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } - bb40 (cleanup): { - drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + bb40: { + drop((((*_3) as B).0: SyncInt)) -> [return: bb1, unwind: bb2]; } bb41: { @@ -256,122 +256,118 @@ yields () } bb42: { - drop((((*_3) as B).0: SyncInt)) -> [return: bb3, unwind: bb2]; - } - - bb43: { _31 = discriminant((*_3)); - switchInt(move _31) -> [0: bb38, otherwise: bb42]; + switchInt(move _31) -> [0: bb37, otherwise: bb41]; } - bb44 (cleanup): { + bb43 (cleanup): { _32 = discriminant((*_3)); - switchInt(move _32) -> [0: bb4, otherwise: bb39]; + switchInt(move _32) -> [0: bb3, otherwise: bb38]; } - bb45: { + bb44: { _33 = discriminant((*_3)); - switchInt(move _33) -> [0: bb18, otherwise: bb41]; + switchInt(move _33) -> [0: bb17, otherwise: bb40]; } - bb46: { + bb45: { StorageDead(_34); - goto -> bb43; + goto -> bb42; } - bb47: { + bb46: { StorageDead(_34); - goto -> bb45; + goto -> bb44; } - bb48 (cleanup): { + bb47 (cleanup): { StorageDead(_34); - goto -> bb44; + goto -> bb43; + } + + bb48: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb48, unwind: bb47]; } bb49: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb49, unwind: bb48]; + _2 = move _35; + StorageDead(_35); + goto -> bb48; } bb50: { _2 = move _35; StorageDead(_35); - goto -> bb49; + goto -> bb55; } bb51: { - _2 = move _35; - StorageDead(_35); - goto -> bb56; + StorageLive(_35); + _35 = yield(const ()) -> [resume: bb49, drop: bb50]; } bb52: { - StorageLive(_35); - _35 = yield(const ()) -> [resume: bb50, drop: bb51]; + _37 = discriminant(_36); + switchInt(move _37) -> [0: bb46, 1: bb51, otherwise: bb11]; } bb53: { - _37 = discriminant(_36); - switchInt(move _37) -> [0: bb47, 1: bb52, otherwise: bb12]; + _36 = as Future>::poll(move _38, move _39) -> [return: bb52, unwind: bb47]; } bb54: { - _36 = as Future>::poll(move _38, move _39) -> [return: bb53, unwind: bb48]; + _40 = move _2; + _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb53, unwind: bb47]; } bb55: { - _40 = move _2; - _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb54, unwind: bb48]; + _41 = &mut _34; + _38 = Pin::<&mut impl Future>::new_unchecked(move _41) -> [return: bb54, unwind: bb47]; } bb56: { - _41 = &mut _34; - _38 = Pin::<&mut impl Future>::new_unchecked(move _41) -> [return: bb55, unwind: bb48]; + _2 = move _42; + StorageDead(_42); + goto -> bb62; } bb57: { _2 = move _42; StorageDead(_42); - goto -> bb63; + goto -> bb55; } bb58: { - _2 = move _42; - StorageDead(_42); - goto -> bb56; + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb56, drop: bb57]; } bb59: { - StorageLive(_42); - _42 = yield(const ()) -> [resume: bb57, drop: bb58]; + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb45, 1: bb58, otherwise: bb11]; } bb60: { - _44 = discriminant(_43); - switchInt(move _44) -> [0: bb46, 1: bb59, otherwise: bb12]; + _43 = as Future>::poll(move _45, move _46) -> [return: bb59, unwind: bb47]; } bb61: { - _43 = as Future>::poll(move _45, move _46) -> [return: bb60, unwind: bb48]; - } - - bb62: { _47 = move _2; - _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb61, unwind: bb48]; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb60, unwind: bb47]; } - bb63: { + bb62: { _48 = &mut _34; - _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb62, unwind: bb48]; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb61, unwind: bb47]; } - bb64: { + bb63: { StorageLive(_34); - _34 = ::drop(move _49) -> [return: bb63, unwind: bb48]; + _34 = ::drop(move _49) -> [return: bb62, unwind: bb47]; } - bb65: { + bb64: { _50 = &mut (*_3); - _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb64, unwind: bb44]; + _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb63, unwind: bb43]; } } diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir index da6f0f8015be8..533dc2634ff2a 100644 --- a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir @@ -25,7 +25,7 @@ yields () bb0: { _3 = move (_1.0: &mut AsyncInt); - goto -> bb24; + goto -> bb23; } bb1: { @@ -37,111 +37,107 @@ yields () } bb3: { + StorageDead(_4); goto -> bb1; } bb4: { - StorageDead(_4); - goto -> bb3; - } - - bb5: { StorageDead(_4); goto -> bb1; } - bb6 (cleanup): { + bb5 (cleanup): { StorageDead(_4); goto -> bb2; } + bb6: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5]; + } + bb7: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + _2 = move _5; + StorageDead(_5); + goto -> bb6; } bb8: { _2 = move _5; StorageDead(_5); - goto -> bb7; + goto -> bb14; } bb9: { - _2 = move _5; - StorageDead(_5); - goto -> bb15; + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb7, drop: bb8]; } bb10: { - StorageLive(_5); - _5 = yield(const ()) -> [resume: bb8, drop: bb9]; + unreachable; } bb11: { - unreachable; + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb4, 1: bb9, otherwise: bb10]; } bb12: { - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; + _6 = as Future>::poll(move _8, move _9) -> [return: bb11, unwind: bb5]; } bb13: { - _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb12, unwind: bb5]; } bb14: { - _10 = move _2; - _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb13, unwind: bb5]; } bb15: { - _11 = &mut _4; - _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; + _2 = move _12; + StorageDead(_12); + goto -> bb21; } bb16: { _2 = move _12; StorageDead(_12); - goto -> bb22; + goto -> bb14; } bb17: { - _2 = move _12; - StorageDead(_12); - goto -> bb15; + StorageLive(_12); + _12 = yield(const ()) -> [resume: bb15, drop: bb16]; } bb18: { - StorageLive(_12); - _12 = yield(const ()) -> [resume: bb16, drop: bb17]; + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb3, 1: bb17, otherwise: bb10]; } bb19: { - _14 = discriminant(_13); - switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11]; + _13 = as Future>::poll(move _15, move _16) -> [return: bb18, unwind: bb5]; } bb20: { - _13 = as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6]; - } - - bb21: { _17 = move _2; - _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6]; + _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb19, unwind: bb5]; } - bb22: { + bb21: { _18 = &mut _4; - _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb21, unwind: bb6]; + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb20, unwind: bb5]; } - bb23: { + bb22: { StorageLive(_4); - _4 = ::drop(move _19) -> [return: bb22, unwind: bb6]; + _4 = ::drop(move _19) -> [return: bb21, unwind: bb5]; } - bb24: { + bb23: { _20 = &mut (*_3); - _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb23, unwind: bb2]; + _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb22, unwind: bb2]; } } diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir index bfb1aed61659a..fe1e2d66c2cbf 100644 --- a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir @@ -25,7 +25,7 @@ yields () bb0: { _3 = move (_1.0: &mut AsyncReference<'_>); - goto -> bb24; + goto -> bb23; } bb1: { @@ -37,111 +37,107 @@ yields () } bb3: { + StorageDead(_4); goto -> bb1; } bb4: { - StorageDead(_4); - goto -> bb3; - } - - bb5: { StorageDead(_4); goto -> bb1; } - bb6 (cleanup): { + bb5 (cleanup): { StorageDead(_4); goto -> bb2; } + bb6: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5]; + } + bb7: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + _2 = move _5; + StorageDead(_5); + goto -> bb6; } bb8: { _2 = move _5; StorageDead(_5); - goto -> bb7; + goto -> bb14; } bb9: { - _2 = move _5; - StorageDead(_5); - goto -> bb15; + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb7, drop: bb8]; } bb10: { - StorageLive(_5); - _5 = yield(const ()) -> [resume: bb8, drop: bb9]; + unreachable; } bb11: { - unreachable; + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb4, 1: bb9, otherwise: bb10]; } bb12: { - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; + _6 = as Future>::poll(move _8, move _9) -> [return: bb11, unwind: bb5]; } bb13: { - _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb12, unwind: bb5]; } bb14: { - _10 = move _2; - _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb13, unwind: bb5]; } bb15: { - _11 = &mut _4; - _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; + _2 = move _12; + StorageDead(_12); + goto -> bb21; } bb16: { _2 = move _12; StorageDead(_12); - goto -> bb22; + goto -> bb14; } bb17: { - _2 = move _12; - StorageDead(_12); - goto -> bb15; + StorageLive(_12); + _12 = yield(const ()) -> [resume: bb15, drop: bb16]; } bb18: { - StorageLive(_12); - _12 = yield(const ()) -> [resume: bb16, drop: bb17]; + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb3, 1: bb17, otherwise: bb10]; } bb19: { - _14 = discriminant(_13); - switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11]; + _13 = as Future>::poll(move _15, move _16) -> [return: bb18, unwind: bb5]; } bb20: { - _13 = as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6]; - } - - bb21: { _17 = move _2; - _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6]; + _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb19, unwind: bb5]; } - bb22: { + bb21: { _18 = &mut _4; - _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb21, unwind: bb6]; + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb20, unwind: bb5]; } - bb23: { + bb22: { StorageLive(_4); - _4 = as AsyncDrop>::drop(move _19) -> [return: bb22, unwind: bb6]; + _4 = as AsyncDrop>::drop(move _19) -> [return: bb21, unwind: bb5]; } - bb24: { + bb23: { _20 = &mut (*_3); - _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb23, unwind: bb2]; + _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb22, unwind: bb2]; } } diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir index 3a42ae5a1534e..dcb038b587155 100644 --- a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir @@ -79,7 +79,7 @@ yields () bb0: { _3 = move (_1.0: &mut AsyncStruct); - goto -> bb90; + goto -> bb89; } bb1: { @@ -90,442 +90,438 @@ yields () resume; } - bb3: { - goto -> bb1; - } - - bb4 (cleanup): { + bb3 (cleanup): { drop(((*_3).2: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } - bb5 (cleanup): { - drop(((*_3).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + bb4 (cleanup): { + drop(((*_3).1: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)]; } - bb6: { + bb5: { StorageDead(_4); goto -> bb1; } - bb7 (cleanup): { + bb6 (cleanup): { StorageDead(_4); goto -> bb2; } + bb7: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + } + bb8: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + _2 = move _5; + StorageDead(_5); + goto -> bb7; } bb9: { _2 = move _5; StorageDead(_5); - goto -> bb8; + goto -> bb15; } bb10: { - _2 = move _5; - StorageDead(_5); - goto -> bb16; + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb8, drop: bb9]; } bb11: { - StorageLive(_5); - _5 = yield(const ()) -> [resume: bb9, drop: bb10]; + unreachable; } bb12: { - unreachable; + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; } bb13: { - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12]; + _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; } bb14: { - _6 = as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7]; + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; } bb15: { - _10 = move _2; - _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7]; + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; } bb16: { - _11 = &mut _4; - _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb15, unwind: bb7]; + StorageLive(_4); + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb15, unwind: bb6]; } bb17: { - StorageLive(_4); - _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7]; + _13 = &mut ((*_3).2: AsyncInt); + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb16, unwind: bb2]; } bb18: { - _13 = &mut ((*_3).2: AsyncInt); - _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2]; + StorageDead(_14); + goto -> bb17; } - bb19: { + bb19 (cleanup): { StorageDead(_14); - goto -> bb18; + goto -> bb3; } - bb20 (cleanup): { - StorageDead(_14); - goto -> bb4; + bb20: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb20, unwind: bb19]; } bb21: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb21, unwind: bb20]; + _2 = move _15; + StorageDead(_15); + goto -> bb20; } bb22: { _2 = move _15; StorageDead(_15); - goto -> bb21; + goto -> bb27; } bb23: { - _2 = move _15; - StorageDead(_15); - goto -> bb28; + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb21, drop: bb22]; } bb24: { - StorageLive(_15); - _15 = yield(const ()) -> [resume: bb22, drop: bb23]; + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb18, 1: bb23, otherwise: bb11]; } bb25: { - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb19, 1: bb24, otherwise: bb12]; + _16 = as Future>::poll(move _18, move _19) -> [return: bb24, unwind: bb19]; } bb26: { - _16 = as Future>::poll(move _18, move _19) -> [return: bb25, unwind: bb20]; - } - - bb27: { _20 = move _2; - _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb26, unwind: bb20]; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb25, unwind: bb19]; } - bb28: { + bb27: { _21 = &mut _14; - _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb27, unwind: bb20]; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb26, unwind: bb19]; } - bb29: { + bb28: { StorageLive(_14); - _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb28, unwind: bb20]; + _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb27, unwind: bb19]; } - bb30: { + bb29: { _23 = &mut ((*_3).1: AsyncInt); - _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb29, unwind: bb4]; + _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb28, unwind: bb3]; } - bb31: { + bb30: { StorageDead(_24); - goto -> bb3; + goto -> bb1; } - bb32: { + bb31: { StorageDead(_24); goto -> bb1; } - bb33 (cleanup): { + bb32 (cleanup): { StorageDead(_24); goto -> bb2; } + bb33: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb33, unwind: bb32]; + } + bb34: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb34, unwind: bb33]; + _2 = move _25; + StorageDead(_25); + goto -> bb33; } bb35: { _2 = move _25; StorageDead(_25); - goto -> bb34; + goto -> bb40; } bb36: { - _2 = move _25; - StorageDead(_25); - goto -> bb41; + StorageLive(_25); + _25 = yield(const ()) -> [resume: bb34, drop: bb35]; } bb37: { - StorageLive(_25); - _25 = yield(const ()) -> [resume: bb35, drop: bb36]; + _27 = discriminant(_26); + switchInt(move _27) -> [0: bb31, 1: bb36, otherwise: bb11]; } bb38: { - _27 = discriminant(_26); - switchInt(move _27) -> [0: bb32, 1: bb37, otherwise: bb12]; + _26 = as Future>::poll(move _28, move _29) -> [return: bb37, unwind: bb32]; } bb39: { - _26 = as Future>::poll(move _28, move _29) -> [return: bb38, unwind: bb33]; + _30 = move _2; + _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb38, unwind: bb32]; } bb40: { - _30 = move _2; - _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb39, unwind: bb33]; + _31 = &mut _24; + _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb39, unwind: bb32]; } bb41: { - _31 = &mut _24; - _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb40, unwind: bb33]; + _2 = move _32; + StorageDead(_32); + goto -> bb47; } bb42: { _2 = move _32; StorageDead(_32); - goto -> bb48; + goto -> bb40; } bb43: { - _2 = move _32; - StorageDead(_32); - goto -> bb41; + StorageLive(_32); + _32 = yield(const ()) -> [resume: bb41, drop: bb42]; } bb44: { - StorageLive(_32); - _32 = yield(const ()) -> [resume: bb42, drop: bb43]; + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb30, 1: bb43, otherwise: bb11]; } bb45: { - _34 = discriminant(_33); - switchInt(move _34) -> [0: bb31, 1: bb44, otherwise: bb12]; + _33 = as Future>::poll(move _35, move _36) -> [return: bb44, unwind: bb32]; } bb46: { - _33 = as Future>::poll(move _35, move _36) -> [return: bb45, unwind: bb33]; + _37 = move _2; + _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb45, unwind: bb32]; } bb47: { - _37 = move _2; - _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb46, unwind: bb33]; + _38 = &mut _24; + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb46, unwind: bb32]; } bb48: { - _38 = &mut _24; - _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb47, unwind: bb33]; + StorageLive(_24); + _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb47, unwind: bb32]; } bb49: { - StorageLive(_24); - _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb48, unwind: bb33]; + _40 = &mut ((*_3).2: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb48, unwind: bb2]; } bb50: { - _40 = &mut ((*_3).2: AsyncInt); - _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb49, unwind: bb2]; + StorageDead(_41); + goto -> bb49; } bb51: { StorageDead(_41); - goto -> bb50; + goto -> bb17; } - bb52: { + bb52 (cleanup): { StorageDead(_41); - goto -> bb18; + goto -> bb3; } - bb53 (cleanup): { - StorageDead(_41); - goto -> bb4; + bb53: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb53, unwind: bb52]; } bb54: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb54, unwind: bb53]; + _2 = move _42; + StorageDead(_42); + goto -> bb53; } bb55: { _2 = move _42; StorageDead(_42); - goto -> bb54; + goto -> bb60; } bb56: { - _2 = move _42; - StorageDead(_42); - goto -> bb61; + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb54, drop: bb55]; } bb57: { - StorageLive(_42); - _42 = yield(const ()) -> [resume: bb55, drop: bb56]; + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb51, 1: bb56, otherwise: bb11]; } bb58: { - _44 = discriminant(_43); - switchInt(move _44) -> [0: bb52, 1: bb57, otherwise: bb12]; + _43 = as Future>::poll(move _45, move _46) -> [return: bb57, unwind: bb52]; } bb59: { - _43 = as Future>::poll(move _45, move _46) -> [return: bb58, unwind: bb53]; + _47 = move _2; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb58, unwind: bb52]; } bb60: { - _47 = move _2; - _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb59, unwind: bb53]; + _48 = &mut _41; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb59, unwind: bb52]; } bb61: { - _48 = &mut _41; - _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb60, unwind: bb53]; + _2 = move _49; + StorageDead(_49); + goto -> bb67; } bb62: { _2 = move _49; StorageDead(_49); - goto -> bb68; + goto -> bb60; } bb63: { - _2 = move _49; - StorageDead(_49); - goto -> bb61; + StorageLive(_49); + _49 = yield(const ()) -> [resume: bb61, drop: bb62]; } bb64: { - StorageLive(_49); - _49 = yield(const ()) -> [resume: bb62, drop: bb63]; + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb50, 1: bb63, otherwise: bb11]; } bb65: { - _51 = discriminant(_50); - switchInt(move _51) -> [0: bb51, 1: bb64, otherwise: bb12]; + _50 = as Future>::poll(move _52, move _53) -> [return: bb64, unwind: bb52]; } bb66: { - _50 = as Future>::poll(move _52, move _53) -> [return: bb65, unwind: bb53]; + _54 = move _2; + _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb65, unwind: bb52]; } bb67: { - _54 = move _2; - _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb66, unwind: bb53]; + _55 = &mut _41; + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb66, unwind: bb52]; } bb68: { - _55 = &mut _41; - _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb67, unwind: bb53]; + StorageLive(_41); + _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb67, unwind: bb52]; } bb69: { - StorageLive(_41); - _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb68, unwind: bb53]; + _57 = &mut ((*_3).1: AsyncInt); + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb68, unwind: bb3]; } bb70: { - _57 = &mut ((*_3).1: AsyncInt); - _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb69, unwind: bb4]; + StorageDead(_58); + goto -> bb69; } bb71: { StorageDead(_58); - goto -> bb70; + goto -> bb29; } - bb72: { + bb72 (cleanup): { StorageDead(_58); - goto -> bb30; + goto -> bb4; } - bb73 (cleanup): { - StorageDead(_58); - goto -> bb5; + bb73: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb73, unwind: bb72]; } bb74: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb74, unwind: bb73]; + _2 = move _59; + StorageDead(_59); + goto -> bb73; } bb75: { _2 = move _59; StorageDead(_59); - goto -> bb74; + goto -> bb80; } bb76: { - _2 = move _59; - StorageDead(_59); - goto -> bb81; + StorageLive(_59); + _59 = yield(const ()) -> [resume: bb74, drop: bb75]; } bb77: { - StorageLive(_59); - _59 = yield(const ()) -> [resume: bb75, drop: bb76]; + _61 = discriminant(_60); + switchInt(move _61) -> [0: bb71, 1: bb76, otherwise: bb11]; } bb78: { - _61 = discriminant(_60); - switchInt(move _61) -> [0: bb72, 1: bb77, otherwise: bb12]; + _60 = as Future>::poll(move _62, move _63) -> [return: bb77, unwind: bb72]; } bb79: { - _60 = as Future>::poll(move _62, move _63) -> [return: bb78, unwind: bb73]; + _64 = move _2; + _63 = std::future::get_context::<'_, '_>(move _64) -> [return: bb78, unwind: bb72]; } bb80: { - _64 = move _2; - _63 = std::future::get_context::<'_, '_>(move _64) -> [return: bb79, unwind: bb73]; + _65 = &mut _58; + _62 = Pin::<&mut impl Future>::new_unchecked(move _65) -> [return: bb79, unwind: bb72]; } bb81: { - _65 = &mut _58; - _62 = Pin::<&mut impl Future>::new_unchecked(move _65) -> [return: bb80, unwind: bb73]; + _2 = move _66; + StorageDead(_66); + goto -> bb87; } bb82: { _2 = move _66; StorageDead(_66); - goto -> bb88; + goto -> bb80; } bb83: { - _2 = move _66; - StorageDead(_66); - goto -> bb81; + StorageLive(_66); + _66 = yield(const ()) -> [resume: bb81, drop: bb82]; } bb84: { - StorageLive(_66); - _66 = yield(const ()) -> [resume: bb82, drop: bb83]; + _68 = discriminant(_67); + switchInt(move _68) -> [0: bb70, 1: bb83, otherwise: bb11]; } bb85: { - _68 = discriminant(_67); - switchInt(move _68) -> [0: bb71, 1: bb84, otherwise: bb12]; + _67 = as Future>::poll(move _69, move _70) -> [return: bb84, unwind: bb72]; } bb86: { - _67 = as Future>::poll(move _69, move _70) -> [return: bb85, unwind: bb73]; - } - - bb87: { _71 = move _2; - _70 = std::future::get_context::<'_, '_>(move _71) -> [return: bb86, unwind: bb73]; + _70 = std::future::get_context::<'_, '_>(move _71) -> [return: bb85, unwind: bb72]; } - bb88: { + bb87: { _72 = &mut _58; - _69 = Pin::<&mut impl Future>::new_unchecked(move _72) -> [return: bb87, unwind: bb73]; + _69 = Pin::<&mut impl Future>::new_unchecked(move _72) -> [return: bb86, unwind: bb72]; } - bb89: { + bb88: { StorageLive(_58); - _58 = ::drop(move _73) -> [return: bb88, unwind: bb73]; + _58 = ::drop(move _73) -> [return: bb87, unwind: bb72]; } - bb90: { + bb89: { _74 = &mut (*_3); - _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb89, unwind: bb5]; + _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb88, unwind: bb4]; } } diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir index b5d451bbdc4a1..ad37224d34f9b 100644 --- a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir @@ -64,7 +64,7 @@ yields () bb0: { _3 = move (_1.0: &mut SyncThenAsync); - goto -> bb74; + goto -> bb73; } bb1: { @@ -75,358 +75,354 @@ yields () resume; } - bb3: { - goto -> bb1; + bb3 (cleanup): { + drop(((*_3).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; } bb4 (cleanup): { - drop(((*_3).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + drop(((*_3).2: SyncInt)) -> [return: bb3, unwind terminate(cleanup)]; } bb5 (cleanup): { - drop(((*_3).2: SyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + drop(((*_3).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)]; } - bb6 (cleanup): { - drop(((*_3).1: AsyncInt)) -> [return: bb5, unwind terminate(cleanup)]; - } - - bb7: { + bb6: { StorageDead(_4); goto -> bb1; } - bb8 (cleanup): { + bb7 (cleanup): { StorageDead(_4); goto -> bb2; } + bb8: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + } + bb9: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8]; + _2 = move _5; + StorageDead(_5); + goto -> bb8; } bb10: { _2 = move _5; StorageDead(_5); - goto -> bb9; + goto -> bb16; } bb11: { - _2 = move _5; - StorageDead(_5); - goto -> bb17; + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb9, drop: bb10]; } bb12: { - StorageLive(_5); - _5 = yield(const ()) -> [resume: bb10, drop: bb11]; + unreachable; } bb13: { - unreachable; + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12]; } bb14: { - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb7, 1: bb12, otherwise: bb13]; + _6 = as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7]; } bb15: { - _6 = as Future>::poll(move _8, move _9) -> [return: bb14, unwind: bb8]; + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7]; } bb16: { - _10 = move _2; - _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb15, unwind: bb8]; + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb15, unwind: bb7]; } bb17: { - _11 = &mut _4; - _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb16, unwind: bb8]; + StorageLive(_4); + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7]; } bb18: { - StorageLive(_4); - _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb17, unwind: bb8]; + _13 = &mut ((*_3).3: AsyncInt); + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2]; } bb19: { - _13 = &mut ((*_3).3: AsyncInt); - _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb18, unwind: bb2]; + drop(((*_3).2: SyncInt)) -> [return: bb18, unwind: bb3]; } bb20: { - drop(((*_3).2: SyncInt)) -> [return: bb19, unwind: bb4]; + StorageDead(_14); + goto -> bb19; } - bb21: { + bb21 (cleanup): { StorageDead(_14); - goto -> bb20; + goto -> bb4; } - bb22 (cleanup): { - StorageDead(_14); - goto -> bb5; + bb22: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb22, unwind: bb21]; } bb23: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb23, unwind: bb22]; + _2 = move _15; + StorageDead(_15); + goto -> bb22; } bb24: { _2 = move _15; StorageDead(_15); - goto -> bb23; + goto -> bb29; } bb25: { - _2 = move _15; - StorageDead(_15); - goto -> bb30; + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb23, drop: bb24]; } bb26: { - StorageLive(_15); - _15 = yield(const ()) -> [resume: bb24, drop: bb25]; + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb20, 1: bb25, otherwise: bb12]; } bb27: { - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb21, 1: bb26, otherwise: bb13]; + _16 = as Future>::poll(move _18, move _19) -> [return: bb26, unwind: bb21]; } bb28: { - _16 = as Future>::poll(move _18, move _19) -> [return: bb27, unwind: bb22]; - } - - bb29: { _20 = move _2; - _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb28, unwind: bb22]; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb27, unwind: bb21]; } - bb30: { + bb29: { _21 = &mut _14; - _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb29, unwind: bb22]; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb28, unwind: bb21]; } - bb31: { + bb30: { StorageLive(_14); - _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb30, unwind: bb22]; + _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb29, unwind: bb21]; } - bb32: { + bb31: { _23 = &mut ((*_3).1: AsyncInt); - _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb31, unwind: bb5]; + _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb30, unwind: bb4]; } - bb33: { + bb32: { StorageDead(_24); - goto -> bb3; + goto -> bb1; } - bb34: { + bb33: { StorageDead(_24); goto -> bb1; } - bb35 (cleanup): { + bb34 (cleanup): { StorageDead(_24); goto -> bb2; } + bb35: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb35, unwind: bb34]; + } + bb36: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb36, unwind: bb35]; + _2 = move _25; + StorageDead(_25); + goto -> bb35; } bb37: { _2 = move _25; StorageDead(_25); - goto -> bb36; + goto -> bb42; } bb38: { - _2 = move _25; - StorageDead(_25); - goto -> bb43; + StorageLive(_25); + _25 = yield(const ()) -> [resume: bb36, drop: bb37]; } bb39: { - StorageLive(_25); - _25 = yield(const ()) -> [resume: bb37, drop: bb38]; + _27 = discriminant(_26); + switchInt(move _27) -> [0: bb33, 1: bb38, otherwise: bb12]; } bb40: { - _27 = discriminant(_26); - switchInt(move _27) -> [0: bb34, 1: bb39, otherwise: bb13]; + _26 = as Future>::poll(move _28, move _29) -> [return: bb39, unwind: bb34]; } bb41: { - _26 = as Future>::poll(move _28, move _29) -> [return: bb40, unwind: bb35]; + _30 = move _2; + _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb40, unwind: bb34]; } bb42: { - _30 = move _2; - _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb41, unwind: bb35]; + _31 = &mut _24; + _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb41, unwind: bb34]; } bb43: { - _31 = &mut _24; - _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb42, unwind: bb35]; + _2 = move _32; + StorageDead(_32); + goto -> bb49; } bb44: { _2 = move _32; StorageDead(_32); - goto -> bb50; + goto -> bb42; } bb45: { - _2 = move _32; - StorageDead(_32); - goto -> bb43; + StorageLive(_32); + _32 = yield(const ()) -> [resume: bb43, drop: bb44]; } bb46: { - StorageLive(_32); - _32 = yield(const ()) -> [resume: bb44, drop: bb45]; + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb32, 1: bb45, otherwise: bb12]; } bb47: { - _34 = discriminant(_33); - switchInt(move _34) -> [0: bb33, 1: bb46, otherwise: bb13]; + _33 = as Future>::poll(move _35, move _36) -> [return: bb46, unwind: bb34]; } bb48: { - _33 = as Future>::poll(move _35, move _36) -> [return: bb47, unwind: bb35]; + _37 = move _2; + _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb47, unwind: bb34]; } bb49: { - _37 = move _2; - _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb48, unwind: bb35]; + _38 = &mut _24; + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb48, unwind: bb34]; } bb50: { - _38 = &mut _24; - _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb49, unwind: bb35]; + StorageLive(_24); + _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb49, unwind: bb34]; } bb51: { - StorageLive(_24); - _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb50, unwind: bb35]; + _40 = &mut ((*_3).3: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb50, unwind: bb2]; } bb52: { - _40 = &mut ((*_3).3: AsyncInt); - _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb51, unwind: bb2]; + drop(((*_3).2: SyncInt)) -> [return: bb51, unwind: bb3]; } bb53: { - drop(((*_3).2: SyncInt)) -> [return: bb52, unwind: bb4]; + StorageDead(_41); + goto -> bb52; } bb54: { StorageDead(_41); - goto -> bb53; + goto -> bb19; } - bb55: { + bb55 (cleanup): { StorageDead(_41); - goto -> bb20; + goto -> bb4; } - bb56 (cleanup): { - StorageDead(_41); - goto -> bb5; + bb56: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb56, unwind: bb55]; } bb57: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb57, unwind: bb56]; + _2 = move _42; + StorageDead(_42); + goto -> bb56; } bb58: { _2 = move _42; StorageDead(_42); - goto -> bb57; + goto -> bb63; } bb59: { - _2 = move _42; - StorageDead(_42); - goto -> bb64; + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb57, drop: bb58]; } bb60: { - StorageLive(_42); - _42 = yield(const ()) -> [resume: bb58, drop: bb59]; + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb54, 1: bb59, otherwise: bb12]; } bb61: { - _44 = discriminant(_43); - switchInt(move _44) -> [0: bb55, 1: bb60, otherwise: bb13]; + _43 = as Future>::poll(move _45, move _46) -> [return: bb60, unwind: bb55]; } bb62: { - _43 = as Future>::poll(move _45, move _46) -> [return: bb61, unwind: bb56]; + _47 = move _2; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb61, unwind: bb55]; } bb63: { - _47 = move _2; - _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb62, unwind: bb56]; + _48 = &mut _41; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb62, unwind: bb55]; } bb64: { - _48 = &mut _41; - _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb63, unwind: bb56]; + _2 = move _49; + StorageDead(_49); + goto -> bb70; } bb65: { _2 = move _49; StorageDead(_49); - goto -> bb71; + goto -> bb63; } bb66: { - _2 = move _49; - StorageDead(_49); - goto -> bb64; + StorageLive(_49); + _49 = yield(const ()) -> [resume: bb64, drop: bb65]; } bb67: { - StorageLive(_49); - _49 = yield(const ()) -> [resume: bb65, drop: bb66]; + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb53, 1: bb66, otherwise: bb12]; } bb68: { - _51 = discriminant(_50); - switchInt(move _51) -> [0: bb54, 1: bb67, otherwise: bb13]; + _50 = as Future>::poll(move _52, move _53) -> [return: bb67, unwind: bb55]; } bb69: { - _50 = as Future>::poll(move _52, move _53) -> [return: bb68, unwind: bb56]; - } - - bb70: { _54 = move _2; - _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb69, unwind: bb56]; + _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb68, unwind: bb55]; } - bb71: { + bb70: { _55 = &mut _41; - _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb70, unwind: bb56]; + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb69, unwind: bb55]; } - bb72: { + bb71: { StorageLive(_41); - _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb71, unwind: bb56]; + _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb70, unwind: bb55]; } - bb73: { + bb72: { _57 = &mut ((*_3).1: AsyncInt); - _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb72, unwind: bb5]; + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb71, unwind: bb4]; } - bb74: { + bb73: { _58 = &mut (*_3); - _59 = ::drop(move _58) -> [return: bb73, unwind: bb6]; + _59 = ::drop(move _58) -> [return: bb72, unwind: bb5]; } } diff --git a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.diff index 9e6df1e9c27d2..b2f525bb0289e 100644 --- a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.diff @@ -98,7 +98,7 @@ + _43 = std::future::ResumeTy(move _44); + _42 = copy (_1.0: &mut {async fn body of double()}); + _41 = discriminant((*_42)); -+ switchInt(move _41) -> [0: bb42, 1: bb41, 2: bb40, 3: bb36, 4: bb37, 5: bb38, 6: bb39, otherwise: bb13]; ++ switchInt(move _41) -> [0: bb41, 1: bb40, 2: bb39, 3: bb35, 4: bb36, 5: bb37, 6: bb38, otherwise: bb13]; } bb1: { @@ -119,7 +119,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb4, unwind: bb12]; + nop; -+ goto -> bb34; ++ goto -> bb4; } bb4: { @@ -154,7 +154,7 @@ - bb8: { - coroutine_drop; + bb8 (cleanup): { -+ goto -> bb35; ++ goto -> bb34; } - bb9 (cleanup): { @@ -343,67 +343,66 @@ + _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb32, unwind: bb6]; } - bb34: { +- bb34: { - StorageDead(_23); - goto -> bb2; -+ goto -> bb4; ++ bb34 (cleanup): { ++ discriminant((*_42)) = 2; ++ resume; } -- bb35: { + bb35: { - StorageDead(_23); - goto -> bb6; -+ bb35 (cleanup): { -+ discriminant((*_42)) = 2; -+ resume; ++ StorageLive(_7); ++ _7 = move _43; ++ goto -> bb12; } - bb36 (cleanup): { - StorageDead(_23); - goto -> bb10; + bb36: { -+ StorageLive(_7); -+ _7 = move _43; -+ goto -> bb12; ++ StorageLive(_14); ++ _14 = move _43; ++ goto -> bb14; } bb37: { - assert(const false, "`async fn` resumed after async drop") -> [success: bb37, unwind: bb36]; -+ StorageLive(_14); -+ _14 = move _43; -+ goto -> bb14; ++ StorageLive(_24); ++ _24 = move _43; ++ goto -> bb25; } bb38: { - _2 = move _24; - StorageDead(_24); - goto -> bb37; -+ StorageLive(_24); -+ _24 = move _43; -+ goto -> bb25; ++ StorageLive(_31); ++ _31 = move _43; ++ goto -> bb26; } bb39: { - _2 = move _24; - StorageDead(_24); - goto -> bb44; -+ StorageLive(_31); -+ _31 = move _43; -+ goto -> bb26; ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb39, unwind continue]; } bb40: { - StorageLive(_24); - _24 = yield(const ()) -> [resume: bb38, drop: bb39]; -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb40, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb40, unwind continue]; } bb41: { - _26 = discriminant(_25); - switchInt(move _26) -> [0: bb35, 1: bb40, otherwise: bb20]; -+ assert(const false, "`async fn` resumed after completion") -> [success: bb41, unwind continue]; - } - - bb42: { +- } +- +- bb42: { - _25 = as Future>::poll(move _27, move _28) -> [return: bb41, unwind: bb36]; - } - diff --git a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir index 6fc7b46c34970..0239f6a98cb05 100644 --- a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir +++ b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir @@ -60,7 +60,7 @@ fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Conte _43 = std::future::ResumeTy(move _44); _42 = copy (_1.0: &mut {async fn body of double()}); _41 = discriminant((*_42)); - switchInt(move _41) -> [0: bb29, 2: bb36, 3: bb32, 4: bb33, 5: bb34, 6: bb35, otherwise: bb37]; + switchInt(move _41) -> [0: bb29, 2: bb35, 3: bb31, 4: bb32, 5: bb33, 6: bb34, otherwise: bb36]; } bb1: { @@ -99,7 +99,7 @@ fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Conte } bb8 (cleanup): { - goto -> bb31; + goto -> bb30; } bb9: { @@ -212,47 +212,43 @@ fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Conte } bb29: { - goto -> bb30; - } - - bb30: { goto -> bb28; } - bb31 (cleanup): { + bb30 (cleanup): { discriminant((*_42)) = 2; resume; } - bb32: { + bb31: { StorageLive(_7); _7 = move _43; goto -> bb11; } - bb33: { + bb32: { StorageLive(_14); _14 = move _43; goto -> bb18; } - bb34: { + bb33: { StorageLive(_24); _24 = move _43; goto -> bb21; } - bb35: { + bb34: { StorageLive(_31); _31 = move _43; goto -> bb27; } - bb36: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb36, unwind continue]; + bb35: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb35, unwind continue]; } - bb37: { + bb36: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.diff index 34ea0eeaa07a2..08e9ff5c2796f 100644 --- a/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.diff @@ -313,7 +313,7 @@ + _183 = std::future::ResumeTy(move _184); + _182 = copy (_1.0: &mut {async fn body of elaborate_drops()}); + _181 = discriminant((*_182)); -+ switchInt(move _181) -> [0: bb170, 1: bb169, 2: bb168, 3: bb150, 4: bb151, 5: bb152, 6: bb153, 7: bb154, 8: bb155, 9: bb156, 10: bb157, 11: bb158, 12: bb159, 13: bb160, 14: bb161, 15: bb162, 16: bb163, 17: bb164, 18: bb165, 19: bb166, 20: bb167, otherwise: bb43]; ++ switchInt(move _181) -> [0: bb169, 1: bb168, 2: bb167, 3: bb149, 4: bb150, 5: bb151, 6: bb152, 7: bb153, 8: bb154, 9: bb155, 10: bb156, 11: bb157, 12: bb158, 13: bb159, 14: bb160, 15: bb161, 16: bb162, 17: bb163, 18: bb164, 19: bb165, 20: bb166, otherwise: bb43]; } bb1: { @@ -497,7 +497,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb22, unwind: bb51]; + nop; -+ goto -> bb148; ++ goto -> bb22; } bb22: { @@ -620,7 +620,7 @@ bb38 (cleanup): { - StorageDead(_24); - goto -> bb39; -+ goto -> bb149; ++ goto -> bb148; } - bb39 (cleanup): { @@ -1456,22 +1456,16 @@ + _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb146, unwind: bb36]; } - bb148: { +- bb148: { - _104 = as Future>::poll(move _106, move _107) -> [return: bb147, unwind: bb135]; -+ goto -> bb22; - } - -- bb149: { -- _108 = move _2; -- _107 = std::future::get_context::<'_, '_>(move _108) -> [return: bb148, unwind: bb135]; -+ bb149 (cleanup): { ++ bb148 (cleanup): { + discriminant((*_182)) = 2; + resume; } - bb150: { -- _109 = &mut _95; -- _106 = Pin::<&mut impl Future>::new_unchecked(move _109) -> [return: bb149, unwind: bb135]; + bb149: { +- _108 = move _2; +- _107 = std::future::get_context::<'_, '_>(move _108) -> [return: bb148, unwind: bb135]; + StorageLive(_17); + StorageLive(_23); + StorageLive(_25); @@ -1480,9 +1474,9 @@ + goto -> bb42; } - bb151: { -- StorageLive(_95); -- _95 = async_drop_in_place::(copy (_110.0: &mut AsyncEnum)) -> [return: bb150, unwind: bb135]; + bb150: { +- _109 = &mut _95; +- _106 = Pin::<&mut impl Future>::new_unchecked(move _109) -> [return: bb149, unwind: bb135]; + StorageLive(_17); + StorageLive(_23); + StorageLive(_25); @@ -1491,9 +1485,9 @@ + goto -> bb44; } - bb152: { -- _111 = &mut _15; -- _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb151, unwind: bb45]; + bb151: { +- StorageLive(_95); +- _95 = async_drop_in_place::(copy (_110.0: &mut AsyncEnum)) -> [return: bb150, unwind: bb135]; + StorageLive(_17); + StorageLive(_23); + StorageLive(_45); @@ -1501,9 +1495,9 @@ + goto -> bb55; } - bb153: { -- StorageDead(_112); -- goto -> bb17; + bb152: { +- _111 = &mut _15; +- _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb151, unwind: bb45]; + StorageLive(_17); + StorageLive(_23); + StorageLive(_52); @@ -1511,137 +1505,141 @@ + goto -> bb56; } - bb154: { + bb153: { - StorageDead(_112); -- goto -> bb30; +- goto -> bb17; + StorageLive(_17); + StorageLive(_62); + _62 = move _183; + goto -> bb67; } -- bb155 (cleanup): { + bb154: { - StorageDead(_112); -- goto -> bb46; -+ bb155: { +- goto -> bb30; + StorageLive(_17); + StorageLive(_69); + _69 = move _183; + goto -> bb68; } - bb156: { -- assert(const false, "`async fn` resumed after async drop") -> [success: bb156, unwind: bb155]; +- bb155 (cleanup): { +- StorageDead(_112); +- goto -> bb46; ++ bb155: { + StorageLive(_17); + StorageLive(_79); + _79 = move _183; + goto -> bb79; } - bb157: { -- _2 = move _113; -- StorageDead(_113); -- goto -> bb156; + bb156: { +- assert(const false, "`async fn` resumed after async drop") -> [success: bb156, unwind: bb155]; + StorageLive(_17); + StorageLive(_86); + _86 = move _183; + goto -> bb80; } - bb158: { + bb157: { - _2 = move _113; - StorageDead(_113); -- goto -> bb163; +- goto -> bb156; + StorageLive(_96); + _96 = move _183; + goto -> bb91; } - bb159: { -- StorageLive(_113); -- _113 = yield(const ()) -> [resume: bb157, drop: bb158]; + bb158: { +- _2 = move _113; +- StorageDead(_113); +- goto -> bb163; + StorageLive(_103); + _103 = move _183; + goto -> bb92; } - bb160: { -- _115 = discriminant(_114); -- switchInt(move _115) -> [0: bb154, 1: bb159, otherwise: bb59]; -+ StorageLive(_113); + bb159: { + StorageLive(_113); +- _113 = yield(const ()) -> [resume: bb157, drop: bb158]; + _113 = move _183; + goto -> bb103; } - bb161: { -- _114 = as Future>::poll(move _116, move _117) -> [return: bb160, unwind: bb155]; + bb160: { +- _115 = discriminant(_114); +- switchInt(move _115) -> [0: bb154, 1: bb159, otherwise: bb59]; + StorageLive(_120); + _120 = move _183; + goto -> bb104; } - bb162: { -- _118 = move _2; -- _117 = std::future::get_context::<'_, '_>(move _118) -> [return: bb161, unwind: bb155]; + bb161: { +- _114 = as Future>::poll(move _116, move _117) -> [return: bb160, unwind: bb155]; + StorageLive(_130); + _130 = move _183; + goto -> bb115; } - bb163: { -- _119 = &mut _112; -- _116 = Pin::<&mut impl Future>::new_unchecked(move _119) -> [return: bb162, unwind: bb155]; + bb162: { +- _118 = move _2; +- _117 = std::future::get_context::<'_, '_>(move _118) -> [return: bb161, unwind: bb155]; + StorageLive(_137); + _137 = move _183; + goto -> bb116; } - bb164: { -- _2 = move _120; -- StorageDead(_120); -- goto -> bb170; + bb163: { +- _119 = &mut _112; +- _116 = Pin::<&mut impl Future>::new_unchecked(move _119) -> [return: bb162, unwind: bb155]; + StorageLive(_147); + _147 = move _183; + goto -> bb127; } - bb165: { + bb164: { - _2 = move _120; - StorageDead(_120); -- goto -> bb163; +- goto -> bb170; + StorageLive(_154); + _154 = move _183; + goto -> bb128; } - bb166: { -- StorageLive(_120); -- _120 = yield(const ()) -> [resume: bb164, drop: bb165]; + bb165: { +- _2 = move _120; +- StorageDead(_120); +- goto -> bb163; + StorageLive(_164); + _164 = move _183; + goto -> bb139; } - bb167: { -- _122 = discriminant(_121); -- switchInt(move _122) -> [0: bb153, 1: bb166, otherwise: bb59]; + bb166: { +- StorageLive(_120); +- _120 = yield(const ()) -> [resume: bb164, drop: bb165]; + StorageLive(_171); + _171 = move _183; + goto -> bb140; } + bb167: { +- _122 = discriminant(_121); +- switchInt(move _122) -> [0: bb153, 1: bb166, otherwise: bb59]; ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb167, unwind continue]; + } + bb168: { - _121 = as Future>::poll(move _123, move _124) -> [return: bb167, unwind: bb155]; -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb168, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb168, unwind continue]; } bb169: { - _125 = move _2; - _124 = std::future::get_context::<'_, '_>(move _125) -> [return: bb168, unwind: bb155]; -+ assert(const false, "`async fn` resumed after completion") -> [success: bb169, unwind continue]; - } - - bb170: { +- } +- +- bb170: { - _126 = &mut _112; - _123 = Pin::<&mut impl Future>::new_unchecked(move _126) -> [return: bb169, unwind: bb155]; - } diff --git a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.diff index 6454844b6cb55..59ab86c82a193 100644 --- a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.diff @@ -69,7 +69,7 @@ + _25 = std::future::ResumeTy(move _26); + _24 = copy (_1.0: &mut {async fn body of simple()}); + _23 = discriminant((*_24)); -+ switchInt(move _23) -> [0: bb26, 1: bb25, 2: bb24, 3: bb22, 4: bb23, otherwise: bb11]; ++ switchInt(move _23) -> [0: bb25, 1: bb24, 2: bb23, 3: bb21, 4: bb22, otherwise: bb11]; } bb1: { @@ -83,7 +83,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb3, unwind: bb9]; + nop; -+ goto -> bb20; ++ goto -> bb3; } bb3: { @@ -110,7 +110,7 @@ - bb6: { - coroutine_drop; + bb6 (cleanup): { -+ goto -> bb21; ++ goto -> bb20; } - bb7 (cleanup): { @@ -208,51 +208,50 @@ + _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb18, unwind: bb4]; } - bb20: { +- bb20: { - _11 = move _2; - _10 = std::future::get_context::<'_, '_>(move _11) -> [return: bb19, unwind: bb12]; -+ goto -> bb3; ++ bb20 (cleanup): { ++ discriminant((*_24)) = 2; ++ resume; } -- bb21: { + bb21: { - _12 = &mut _5; - _9 = Pin::<&mut impl Future>::new_unchecked(move _12) -> [return: bb20, unwind: bb12]; -+ bb21 (cleanup): { -+ discriminant((*_24)) = 2; -+ resume; ++ StorageLive(_6); ++ _6 = move _25; ++ goto -> bb10; } bb22: { - _2 = move _13; - StorageDead(_13); - goto -> bb28; -+ StorageLive(_6); -+ _6 = move _25; -+ goto -> bb10; ++ StorageLive(_13); ++ _13 = move _25; ++ goto -> bb12; } bb23: { - _2 = move _13; - StorageDead(_13); - goto -> bb21; -+ StorageLive(_13); -+ _13 = move _25; -+ goto -> bb12; ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue]; } bb24: { - StorageLive(_13); - _13 = yield(const ()) -> [resume: bb22, drop: bb23]; -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb24, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb24, unwind continue]; } bb25: { - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb10, 1: bb24, otherwise: bb17]; -+ assert(const false, "`async fn` resumed after completion") -> [success: bb25, unwind continue]; - } - - bb26: { +- } +- +- bb26: { - _14 = as Future>::poll(move _16, move _17) -> [return: bb25, unwind: bb12]; - } - diff --git a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir index a09f6ec8f432d..b883f518564d9 100644 --- a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir +++ b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir @@ -39,7 +39,7 @@ fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Conte _25 = std::future::ResumeTy(move _26); _24 = copy (_1.0: &mut {async fn body of simple()}); _23 = discriminant((*_24)); - switchInt(move _23) -> [0: bb18, 2: bb23, 3: bb21, 4: bb22, otherwise: bb24]; + switchInt(move _23) -> [0: bb18, 2: bb22, 3: bb20, 4: bb21, otherwise: bb23]; } bb1: { @@ -68,7 +68,7 @@ fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Conte } bb6 (cleanup): { - goto -> bb20; + goto -> bb19; } bb7: { @@ -131,35 +131,31 @@ fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Conte } bb18: { - goto -> bb19; - } - - bb19: { goto -> bb17; } - bb20 (cleanup): { + bb19 (cleanup): { discriminant((*_24)) = 2; resume; } - bb21: { + bb20: { StorageLive(_6); _6 = move _25; goto -> bb9; } - bb22: { + bb21: { StorageLive(_13); _13 = move _25; goto -> bb16; } - bb23: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue]; + bb22: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb22, unwind continue]; } - bb24: { + bb23: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir index d93774cb286f9..83617c6cd7874 100644 --- a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -36,7 +36,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) _24 = std::future::ResumeTy(move _25); _23 = copy (_1.0: &mut {async fn body of a()}); _22 = discriminant((*_23)); - switchInt(move _22) -> [0: bb13, 3: bb16, 4: bb17, otherwise: bb18]; + switchInt(move _22) -> [0: bb13, 3: bb15, 4: bb16, otherwise: bb17]; } bb1: { @@ -104,30 +104,26 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb13: { - goto -> bb15; + goto -> bb14; } bb14: { - goto -> bb12; + drop(((*_23).0: T)) -> [return: bb12, unwind unreachable]; } bb15: { - drop(((*_23).0: T)) -> [return: bb14, unwind unreachable]; - } - - bb16: { StorageLive(_5); _5 = move _24; goto -> bb4; } - bb17: { + bb16: { StorageLive(_12); _12 = move _24; goto -> bb11; } - bb18: { + bb17: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir index 0015cb779f56e..b6fb5c325d767 100644 --- a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -36,7 +36,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) _24 = std::future::ResumeTy(move _25); _23 = copy (_1.0: &mut {async fn body of a()}); _22 = discriminant((*_23)); - switchInt(move _22) -> [0: bb16, 2: bb22, 3: bb20, 4: bb21, otherwise: bb23]; + switchInt(move _22) -> [0: bb16, 2: bb21, 3: bb19, 4: bb20, otherwise: bb22]; } bb1: { @@ -55,7 +55,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb4 (cleanup): { - goto -> bb19; + goto -> bb18; } bb5: { @@ -118,39 +118,35 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb16: { - goto -> bb18; + goto -> bb17; } bb17: { - goto -> bb15; + drop(((*_23).0: T)) -> [return: bb15, unwind: bb4]; } - bb18: { - drop(((*_23).0: T)) -> [return: bb17, unwind: bb4]; - } - - bb19 (cleanup): { + bb18 (cleanup): { discriminant((*_23)) = 2; resume; } - bb20: { + bb19: { StorageLive(_5); _5 = move _24; goto -> bb7; } - bb21: { + bb20: { StorageLive(_12); _12 = move _24; goto -> bb14; } - bb22: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb22, unwind continue]; + bb21: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb21, unwind continue]; } - bb23: { + bb22: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir index 3d1ee14cc0740..e06189e941211 100644 --- a/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir +++ b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir @@ -45,7 +45,7 @@ yields () bb0: { _3 = move (_1.0: &mut [Foo; 1]); - goto -> bb44; + goto -> bb43; } bb1: { @@ -261,12 +261,8 @@ yields () } bb43: { - goto -> bb42; - } - - bb44: { _4 = &raw mut (*_3); _5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit)); - goto -> bb43; + goto -> bb42; } } diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.diff index c893394038552..cf55f3f3b12c6 100644 --- a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.diff @@ -46,7 +46,7 @@ + _10 = std::future::ResumeTy(move _11); + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}); + _8 = discriminant((*_9)); -+ switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _8) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -58,18 +58,14 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); @@ -79,7 +75,7 @@ + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir index bc31fc3498c81..4dec40924719b 100644 --- a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -15,7 +15,7 @@ fn add::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:34:13: 3 bb0: { _8 = discriminant((*_1)); - switchInt(move _8) -> [0: bb2, otherwise: bb4]; + switchInt(move _8) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -23,14 +23,10 @@ fn add::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:34:13: 3 } bb2: { - goto -> bb3; - } - - bb3: { goto -> bb1; } - bb4: { + bb3: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.diff index af2d7dede4c60..b6c22224c74f8 100644 --- a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.diff @@ -95,7 +95,7 @@ + _28 = std::future::ResumeTy(move _29); + _27 = copy (_1.0: &mut {async fn body of add()}); + _26 = discriminant((*_27)); -+ switchInt(move _26) -> [0: bb28, 1: bb27, 2: bb26, 3: bb25, otherwise: bb6]; ++ switchInt(move _26) -> [0: bb27, 1: bb26, 2: bb25, 3: bb24, otherwise: bb6]; } bb1: { @@ -210,7 +210,7 @@ - drop(_1) -> [return: bb13, unwind: bb28]; + nop; + nop; -+ goto -> bb23; ++ goto -> bb13; } bb13: { @@ -291,26 +291,19 @@ - StorageDead(_13); - StorageDead(_12); - drop(_10) -> [return: bb23, unwind terminate(cleanup)]; -+ goto -> bb24; ++ goto -> bb23; } -- bb23 (cleanup): { + bb23 (cleanup): { - StorageDead(_10); - goto -> bb26; -+ bb23: { -+ goto -> bb13; - } - - bb24 (cleanup): { -- goto -> bb25; + discriminant((*_27)) = 2; + resume; } -- bb25 (cleanup): { -- StorageDead(_9); -- goto -> bb26; -+ bb25: { +- bb24 (cleanup): { +- goto -> bb25; ++ bb24: { + StorageLive(_5); + StorageLive(_8); + StorageLive(_23); @@ -319,11 +312,18 @@ + goto -> bb9; } +- bb25 (cleanup): { +- StorageDead(_9); +- goto -> bb26; ++ bb25: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb25, unwind continue]; + } + - bb26 (cleanup): { - StorageDead(_8); - goto -> bb27; + bb26: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb26, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb26, unwind continue]; } - bb27 (cleanup): { @@ -331,10 +331,8 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb28, unwind terminate(cleanup)]; -+ bb27: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb27, unwind continue]; - } - +- } +- - bb28 (cleanup): { - resume; - } @@ -354,7 +352,7 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb28, unwind terminate(cleanup)]; -+ bb28: { ++ bb27: { + nop; + (((*_27) as variant#3).0: u32) = copy ((*_27).0: u32); + nop; diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir index 36b32d640e6ce..cd2092e97177a 100644 --- a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir @@ -48,7 +48,7 @@ fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () { bb0: { _26 = discriminant((*_1)); - switchInt(move _26) -> [0: bb11, 3: bb14, otherwise: bb15]; + switchInt(move _26) -> [0: bb11, 3: bb12, otherwise: bb13]; } bb1: { @@ -71,7 +71,7 @@ fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () { StorageDead(_5); nop; nop; - goto -> bb12; + goto -> bb5; } bb5: { @@ -104,18 +104,10 @@ fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () { } bb11: { - goto -> bb13; - } - - bb12: { - goto -> bb5; - } - - bb13: { goto -> bb10; } - bb14: { + bb12: { StorageLive(_5); StorageLive(_8); StorageLive(_23); @@ -123,7 +115,7 @@ fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () { goto -> bb1; } - bb15: { + bb13: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.diff index 3e791a06683e3..b28ba99b82191 100644 --- a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.diff @@ -141,7 +141,7 @@ + _52 = std::future::ResumeTy(move _53); + _51 = copy (_1.0: &mut {async fn body of build_aggregate()}); + _50 = discriminant((*_51)); -+ switchInt(move _50) -> [0: bb49, 1: bb48, 2: bb47, 3: bb45, 4: bb46, otherwise: bb7]; ++ switchInt(move _50) -> [0: bb48, 1: bb47, 2: bb46, 3: bb44, 4: bb45, otherwise: bb7]; } bb1: { @@ -397,7 +397,7 @@ StorageDead(_4); StorageDead(_3); - drop(_1) -> [return: bb24, unwind: bb52]; -+ goto -> bb43; ++ goto -> bb24; } bb24: { @@ -611,14 +611,10 @@ - bb52 (cleanup): { + bb42 (cleanup): { -+ goto -> bb44; -+ } -+ -+ bb43: { -+ goto -> bb24; ++ goto -> bb43; + } + -+ bb44 (cleanup): { ++ bb43 (cleanup): { + discriminant((*_51)) = 2; resume; } @@ -628,7 +624,7 @@ - StorageDead(_28); - StorageDead(_8); - goto -> bb54; -+ bb45: { ++ bb44: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); @@ -642,7 +638,7 @@ - bb54 (cleanup): { - StorageDead(_29); - goto -> bb56; -+ bb46: { ++ bb45: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); @@ -659,14 +655,14 @@ - StorageDead(_13); - StorageDead(_8); - goto -> bb56; -+ bb47: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb47, unwind continue]; ++ bb46: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb46, unwind continue]; } - bb56 (cleanup): { - goto -> bb57; -+ bb48: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb48, unwind continue]; ++ bb47: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb47, unwind continue]; } - bb57 (cleanup): { @@ -677,7 +673,7 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb52, unwind terminate(cleanup)]; -+ bb49: { ++ bb48: { + StorageLive(_3); + _3 = copy ((*_51).0: u32); + StorageLive(_4); diff --git a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir index 11cafacb20685..d107b3a2dbbbd 100644 --- a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir @@ -86,7 +86,7 @@ fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) - bb0: { _50 = discriminant((*_1)); - switchInt(move _50) -> [0: bb16, 3: bb19, 4: bb20, otherwise: bb21]; + switchInt(move _50) -> [0: bb16, 3: bb17, 4: bb18, otherwise: bb19]; } bb1: { @@ -130,7 +130,7 @@ fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) - nop; StorageDead(_4); StorageDead(_3); - goto -> bb17; + goto -> bb8; } bb8: { @@ -178,18 +178,10 @@ fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) - } bb16: { - goto -> bb18; - } - - bb17: { - goto -> bb8; - } - - bb18: { goto -> bb15; } - bb19: { + bb17: { StorageLive(_3); StorageLive(_4); StorageLive(_7); @@ -199,7 +191,7 @@ fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) - goto -> bb4; } - bb20: { + bb18: { StorageLive(_3); StorageLive(_4); StorageLive(_7); @@ -211,7 +203,7 @@ fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) - goto -> bb1; } - bb21: { + bb19: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.diff index e54cc4c2f3cd3..dee4d01136250 100644 --- a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.diff @@ -46,7 +46,7 @@ + _10 = std::future::ResumeTy(move _11); + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}); + _8 = discriminant((*_9)); -+ switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _8) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -58,18 +58,14 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); @@ -79,7 +75,7 @@ + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir index 97b9a7098b5ec..a098d65cbc084 100644 --- a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -15,7 +15,7 @@ fn foo::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:21:13: 2 bb0: { _8 = discriminant((*_1)); - switchInt(move _8) -> [0: bb2, otherwise: bb4]; + switchInt(move _8) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -23,14 +23,10 @@ fn foo::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:21:13: 2 } bb2: { - goto -> bb3; - } - - bb3: { goto -> bb1; } - bb4: { + bb3: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.diff index cfbf542c9da83..e2a229fc36c73 100644 --- a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.diff @@ -128,7 +128,7 @@ + _38 = std::future::ResumeTy(move _39); + _36 = copy (_1.0: &mut {async fn body of foo()}); + _35 = discriminant((*_36)); -+ switchInt(move _35) -> [0: bb26, 1: bb25, 2: bb24, 3: bb23, otherwise: bb6]; ++ switchInt(move _35) -> [0: bb25, 1: bb24, 2: bb23, 3: bb22, otherwise: bb6]; } bb1: { @@ -266,7 +266,7 @@ - drop(_1) -> [return: bb12, unwind: bb25]; + nop; + nop; -+ goto -> bb21; ++ goto -> bb12; } bb12: { @@ -347,26 +347,19 @@ - StorageDead(_16); - StorageDead(_15); - drop(_13) -> [return: bb21, unwind terminate(cleanup)]; -+ goto -> bb22; ++ goto -> bb21; } -- bb21 (cleanup): { + bb21 (cleanup): { - StorageDead(_13); - goto -> bb24; -+ bb21: { -+ goto -> bb12; - } - - bb22 (cleanup): { -- goto -> bb23; + discriminant((*_36)) = 2; + resume; } -- bb23 (cleanup): { -- StorageDead(_10); -- goto -> bb24; -+ bb23: { +- bb22 (cleanup): { +- goto -> bb23; ++ bb22: { + StorageLive(_5); + StorageLive(_7); + StorageLive(_8); @@ -377,6 +370,13 @@ + goto -> bb9; } +- bb23 (cleanup): { +- StorageDead(_10); +- goto -> bb24; ++ bb23: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue]; + } + - bb24 (cleanup): { - StorageDead(_9); - StorageDead(_8); @@ -387,15 +387,13 @@ - StorageDead(_3); - drop(_1) -> [return: bb25, unwind terminate(cleanup)]; + bb24: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb24, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb24, unwind continue]; } - bb25 (cleanup): { - resume; -+ bb25: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb25, unwind continue]; - } - +- } +- - bb26 (cleanup): { - StorageDead(_13); - goto -> bb27; @@ -410,7 +408,7 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb25, unwind terminate(cleanup)]; -+ bb26: { ++ bb25: { + nop; + (((*_36) as variant#3).0: &u32) = copy ((*_36).0: &u32); + nop; diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir index 6e17bfb29bbc4..d5d9182fb2071 100644 --- a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir @@ -72,7 +72,7 @@ fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () { bb0: { _35 = discriminant((*_1)); - switchInt(move _35) -> [0: bb9, 3: bb12, otherwise: bb13]; + switchInt(move _35) -> [0: bb9, 3: bb10, otherwise: bb11]; } bb1: { @@ -94,7 +94,7 @@ fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () { StorageDead(_5); nop; nop; - goto -> bb10; + goto -> bb4; } bb4: { @@ -126,18 +126,10 @@ fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () { } bb9: { - goto -> bb11; - } - - bb10: { - goto -> bb4; - } - - bb11: { goto -> bb8; } - bb12: { + bb10: { StorageLive(_5); StorageLive(_7); StorageLive(_8); @@ -147,7 +139,7 @@ fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () { goto -> bb1; } - bb13: { + bb11: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.diff index b6e211f990954..5707f3dcd4439 100644 --- a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.diff @@ -95,7 +95,7 @@ + _36 = std::future::ResumeTy(move _37); + _35 = copy (_1.0: &mut {async fn body of hello_world()}); + _34 = discriminant((*_35)); -+ switchInt(move _34) -> [0: bb33, 1: bb32, 2: bb31, 3: bb30, otherwise: bb8]; ++ switchInt(move _34) -> [0: bb32, 1: bb31, 2: bb30, 3: bb29, otherwise: bb8]; } bb1: { @@ -259,7 +259,7 @@ - drop(_1) -> [return: bb15, unwind: bb32]; + nop; + nop; -+ goto -> bb28; ++ goto -> bb15; } bb15: { @@ -396,14 +396,10 @@ - bb32 (cleanup): { + bb27 (cleanup): { -+ goto -> bb29; -+ } -+ -+ bb28: { -+ goto -> bb15; ++ goto -> bb28; + } + -+ bb29 (cleanup): { ++ bb28 (cleanup): { + discriminant((*_35)) = 2; resume; } @@ -412,7 +408,7 @@ - StorageDead(_18); - StorageDead(_10); - goto -> bb34; -+ bb30: { ++ bb29: { + StorageLive(_5); + StorageLive(_9); + StorageLive(_10); @@ -435,15 +431,15 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb32, unwind terminate(cleanup)]; -+ bb31: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb31, unwind continue]; ++ bb30: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb30, unwind continue]; + } + -+ bb32: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb32, unwind continue]; ++ bb31: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb31, unwind continue]; + } + -+ bb33: { ++ bb32: { + nop; + (((*_35) as variant#3).0: [u8; 1]) = [const 0_u8; 1]; + nop; diff --git a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir index c8ee84c2c78fd..b32943d88c10f 100644 --- a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir @@ -54,7 +54,7 @@ fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () { bb0: { _34 = discriminant((*_1)); - switchInt(move _34) -> [0: bb9, 3: bb12, otherwise: bb13]; + switchInt(move _34) -> [0: bb9, 3: bb10, otherwise: bb11]; } bb1: { @@ -78,7 +78,7 @@ fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () { StorageDead(_5); nop; nop; - goto -> bb10; + goto -> bb4; } bb4: { @@ -112,18 +112,10 @@ fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () { } bb9: { - goto -> bb11; - } - - bb10: { - goto -> bb4; - } - - bb11: { goto -> bb8; } - bb12: { + bb10: { StorageLive(_5); StorageLive(_9); StorageLive(_10); @@ -135,7 +127,7 @@ fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () { goto -> bb1; } - bb13: { + bb11: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.diff index 6d004faeaa398..334b4e5dd526c 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.diff @@ -44,7 +44,7 @@ + _10 = std::future::ResumeTy(move _11); + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}); + _8 = discriminant((*_9)); -+ switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _8) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -56,18 +56,14 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); @@ -77,7 +73,7 @@ + _7 = Mul(move _3, move _4); + StorageDead(_4); + StorageDead(_3); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir index e367ee4f35112..686b4323e0185 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -14,7 +14,7 @@ fn includes_never::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn. bb0: { _8 = discriminant((*_1)); - switchInt(move _8) -> [0: bb2, otherwise: bb4]; + switchInt(move _8) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -22,14 +22,10 @@ fn includes_never::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn. } bb2: { - goto -> bb3; - } - - bb3: { goto -> bb1; } - bb4: { + bb3: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.diff index 35f51cf908fe1..7b73b8be0abe4 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.diff @@ -44,7 +44,7 @@ + _10 = std::future::ResumeTy(move _11); + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}); + _8 = discriminant((*_9)); -+ switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _8) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -56,18 +56,14 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); @@ -77,7 +73,7 @@ + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir index e62115da97a6b..3ae5c1dc89643 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir @@ -14,7 +14,7 @@ fn includes_never::{closure#0}::{closure#1}(_1: &mut {async block@$DIR/async_fn. bb0: { _8 = discriminant((*_1)); - switchInt(move _8) -> [0: bb2, otherwise: bb4]; + switchInt(move _8) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -22,14 +22,10 @@ fn includes_never::{closure#0}::{closure#1}(_1: &mut {async block@$DIR/async_fn. } bb2: { - goto -> bb3; - } - - bb3: { goto -> bb1; } - bb4: { + bb3: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.diff index 4f2cf485c6250..47aeaec0fa8fd 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.diff @@ -125,7 +125,7 @@ + _51 = std::future::ResumeTy(move _52); + _50 = copy (_1.0: &mut {async fn body of includes_never()}); + _49 = discriminant((*_50)); -+ switchInt(move _49) -> [0: bb30, 1: bb29, 2: bb28, 3: bb27, otherwise: bb6]; ++ switchInt(move _49) -> [0: bb29, 1: bb28, 2: bb27, 3: bb26, otherwise: bb6]; } bb1: { @@ -247,7 +247,7 @@ - drop(_1) -> [return: bb14, unwind: bb29]; + nop; + nop; -+ goto -> bb25; ++ goto -> bb14; } bb13: { @@ -345,26 +345,19 @@ bb24 (cleanup): { - StorageDead(_9); - goto -> bb27; -+ goto -> bb26; ++ goto -> bb25; } -- bb25 (cleanup): { + bb25 (cleanup): { - goto -> bb26; -+ bb25: { -+ goto -> bb14; - } - - bb26 (cleanup): { -- StorageDead(_7); -- goto -> bb27; + discriminant((*_50)) = 2; + resume; } -- bb27 (cleanup): { -- StorageDead(_6); -- goto -> bb28; -+ bb27: { +- bb26 (cleanup): { +- StorageDead(_7); +- goto -> bb27; ++ bb26: { + StorageLive(_5); + StorageLive(_6); + StorageLive(_22); @@ -373,21 +366,26 @@ + goto -> bb9; } +- bb27 (cleanup): { +- StorageDead(_6); +- goto -> bb28; ++ bb27: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb27, unwind continue]; + } + - bb28 (cleanup): { - StorageDead(_5); - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb29, unwind terminate(cleanup)]; + bb28: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb28, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind continue]; } - bb29 (cleanup): { - resume; -+ bb29: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind continue]; - } - +- } +- - bb30 (cleanup): { - StorageDead(_9); - goto -> bb31; @@ -399,7 +397,7 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb29, unwind terminate(cleanup)]; -+ bb30: { ++ bb29: { + nop; + (((*_50) as variant#3).0: bool) = copy ((*_50).0: bool); + nop; diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir index f65034a272309..97fdec425898f 100644 --- a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir @@ -82,7 +82,7 @@ fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> bb0: { _49 = discriminant((*_1)); - switchInt(move _49) -> [0: bb9, 3: bb12, otherwise: bb13]; + switchInt(move _49) -> [0: bb9, 3: bb10, otherwise: bb11]; } bb1: { @@ -101,7 +101,7 @@ fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> StorageDead(_5); nop; nop; - goto -> bb10; + goto -> bb4; } bb4: { @@ -130,18 +130,10 @@ fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> } bb9: { - goto -> bb11; - } - - bb10: { - goto -> bb4; - } - - bb11: { goto -> bb8; } - bb12: { + bb10: { StorageLive(_5); StorageLive(_6); StorageLive(_22); @@ -149,7 +141,7 @@ fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> goto -> bb1; } - bb13: { + bb11: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.diff index 48c288bd6f9ed..1b02ab76a443e 100644 --- a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.diff @@ -44,7 +44,7 @@ + _10 = std::future::ResumeTy(move _11); + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}); + _8 = discriminant((*_9)); -+ switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; ++ switchInt(move _8) -> [0: bb4, 1: bb2, otherwise: bb3]; } bb1: { @@ -56,18 +56,14 @@ - bb2 (cleanup): { - resume; + bb2: { -+ goto -> bb1; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; + } + + bb3: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; -+ } -+ -+ bb4: { + unreachable; + } + -+ bb5: { ++ bb4: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); @@ -77,7 +73,7 @@ + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); -+ goto -> bb2; ++ goto -> bb1; } } diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir index 6cbf36dfed9e9..7a21ec09f8a10 100644 --- a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -14,7 +14,7 @@ fn partial_init::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs bb0: { _8 = discriminant((*_1)); - switchInt(move _8) -> [0: bb2, otherwise: bb4]; + switchInt(move _8) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -22,14 +22,10 @@ fn partial_init::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs } bb2: { - goto -> bb3; - } - - bb3: { goto -> bb1; } - bb4: { + bb3: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.diff index 2b91b6e998f52..11939da81cad4 100644 --- a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.diff @@ -81,7 +81,7 @@ + _29 = std::future::ResumeTy(move _30); + _28 = copy (_1.0: &mut {async fn body of partial_init()}); + _27 = discriminant((*_28)); -+ switchInt(move _27) -> [0: bb32, 1: bb31, 2: bb30, 3: bb29, otherwise: bb7]; ++ switchInt(move _27) -> [0: bb31, 1: bb30, 2: bb29, 3: bb28, otherwise: bb7]; } bb1: { @@ -211,7 +211,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb14, unwind: bb32]; + nop; -+ goto -> bb27; ++ goto -> bb14; } bb14: { @@ -313,28 +313,20 @@ } bb26 (cleanup): { -- goto -> bb27; -+ goto -> bb28; + goto -> bb27; } -- bb27 (cleanup): { + bb27 (cleanup): { - StorageDead(_9); - drop(_6) -> [return: bb28, unwind terminate(cleanup)]; -+ bb27: { -+ goto -> bb14; - } - - bb28 (cleanup): { -- StorageDead(_6); -- goto -> bb29; + discriminant((*_28)) = 2; + resume; } -- bb29 (cleanup): { -- StorageDead(_8); -- goto -> bb31; -+ bb29: { +- bb28 (cleanup): { +- StorageDead(_6); +- goto -> bb29; ++ bb28: { + StorageLive(_4); + StorageLive(_5); + StorageLive(_8); @@ -344,11 +336,18 @@ + goto -> bb10; } +- bb29 (cleanup): { +- StorageDead(_8); +- goto -> bb31; ++ bb29: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb29, unwind continue]; + } + - bb30 (cleanup): { - StorageDead(_6); - goto -> bb31; + bb30: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb30, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb30, unwind continue]; } - bb31 (cleanup): { @@ -356,10 +355,8 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb32, unwind terminate(cleanup)]; -+ bb31: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb31, unwind continue]; - } - +- } +- - bb32 (cleanup): { - resume; - } @@ -380,7 +377,7 @@ - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb32, unwind terminate(cleanup)]; -+ bb32: { ++ bb31: { + nop; + (((*_28) as variant#3).0: u32) = copy ((*_28).0: u32); + StorageLive(_4); diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir index c404d49b5ee5f..c76b3ca617f76 100644 --- a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir @@ -47,7 +47,7 @@ fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () { bb0: { _27 = discriminant((*_1)); - switchInt(move _27) -> [0: bb11, 3: bb14, otherwise: bb15]; + switchInt(move _27) -> [0: bb11, 3: bb12, otherwise: bb13]; } bb1: { @@ -71,7 +71,7 @@ fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () { StorageDead(_5); StorageDead(_4); nop; - goto -> bb12; + goto -> bb5; } bb5: { @@ -105,18 +105,10 @@ fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () { } bb11: { - goto -> bb13; - } - - bb12: { - goto -> bb5; - } - - bb13: { goto -> bb10; } - bb14: { + bb12: { StorageLive(_4); StorageLive(_5); StorageLive(_8); @@ -125,7 +117,7 @@ fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () { goto -> bb1; } - bb15: { + bb13: { return; } } diff --git a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.diff index 8ae369ae38ef4..6e9edd2faebcd 100644 --- a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.diff @@ -108,7 +108,7 @@ + _47 = std::future::ResumeTy(move _48); + _46 = copy (_1.0: &mut {async fn body of uninhabited_variant()}); + _45 = discriminant((*_46)); -+ switchInt(move _45) -> [0: bb56, 1: bb55, 2: bb54, 3: bb52, 4: bb53, otherwise: bb1]; ++ switchInt(move _45) -> [0: bb55, 1: bb54, 2: bb53, 3: bb51, 4: bb52, otherwise: bb1]; } bb1: { @@ -367,7 +367,7 @@ - drop(_1) -> [return: bb27, unwind: bb56]; + (((*_46) as variant#4).2: bool) = const false; + nop; -+ goto -> bb50; ++ goto -> bb27; } bb27: { @@ -572,7 +572,7 @@ - bb56 (cleanup): { - resume; + bb45 (cleanup): { -+ goto -> bb51; ++ goto -> bb50; } - bb57 (cleanup): { @@ -609,22 +609,16 @@ - bb61 (cleanup): { - StorageDead(_4); - goto -> bb70; -+ bb50: { -+ goto -> bb27; ++ bb50 (cleanup): { ++ discriminant((*_46)) = 2; ++ resume; } - bb62 (cleanup): { - _43 = const false; - StorageDead(_3); - drop(_1) -> [return: bb56, unwind terminate(cleanup)]; -+ bb51 (cleanup): { -+ discriminant((*_46)) = 2; -+ resume; - } - -- bb63: { -- drop(_3) -> [return: bb26, unwind: bb55]; -+ bb52: { ++ bb51: { + StorageLive(_4); + StorageLive(_6); + StorageLive(_7); @@ -634,9 +628,9 @@ + goto -> bb11; } -- bb64: { -- switchInt(copy _43) -> [0: bb26, otherwise: bb63]; -+ bb53: { +- bb63: { +- drop(_3) -> [return: bb26, unwind: bb55]; ++ bb52: { + StorageLive(_4); + StorageLive(_24); + StorageLive(_25); @@ -647,18 +641,22 @@ + goto -> bb22; } +- bb64: { +- switchInt(copy _43) -> [0: bb26, otherwise: bb63]; ++ bb53: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb53, unwind continue]; + } + - bb65: { - drop(_3) -> [return: bb35, unwind: bb62]; + bb54: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb54, unwind continue]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb54, unwind continue]; } - bb66: { - switchInt(copy _43) -> [0: bb35, otherwise: bb65]; -+ bb55: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb55, unwind continue]; - } - +- } +- - bb67 (cleanup): { - drop(_3) -> [return: bb55, unwind terminate(cleanup)]; - } @@ -673,7 +671,7 @@ - - bb70 (cleanup): { - switchInt(copy _43) -> [0: bb62, otherwise: bb69]; -+ bb56: { ++ bb55: { + (((*_46) as variant#4).2: bool) = const false; + nop; + (((*_46) as variant#4).2: bool) = const true; diff --git a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir index a4a7516e57103..19cde28ce35fb 100644 --- a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir +++ b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir @@ -68,7 +68,7 @@ fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_varia bb0: { _45 = discriminant((*_1)); - switchInt(move _45) -> [0: bb22, 3: bb25, 4: bb26, otherwise: bb27]; + switchInt(move _45) -> [0: bb22, 3: bb23, 4: bb24, otherwise: bb25]; } bb1: { @@ -114,7 +114,7 @@ fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_varia bb8: { (((*_1) as variant#4).2: bool) = const false; nop; - goto -> bb23; + goto -> bb9; } bb9: { @@ -180,18 +180,10 @@ fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_varia } bb22: { - goto -> bb24; - } - - bb23: { - goto -> bb9; - } - - bb24: { goto -> bb21; } - bb25: { + bb23: { StorageLive(_4); StorageLive(_6); StorageLive(_7); @@ -200,7 +192,7 @@ fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_varia goto -> bb4; } - bb26: { + bb24: { StorageLive(_4); StorageLive(_24); StorageLive(_25); @@ -210,7 +202,7 @@ fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_varia goto -> bb1; } - bb27: { + bb25: { return; } } diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff index 17671228295e3..d9d65147e1e83 100644 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff @@ -47,7 +47,7 @@ - _5 = ::clone(move _6) -> [return: bb1, unwind: bb31]; + _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}); + _17 = discriminant((*_18)); -+ switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35]; ++ switchInt(move _17) -> [0: bb35, 1: bb33, 2: bb32, 3: bb30, 4: bb31, otherwise: bb34]; } bb1: { @@ -149,7 +149,7 @@ bb13: { - drop(_1) -> [return: bb14, unwind: bb37]; -+ goto -> bb29; ++ goto -> bb14; } bb14: { @@ -261,39 +261,31 @@ - StorageDead(_12); - StorageDead(_10); - StorageDead(_9); -- goto -> bb29; -+ goto -> bb30; + goto -> bb29; } -- bb29 (cleanup): { + bb29 (cleanup): { - StorageDead(_11); - StorageDead(_8); - goto -> bb35; -+ bb29: { -+ goto -> bb14; - } - - bb30 (cleanup): { -- StorageDead(_7); -- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; + discriminant((*_18)) = 2; + resume; } -- bb31 (cleanup): { -- StorageDead(_6); -- goto -> bb32; -+ bb31: { +- bb30 (cleanup): { +- StorageDead(_7); +- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; ++ bb30: { + StorageLive(_3); + StorageLive(_4); + _3 = move _2; + goto -> bb4; } -- bb32 (cleanup): { -- StorageDead(_5); -- goto -> bb33; -+ bb32: { +- bb31 (cleanup): { +- StorageDead(_6); +- goto -> bb32; ++ bb31: { + StorageLive(_8); + StorageLive(_9); + StorageLive(_11); @@ -302,26 +294,31 @@ + goto -> bb10; } +- bb32 (cleanup): { +- StorageDead(_5); +- goto -> bb33; ++ bb32: { ++ assert(const false, "coroutine resumed after panicking") -> [success: bb32, unwind continue]; + } + - bb33 (cleanup): { - StorageDead(_4); - goto -> bb34; + bb33: { -+ assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue]; ++ assert(const false, "coroutine resumed after completion") -> [success: bb33, unwind continue]; } - bb34 (cleanup): { - StorageDead(_3); - goto -> bb35; + bb34: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue]; ++ unreachable; } - bb35 (cleanup): { - drop(_2) -> [return: bb36, unwind terminate(cleanup)]; -+ bb35: { -+ unreachable; - } - +- } +- - bb36 (cleanup): { - drop(_1) -> [return: bb37, unwind terminate(cleanup)]; - } @@ -332,7 +329,7 @@ - - bb38 (cleanup): { - drop(_1) -> [return: bb37, unwind terminate(cleanup)]; -+ bb36: { ++ bb35: { + (((*_18) as variant#4).0: std::string::String) = move _2; + StorageLive(_3); + StorageLive(_4); diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff index 97c45da8a18f1..d25c2f61b722a 100644 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff @@ -47,7 +47,7 @@ - _5 = ::clone(move _6) -> [return: bb1, unwind: bb31]; + _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}); + _17 = discriminant((*_18)); -+ switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35]; ++ switchInt(move _17) -> [0: bb35, 1: bb33, 2: bb32, 3: bb30, 4: bb31, otherwise: bb34]; } bb1: { @@ -149,7 +149,7 @@ bb13: { - drop(_1) -> [return: bb14, unwind: bb37]; -+ goto -> bb29; ++ goto -> bb14; } bb14: { @@ -261,39 +261,31 @@ - StorageDead(_12); - StorageDead(_10); - StorageDead(_9); -- goto -> bb29; -+ goto -> bb30; + goto -> bb29; } -- bb29 (cleanup): { + bb29 (cleanup): { - StorageDead(_11); - StorageDead(_8); - goto -> bb35; -+ bb29: { -+ goto -> bb14; - } - - bb30 (cleanup): { -- StorageDead(_7); -- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; + discriminant((*_18)) = 2; + resume; } -- bb31 (cleanup): { -- StorageDead(_6); -- goto -> bb32; -+ bb31: { +- bb30 (cleanup): { +- StorageDead(_7); +- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; ++ bb30: { + StorageLive(_3); + StorageLive(_4); + _3 = move _2; + goto -> bb4; } -- bb32 (cleanup): { -- StorageDead(_5); -- goto -> bb33; -+ bb32: { +- bb31 (cleanup): { +- StorageDead(_6); +- goto -> bb32; ++ bb31: { + StorageLive(_8); + StorageLive(_9); + StorageLive(_11); @@ -302,26 +294,31 @@ + goto -> bb10; } +- bb32 (cleanup): { +- StorageDead(_5); +- goto -> bb33; ++ bb32: { ++ assert(const false, "coroutine resumed after panicking") -> [success: bb32, unwind continue]; + } + - bb33 (cleanup): { - StorageDead(_4); - goto -> bb34; + bb33: { -+ assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue]; ++ assert(const false, "coroutine resumed after completion") -> [success: bb33, unwind continue]; } - bb34 (cleanup): { - StorageDead(_3); - goto -> bb35; + bb34: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue]; ++ unreachable; } - bb35 (cleanup): { - drop(_2) -> [return: bb36, unwind terminate(cleanup)]; -+ bb35: { -+ unreachable; - } - +- } +- - bb36 (cleanup): { - drop(_1) -> [return: bb37, unwind terminate(cleanup)]; - } @@ -332,7 +329,7 @@ - - bb38 (cleanup): { - drop(_1) -> [return: bb37, unwind terminate(cleanup)]; -+ bb36: { ++ bb35: { + (((*_18) as variant#4).0: std::string::String) = move _2; + StorageLive(_3); + StorageLive(_4); diff --git a/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir index f01f48598142c..e8873e341cc77 100644 --- a/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir +++ b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir @@ -14,7 +14,7 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb0: { _7 = discriminant((*_1)); - switchInt(move _7) -> [0: bb5, 3: bb8, otherwise: bb9]; + switchInt(move _7) -> [0: bb5, 3: bb6, otherwise: bb7]; } bb1: { @@ -25,7 +25,7 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb2: { nop; - goto -> bb6; + goto -> bb3; } bb3: { @@ -37,24 +37,16 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 } bb5: { - goto -> bb7; - } - - bb6: { - goto -> bb3; - } - - bb7: { goto -> bb4; } - bb8: { + bb6: { StorageLive(_4); StorageLive(_5); goto -> bb1; } - bb9: { + bb7: { return; } } diff --git a/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir index 64d45346b93c3..9e450d702cc38 100644 --- a/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir @@ -14,7 +14,7 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb0: { _7 = discriminant((*_1)); - switchInt(move _7) -> [0: bb7, 3: bb10, otherwise: bb11]; + switchInt(move _7) -> [0: bb7, 3: bb8, otherwise: bb9]; } bb1: { @@ -25,7 +25,7 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb2: { nop; - goto -> bb8; + goto -> bb3; } bb3: { @@ -46,24 +46,16 @@ fn main::{closure#0}(_1: &mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 } bb7: { - goto -> bb9; - } - - bb8: { - goto -> bb3; - } - - bb9: { goto -> bb6; } - bb10: { + bb8: { StorageLive(_4); StorageLive(_5); goto -> bb1; } - bb11: { + bb9: { return; } } diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff index 9e4fb0cb64788..8c0fbf60ca97c 100644 --- a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff +++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff @@ -51,7 +51,7 @@ - _5 = yield(move _6) -> [resume: bb1, drop: bb6]; + _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}); + _12 = discriminant((*_13)); -+ switchInt(move _12) -> [0: bb10, 1: bb8, 3: bb7, otherwise: bb9]; ++ switchInt(move _12) -> [0: bb9, 1: bb7, 3: bb6, otherwise: bb8]; } bb1: { @@ -88,7 +88,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb5, unwind unreachable]; + nop; -+ goto -> bb6; ++ goto -> bb5; } bb5: { @@ -102,28 +102,24 @@ - StorageDead(_5); - StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; -+ goto -> bb5; ++ StorageLive(_5); ++ StorageLive(_6); ++ _5 = move _2; ++ goto -> bb1; } bb7: { - StorageDead(_3); - drop(_1) -> [return: bb8, unwind unreachable]; -+ StorageLive(_5); -+ StorageLive(_6); -+ _5 = move _2; -+ goto -> bb1; ++ assert(const false, "coroutine resumed after completion") -> [success: bb7, unwind unreachable]; } bb8: { - coroutine_drop; -+ assert(const false, "coroutine resumed after completion") -> [success: bb8, unwind unreachable]; -+ } -+ -+ bb9: { + unreachable; + } + -+ bb10: { ++ bb9: { + nop; + (((*_13) as variant#3).0: Foo) = Foo(const 5_i32); + nop; diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff index fa89df127094a..c0afae90bd28c 100644 --- a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff +++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff @@ -51,7 +51,7 @@ - _5 = yield(move _6) -> [resume: bb1, drop: bb6]; + _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}); + _12 = discriminant((*_13)); -+ switchInt(move _12) -> [0: bb18, 1: bb16, 2: bb15, 3: bb14, otherwise: bb17]; ++ switchInt(move _12) -> [0: bb17, 1: bb15, 2: bb14, 3: bb13, otherwise: bb16]; } bb1: { @@ -90,7 +90,7 @@ - StorageDead(_3); - drop(_1) -> [return: bb5, unwind: bb14]; + nop; -+ goto -> bb12; ++ goto -> bb5; } bb5: { @@ -141,49 +141,44 @@ bb11 (cleanup): { - StorageDead(_8); - StorageDead(_7); -- goto -> bb12; -+ goto -> bb13; + goto -> bb12; } -- bb12 (cleanup): { + bb12 (cleanup): { - StorageDead(_4); - goto -> bb13; -+ bb12: { -+ goto -> bb5; ++ discriminant((*_13)) = 2; ++ resume; } - bb13 (cleanup): { +- bb13 (cleanup): { - StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; -+ discriminant((*_13)) = 2; -+ resume; ++ bb13: { ++ StorageLive(_5); ++ StorageLive(_6); ++ _5 = move _2; ++ goto -> bb1; } - bb14 (cleanup): { - resume; + bb14: { -+ StorageLive(_5); -+ StorageLive(_6); -+ _5 = move _2; -+ goto -> bb1; ++ assert(const false, "coroutine resumed after panicking") -> [success: bb14, unwind continue]; } - bb15 (cleanup): { - StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + bb15: { -+ assert(const false, "coroutine resumed after panicking") -> [success: bb15, unwind continue]; ++ assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind continue]; + } + + bb16: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb16, unwind continue]; -+ } -+ -+ bb17: { + unreachable; + } + -+ bb18: { ++ bb17: { + nop; + (((*_13) as variant#3).0: Foo) = Foo(const 5_i32); + nop; diff --git a/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff index 0c4a54e8d17a3..94e773afa67b2 100644 --- a/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff @@ -69,12 +69,12 @@ goto -> bb15; } - bb9 (cleanup): { - resume; + bb9: { + return; } - bb10: { - return; + bb10 (cleanup): { + resume; } bb11: { @@ -83,7 +83,7 @@ bb12: { _7 = const false; - goto -> bb10; + goto -> bb9; } bb13: { @@ -96,15 +96,15 @@ } bb15: { - switchInt(copy _4) -> [0: bb11, otherwise: bb10]; + switchInt(copy _4) -> [0: bb11, otherwise: bb9]; } bb16 (cleanup): { - goto -> bb9; + goto -> bb10; } bb17 (cleanup): { - switchInt(copy _4) -> [0: bb16, otherwise: bb9]; + switchInt(copy _4) -> [0: bb16, otherwise: bb10]; } } diff --git a/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff index 3599b017876ef..321fcbf680385 100644 --- a/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff @@ -62,12 +62,12 @@ goto -> bb15; } - bb9 (cleanup): { - resume; + bb9: { + return; } - bb10: { - return; + bb10 (cleanup): { + resume; } bb11: { @@ -76,7 +76,7 @@ bb12: { _6 = const false; - goto -> bb10; + goto -> bb9; } bb13: { @@ -89,15 +89,15 @@ } bb15: { - switchInt(copy _4) -> [1: bb11, otherwise: bb10]; + switchInt(copy _4) -> [1: bb11, otherwise: bb9]; } bb16 (cleanup): { - goto -> bb9; + goto -> bb10; } bb17 (cleanup): { - switchInt(copy _4) -> [1: bb16, otherwise: bb9]; + switchInt(copy _4) -> [1: bb16, otherwise: bb10]; } } diff --git a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff index 5355d0d83ff89..6bf6ede926004 100644 --- a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff @@ -363,44 +363,44 @@ } bb11: { - _0 = const 3_u8; - goto -> bb14; + _22 = const false; + _23 = const false; + StorageDead(_2); + _19 = discriminant(_1); + switchInt(move _19) -> [0: bb14, 1: bb13, 2: bb12, otherwise: bb2]; } bb12: { - _0 = const 2_u8; - goto -> bb14; + _0 = const 3_u8; + goto -> bb15; } bb13: { - _0 = const 1_u8; - goto -> bb14; + _0 = const 2_u8; + goto -> bb15; } bb14: { - StorageDead(_1); - return; + _0 = const 1_u8; + goto -> bb15; } bb15: { - _22 = const false; - _23 = const false; - StorageDead(_2); - _19 = discriminant(_1); - switchInt(move _19) -> [0: bb13, 1: bb12, 2: bb11, otherwise: bb2]; + StorageDead(_1); + return; } bb16: { - switchInt(copy _23) -> [0: bb15, otherwise: bb17]; + switchInt(copy _23) -> [0: bb11, otherwise: bb17]; } bb17: { - drop(((_2 as Some).0: std::string::String)) -> [return: bb15, unwind unreachable]; + drop(((_2 as Some).0: std::string::String)) -> [return: bb11, unwind unreachable]; } bb18: { _24 = discriminant(_2); - switchInt(move _24) -> [1: bb16, otherwise: bb15]; + switchInt(move _24) -> [1: bb16, otherwise: bb11]; } bb19: { @@ -489,16 +489,16 @@ + + bb27: { + _24 = discriminant(_2); -+ switchInt(move _24) -> [1: bb28, otherwise: bb15]; ++ switchInt(move _24) -> [1: bb28, otherwise: bb11]; + } + + bb28: { -+ goto -> bb15; ++ goto -> bb11; + } + + bb29: { + _24 = discriminant(_2); -+ switchInt(move _24) -> [1: bb30, otherwise: bb15]; ++ switchInt(move _24) -> [1: bb30, otherwise: bb11]; + } + + bb30: { diff --git a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff index 25f6cc39b42ff..8e52a92f5d0d7 100644 --- a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff @@ -363,61 +363,61 @@ } bb11: { - _0 = const 3_u8; - goto -> bb14; + _22 = const false; + _23 = const false; + StorageDead(_2); + _19 = discriminant(_1); + switchInt(move _19) -> [0: bb14, 1: bb13, 2: bb12, otherwise: bb2]; } bb12: { - _0 = const 2_u8; - goto -> bb14; + _0 = const 3_u8; + goto -> bb15; } bb13: { - _0 = const 1_u8; - goto -> bb14; + _0 = const 2_u8; + goto -> bb15; } bb14: { + _0 = const 1_u8; + goto -> bb15; + } + + bb15: { StorageDead(_1); return; } - bb15 (cleanup): { + bb16 (cleanup): { resume; } - bb16: { - _22 = const false; - _23 = const false; - StorageDead(_2); - _19 = discriminant(_1); - switchInt(move _19) -> [0: bb13, 1: bb12, 2: bb11, otherwise: bb2]; - } - bb17: { - switchInt(copy _23) -> [0: bb16, otherwise: bb18]; + switchInt(copy _23) -> [0: bb11, otherwise: bb18]; } bb18: { - drop(((_2 as Some).0: std::string::String)) -> [return: bb16, unwind: bb15]; + drop(((_2 as Some).0: std::string::String)) -> [return: bb11, unwind: bb16]; } bb19: { _24 = discriminant(_2); - switchInt(move _24) -> [1: bb17, otherwise: bb16]; + switchInt(move _24) -> [1: bb17, otherwise: bb11]; } bb20 (cleanup): { - switchInt(copy _23) -> [0: bb15, otherwise: bb21]; + switchInt(copy _23) -> [0: bb16, otherwise: bb21]; } bb21 (cleanup): { - drop(((_2 as Some).0: std::string::String)) -> [return: bb15, unwind terminate(cleanup)]; + drop(((_2 as Some).0: std::string::String)) -> [return: bb16, unwind terminate(cleanup)]; } bb22 (cleanup): { _26 = discriminant(_2); - switchInt(move _26) -> [1: bb20, otherwise: bb15]; + switchInt(move _26) -> [1: bb20, otherwise: bb16]; } bb23: { @@ -506,16 +506,16 @@ + + bb31: { + _24 = discriminant(_2); -+ switchInt(move _24) -> [1: bb32, otherwise: bb16]; ++ switchInt(move _24) -> [1: bb32, otherwise: bb11]; + } + + bb32: { -+ goto -> bb16; ++ goto -> bb11; + } + + bb33: { + _24 = discriminant(_2); -+ switchInt(move _24) -> [1: bb34, otherwise: bb16]; ++ switchInt(move _24) -> [1: bb34, otherwise: bb11]; + } + + bb34: { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 984e1965e03c5..3b5b917af5c75 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -226,7 +226,7 @@ - bb22: { - drop(_2) -> [return: bb24, unwind: bb26]; + bb19: { -+ goto -> bb24; ++ goto -> bb21; } - bb23: { @@ -251,10 +251,6 @@ - bb26 (cleanup): { + bb23 (cleanup): { resume; -+ } -+ -+ bb24: { -+ goto -> bb21; } } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 984e1965e03c5..3b5b917af5c75 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -226,7 +226,7 @@ - bb22: { - drop(_2) -> [return: bb24, unwind: bb26]; + bb19: { -+ goto -> bb24; ++ goto -> bb21; } - bb23: { @@ -251,10 +251,6 @@ - bb26 (cleanup): { + bb23 (cleanup): { resume; -+ } -+ -+ bb24: { -+ goto -> bb21; } } diff --git a/tests/mir-opt/otherwise_drops.result_ok.ElaborateDrops.diff b/tests/mir-opt/otherwise_drops.result_ok.ElaborateDrops.diff index c9f2f8438990c..d1f4298c86886 100644 --- a/tests/mir-opt/otherwise_drops.result_ok.ElaborateDrops.diff +++ b/tests/mir-opt/otherwise_drops.result_ok.ElaborateDrops.diff @@ -48,7 +48,7 @@ bb5: { - drop(_1) -> [return: bb6, unwind: bb9]; -+ goto -> bb10; ++ goto -> bb6; } bb6: { @@ -67,10 +67,6 @@ bb9 (cleanup): { resume; -+ } -+ -+ bb10: { -+ goto -> bb6; } } diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String].AddMovesForPackedDrops.before.mir index 3c8da0d94bff0..227f02d4c0e25 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String].AddMovesForPackedDrops.before.mir @@ -10,7 +10,7 @@ fn std::ptr::drop_glue(_1: &mut [String]) -> () { let mut _7: bool; bb0: { - goto -> bb8; + goto -> bb7; } bb1: { @@ -48,8 +48,4 @@ fn std::ptr::drop_glue(_1: &mut [String]) -> () { _3 = const 0_usize; goto -> bb6; } - - bb8: { - goto -> bb7; - } } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir index b7423ecc6a02f..4e1a59cea791c 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir @@ -70,7 +70,7 @@ fn method_1(_1: Guard) -> () { } bb7: { - goto -> bb15; + goto -> bb8; } bb8: { @@ -104,8 +104,4 @@ fn method_1(_1: Guard) -> () { bb14 (cleanup): { resume; } - - bb15: { - goto -> bb8; - } } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir index b7423ecc6a02f..4e1a59cea791c 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir @@ -70,7 +70,7 @@ fn method_1(_1: Guard) -> () { } bb7: { - goto -> bb15; + goto -> bb8; } bb8: { @@ -104,8 +104,4 @@ fn method_1(_1: Guard) -> () { bb14 (cleanup): { resume; } - - bb15: { - goto -> bb8; - } } diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_glue.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_glue.Vec_i32_.AddMovesForPackedDrops.before.mir index d249e573a78b7..4f124c666bfb0 100644 --- a/tests/mir-opt/unusual_item_types.core.ptr-drop_glue.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_glue.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -6,7 +6,7 @@ fn std::ptr::drop_glue(_1: &mut Vec) -> () { let mut _3: (); bb0: { - goto -> bb6; + goto -> bb5; } bb1: { @@ -17,20 +17,16 @@ fn std::ptr::drop_glue(_1: &mut Vec) -> () { resume; } - bb3: { - goto -> bb1; - } - - bb4 (cleanup): { + bb3 (cleanup): { drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate(cleanup)]; } - bb5: { - drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb3, unwind: bb2]; + bb4: { + drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb1, unwind: bb2]; } - bb6: { + bb5: { _2 = &mut (*_1); - _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; + _3 = as Drop>::drop(move _2) -> [return: bb4, unwind: bb3]; } } diff --git a/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs b/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs new file mode 100644 index 0000000000000..2a1d4828f4a93 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs @@ -0,0 +1,27 @@ +//@ compile-flags:--crate-name=test +//@ aux-build:coherence_lib.rs + +// Ensure that `Box` in particular isn't fundamental over +// the allocator parameter (but is over T). + +#![feature(allocator_api)] + +extern crate coherence_lib as lib; + +use lib::*; +use std::alloc::{Allocator, AllocError, Layout}; +use std::ptr::NonNull; + +struct Local; + +unsafe impl Allocator for Local { + fn allocate(&self, _layout: Layout) -> Result, AllocError> { + Err(AllocError) + } + unsafe fn deallocate(&self, _ptr: NonNull, _layout: Layout) {} +} + +impl Remote for Box {} + //~^ ERROR: only traits defined in the current crate can be implemented for types defined outside of the crate [E0117] + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-box[foreign_local].stderr b/tests/ui/coherence/impl-foreign-for-box[foreign_local].stderr new file mode 100644 index 0000000000000..26094c7effa9a --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-box[foreign_local].stderr @@ -0,0 +1,15 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/impl-foreign-for-box[foreign_local].rs:24:1 + | +LL | impl Remote for Box {} + | ^^^^^^^^^^^^^^^^--------------- + | | + | `str` is not defined in the current crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr index 596f8436567ae..bdd75df6b77fe 100644 --- a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -2,10 +2,9 @@ error[E0117]: only traits defined in the current crate can be implemented for ty --> $DIR/impl-foreign-for-fundamental[foreign].rs:10:1 | LL | impl Remote for Box { - | ^^^^^------^^^^^-------- - | | | - | | `i32` is not defined in the current crate - | `std::alloc::Global` is not defined in the current crate + | ^^^^^^^^^^^^^^^^-------- + | | + | `i32` is not defined in the current crate | = note: impl doesn't have any local type before any uncovered type parameters = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules @@ -15,10 +14,9 @@ error[E0117]: only traits defined in the current crate can be implemented for ty --> $DIR/impl-foreign-for-fundamental[foreign].rs:14:1 | LL | impl Remote for Box> { - | ^^^^^^^^------^^^^^---------- - | | | - | | `Rc` is not defined in the current crate - | `std::alloc::Global` is not defined in the current crate + | ^^^^^^^^^^^^^^^^^^^---------- + | | + | `Rc` is not defined in the current crate | = note: impl doesn't have any local type before any uncovered type parameters = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr index 91f1886142cf6..af661faa4ea50 100644 --- a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -6,7 +6,6 @@ LL | impl Remote1> for i32 { | | | | | `i32` is not defined in the current crate | `String` is not defined in the current crate - | `std::alloc::Global` is not defined in the current crate | = note: impl doesn't have any local type before any uncovered type parameters = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules @@ -20,7 +19,6 @@ LL | impl Remote1>> for f64 { | | | | | `f64` is not defined in the current crate | `Rc` is not defined in the current crate - | `std::alloc::Global` is not defined in the current crate | = note: impl doesn't have any local type before any uncovered type parameters = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules @@ -34,7 +32,6 @@ LL | impl Remote1>> for f32 { | | | | | `f32` is not defined in the current crate | `Rc` is not defined in the current crate - | `std::alloc::Global` is not defined in the current crate | = note: impl doesn't have any local type before any uncovered type parameters = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules diff --git a/tests/ui/consts/const-eval/atomic.rs b/tests/ui/consts/const-eval/atomic.rs new file mode 100644 index 0000000000000..c8501851653d0 --- /dev/null +++ b/tests/ui/consts/const-eval/atomic.rs @@ -0,0 +1,99 @@ +//@ check-pass +#![feature(const_atomic, const_raw_ptr_comparison)] + +use std::sync::atomic::*; +use std::sync::atomic::Ordering::*; + +const BOOL: () = { + let mut atomic: AtomicBool = AtomicBool::new(false); + + unsafe { + assert!(*atomic.get_mut() == false); + atomic.store(true, SeqCst); + assert!(*atomic.get_mut() == true); + atomic.fetch_or(false, SeqCst); + assert!(*atomic.get_mut() == true); + atomic.fetch_and(false, SeqCst); + assert!(*atomic.get_mut() == false); + atomic.fetch_nand(true, SeqCst); + assert!(*atomic.get_mut() == true); + atomic.fetch_xor(true, SeqCst); + assert!(*atomic.get_mut() == false); + } +}; + +const FENCES: () = { + fence(SeqCst); + fence(Release); + fence(Acquire); + fence(AcqRel); + compiler_fence(SeqCst); + compiler_fence(Release); + compiler_fence(Acquire); + compiler_fence(AcqRel); +}; + +const fn compare_result_u64(a: Result, b: Result) -> bool { + match (a, b) { + (Ok(a), Ok(b)) => a == b, + (Err(a), Err(b)) => a == b, + _ => false, + } +} + +#[cfg(target_has_atomic = "64")] +const ATOMIC_INT: () = { + let atomic = AtomicU64::new(0); + + atomic.store(1, SeqCst); + assert!(compare_result_u64(atomic.compare_exchange(0, 0x100, AcqRel, Acquire), Err(1))); + assert!(compare_result_u64(atomic.compare_exchange(0, 1, Release, Relaxed), Err(1))); + assert!(compare_result_u64(atomic.compare_exchange(1, 0, AcqRel, Relaxed), Ok(1))); + assert!(compare_result_u64(atomic.compare_exchange(0, 1, Relaxed, Relaxed), Ok(0))); + // compare_exchange_weak always succeeds when possible, but that is not a guarantee. + assert!(compare_result_u64(atomic.compare_exchange_weak(1, 0x100, AcqRel, Acquire), Ok(1))); + assert!(compare_result_u64(atomic.compare_exchange_weak(0, 2, Acquire, Relaxed), Err(0x100))); + assert!(compare_result_u64(atomic.compare_exchange_weak(0, 1, Release, Relaxed), Err(0x100))); + assert!(atomic.load(Relaxed) == 0x100); + + assert!(atomic.fetch_max(0x10, SeqCst) == 0x100); + assert!(atomic.fetch_max(0x100, SeqCst) == 0x100); + assert!(atomic.fetch_max(0x1000, SeqCst) == 0x100); + assert!(atomic.fetch_max(0x1000, SeqCst) == 0x1000); + assert!(atomic.fetch_max(0x2000, SeqCst) == 0x1000); + assert!(atomic.fetch_max(0x2000, SeqCst) == 0x2000); + + assert!(atomic.fetch_min(0x2000, SeqCst) == 0x2000); + assert!(atomic.fetch_min(0x2000, SeqCst) == 0x2000); + assert!(atomic.fetch_min(0x1000, SeqCst) == 0x2000); + assert!(atomic.fetch_min(0x1000, SeqCst) == 0x1000); + assert!(atomic.fetch_min(0x100, SeqCst) == 0x1000); + assert!(atomic.fetch_min(0x10, SeqCst) == 0x100); + + assert!(atomic.swap(1, SeqCst) == 0x10); + assert!(atomic.load(Relaxed) == 1); + + let atomic_signed = AtomicI64::new(0); + assert!(atomic_signed.fetch_min(-1, SeqCst) == 0); + assert!(atomic_signed.load(SeqCst) == -1); + assert!(atomic_signed.fetch_min(1, SeqCst) == -1); + assert!(atomic_signed.load(SeqCst) == -1); + assert!(atomic_signed.fetch_max(1, SeqCst) == -1); + assert!(atomic_signed.load(SeqCst) == 1); + assert!(atomic_signed.fetch_max(-1, SeqCst) == 1); + assert!(atomic_signed.load(SeqCst) == 1); +}; + +const ATOMIC_PTR: () = { + use std::ptr; + let array = [0i32; 4]; // a target to point to, to test provenance things + let x = array.as_ptr() as *mut i32; + + let ptr = AtomicPtr::::new(ptr::null_mut()); + assert!(ptr.load(Relaxed).guaranteed_eq(0 as *mut i32).unwrap()); + ptr.store(ptr::without_provenance_mut(13), SeqCst); + assert!(ptr.swap(x, Relaxed).guaranteed_eq(13 as *mut i32).unwrap()); + unsafe { assert!(ptr.load(Acquire).read() == 0) }; +}; + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs index 9546f34792ad4..205eb1d7fe935 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -8,7 +8,7 @@ use std::sync::atomic::Ordering; const MUTATE_INTERIOR_MUT: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); - FOO.fetch_add(1, Ordering::Relaxed) //~ERROR calling non-const function `Atomic::::fetch_add` + FOO.fetch_add(1, Ordering::Relaxed) //~ERROR constant accesses mutable global memory }; const READ_INTERIOR_MUT: usize = { diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr index 852b4518a920c..e718aac5329a4 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -1,8 +1,17 @@ -error[E0080]: calling non-const function `Atomic::::fetch_add` +error[E0080]: constant accesses mutable global memory --> $DIR/const_refers_to_static.rs:11:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `MUTATE_INTERIOR_MUT` failed here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `MUTATE_INTERIOR_MUT` failed inside this call + | +note: inside `Atomic::::fetch_add` + --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL + ::: $SRC_DIR/core/src/sync/atomic.rs:LL:COL + | + = note: in this macro invocation +note: inside `atomic::atomic_add::` + --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL + = note: this error originates in the macro `atomic_int` which comes from the expansion of the macro `atomic_int_ptr_sized` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: constant accesses mutable global memory --> $DIR/const_refers_to_static.rs:16:14 @@ -26,7 +35,7 @@ LL | REF_INTERIOR_MUT => {}, warning: skipping const checks | -help: skipping check that does not even have a feature gate +help: skipping check for `const_atomic` feature --> $DIR/const_refers_to_static.rs:11:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 65be5d90d011c..a88bb52738e9f 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -28,6 +28,7 @@ LL | help(1)?; | ^^^^^^^ the trait `From` is not implemented for `()` | = help: the following other types implement trait `From`: + `(T,)` implements `From<[T; 1]>` `(T, T)` implements `From<[T; 2]>` `(T, T, T)` implements `From<[T; 3]>` `(T, T, T, T)` implements `From<[T; 4]>` @@ -35,7 +36,6 @@ LL | help(1)?; `(T, T, T, T, T, T)` implements `From<[T; 6]>` `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` - `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` and 4 others = note: required for `!` to implement `Into<()>` note: required by a bound in `help` diff --git a/tests/ui/feature-gates/feature-gate-register_tool.rs b/tests/ui/feature-gates/feature-gate-register_tool.rs index 4034a95e8fb65..e884e1d4c070d 100644 --- a/tests/ui/feature-gates/feature-gate-register_tool.rs +++ b/tests/ui/feature-gates/feature-gate-register_tool.rs @@ -1,3 +1,4 @@ +#![allow(duplicate_tools)] //~ WARN [unknown_lints] #![register_tool(tool)] //~ ERROR the `register_tool` attribute is an experimental feature #![register_attribute_tool(attr_tool)] //~ ERROR the `register_attribute_tool` attribute is an experimental feature #![register_lint_tool(lint_tool)] //~ ERROR the `register_lint_tool` attribute is an experimental feature diff --git a/tests/ui/feature-gates/feature-gate-register_tool.stderr b/tests/ui/feature-gates/feature-gate-register_tool.stderr index 678ae48a00143..5f7a83a7c3a6c 100644 --- a/tests/ui/feature-gates/feature-gate-register_tool.stderr +++ b/tests/ui/feature-gates/feature-gate-register_tool.stderr @@ -1,5 +1,17 @@ +warning: unknown lint: `duplicate_tools` + --> $DIR/feature-gate-register_tool.rs:1:10 + | +LL | #![allow(duplicate_tools)] + | ^^^^^^^^^^^^^^^ + | + = note: the `duplicate_tools` lint is unstable + = note: see issue #66079 for more information + = help: add `#![feature(register_tool)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: `#[warn(unknown_lints)]` on by default + error[E0658]: the `register_tool` attribute is an experimental feature - --> $DIR/feature-gate-register_tool.rs:1:4 + --> $DIR/feature-gate-register_tool.rs:2:4 | LL | #![register_tool(tool)] | ^^^^^^^^^^^^^ @@ -9,7 +21,7 @@ LL | #![register_tool(tool)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `register_attribute_tool` attribute is an experimental feature - --> $DIR/feature-gate-register_tool.rs:2:4 + --> $DIR/feature-gate-register_tool.rs:3:4 | LL | #![register_attribute_tool(attr_tool)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +31,7 @@ LL | #![register_attribute_tool(attr_tool)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `register_lint_tool` attribute is an experimental feature - --> $DIR/feature-gate-register_tool.rs:3:4 + --> $DIR/feature-gate-register_tool.rs:4:4 | LL | #![register_lint_tool(lint_tool)] | ^^^^^^^^^^^^^^^^^^ @@ -28,6 +40,6 @@ LL | #![register_lint_tool(lint_tool)] = help: add `#![feature(register_tool)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/fn/fn-ptr-pattern.rs b/tests/ui/fn/fn-ptr-pattern.rs new file mode 100644 index 0000000000000..017356d561915 --- /dev/null +++ b/tests/ui/fn/fn-ptr-pattern.rs @@ -0,0 +1,28 @@ +fn patterns( + pat1: fn(true: bool), + //~^ ERROR patterns aren't allowed in function pointer types + pat2: fn(1..3: bool), + //~^ ERROR patterns aren't allowed in function pointer types + pat3: fn((x, y): (bool, bool)), + //~^ ERROR patterns aren't allowed in function pointer types + pat4: fn(self), + //~^ ERROR `self` parameter is only allowed in associated functions + pat5: fn(self, self), + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR unexpected `self` parameter in function + pat6: fn(bool, self), + //~^ ERROR unexpected `self` parameter in function + pat7: fn(Thing { a, b }: Thing), + //~^ ERROR patterns aren't allowed in function pointer types + pat8: fn(NoThing { a, b }: NoThing), + //~^ ERROR patterns aren't allowed in function pointer types + //~| ERROR cannot find type `NoThing` in this scope + pat9: fn((((((x))))): bool), + //~^ ERROR patterns aren't allowed in function pointer types +) { } + +struct Thing { a: bool, b: bool } + +fn main() { + +} diff --git a/tests/ui/fn/fn-ptr-pattern.stderr b/tests/ui/fn/fn-ptr-pattern.stderr new file mode 100644 index 0000000000000..99d890cbbc9dc --- /dev/null +++ b/tests/ui/fn/fn-ptr-pattern.stderr @@ -0,0 +1,113 @@ +error[E0642]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:4:14 + | +LL | pat2: fn(1..3: bool), + | ^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat2: fn(1..3: bool), +LL + pat2: fn(_: bool), + | + +error[E0642]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:6:14 + | +LL | pat3: fn((x, y): (bool, bool)), + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat3: fn((x, y): (bool, bool)), +LL + pat3: fn(_: (bool, bool)), + | + +error: unexpected `self` parameter in function + --> $DIR/fn-ptr-pattern.rs:10:20 + | +LL | pat5: fn(self, self), + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/fn-ptr-pattern.rs:13:20 + | +LL | pat6: fn(bool, self), + | ^^^^ must be the first parameter of an associated function + +error[E0642]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:15:14 + | +LL | pat7: fn(Thing { a, b }: Thing), + | ^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat7: fn(Thing { a, b }: Thing), +LL + pat7: fn(_: Thing), + | + +error[E0642]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:17:14 + | +LL | pat8: fn(NoThing { a, b }: NoThing), + | ^^^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat8: fn(NoThing { a, b }: NoThing), +LL + pat8: fn(_: NoThing), + | + +error[E0642]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:20:14 + | +LL | pat9: fn((((((x))))): bool), + | ^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat9: fn((((((x))))): bool), +LL + pat9: fn(_: bool), + | + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/fn-ptr-pattern.rs:2:14 + | +LL | pat1: fn(true: bool), + | ^^^^ + +error: `self` parameter is only allowed in associated functions + --> $DIR/fn-ptr-pattern.rs:8:14 + | +LL | pat4: fn(self), + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/fn-ptr-pattern.rs:10:14 + | +LL | pat5: fn(self, self), + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0425]: cannot find type `NoThing` in this scope + --> $DIR/fn-ptr-pattern.rs:17:32 + | +LL | pat8: fn(NoThing { a, b }: NoThing), + | ^^^^^^^ +... +LL | struct Thing { a: bool, b: bool } + | ------------ similarly named struct `Thing` defined here + | +help: a struct with a similar name exists + | +LL - pat8: fn(NoThing { a, b }: NoThing), +LL + pat8: fn(NoThing { a, b }: Thing), + | + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0425, E0561, E0642. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.rs b/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.rs new file mode 100644 index 0000000000000..83a3577707364 --- /dev/null +++ b/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.rs @@ -0,0 +1,21 @@ +use std::fmt::Debug; + +fn testing_debug(t: T) {} +fn testing_mytrait(t: T) {} + +trait MyTrait {} + +impl MyTrait for (i8,) {} +impl MyTrait for (i8,i8) {} +impl MyTrait for (i8,i8,i8) {} +impl MyTrait for (i8,i8,i8,i8) {} +impl MyTrait for (i8,i8,i8,i8,i8) {} + +struct Foo; + +fn main() { + testing_debug((1, Foo)); + //~^ ERROR `Foo` doesn't implement `Debug` [E0277] + testing_mytrait((1, Foo)); + //~^ ERROR the trait bound `({integer}, Foo): MyTrait` is not satisfied [E0277] +} diff --git a/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.stderr b/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.stderr new file mode 100644 index 0000000000000..fb9bb2642971a --- /dev/null +++ b/tests/ui/suggestions/multiple_tuples_implement_same_trait_continuous_arities.stderr @@ -0,0 +1,42 @@ +error[E0277]: `Foo` doesn't implement `Debug` + --> $DIR/multiple_tuples_implement_same_trait_continuous_arities.rs:17:23 + | +LL | testing_debug((1, Foo)); + | ------------- ^^^ the trait `Debug` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Debug`: + (T₁, T₂, …, Tₙ) up to tuples of arity 12 + and 5 others + = note: required for `({integer}, Foo)` to implement `Debug` +note: required by a bound in `testing_debug` + --> $DIR/multiple_tuples_implement_same_trait_continuous_arities.rs:3:21 + | +LL | fn testing_debug(t: T) {} + | ^^^^^ required by this bound in `testing_debug` +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | struct Foo; + | + +error[E0277]: the trait bound `({integer}, Foo): MyTrait` is not satisfied + --> $DIR/multiple_tuples_implement_same_trait_continuous_arities.rs:19:21 + | +LL | testing_mytrait((1, Foo)); + | --------------- ^^^^^^^^ the trait `MyTrait` is not implemented for `({integer}, Foo)` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `MyTrait`: + (T₁, T₂, …, Tₙ) for tuples of arity 1 up to and including 5 +note: required by a bound in `testing_mytrait` + --> $DIR/multiple_tuples_implement_same_trait_continuous_arities.rs:4:23 + | +LL | fn testing_mytrait(t: T) {} + | ^^^^^^^ required by this bound in `testing_mytrait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.rs b/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.rs new file mode 100644 index 0000000000000..d5d860ceab838 --- /dev/null +++ b/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.rs @@ -0,0 +1,23 @@ +fn testing_mytrait(t: T) {} +fn testing_anothertrait(t: T) {} + +trait MyTrait {} + +impl MyTrait for (i8,) {} +impl MyTrait for (i8,i8,i8) {} +impl MyTrait for (i8,i8,i8,i8) {} +impl MyTrait for (i8,i8,i8,i8,i8) {} +impl MyTrait for (i8,i8,i8,i8,i8,i8) {} + +trait AnotherTrait {} +impl AnotherTrait for (i8,) {} +impl AnotherTrait for (i8,i8) {} + +struct Foo; + +fn main() { + testing_mytrait((1, Foo)); + //~^ ERROR the trait bound `({integer}, Foo): MyTrait` is not satisfied [E0277] + testing_anothertrait((1, Foo)); + //~^ ERROR the trait bound `({integer}, Foo): AnotherTrait` is not satisfied [E0277] +} diff --git a/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.stderr b/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.stderr new file mode 100644 index 0000000000000..1786c2142f677 --- /dev/null +++ b/tests/ui/suggestions/multiple_tuples_implement_same_trait_discontinuous_arities.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `({integer}, Foo): MyTrait` is not satisfied + --> $DIR/multiple_tuples_implement_same_trait_discontinuous_arities.rs:19:21 + | +LL | testing_mytrait((1, Foo)); + | --------------- ^^^^^^^^ the trait `MyTrait` is not implemented for `({integer}, Foo)` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `MyTrait`: + (i8,) + (i8, i8, i8) + (i8, i8, i8, i8) + (i8, i8, i8, i8, i8) + (i8, i8, i8, i8, i8, i8) +note: required by a bound in `testing_mytrait` + --> $DIR/multiple_tuples_implement_same_trait_discontinuous_arities.rs:1:23 + | +LL | fn testing_mytrait(t: T) {} + | ^^^^^^^ required by this bound in `testing_mytrait` + +error[E0277]: the trait bound `({integer}, Foo): AnotherTrait` is not satisfied + --> $DIR/multiple_tuples_implement_same_trait_discontinuous_arities.rs:21:26 + | +LL | testing_anothertrait((1, Foo)); + | -------------------- ^^^^^^^^ the trait `AnotherTrait` is not implemented for `({integer}, Foo)` + | | + | required by a bound introduced by this call + | +help: the following other types implement trait `AnotherTrait` + --> $DIR/multiple_tuples_implement_same_trait_discontinuous_arities.rs:13:1 + | +LL | impl AnotherTrait for (i8,) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(i8,)` +LL | impl AnotherTrait for (i8,i8) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(i8, i8)` +note: required by a bound in `testing_anothertrait` + --> $DIR/multiple_tuples_implement_same_trait_discontinuous_arities.rs:2:28 + | +LL | fn testing_anothertrait(t: T) {} + | ^^^^^^^^^^^^ required by this bound in `testing_anothertrait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/tool-attributes/auxiliary/use_tool.rs b/tests/ui/tool-attributes/auxiliary/use_tool.rs new file mode 100644 index 0000000000000..3faf2424c3b9b --- /dev/null +++ b/tests/ui/tool-attributes/auxiliary/use_tool.rs @@ -0,0 +1,2 @@ +#![feature(register_tool)] +#![register_tool(foo)] diff --git a/tests/ui/tool-attributes/crate-attr-dup-tool.rs b/tests/ui/tool-attributes/crate-attr-dup-tool.rs new file mode 100644 index 0000000000000..72bd2f013697d --- /dev/null +++ b/tests/ui/tool-attributes/crate-attr-dup-tool.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ compile-flags: -Z crate-attr=feature(register_tool) -Z crate-attr=register_tool(foo) +//@ compile-flags: -Z crate-attr=register_attribute_tool(bar) -Z crate-attr=register_lint_tool(baz) +//@ compile-flags: -A duplicate_features -A duplicate_tools +#![feature(register_tool)] +#![register_tool(foo)] +#![register_attribute_tool(bar)] +#![register_lint_tool(baz)] + +#[foo::foo] +#[bar::bar] +#[allow(foo::baz, baz::baz)] +fn main() {} diff --git a/tests/ui/tool-attributes/cross-crate.rs b/tests/ui/tool-attributes/cross-crate.rs new file mode 100644 index 0000000000000..1992174aca3e1 --- /dev/null +++ b/tests/ui/tool-attributes/cross-crate.rs @@ -0,0 +1,10 @@ +//@ aux-build: use_tool.rs + +// `use_tool` references tool "foo", and we want to check that it has no impact on this crate. +extern crate use_tool; + +#[foo::bar] //~ ERROR cannot find module or crate `foo` in this scope +#[allow(foo::baz)] //~ ERROR unknown tool name `foo` + //~| ERROR unknown tool name `foo` + //~| ERROR unknown tool name `foo` +fn main() {} diff --git a/tests/ui/tool-attributes/cross-crate.stderr b/tests/ui/tool-attributes/cross-crate.stderr new file mode 100644 index 0000000000000..051a1b05405e9 --- /dev/null +++ b/tests/ui/tool-attributes/cross-crate.stderr @@ -0,0 +1,36 @@ +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::baz` + --> $DIR/cross-crate.rs:7:9 + | +LL | #[allow(foo::baz)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error[E0433]: cannot find module or crate `foo` in this scope + --> $DIR/cross-crate.rs:6:3 + | +LL | #[foo::bar] + | ^^^ use of unresolved module or unlinked crate `foo` + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::baz` + --> $DIR/cross-crate.rs:7:9 + | +LL | #[allow(foo::baz)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::baz` + --> $DIR/cross-crate.rs:7:9 + | +LL | #[allow(foo::baz)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0433, E0710. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/tool-attributes/duplicate-tool.rs b/tests/ui/tool-attributes/duplicate-tool.rs index 603292d1eb3cd..3c5ede7698202 100644 --- a/tests/ui/tool-attributes/duplicate-tool.rs +++ b/tests/ui/tool-attributes/duplicate-tool.rs @@ -1,15 +1,16 @@ //@ check-pass #![feature(register_tool)] +#![warn(duplicate_tools)] // Register a tool multiple times is okay. #![register_tool(foo)] -#![register_tool(foo)] +#![register_tool(foo)] //~ WARN [duplicate_tools] #![register_tool(bar)] -#![register_attribute_tool(bar)] +#![register_attribute_tool(bar)] //~ WARN [duplicate_tools] #![register_tool(baz)] -#![register_lint_tool(baz)] -#![register_attribute_tool(qux)] +#![register_lint_tool(baz)] //~ WARN [duplicate_tools] #![register_attribute_tool(qux)] +#![register_attribute_tool(qux)] //~ WARN [duplicate_tools] #![register_lint_tool(quux)] -#![register_lint_tool(quux)] +#![register_lint_tool(quux)] //~ WARN [duplicate_tools] fn main() {} diff --git a/tests/ui/tool-attributes/duplicate-tool.stderr b/tests/ui/tool-attributes/duplicate-tool.stderr new file mode 100644 index 0000000000000..b0298f6414d57 --- /dev/null +++ b/tests/ui/tool-attributes/duplicate-tool.stderr @@ -0,0 +1,48 @@ +warning: duplicate tool `foo` registered + --> $DIR/duplicate-tool.rs:6:18 + | +LL | #![register_tool(foo)] + | --- already registered here +LL | #![register_tool(foo)] + | ^^^ + | +note: the lint level is defined here + --> $DIR/duplicate-tool.rs:3:9 + | +LL | #![warn(duplicate_tools)] + | ^^^^^^^^^^^^^^^ + +warning: duplicate tool `bar` registered + --> $DIR/duplicate-tool.rs:8:28 + | +LL | #![register_tool(bar)] + | --- already registered here +LL | #![register_attribute_tool(bar)] + | ^^^ + +warning: duplicate tool `baz` registered + --> $DIR/duplicate-tool.rs:10:23 + | +LL | #![register_tool(baz)] + | --- already registered here +LL | #![register_lint_tool(baz)] + | ^^^ + +warning: duplicate tool `qux` registered + --> $DIR/duplicate-tool.rs:12:28 + | +LL | #![register_attribute_tool(qux)] + | --- already registered here +LL | #![register_attribute_tool(qux)] + | ^^^ + +warning: duplicate tool `quux` registered + --> $DIR/duplicate-tool.rs:14:23 + | +LL | #![register_lint_tool(quux)] + | ---- already registered here +LL | #![register_lint_tool(quux)] + | ^^^^ + +warning: 5 warnings emitted + diff --git a/tests/ui/tool-attributes/invalid-tool.rs b/tests/ui/tool-attributes/invalid-tool.rs index aec31cc7f667c..51bf9bdf4b043 100644 --- a/tests/ui/tool-attributes/invalid-tool.rs +++ b/tests/ui/tool-attributes/invalid-tool.rs @@ -2,5 +2,24 @@ #![register_tool(1)] //~^ ERROR malformed `register_tool` attribute input +#![register_tool(_)] +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR expected identifier, found reserved identifier `_` +//~| ERROR expected identifier, found reserved identifier `_` +//~| ERROR malformed `register_tool` attribute input + +// Special path keywords cannot be used. +#![register_tool(crate)] +//~^ ERROR malformed `register_tool` attribute input +#![register_tool(self)] +//~^ ERROR malformed `register_tool` attribute input +#![register_tool(Self)] +//~^ ERROR malformed `register_tool` attribute input +#![register_tool(super)] +//~^ ERROR malformed `register_tool` attribute input + +// These are okay +#![register_tool(r#type)] +#![register_tool(铁锈)] fn main() {} diff --git a/tests/ui/tool-attributes/invalid-tool.stderr b/tests/ui/tool-attributes/invalid-tool.stderr index b4e2c3e7eaccb..5d7742c45d248 100644 --- a/tests/ui/tool-attributes/invalid-tool.stderr +++ b/tests/ui/tool-attributes/invalid-tool.stderr @@ -1,3 +1,17 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/invalid-tool.rs:5:18 + | +LL | #![register_tool(_)] + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/invalid-tool.rs:5:18 + | +LL | #![register_tool(_)] + | ^ expected identifier, found reserved identifier + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0565]: malformed `register_tool` attribute input --> $DIR/invalid-tool.rs:3:4 | @@ -12,6 +26,84 @@ LL - #![register_tool(1)] LL + #![register_tool(tool1, tool2, ...)] | -error: aborting due to 1 previous error +error: expected identifier, found reserved identifier `_` + --> $DIR/invalid-tool.rs:5:18 + | +LL | #![register_tool(_)] + | ^ expected identifier, found reserved identifier + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0565]: malformed `register_tool` attribute input + --> $DIR/invalid-tool.rs:5:4 + | +LL | #![register_tool(_)] + | ^^^^^^^^^^^^^^-^ + | | + | expected a valid identifier here + | +help: must be of the form + | +LL - #![register_tool(_)] +LL + #![register_tool(tool1, tool2, ...)] + | + +error[E0565]: malformed `register_tool` attribute input + --> $DIR/invalid-tool.rs:12:4 + | +LL | #![register_tool(crate)] + | ^^^^^^^^^^^^^^-----^ + | | + | expected a valid identifier here + | +help: must be of the form + | +LL - #![register_tool(crate)] +LL + #![register_tool(tool1, tool2, ...)] + | + +error[E0565]: malformed `register_tool` attribute input + --> $DIR/invalid-tool.rs:14:4 + | +LL | #![register_tool(self)] + | ^^^^^^^^^^^^^^----^ + | | + | expected a valid identifier here + | +help: must be of the form + | +LL - #![register_tool(self)] +LL + #![register_tool(tool1, tool2, ...)] + | + +error[E0565]: malformed `register_tool` attribute input + --> $DIR/invalid-tool.rs:16:4 + | +LL | #![register_tool(Self)] + | ^^^^^^^^^^^^^^----^ + | | + | expected a valid identifier here + | +help: must be of the form + | +LL - #![register_tool(Self)] +LL + #![register_tool(tool1, tool2, ...)] + | + +error[E0565]: malformed `register_tool` attribute input + --> $DIR/invalid-tool.rs:18:4 + | +LL | #![register_tool(super)] + | ^^^^^^^^^^^^^^-----^ + | | + | expected a valid identifier here + | +help: must be of the form + | +LL - #![register_tool(super)] +LL + #![register_tool(tool1, tool2, ...)] + | + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.stderr b/tests/ui/traits/const-traits/reservation-impl-ice.stderr index d30c014d63f11..125a4710693cc 100644 --- a/tests/ui/traits/const-traits/reservation-impl-ice.stderr +++ b/tests/ui/traits/const-traits/reservation-impl-ice.stderr @@ -5,6 +5,7 @@ LL | impls_from::<()>(); | ^^ the trait `From` is not implemented for `()` | = help: the following other types implement trait `From`: + `(T,)` implements `From<[T; 1]>` `(T, T)` implements `From<[T; 2]>` `(T, T, T)` implements `From<[T; 3]>` `(T, T, T, T)` implements `From<[T; 4]>` @@ -12,7 +13,6 @@ LL | impls_from::<()>(); `(T, T, T, T, T, T)` implements `From<[T; 6]>` `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` - `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` and 4 others note: required by a bound in `impls_from` --> $DIR/reservation-impl-ice.rs:4:24 diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr index 20454e12de558..f5055e05c7cd3 100644 --- a/tests/ui/try-trait/issue-32709.stderr +++ b/tests/ui/try-trait/issue-32709.stderr @@ -10,6 +10,7 @@ LL | Err(5)?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: + `(T,)` implements `From<[T; 1]>` `(T, T)` implements `From<[T; 2]>` `(T, T, T)` implements `From<[T; 3]>` `(T, T, T, T)` implements `From<[T; 4]>` @@ -17,7 +18,6 @@ LL | Err(5)?; `(T, T, T, T, T, T)` implements `From<[T; 6]>` `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` - `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` and 4 others error: aborting due to 1 previous error