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_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f3eb55afa4ec7..10e20ac06864f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1604,8 +1604,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ), } } - CastKind::Subtype => { - bug!("CastKind::Subtype shouldn't exist in borrowck") + CastKind::Subtype | CastKind::BoxDerefTransmute => { + bug!("CastKind::{cast_kind:?} shouldn't exist in borrowck") } } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 451983a9053b8..d57f662fc1938 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -823,7 +823,11 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: let operand = codegen_operand(fx, operand); crate::unsize::coerce_unsized_into(fx, operand, lval); } - Rvalue::Cast(CastKind::Transmute | CastKind::Subtype, ref operand, _to_ty) => { + Rvalue::Cast( + CastKind::Transmute | CastKind::BoxDerefTransmute | CastKind::Subtype, + ref operand, + _to_ty, + ) => { let operand = codegen_operand(fx, operand); lval.write_cvalue_transmute(fx, operand); } 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_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index a5d78fc8a7f35..344a4834862e4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -619,7 +619,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("Unsupported cast of {operand:?} to {cast:?}"); }) } - mir::CastKind::Transmute | mir::CastKind::Subtype => { + mir::CastKind::Transmute | mir::CastKind::BoxDerefTransmute | mir::CastKind::Subtype => { self.codegen_transmute_operand(bx, operand, cast) } }; diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 8c0500e0e6593..d5c7a9762cd4a 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -17,7 +17,7 @@ use super::{ throw_ub_format, }; use crate::enter_trace_span; -use crate::interpret::Writeable; +use crate::interpret::{Projectable, Writeable}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn cast( @@ -31,10 +31,66 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // possible. let cast_layout = if cast_ty == dest.layout.ty { dest.layout } else { self.layout_of(cast_ty)? }; - // FIXME: In which cases should we trigger UB when the source is uninit? + + // Check that the input is valid. + // Can be skipped for transmuts and unsizing as those do validation below. + if !matches!( + cast_kind, + CastKind::Transmute + | CastKind::Subtype + | CastKind::BoxDerefTransmute + | CastKind::PointerCoercion(PointerCoercion::Unsize, _) + ) && M::enforce_validity(self, src.layout) + { + match src.layout.ty.kind() { + ty::RawPtr { .. } => { + // We only need to check anything for wide pointers. + if matches!(src.layout.backend_repr, rustc_abi::BackendRepr::ScalarPair { .. }) + { + self.deref_pointer(src)?; + } + } + ty::FnPtr { .. } => { + let ptr = self.read_pointer(src)?; + self.get_ptr_fn(ptr)?; + } + ty::Closure(_closure, args) => { + // Can only happen for non-capturing closures, which have nothing to validate. + let args = args.as_closure(); + assert!(args.upvar_tys().is_empty()); + } + // Types that have no requirements or whose requirements are checked by the actual + // cast operation. + ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Bool + | ty::Char + | ty::FnDef(..) => {} + + _ => { + span_bug!( + self.cur_span(), + "unexpected input type in non-transmute/unsize cast: {}", + src.layout.ty + ) + } + } + } + match cast_kind { CastKind::PointerCoercion(PointerCoercion::Unsize, _) => { self.unsize_into(src, cast_layout, dest)?; + // Validate the entire thing and reset any padding in the output. + // It is enough to validate the output because we are only adding metadata, + // not discarding anything from the input that may have been invalid. + if M::enforce_validity(self, dest.layout()) { + self.validate_place( + dest, + M::enforce_validity_recursively(self, dest.layout()), + /*reset_provenance_and_padding*/ true, + )?; + } } CastKind::PointerExposeProvenance => { @@ -133,7 +189,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - CastKind::Transmute | CastKind::Subtype => { + CastKind::Transmute | CastKind::Subtype | CastKind::BoxDerefTransmute => { assert!(src.layout.is_sized()); assert!(dest.layout.is_sized()); assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely... @@ -147,6 +203,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); } + if matches!(cast_kind, CastKind::BoxDerefTransmute) { + // Do the extra UB checking by making the input an actual `Box` pointer + // and dereferencing it. + let ptr = self.read_immediate(src)?; + let pointee_ty = cast_ty.builtin_deref(true).unwrap(); + let box_ty = Ty::new_box(*self.tcx, pointee_ty); + let ptr = ptr.transmute(self.layout_of(box_ty)?, self)?; + self.deref_pointer(&ptr)?; + } + + // This does validation at `src` and `dest` type. self.copy_op_allow_transmute(src, dest)?; } } @@ -266,6 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Let's make sure v is sign-extended *if* it has a signed type. let signed = src_layout.backend_repr.is_signed(); // Also asserts that abi is `Scalar`. + // We go through the actual type of `src` to ensure the value is valid. let v = match src_layout.ty.kind() { ty::Uint(_) | ty::RawPtr(..) | ty::FnPtr(..) => scalar.to_uint(src_layout.size)?, ty::Int(_) => scalar.to_int(src_layout.size)? as u128, // we will cast back to `i128` below if the sign matters @@ -458,6 +526,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } + /// Perform an unsizing coercion. The caller is responsible for checking validity afterwards! pub fn unsize_into( &mut self, src: &OpTy<'tcx, M::Provenance>, @@ -489,7 +558,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if src_field.layout.is_1zst() && cast_ty_field.is_1zst() { // Skip 1-ZST fields. } else if src_field.layout.ty == cast_ty_field.ty { - self.copy_op(&src_field, &dst_field)?; + // The caller performs validation. + self.copy_op_no_validate( + &src_field, &dst_field, /* allow_transmute */ false, + )?; } else { if found_cast_field { span_bug!(self.cur_span(), "unsize_into: more than one field to cast"); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 23f95c2797f2e..f8c308ece55b7 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); } @@ -472,7 +476,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Check that the memory between them is dereferenceable at all, starting from the // origin pointer: `dist` is `a - b`, so it is based on `b`. - self.check_ptr_access_signed(b, dist, CheckInAllocMsg::Dereferenceable) + self.check_ptr_access_signed(b, dist, CheckInAllocMsg::Dereferenceable("pointer")) .map_err_kind(|_| { // This could mean they point to different allocations, or they point to the same allocation // but not the entire range between the pointers is in-bounds. @@ -494,7 +498,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.check_ptr_access_signed( a, dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large - CheckInAllocMsg::Dereferenceable, + CheckInAllocMsg::Dereferenceable("pointer"), ) .map_err_kind(|_| { // Make the error more specific. 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/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 0598fbfad6e4d..3f353d50f191a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1070,14 +1070,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { expected_trait: Option<&'tcx ty::List>>, ) -> InterpResult<'tcx, Ty<'tcx>> { trace!("get_ptr_vtable({:?})", ptr); - let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr, 0)?; + let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr, 0).map_err_kind(|err| { + let err_ub!(DanglingIntPointer { addr, .. }) = err else { bug!() }; + err_ub!(InvalidVTablePointer(Pointer::without_provenance(addr))) + })?; if offset.bytes() != 0 { - throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset))) + throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset).into())) } let Some(GlobalAlloc::VTable(ty, vtable_dyn_type)) = self.tcx.try_get_global_alloc(alloc_id) else { - throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset))) + throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset).into())) }; if let Some(expected_dyn_type) = expected_trait { self.check_vtable_for_type(vtable_dyn_type, expected_dyn_type)?; @@ -1719,11 +1722,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: i64, ) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> { self.ptr_try_get_alloc_id(ptr, size) - .map_err(|offset| { + .map_err(|addr| { err_ub!(DanglingIntPointer { - addr: offset, + addr, inbounds_size: size, - msg: CheckInAllocMsg::Dereferenceable + msg: CheckInAllocMsg::Dereferenceable("pointer") }) }) .into() 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/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 0c1e171c0edc9..7ef1597c1c06f 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -640,7 +640,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Try returning an immediate for the operand. If the layout does not permit loading this as an /// immediate, return where in memory we can find the data. /// Note that for a given layout, this operation will either always return Left or Right! - /// succeed! Whether it returns Left depends on whether the layout can be represented + /// Whether it returns Left depends on whether the layout can be represented /// in an `Immediate`, not on which data is stored there currently. /// /// This is an internal function that should not usually be used; call `read_immediate` instead. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index ca8c096d3ab41..5739b4a005491 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); @@ -428,8 +441,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - /// Returns the result of the specified operation, whether it overflowed, and - /// the result type. + /// Returns the result of the specified operation. pub fn unary_op( &self, un_op: mir::UnOp, @@ -486,6 +498,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } ty::RawPtr(..) | ty::Ref(..) => { assert_eq!(un_op, PtrMetadata); + self.deref_pointer(val)?; // validity check let (_, meta) = val.to_scalar_and_meta(); interp_ok(match meta { MemPlaceMeta::Meta(scalar) => { @@ -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/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d317419ff7e2b..49e9e74191f39 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -13,9 +13,10 @@ use tracing::field::Empty; use tracing::{instrument, trace}; use super::{ - AllocInit, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, - InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, - Projectable, Provenance, Scalar, alloc_range, interp_ok, mir_assign_valid_types, + AllocInit, AllocRef, AllocRefMut, CheckAlignMsg, CheckInAllocMsg, CtfeProvenance, ImmTy, + Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, + Operand, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, err_ub_format, + interp_ok, mir_assign_valid_types, throw_ub_format, }; use crate::enter_trace_span; @@ -462,22 +463,74 @@ where /// Take an operand, representing a pointer, and dereference it to a place. /// Corresponds to the `*` operator in Rust. + /// Unlike `imm_ptr_to_mplace`, this checks that the pointer is valid for its type. #[instrument(skip(self), level = "trace")] pub fn deref_pointer( &self, src: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - if src.layout().ty.is_box() { - // Derefer should have removed all Box derefs. - // Some `Box` are not immediates (if they have a custom allocator) - // so the code below would fail. + let ptr_ty = src.layout().ty; + if !(ptr_ty.is_ref() || ptr_ty.is_raw_ptr() || ptr_ty.is_box_global(*self.tcx)) { bug!("dereferencing {}", src.layout().ty); } let val = self.read_immediate(src)?; + // Construct a place for that pointer. trace!("deref to {} on {:?}", val.layout.ty, *val); - let mplace = self.imm_ptr_to_mplace(&val)?; + + // This is conceptually a typed load from `src` to get the pointer. Most of the time when + // we do typed loads for primitive operations, all relevant invariants are checked + // implicitly, e.g. when we call `to_bool()` on a Boolean. + // But here, we do need to specifically check for metadata validity, null, alignment, and + // dereferenceability, or they will not be checked anywhere at all. + // This duplicates some of the logic in the validity check, but so far we found no + // good way to share that logic. + if ptr_ty.is_ref() || ptr_ty.is_box() { + let kind = if ptr_ty.is_ref() { "reference" } else { "box" }; + + // Null check. + let scalar_ptr = Scalar::from_maybe_pointer(mplace.ptr(), self); + if self.scalar_may_be_null(scalar_ptr)? { + let maybe = !M::Provenance::OFFSET_IS_ADDR && matches!(scalar_ptr, Scalar::Ptr(..)); + throw_ub_format!( + "dereferencing a {maybe}null {kind}", + maybe = if maybe { "maybe-" } else { "" } + ); + } + + // Dereferencability and alignment check. This also implicitly checks metadata validity. + let (size, align) = self + .size_and_align_of_val(&mplace)? + .unwrap_or_else(|| (mplace.layout.size, mplace.layout.align.abi)); + self.check_ptr_access(mplace.ptr(), size, CheckInAllocMsg::Dereferenceable(kind))?; + self.check_ptr_align(mplace.ptr(), align).map_err_kind(|err| { + let err_ub!(AlignmentCheckFailed(Misalignment { required, has }, _msg)) = err else { bug!() }; + err_ub_format!( + "encountered an unaligned {kind} (required {required_bytes} byte alignment but found {found_bytes})", + required_bytes = required.bytes(), + found_bytes = has.bytes() + ) + })?; + } else { + assert!(ptr_ty.is_raw_ptr()); + // For raw pointers, the validity invariant is pretty weak, but we do require the vtable + // to make sense, so we do have to check that if there is one. + if mplace.layout.is_unsized() { + let tail = self.tcx.struct_tail_for_codegen(mplace.layout.ty, self.typing_env); + match tail.kind() { + ty::Dynamic(data, _) => { + let vtable = mplace.meta().unwrap_meta().to_pointer(self)?; + self.get_ptr_vtable_ty(vtable, Some(data))?; + } + ty::Slice(..) | ty::Str | ty::Foreign(..) => { + // Nothing to check (`read_immediate` already ensured initialization). + } + _ => bug!("Unexpected unsized type tail: {:?}", tail), + } + } + } + interp_ok(mplace) } @@ -831,8 +884,13 @@ where self.copy_op_inner(src, dest, /* allow_transmute */ false) } - /// Copies the data from an operand to a place. - /// `allow_transmute` indicates whether the layouts may disagree. + /// Perform a typed copy of the data from an operand to a place. + /// + /// `allow_transmute` indicates whether the layouts may disagree. In that case there are + /// technically *two* typed copies: `src` is a not-yet-loaded value, so we're doing a typed copy + /// at `src` type from there to some intermediate storage. And then we're doing a second typed + /// copy at `dest` type from that intermediate storage to `dest`. As an optimization, we only + /// make a single direct copy here, but we still have to ensure the data is valid at both types. #[inline(always)] #[instrument(skip(self), level = "trace")] fn copy_op_inner( @@ -841,11 +899,6 @@ where dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, ) -> InterpResult<'tcx> { - // These are technically *two* typed copies: `src` is a not-yet-loaded value, - // so we're doing a typed copy at `src` type from there to some intermediate storage. - // And then we're doing a second typed copy at `dest` type from that intermediate storage to - // `dest`. But as an optimization, we only make a single direct copy here. - // Do the actual copy. self.copy_op_no_validate(src, dest, allow_transmute)?; @@ -874,10 +927,10 @@ where interp_ok(()) } - /// Copies the data from an operand to a place. + /// Perform an untyped copy of the data from an operand to a place. + /// You are responsible for validating that things get copied at the right type. + /// /// `allow_transmute` indicates whether the layouts may disagree. - /// Also, if you use this you are responsible for validating that things get copied at the - /// right type. #[instrument(skip(self), level = "trace")] pub(super) fn copy_op_no_validate( &mut self, diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 27f91b2b89b2c..58c720c161b1b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -427,4 +427,22 @@ where Subslice { from, to, from_end } => self.project_subslice(base, from, to, from_end)?, }) } + + /// Given a value of type `Box`, returns the inner value of raw pointer type, as well as + /// the allocator. + pub(super) fn project_to_ptr_in_box>( + &self, + box_: &P, + ) -> InterpResult<'tcx, (P, P)> { + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(box_.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); + let [ptr, alloc] = self.project_fields(box_, [FieldIdx::ZERO, FieldIdx::ONE])?; + + // We simply transmute the pointer we care about to the underlying raw pointer. + // (We could project a bit but that would end up at a pattern type that needs a transmute.) + let pointee_ty = box_.layout().ty.builtin_deref(false).unwrap(); + let raw_ptr_ty = Ty::new_ptr(*self.tcx, pointee_ty, ty::Mutability::Mut); + let raw_ptr = ptr.transmute(self.layout_of(raw_ptr_ty)?, self)?; // The actual raw pointer + interp_ok((raw_ptr, alloc)) + } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0ffe22d42eb38..9c3ccafa6e41c 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -565,6 +565,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ty: Ty<'tcx>, ptr_kind: PtrKind, ) -> InterpResult<'tcx> { + // Note that some of those checks (those that encode the basic validity invariant of + // pointers) are duplicated in `place_deref`, so changes here might need updates there. let ptr = self.read_immediate(value, ptr_kind.into())?; if self.reset_provenance_and_padding { // There's no padding in a pointer. @@ -604,7 +606,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { self.ecx.check_ptr_access( place.ptr(), size, - CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message + CheckInAllocMsg::Dereferenceable("pointer"), // will anyway be replaced by validity message ), self.path, Ub(DanglingIntPointer { addr: 0, .. }) => diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 92d13b30c5fff..c80a082674141 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -3,7 +3,7 @@ use std::num::NonZero; -use rustc_abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; +use rustc_abi::{FieldsShape, VariantIdx, Variants}; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, Ty}; use tracing::trace; @@ -12,6 +12,9 @@ use super::{InterpCx, MPlaceTy, Machine, Projectable, interp_ok, throw_inval}; /// How to traverse a value and what to do when we are at the leaves. pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { + // The `From` rules out `ImmTy`... we could use a `TryFrom` instead since the only + // case we need this is visiting something unsized which cannot happen when visiting an `ImmTy`. + // But so far this was just not needed. type V: Projectable<'tcx, M::Provenance> + From>; /// The visitor must have an `InterpCx` in it. @@ -111,33 +114,9 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // allocator field. We also assert tons of things to ensure we do not miss // any other fields. - // `Box` has two fields: the pointer we care about, and the allocator. - assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); - let [unique_ptr, alloc] = - self.ecx().project_fields(v, [FieldIdx::ZERO, FieldIdx::ONE])?; - - // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... - // (which means another 2 fields, the second of which is a `PhantomData`) - assert_eq!(unique_ptr.layout().fields.count(), 2); - let [nonnull_ptr, phantom] = - self.ecx().project_fields(&unique_ptr, [FieldIdx::ZERO, FieldIdx::ONE])?; - assert!( - phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), - "2nd field of `Unique` should be PhantomData but is {:?}", - phantom.layout().ty, - ); - - // ... that contains a `NonNull` whose only field finally is a raw ptr we can - // dereference. - assert_eq!(nonnull_ptr.layout().fields.count(), 1); - let pat_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // `*mut T is !null` - let base = match *pat_ptr.layout().ty.kind() { - ty::Pat(base, _) => self.ecx().layout_of(base)?, - _ => unreachable!(), - }; - let raw_ptr = pat_ptr.transmute(base, self.ecx())?; // The actual raw pointer - - // Hand this actual pointer to the visitor. + let (raw_ptr, alloc) = self.ecx().project_to_ptr_in_box(v)?; + + // Hand the actual pointer to the visitor. self.visit_box(ty, &raw_ptr)?; // The second `Box` field is the allocator, which we recursively check for validity 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/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e2c67b29943d6..4636030e8717f 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -251,7 +251,8 @@ pub enum CheckInAllocMsg { /// We are doing pointer arithmetic. InboundsPointerArithmetic, /// None of the above -- generic/unspecific inbounds test. - Dereferenceable, + /// The string is the subject of the test, e.g. "pointer". + Dereferenceable(&'static str), } impl fmt::Display for CheckInAllocMsg { @@ -260,7 +261,7 @@ impl fmt::Display for CheckInAllocMsg { match self { MemoryAccess => write!(f, "memory access failed"), InboundsPointerArithmetic => write!(f, "in-bounds pointer arithmetic failed"), - Dereferenceable => write!(f, "pointer not dereferenceable"), + Dereferenceable(what) => write!(f, "{what} not dereferenceable"), } } } @@ -391,7 +392,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Using a pointer-not-to-a-va-list as variable argument list pointer. InvalidVaListPointer(Pointer), /// Using a pointer-not-to-a-vtable as vtable pointer. - InvalidVTablePointer(Pointer), + InvalidVTablePointer(Pointer>), /// Using a vtable for the wrong trait. InvalidVTableTrait { /// The vtable that was actually referenced by the wide pointer metadata. @@ -452,11 +453,11 @@ impl<'tcx> fmt::Display for UndefinedBehaviorInfo<'tcx> { CheckInAllocMsg::InboundsPointerArithmetic => { write!(f, "attempting to offset pointer by {inbounds_size_fmt}") } - CheckInAllocMsg::Dereferenceable if inbounds_size == 0 => { - write!(f, "pointer must point to some allocation") + CheckInAllocMsg::Dereferenceable(what) if inbounds_size == 0 => { + write!(f, "{what} must point to some allocation") } - CheckInAllocMsg::Dereferenceable => { - write!(f, "pointer must be dereferenceable for {inbounds_size_fmt}") + CheckInAllocMsg::Dereferenceable(what) => { + write!(f, "{what} must be dereferenceable for {inbounds_size_fmt}") } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 9712ac02775d4..17eeb7c3c12aa 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -792,6 +792,7 @@ impl<'tcx> Rvalue<'tcx> { | CastKind::PointerCoercion(_, _) | CastKind::PointerWithExposedProvenance | CastKind::Transmute + | CastKind::BoxDerefTransmute | CastKind::Subtype, _, _, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 5771019ddca46..b005cf0c8d10f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1496,6 +1496,14 @@ pub enum CastKind { /// MIR is well-formed if the input and output types have different sizes, /// but running a transmute between differently-sized types is UB. Transmute, + /// A special transmute used by elaborated `box` deref's to turn the inner pointer into a raw + /// pointer. This is almost equivalent to a regular transmute except that if the input would not + /// be valid as `Box`, the cast is UB. Backends that do not care about UB detection can treat + /// this like a regular transmute. + /// + /// Well-formedness: The input type must be a pointer type or a newtype around one (e.g. + /// `NonNull`). The output type must be a raw pointer. + BoxDerefTransmute, /// A `Subtype` cast is applied to any [`StatementKind::Assign`] where /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping 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_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 717c1cb39cb61..5c925b9ecaa42 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> { location, Place::from(ptr_local), Rvalue::Cast( - CastKind::Transmute, + CastKind::BoxDerefTransmute, Operand::Copy( Place::from(place.local) .project_deeper(&build_projection(unique_ty, nonnull_ty), tcx), 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_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 56a9a179c8fcb..4413d5064bd14 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1386,7 +1386,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - CastKind::Transmute => { + CastKind::Transmute | CastKind::BoxDerefTransmute => { // Unlike `mem::transmute`, a MIR `Transmute` is well-formed // for any two `Sized` types, just potentially UB to run. @@ -1416,6 +1416,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { format!("Cannot transmute to non-`Sized` type {target_type:?}"), ); } + + if matches!(kind, CastKind::BoxDerefTransmute) { + if !target_type.is_raw_ptr() { + self.fail( + location, + format!( + "Cannot BoxDerefTransmute to non-pointer type {target_type}" + ), + ); + } + } } CastKind::Subtype => { if !util::sub_types(self.tcx, self.typing_env, op_ty, *target_type) { 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/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index def6c837a2b85..a65798aff1a00 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -1087,6 +1087,7 @@ pub enum CastKind { PtrToPtr, FnPtrToPtr, Transmute, + BoxDerefTransmute, Subtype, } 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_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index 0e901cf871126..124329526028d 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -365,6 +365,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind { PtrToPtr => crate::mir::CastKind::PtrToPtr, FnPtrToPtr => crate::mir::CastKind::FnPtrToPtr, Transmute => crate::mir::CastKind::Transmute, + BoxDerefTransmute => crate::mir::CastKind::BoxDerefTransmute, Subtype => crate::mir::CastKind::Subtype, } } 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/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 57d7942fa32f5..b53215355e5b4 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -189,7 +189,7 @@ fn check_rvalue<'tcx>( Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => { Err((span, "casting pointers to ints is unstable in const fn".into())) }, - Rvalue::Cast(CastKind::Transmute, _, _) => Err(( + Rvalue::Cast(CastKind::Transmute | CastKind::BoxDerefTransmute, _, _) => Err(( span, "transmute can attempt to turn pointers into integers, so is unstable in const fn".into(), )), 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/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 48311985ca3b4..9ca3212edef2a 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -601,7 +601,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). - this.check_ptr_access(place.ptr(), size, CheckInAllocMsg::Dereferenceable)?; + this.check_ptr_access(place.ptr(), size, CheckInAllocMsg::Dereferenceable("pointer"))?; // It is crucial that this gets called on all code paths, to ensure we track tag creation. let log_creation = |this: &MiriInterpCx<'tcx>, diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index efeab43d51fa4..185596d7232e9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -244,7 +244,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). - this.check_ptr_access(place.ptr(), ptr_size, CheckInAllocMsg::Dereferenceable)?; + this.check_ptr_access(place.ptr(), ptr_size, CheckInAllocMsg::Dereferenceable("pointer"))?; // It is crucial that this gets called on all code paths, to ensure we track tag creation. let log_creation = |this: &MiriInterpCx<'tcx>, 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..a366805289227 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -339,7 +339,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { { assert!(init_val != uninit_val); let this = self.eval_context_mut(); - this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?; + this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable("pointer"))?; assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?; @@ -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()?, @@ -391,7 +389,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 'tcx: 'a, { let this = self.eval_context_mut(); - this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?; + this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable("pointer"))?; assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?; 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/fail/coroutine-pinned-moved.stderr b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr index 7998db2424b36..664bab4b62f6d 100644 --- a/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr +++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling +error: Undefined Behavior: reference not dereferenceable: ALLOC has been freed, so this pointer is dangling --> tests/fail/coroutine-pinned-moved.rs:LL:CC | LL | *num += 1; diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr index 50f041931aea9..3f066b6565880 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: reference not dereferenceable: reference must be dereferenceable for 4 bytes, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) --> tests/fail/dangling_pointers/deref-invalid-ptr.rs:LL:CC | LL | let _y = unsafe { *(&*x as *const u32) }; - | ^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | ^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr index 3faff2248e408..83451d00daecf 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling +error: Undefined Behavior: reference not dereferenceable: ALLOC has been freed, so this pointer is dangling --> tests/fail/dangling_pointers/stack_temporary.rs:LL:CC | LL | let val = *x; diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr index dc3565ce399be..f55c904425510 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: reference not dereferenceable: reference must be dereferenceable for 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) --> tests/fail/dangling_pointers/storage_dead_dangling.rs:LL:CC | LL | let _x = unsafe { *&mut *(LEAK as *mut i32) }; diff --git a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr index b0f9ffb451973..6d9cd81f3f802 100644 --- a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr +++ b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: reference not dereferenceable: reference must be dereferenceable for 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) --> tests/fail/provenance/pointer_partial_overwrite.rs:LL:CC | LL | let x = *p; diff --git a/src/tools/miri/tests/fail/rc_as_ptr.stderr b/src/tools/miri/tests/fail/rc_as_ptr.stderr index 42bf8637e0da8..c86ee3300f03c 100644 --- a/src/tools/miri/tests/fail/rc_as_ptr.stderr +++ b/src/tools/miri/tests/fail/rc_as_ptr.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling +error: Undefined Behavior: box not dereferenceable: ALLOC has been freed, so this pointer is dangling --> tests/fail/rc_as_ptr.rs:LL:CC | LL | assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) }); diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs index b5a9b2bf18ee3..9aed9f6341b0f 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs @@ -19,7 +19,7 @@ fn main() { unsafe { (&mut ptr as *mut _ as *mut *const u8).write(&buf as *const _ as *const u8); } - // Re-borrow that. This should be UB. - let _ptr = &*ptr; //~ERROR: required 256 byte alignment + // Dereference that. This should be UB. + let _ptr = &raw const *ptr; //~ERROR: required 256 byte alignment } } diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr index 7c85a3be5a265..f696f0935eaec 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: constructing invalid value of type &dyn std::fmt::Debug: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) +error: Undefined Behavior: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) --> tests/fail/unaligned_pointers/dyn_alignment.rs:LL:CC | -LL | let _ptr = &*ptr; - | ^^^^^ Undefined Behavior occurred here +LL | let _ptr = &raw const *ptr; + | ^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.rs b/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.rs new file mode 100644 index 0000000000000..2fb63941284fb --- /dev/null +++ b/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.rs @@ -0,0 +1,7 @@ +fn foo() {} + +fn main() { + let mut f = &foo; + unsafe { (&raw mut f).cast::().write(0) }; + f(); //~ERROR: null reference +} diff --git a/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.stderr b/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.stderr new file mode 100644 index 0000000000000..b5af5c3637fb8 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/call_null_ref_fn_def.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: dereferencing a null reference + --> tests/fail/validity/call_null_ref_fn_def.rs:LL:CC + | +LL | f(); + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_dangling_ref.rs b/src/tools/miri/tests/fail/validity/cast_dangling_ref.rs new file mode 100644 index 0000000000000..aaf4550d29505 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_dangling_ref.rs @@ -0,0 +1,11 @@ +#[repr(C)] +struct S { + a: (), + b: i8, +} + +fn main() { + let mut x = &S { a: (), b: 0 }; + unsafe { (&raw mut x).cast::().write(16) }; + let _val = x as *const _; //~ERROR: must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer +} diff --git a/src/tools/miri/tests/fail/validity/cast_dangling_ref.stderr b/src/tools/miri/tests/fail/validity/cast_dangling_ref.stderr new file mode 100644 index 0000000000000..cd3e5943ab81e --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_dangling_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: reference not dereferenceable: reference must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) + --> tests/fail/validity/cast_dangling_ref.rs:LL:CC + | +LL | let _val = x as *const _; + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.rs new file mode 100644 index 0000000000000..b892c1155cfeb --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.rs @@ -0,0 +1,36 @@ +//! Even just *casting* a function pointer, withot ever calling it, requires validity. +#![feature(core_intrinsics, custom_mir)] +#![allow(internal_features)] +#![allow(unused_assignments)] + +use core::intrinsics::mir::*; + +// Overwrites `ptr` by invoking the callback, then casts `ptr` to `*mut u8`. +// Needs to use custom MIR to avoid copies that perform their own validation. +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn test(ptr: fn(), overwrite: fn(&mut fn())) { + mir! { + let ptrptr; + let ptr2 : *mut u8; + let _unused; + + { + ptrptr = &mut ptr; + Call(_unused = overwrite(ptrptr), ReturnTo(ret), UnwindContinue()) + } + + ret = { + ptr2 = ptr as *mut u8; //~ERROR: does not point to a function + Return() + } + } +} + +fn f() {} + +fn main() { + test(f, |ptrptr| unsafe { + let ptrptr = std::ptr::from_mut(ptrptr); + ptrptr.cast::<*const ()>().write(&()) + }); +} diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.stderr new file mode 100644 index 0000000000000..9df62ef619e82 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: using ALLOC as function pointer but it does not point to a function + --> tests/fail/validity/cast_fn_ptr_invalid.rs:LL:CC + | +LL | ptr2 = ptr as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: stack backtrace: + 0: test + at tests/fail/validity/cast_fn_ptr_invalid.rs:LL:CC + 1: main + at tests/fail/validity/cast_fn_ptr_invalid.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_null_ref.rs b/src/tools/miri/tests/fail/validity/cast_null_ref.rs new file mode 100644 index 0000000000000..5faf5260e7f07 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_null_ref.rs @@ -0,0 +1,5 @@ +fn main() { + let mut x = &(); + unsafe { (&raw mut x).cast::().write(0) }; + let _val = x as *const _; //~ERROR: null reference +} diff --git a/src/tools/miri/tests/fail/validity/cast_null_ref.stderr b/src/tools/miri/tests/fail/validity/cast_null_ref.stderr new file mode 100644 index 0000000000000..5b396d4931e11 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_null_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: dereferencing a null reference + --> tests/fail/validity/cast_null_ref.rs:LL:CC + | +LL | let _val = x as *const _; + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.rs b/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.rs new file mode 100644 index 0000000000000..4e0fe29257e31 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.rs @@ -0,0 +1,47 @@ +#![feature(core_intrinsics, custom_mir)] +#![allow(internal_features)] +#![allow(unused_assignments)] + +use core::intrinsics::mir::*; + +// Overwrites `ptr` by invoking the callback, then casts `ptr` to `*mut u8`. +// Needs to use custom MIR to avoid copies that perform their own validation. +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn test(ptr: *const T, data: U, overwrite: fn(&mut *const T, U)) { + mir! { + let ptrptr; + let ptr2 : *mut u8; // cast drops metadata! + let _unused; + + { + ptrptr = &mut ptr; + Call(_unused = overwrite(ptrptr, data), ReturnTo(ret), UnwindContinue()) + } + + ret = { + ptr2 = CastPtrToPtr(ptr); //~ERROR: vtable for `std::fmt::Debug` but `std::fmt::Display` was expected + Return() + } + } +} + +#[allow(unused)] +struct S { + f: i32, + g: Tail, +} + +fn main() { + let x = S { f: 0, g: 0 }; + let ptr1: *const S = &x; + let ptr2: *const S = &x; + test::, _>( + ptr2, + ptr1, + |ptrptr2, ptr1| unsafe { + // Give ptr2 the vtable from ptr1. + let ptrptr2 = std::ptr::from_mut(ptrptr2); + ptrptr2.copy_from(&raw const ptr1 as *const _, 1) ; + } + ); +} diff --git a/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.stderr b/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.stderr new file mode 100644 index 0000000000000..ba8a1156dfb06 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_raw_ptr_invalid_vtable.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: using vtable for `std::fmt::Debug` but `std::fmt::Display` was expected + --> tests/fail/validity/cast_raw_ptr_invalid_vtable.rs:LL:CC + | +LL | ptr2 = CastPtrToPtr(ptr); + | ^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: stack backtrace: + 0: test::, *const S> + at tests/fail/validity/cast_raw_ptr_invalid_vtable.rs:LL:CC + 1: main + at tests/fail/validity/cast_raw_ptr_invalid_vtable.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_unaligned_ref.rs b/src/tools/miri/tests/fail/validity/cast_unaligned_ref.rs new file mode 100644 index 0000000000000..97278d9ad6aca --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_unaligned_ref.rs @@ -0,0 +1,8 @@ +#[repr(align(8))] +struct S {} + +fn main() { + let mut x = &S {}; + unsafe { (&raw mut x).cast::().write(1) }; + let _val = x as *const _; //~ERROR: unaligned reference +} diff --git a/src/tools/miri/tests/fail/validity/cast_unaligned_ref.stderr b/src/tools/miri/tests/fail/validity/cast_unaligned_ref.stderr new file mode 100644 index 0000000000000..674a679b326d5 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_unaligned_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) + --> tests/fail/validity/cast_unaligned_ref.rs:LL:CC + | +LL | let _val = x as *const _; + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_dangling_box.rs b/src/tools/miri/tests/fail/validity/deref_dangling_box.rs new file mode 100644 index 0000000000000..9f365c6c915b2 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_dangling_box.rs @@ -0,0 +1,11 @@ +#[repr(C)] +struct S { + a: (), + b: i8, +} + +fn main() { + let mut x = Box::new(S { a: (), b: 0 }); + unsafe { (&raw mut x).cast::().write(16) }; + let _ = x.a; //~ERROR: must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer +} diff --git a/src/tools/miri/tests/fail/validity/deref_dangling_box.stderr b/src/tools/miri/tests/fail/validity/deref_dangling_box.stderr new file mode 100644 index 0000000000000..cedf1e5ef460a --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_dangling_box.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: box not dereferenceable: box must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) + --> tests/fail/validity/deref_dangling_box.rs:LL:CC + | +LL | let _ = x.a; + | ^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_dangling_ref.rs b/src/tools/miri/tests/fail/validity/deref_dangling_ref.rs new file mode 100644 index 0000000000000..92abcdb5388ef --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_dangling_ref.rs @@ -0,0 +1,11 @@ +#[repr(C)] +struct S { + a: (), + b: i8, +} + +fn main() { + let mut x = &S { a: (), b: 0 }; + unsafe { (&raw mut x).cast::().write(16) }; + let _ = x.a; //~ERROR: must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer +} diff --git a/src/tools/miri/tests/fail/validity/deref_dangling_ref.stderr b/src/tools/miri/tests/fail/validity/deref_dangling_ref.stderr new file mode 100644 index 0000000000000..f90d50549c3b3 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_dangling_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: reference not dereferenceable: reference must be dereferenceable for 1 byte, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) + --> tests/fail/validity/deref_dangling_ref.rs:LL:CC + | +LL | let _ = x.a; + | ^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_null_box.rs b/src/tools/miri/tests/fail/validity/deref_null_box.rs new file mode 100644 index 0000000000000..418b5906be02d --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_null_box.rs @@ -0,0 +1,5 @@ +fn main() { + let mut x = Box::new(()); + unsafe { (&raw mut x).cast::().write(0) }; + let _ = *x; //~ERROR: null box +} diff --git a/src/tools/miri/tests/fail/validity/deref_null_box.stderr b/src/tools/miri/tests/fail/validity/deref_null_box.stderr new file mode 100644 index 0000000000000..3fcc098160eb2 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_null_box.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: dereferencing a null box + --> tests/fail/validity/deref_null_box.rs:LL:CC + | +LL | let _ = *x; + | ^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_null_ref.rs b/src/tools/miri/tests/fail/validity/deref_null_ref.rs new file mode 100644 index 0000000000000..392fac587ae26 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_null_ref.rs @@ -0,0 +1,5 @@ +fn main() { + let mut x = &(); + unsafe { (&raw mut x).cast::().write(0) }; + let _ = *x; //~ERROR: null reference +} diff --git a/src/tools/miri/tests/fail/validity/deref_null_ref.stderr b/src/tools/miri/tests/fail/validity/deref_null_ref.stderr new file mode 100644 index 0000000000000..7611049cb027d --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_null_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: dereferencing a null reference + --> tests/fail/validity/deref_null_ref.rs:LL:CC + | +LL | let _ = *x; + | ^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.rs b/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.rs new file mode 100644 index 0000000000000..8f10124ae220d --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.rs @@ -0,0 +1,12 @@ +struct S { + f: i32, + #[allow(unused)] + g: Tail, +} + +fn main() { + let x = S { f: 0, g: 0 }; + let mut ptr: *const S = &x; + unsafe { (&raw mut ptr).cast::().add(1).write(0) }; + let _val = unsafe { &(*ptr).f }; //~ERROR: vtable +} diff --git a/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.stderr b/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.stderr new file mode 100644 index 0000000000000..cbbe283f05e9a --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_raw_ptr_no_vtable.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: using null pointer as vtable pointer but it does not point to a vtable + --> tests/fail/validity/deref_raw_ptr_no_vtable.rs:LL:CC + | +LL | let _val = unsafe { &(*ptr).f }; + | ^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.rs b/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.rs new file mode 100644 index 0000000000000..54b248add7566 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.rs @@ -0,0 +1,14 @@ +struct S { + f: i32, + #[allow(unused)] + g: Tail, +} + +fn main() { + let x = S { f: 0, g: 0 }; + let ptr1: *const S = &x; + let mut ptr2: *const S = &x; + // Give ptr2 the vtable from ptr1. + unsafe { (&raw mut ptr2).copy_from(&raw const ptr1 as *const _, 1) }; + let _val = unsafe { &(*ptr2).f }; //~ERROR: vtable +} diff --git a/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.stderr b/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.stderr new file mode 100644 index 0000000000000..69109e5d2040d --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_raw_ptr_wrong_vtable.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: using vtable for `std::fmt::Debug` but `std::fmt::Display` was expected + --> tests/fail/validity/deref_raw_ptr_wrong_vtable.rs:LL:CC + | +LL | let _val = unsafe { &(*ptr2).f }; + | ^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_unaligned_box.rs b/src/tools/miri/tests/fail/validity/deref_unaligned_box.rs new file mode 100644 index 0000000000000..2f41e36e25a9b --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_unaligned_box.rs @@ -0,0 +1,10 @@ +#[repr(align(8))] +struct S { + f: (), +} + +fn main() { + let mut x = Box::new(S { f: () }); + unsafe { (&raw mut x).cast::().write(1) }; + let _ = &x.f; //~ERROR: unaligned box +} diff --git a/src/tools/miri/tests/fail/validity/deref_unaligned_box.stderr b/src/tools/miri/tests/fail/validity/deref_unaligned_box.stderr new file mode 100644 index 0000000000000..1a5818334e011 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_unaligned_box.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: encountered an unaligned box (required ALIGN byte alignment but found ALIGN) + --> tests/fail/validity/deref_unaligned_box.rs:LL:CC + | +LL | let _ = &x.f; + | ^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/deref_unaligned_ref.rs b/src/tools/miri/tests/fail/validity/deref_unaligned_ref.rs new file mode 100644 index 0000000000000..837b0f456ca47 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_unaligned_ref.rs @@ -0,0 +1,10 @@ +#[repr(align(8))] +struct S { + f: (), +} + +fn main() { + let mut x = &S { f: () }; + unsafe { (&raw mut x).cast::().write(1) }; + let _ = &x.f; //~ERROR: unaligned reference +} diff --git a/src/tools/miri/tests/fail/validity/deref_unaligned_ref.stderr b/src/tools/miri/tests/fail/validity/deref_unaligned_ref.stderr new file mode 100644 index 0000000000000..9595dd9a2f116 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/deref_unaligned_ref.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) + --> tests/fail/validity/deref_unaligned_ref.rs:LL:CC + | +LL | let _ = &x.f; + | ^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.rs b/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.rs new file mode 100644 index 0000000000000..92522f76b3d8f --- /dev/null +++ b/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.rs @@ -0,0 +1,36 @@ +#![feature(core_intrinsics, custom_mir)] +#![allow(internal_features)] +#![allow(unused_assignments)] + +use core::intrinsics::mir::*; + +fn main() { + test8345(&1, |ptrptr| unsafe { + let ptrptr = std::ptr::from_mut(ptrptr); + ptrptr.cast::<(usize, usize)>().write((0, 1)) + }); +} + +trait A {} +impl A for T {} + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn test8345(mut ptr: &dyn A, overwrite: fn(&mut &dyn A)) { + mir! { + let ptrptr; + let _unused; + let idk; + + { + ptrptr = &mut ptr; + // Overwrite `ptr` to make it invalid. + Call(_unused = overwrite(ptrptr), ReturnTo(ret), UnwindContinue()) + } + + ret = { + // Do something with `ptr`. + idk = PtrMetadata(ptr); //~ERROR: null reference + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.stderr b/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.stderr new file mode 100644 index 0000000000000..ecd428cd1cb6b --- /dev/null +++ b/src/tools/miri/tests/fail/validity/ptr_metadata_invalid_vtable.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: dereferencing a null reference + --> tests/fail/validity/ptr_metadata_invalid_vtable.rs:LL:CC + | +LL | idk = PtrMetadata(ptr); + | ^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: stack backtrace: + 0: test8345 + at tests/fail/validity/ptr_metadata_invalid_vtable.rs:LL:CC + 1: main + at tests/fail/validity/ptr_metadata_invalid_vtable.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + 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/const_prop/transmute.unreachable_box.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index 6ebce526c9833..a6756ba0245c7 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); +- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute); ++ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index 6ebce526c9833..a6756ba0245c7 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); +- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute); ++ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (BoxDerefTransmute); unreachable; } } 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/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff index 0a21dea1335b4..352d9345eef84 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); + _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff index 0a21dea1335b4..352d9345eef84 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); + _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 9e717a74776d1..8b5ad1519d27c 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -73,7 +73,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index f0b1feca4b28e..14943534b98be 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff @@ -53,7 +53,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index dc5f656f17a59..f8d47dcae5b27 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -73,7 +73,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index f0b1feca4b28e..14943534b98be 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff @@ -53,7 +53,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); 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/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff index 73cd8e4fdfd81..ceacf606f3553 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff @@ -23,7 +23,7 @@ + StorageLive(_7); + StorageLive(_5); + _7 = no_retag copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); -+ _6 = copy _7 as *const dyn std::ops::FnMut (Transmute); ++ _6 = copy _7 as *const dyn std::ops::FnMut (BoxDerefTransmute); + _5 = &mut (*_6); + _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index 469d2ef000c5c..862174fd94bff 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -23,7 +23,7 @@ + StorageLive(_7); + StorageLive(_5); + _7 = no_retag copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); -+ _6 = copy _7 as *const dyn std::ops::FnMut (Transmute); ++ _6 = copy _7 as *const dyn std::ops::FnMut (BoxDerefTransmute); + _5 = &mut (*_6); + _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2]; } diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff index 1046a86fe9f6d..0dc8adb257423 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff @@ -24,7 +24,7 @@ + StorageLive(_7); + StorageLive(_5); + _7 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); -+ _6 = copy _7 as *const dyn std::ops::Fn(i32) (Transmute); ++ _6 = copy _7 as *const dyn std::ops::Fn(i32) (BoxDerefTransmute); + _5 = &(*_6); + _2 = >::call(move _5, move _4) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index bb24c02f3578b..1b320f9200405 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -24,7 +24,7 @@ + StorageLive(_7); + StorageLive(_5); + _7 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); -+ _6 = copy _7 as *const dyn std::ops::Fn(i32) (Transmute); ++ _6 = copy _7 as *const dyn std::ops::Fn(i32) (BoxDerefTransmute); + _5 = &(*_6); + _2 = >::call(move _5, move _4) -> [return: bb4, unwind: bb2]; } diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 0445a476c5cc9..f4972c7d1437e 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -20,7 +20,7 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_5); StorageLive(_6); _6 = no_retag copy (((*_4).0: std::ptr::Unique).0: std::ptr::NonNull); - _5 = copy _6 as *const T (Transmute); + _5 = copy _6 as *const T (BoxDerefTransmute); _3 = &mut (*_5); StorageDead(_6); StorageDead(_5); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 38076dc14b6a1..d5a0450af828e 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -18,7 +18,7 @@ fn d(_1: &Box) -> &T { StorageLive(_4); StorageLive(_5); _5 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); - _4 = copy _5 as *const T (Transmute); + _4 = copy _5 as *const T (BoxDerefTransmute); _2 = &(*_4); StorageDead(_5); StorageDead(_4); diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 644d6d320de04..8ca4ca123c829 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -12,7 +12,7 @@ StorageLive(_2); StorageLive(_3); _3 = move _1; - _4 = copy ((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (Transmute); + _4 = copy ((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (BoxDerefTransmute); _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3]; } 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/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff index 4f8b7c4160f99..adf61031b3699 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff @@ -17,7 +17,7 @@ } bb1: { - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); + _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); PlaceMention((*_2)); unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff index 4f8b7c4160f99..adf61031b3699 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -17,7 +17,7 @@ } bb1: { - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); + _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); PlaceMention((*_2)); unreachable; } 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/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir index fc254be264748..549af7af4d888 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir @@ -65,7 +65,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 37 (inlined without_provenance_mut::) { + scope 37 (inlined std::ptr::without_provenance_mut::) { } } scope 32 (inlined std::ptr::const_ptr::::addr) { @@ -109,7 +109,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 7 { } scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 12 (inlined std::ptr::without_provenance_mut::) { } } scope 13 (inlined NonNull::::as_ptr) { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.runtime-optimized.after.panic-abort.mir index 5f8fefc57c412..2e662fc36ac67 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.runtime-optimized.after.panic-abort.mir @@ -34,7 +34,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 25 (inlined without_provenance_mut::) { + scope 25 (inlined std::ptr::without_provenance_mut::) { } } scope 20 (inlined std::ptr::const_ptr::::addr) { @@ -77,7 +77,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 7 { } scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 12 (inlined std::ptr::without_provenance_mut::) { } } scope 13 (inlined NonNull::::as_ptr) { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.runtime-optimized.after.panic-abort.mir index bd0e3a025f425..c2c521729b75c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.runtime-optimized.after.panic-abort.mir @@ -103,7 +103,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 7 { } scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 12 (inlined std::ptr::without_provenance_mut::) { } } scope 13 (inlined NonNull::::as_ptr) { diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.runtime-optimized.after.panic-abort.mir index 7596384ac4a89..889d7c1e69afb 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.runtime-optimized.after.panic-abort.mir @@ -21,7 +21,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { } } } - scope 10 (inlined without_provenance_mut::) { + scope 10 (inlined std::ptr::without_provenance_mut::) { } } scope 5 (inlined std::ptr::const_ptr::::addr) { 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/const-ptr/forbidden_slices.rs b/tests/ui/const-ptr/forbidden_slices.rs index fcb0dccf750e3..7c2d86bff75b2 100644 --- a/tests/ui/const-ptr/forbidden_slices.rs +++ b/tests/ui/const-ptr/forbidden_slices.rs @@ -20,7 +20,7 @@ pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) }; // Out of bounds pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) }; -//~^ ERROR: dangling reference (going beyond the bounds of its allocation) +//~^ ERROR: reference must be dereferenceable for 8 bytes // Reading uninitialized data pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; //~ ERROR: uninitialized memory @@ -39,14 +39,14 @@ pub static S7: &[u16] = unsafe { // Unaligned read pub static S8: &[u64] = unsafe { - //~^ ERROR: dangling reference (going beyond the bounds of its allocation) let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::(); from_raw_parts(ptr, 1) + //~^ ERROR: reference must be dereferenceable for 8 bytes }; pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; -//~^ ERROR encountered a null reference +//~^ ERROR: null reference pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; // errors inside libcore //~^ ERROR 0 < pointee_size && pointee_size <= isize::MAX as usize pub static R2: &[u32] = unsafe { @@ -70,9 +70,9 @@ pub static R6: &[bool] = unsafe { from_ptr_range(ptr..ptr.add(4)) }; pub static R7: &[u16] = unsafe { - //~^ ERROR: unaligned reference (required 2 byte alignment but found 1) let ptr = (&D2 as *const Struct as *const u16).byte_add(1); from_ptr_range(ptr..ptr.add(4)) + //~^ ERROR: unaligned reference (required 2 byte alignment but found 1) }; pub static R8: &[u64] = unsafe { let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::(); diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index e23b4e5b1aa75..fb5b9c9764076 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -1,35 +1,20 @@ -error[E0080]: constructing invalid value of type &[u32]: encountered a null reference - --> $DIR/forbidden_slices.rs:16:1 +error[E0080]: dereferencing a null reference + --> $DIR/forbidden_slices.rs:16:34 | LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `S0` failed here -error[E0080]: constructing invalid value of type &[()]: encountered a null reference - --> $DIR/forbidden_slices.rs:18:1 +error[E0080]: dereferencing a null reference + --> $DIR/forbidden_slices.rs:18:33 | LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `S1` failed here -error[E0080]: constructing invalid value of type &[u32]: encountered a dangling reference (going beyond the bounds of its allocation) - --> $DIR/forbidden_slices.rs:22:1 +error[E0080]: reference not dereferenceable: reference must be dereferenceable for 8 bytes, but got ALLOC$ID which is only 4 bytes from the end of the allocation + --> $DIR/forbidden_slices.rs:22:34 | LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) }; - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ HEX_DUMP - } + | ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `S2` failed here error[E0080]: constructing invalid value of type &[u8]: at .[0], encountered uninitialized memory, but expected an integer --> $DIR/forbidden_slices.rs:26:1 @@ -77,27 +62,17 @@ LL | pub static S7: &[u16] = unsafe { ╾ALLOC$ID╼ HEX_DUMP } -error[E0080]: constructing invalid value of type &[u64]: encountered a dangling reference (going beyond the bounds of its allocation) - --> $DIR/forbidden_slices.rs:41:1 +error[E0080]: reference not dereferenceable: reference must be dereferenceable for 8 bytes, but got ALLOC$ID+0x1 which is only 7 bytes from the end of the allocation + --> $DIR/forbidden_slices.rs:44:5 | -LL | pub static S8: &[u64] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ HEX_DUMP - } +LL | from_raw_parts(ptr, 1) + | ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `S8` failed here -error[E0080]: constructing invalid value of type &[u32]: encountered a null reference - --> $DIR/forbidden_slices.rs:48:1 +error[E0080]: dereferencing a null reference + --> $DIR/forbidden_slices.rs:48:34 | LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `R0` failed here error[E0080]: evaluation panicked: assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize --> $DIR/forbidden_slices.rs:50:33 @@ -146,16 +121,11 @@ LL | pub static R6: &[bool] = unsafe { ╾ALLOC$ID╼ HEX_DUMP } -error[E0080]: constructing invalid value of type &[u16]: encountered an unaligned reference (required 2 byte alignment but found 1) - --> $DIR/forbidden_slices.rs:72:1 - | -LL | pub static R7: &[u16] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +error[E0080]: encountered an unaligned reference (required 2 byte alignment but found 1) + --> $DIR/forbidden_slices.rs:74:5 | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ HEX_DUMP - } +LL | from_ptr_range(ptr..ptr.add(4)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `R7` failed here error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 8 bytes, but got ALLOC$ID+0x1 which is only 7 bytes from the end of the allocation --> $DIR/forbidden_slices.rs:79:25 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/const-eval/heap/dealloc_intrinsic_dangling.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs index 80cf3ffef11a5..5609fb56a1322 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs @@ -10,10 +10,10 @@ use std::intrinsics; const _X: &'static u8 = unsafe { - //~^ ERROR: dangling reference (use-after-free) let ptr = intrinsics::const_allocate(4, 4); intrinsics::const_deallocate(ptr, 4, 4); &*ptr + //~^ ERROR: this pointer is dangling }; const _Y: u8 = unsafe { diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr index e9b7f99ee6d99..01fe36c0a537a 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -1,15 +1,10 @@ -error[E0080]: constructing invalid value of type &u8: encountered a dangling reference (use-after-free) - --> $DIR/dealloc_intrinsic_dangling.rs:12:1 +error[E0080]: reference not dereferenceable: ALLOC$ID has been freed, so this pointer is dangling + --> $DIR/dealloc_intrinsic_dangling.rs:15:5 | -LL | const _X: &'static u8 = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ │ ╾─╼ - } +LL | &*ptr + | ^^^^^ evaluation of `_X` failed here -error[E0080]: memory access failed: ALLOC$ID has been freed, so this pointer is dangling +error[E0080]: reference not dereferenceable: ALLOC$ID has been freed, so this pointer is dangling --> $DIR/dealloc_intrinsic_dangling.rs:23:5 | LL | *reference diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index 64e892e61af47..90e8176d79c59 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -1,4 +1,4 @@ -error[E0080]: memory access failed: ALLOC$ID has been freed, so this pointer is dangling +error[E0080]: reference not dereferenceable: ALLOC$ID has been freed, so this pointer is dangling --> $DIR/issue-49296.rs:9:16 | LL | const X: u64 = *wat(42); diff --git a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr index 8dbb05c15725a..c9f1e5f1639bb 100644 --- a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr +++ b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr @@ -1,8 +1,11 @@ -error[E0080]: memory access failed: attempting to access 1 byte, but got 0x1[noalloc] which is a dangling pointer (it has no provenance) - --> $DIR/nonnull_as_ref_ub.rs:4:29 +error[E0080]: reference not dereferenceable: reference must be dereferenceable for 1 byte, but got 0x1[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/nonnull_as_ref_ub.rs:4:39 | LL | const _: () = assert!(42 == *unsafe { NON_NULL.as_ref() }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + | ^^^^^^^^^^^^^^^^^ evaluation of `_` failed inside this call + | +note: inside `NonNull::::as_ref::<'_>` + --> $SRC_DIR/core/src/ptr/non_null.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 1efd30818b2e5..70ca9dbcd1037 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -1,24 +1,14 @@ -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-incorrect-vtable.rs:18:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-incorrect-vtable.rs:19:14 | -LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾──╼╾──╼ - } +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_ALIGNMENT` failed here -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-incorrect-vtable.rs:22:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-incorrect-vtable.rs:23:14 | -LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾──╼╾──╼ - } +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_SIZE` failed here error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC$ID, but expected a vtable pointer --> $DIR/ub-incorrect-vtable.rs:31:1 diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index bc26c93513964..b4e1be920b8f3 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -1,24 +1,14 @@ -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-incorrect-vtable.rs:18:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-incorrect-vtable.rs:19:14 | -LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾──────╼╾──────╼ - } +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_ALIGNMENT` failed here -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-incorrect-vtable.rs:22:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-incorrect-vtable.rs:23:14 | -LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾──────╼╾──────╼ - } +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_SIZE` failed here error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC$ID, but expected a vtable pointer --> $DIR/ub-incorrect-vtable.rs:31:1 diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs index 4185b0261b296..b7a49f5fe78e7 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -17,11 +17,11 @@ trait Trait {} const INVALID_VTABLE_ALIGNMENT: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; -//~^^ ERROR vtable +//~^ ERROR vtable const INVALID_VTABLE_SIZE: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; -//~^^ ERROR vtable +//~^ ERROR vtable #[repr(transparent)] struct W(T); diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs index 679de8b0cf101..4bb897ab11bd4 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.rs +++ b/tests/ui/consts/const-eval/ub-nonnull.rs @@ -19,9 +19,9 @@ const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR invalid value const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { - let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + let ptr: *const [u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle // Use address-of-element for pointer arithmetic. This could wrap around to null! - let out_of_bounds_ptr = &ptr[255]; //~ ERROR in-bounds pointer arithmetic failed + let out_of_bounds_ptr = &(*ptr)[255]; //~ ERROR in-bounds pointer arithmetic failed mem::transmute(out_of_bounds_ptr) } }; diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 81f2ff3ca5fa4..d34425ea79ad9 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -12,8 +12,8 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 255 bytes, but got ALLOC$ID which is only 1 byte from the end of the allocation --> $DIR/ub-nonnull.rs:24:29 | -LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here +LL | let out_of_bounds_ptr = &(*ptr)[255]; + | ^^^^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here error[E0080]: constructing invalid value of type NonZero: at .0.0, encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:28:1 diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index 327a5689de062..64b13f91e839b 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -140,11 +140,11 @@ const DYN_METADATA: ptr::DynMetadata = ptr::metadata::(ptr:: static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) - //~^^ ERROR null pointer + //~^ ERROR null pointer }; static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - //~^^ ERROR vtable + //~^ ERROR vtable }; fn main() {} diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index b442a43c6276f..10c6dafeac7cd 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -226,38 +226,23 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u ╾ALLOC$ID╼ HEX_DUMP } -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:119:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-wide-ptr.rs:119:57 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾─╼ - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `TRAIT_OBJ_UNALIGNED_VTABLE` failed here -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:121:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-wide-ptr.rs:121:57 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾─╼ - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `TRAIT_OBJ_BAD_DROP_FN_NULL` failed here -error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:123:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-wide-ptr.rs:123:56 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾─╼ - } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `TRAIT_OBJ_BAD_DROP_FN_INT` failed here error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC$ID, but expected a vtable pointer --> $DIR/ub-wide-ptr.rs:125:1 @@ -303,27 +288,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾─╼ } -error[E0080]: constructing invalid value of type *const dyn Trait: encountered null pointer, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:141:1 - | -LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +error[E0080]: using null pointer as vtable pointer but it does not point to a vtable + --> $DIR/ub-wide-ptr.rs:142:5 | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ HEX_DUMP - } +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF` failed here -error[E0080]: constructing invalid value of type *const dyn Trait: encountered ALLOC$ID, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:145:1 +error[E0080]: using ALLOC$ID as vtable pointer but it does not point to a vtable + --> $DIR/ub-wide-ptr.rs:146:5 | -LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - ╾ALLOC$ID╼ ╾ALLOC$ID╼ │ ╾─╼ - } +LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF` failed here error: aborting due to 29 previous errors diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs index ebf1f88eb8e72..3438790232fe5 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -84,8 +84,8 @@ fn dangling() { // Undefined behaviour (integer as pointer), who doesn't love tests like this. Some(&mut *(42 as *mut i32)) } } - const INT2PTR: Option<&mut i32> = helper_int2ptr(); //~ ERROR encountered a dangling reference - static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); //~ ERROR encountered a dangling reference + const INT2PTR: Option<&mut i32> = helper_int2ptr(); //~ ERROR reference not dereferenceable + static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); //~ ERROR reference not dereferenceable const fn helper_dangling() -> Option<&'static mut i32> { unsafe { // Undefined behaviour (dangling pointer), who doesn't love tests like this. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr index ad19f78ef831b..d631dd3376086 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -120,27 +120,29 @@ LL | const RAW_MUT_COERCE_C: SyncPtr = SyncPtr { x: &mut 0 }; = note: to avoid accidentally creating global mutable state, such temporaries must be immutable = help: if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut` -error[E0080]: constructing invalid value of type Option<&mut i32>: at ..0, encountered a dangling reference (0x2a[noalloc] has no provenance) - --> $DIR/mut_ref_in_final.rs:87:5 +error[E0080]: reference not dereferenceable: reference must be dereferenceable for 4 bytes, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/mut_ref_in_final.rs:87:39 | LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value + | ^^^^^^^^^^^^^^^^ evaluation of `dangling::INT2PTR` failed inside this call | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } +note: inside `helper_int2ptr` + --> $DIR/mut_ref_in_final.rs:85:14 + | +LL | Some(&mut *(42 as *mut i32)) + | ^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here -error[E0080]: constructing invalid value of type Option<&mut i32>: at ..0, encountered a dangling reference (0x2a[noalloc] has no provenance) - --> $DIR/mut_ref_in_final.rs:88:5 +error[E0080]: reference not dereferenceable: reference must be dereferenceable for 4 bytes, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/mut_ref_in_final.rs:88:47 | LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value + | ^^^^^^^^^^^^^^^^ evaluation of `dangling::INT2PTR_STATIC` failed inside this call | - = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } +note: inside `helper_int2ptr` + --> $DIR/mut_ref_in_final.rs:85:14 + | +LL | Some(&mut *(42 as *mut i32)) + | ^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here error[E0080]: constructing invalid value of type Option<&mut i32>: at ..0, encountered a dangling reference (use-after-free) --> $DIR/mut_ref_in_final.rs:94:5 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/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 268527c0e5bf8..a809e7c265d22 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -17,11 +17,11 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: accessing memory with alignment 1, but alignment 4 is required - --> $DIR/intrinsic-raw_eq-const-bad.rs:17:5 +error[E0080]: encountered an unaligned reference (required 4 byte alignment but found 1) + --> $DIR/intrinsic-raw_eq-const-bad.rs:17:29 | LL | std::intrinsics::raw_eq(aref, aref) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_NOT_ALIGNED` failed here + | ^^^^ evaluation of `RAW_EQ_NOT_ALIGNED` failed here error: aborting due to 3 previous errors 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