diff options
| author | Ralf Jung <post@ralfj.de> | 2024-12-04 07:44:16 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-04 07:44:16 +0000 |
| commit | 86d6dc008ec2473368a044e21af43f4495dc408f (patch) | |
| tree | 7a11f980ad18ccd73f0fd511abb06740908dddc7 | |
| parent | aaa4e75f7639e006af5747dd35b8b0ef19df2cf7 (diff) | |
| parent | 76c27a98495e5d61b32ad285e5d1a6533678cf38 (diff) | |
| download | rust-86d6dc008ec2473368a044e21af43f4495dc408f.tar.gz rust-86d6dc008ec2473368a044e21af43f4495dc408f.zip | |
Merge pull request #4070 from rust-lang/rustup-2024-12-04
Automatic Rustup
1616 files changed, 17596 insertions, 11722 deletions
diff --git a/.gitignore b/.gitignore index 948133cd76e..ce9db8b861d 100644 --- a/.gitignore +++ b/.gitignore @@ -46,8 +46,7 @@ no_llvm_build /inst/ /llvm/ /mingw-build/ -build/ -!/compiler/rustc_mir_build/src/build/ +/build /build-rust-analyzer/ /dist/ /unicode-downloads diff --git a/.mailmap b/.mailmap index fdb62a9d778..874a42656c5 100644 --- a/.mailmap +++ b/.mailmap @@ -254,6 +254,7 @@ Jack Huey <jack.huey@umassmed.edu> <jackh726@gmail.com> Jacob <jacob.macritchie@gmail.com> Jacob Greenfield <xales@naveria.com> Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com> +Jacob Pratt <jacob@jhpratt.dev> <jacopratt@tesla.com> Jake Vossen <jake@vossen.dev> Jakob Degen <jakob.e.degen@gmail.com> <jakob@degen.com> Jakob Lautrup Nysom <jako3047@gmail.com> diff --git a/Cargo.lock b/Cargo.lock index 29176a3ae8e..f59dcdcf28d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -536,7 +536,7 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clippy" -version = "0.1.84" +version = "0.1.85" dependencies = [ "anstream", "cargo_metadata", @@ -567,8 +567,9 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.84" +version = "0.1.85" dependencies = [ + "clippy_utils", "itertools", "serde", "toml 0.7.8", @@ -580,6 +581,7 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "aho-corasick", + "chrono", "clap", "indoc", "itertools", @@ -590,7 +592,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.84" +version = "0.1.85" dependencies = [ "arrayvec", "cargo_metadata", @@ -613,12 +615,12 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.84" +version = "0.1.85" dependencies = [ "arrayvec", - "clippy_config", "itertools", "rustc_apfloat", + "serde", ] [[package]] @@ -1876,16 +1878,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - -[[package]] name = "jobserver" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2285,7 +2277,6 @@ dependencies = [ "ctrlc", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -2295,6 +2286,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -3149,12 +3141,12 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", "rustc_driver_impl", "rustc_smir", "stable_mir", + "tikv-jemalloc-sys", ] [[package]] @@ -3820,7 +3812,6 @@ dependencies = [ name = "rustc_index" version = "0.0.0" dependencies = [ - "arrayvec", "rustc_index_macros", "rustc_macros", "rustc_serialize", @@ -4137,6 +4128,7 @@ name = "rustc_monomorphize" version = "0.0.0" dependencies = [ "rustc_abi", + "rustc_attr", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4711,9 +4703,9 @@ checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ruzstd" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3938e133aac070997ddc684d4b393777d293ba170f2988c8fd5ea2ad4ce21" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" dependencies = [ "twox-hash", ] @@ -5259,6 +5251,16 @@ name = "tier-check" version = "0.1.0" [[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "time" version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5801,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-component-ld" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" +checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938" dependencies = [ "anyhow", "clap", "lexopt", + "libc", "tempfile", "wasi-preview1-component-adapter-provider", "wasmparser 0.219.1", "wat", + "windows-sys 0.59.0", + "winsplit", "wit-component", "wit-parser", ] @@ -6184,6 +6189,12 @@ dependencies = [ ] [[package]] +name = "winsplit" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956" + +[[package]] name = "wit-component" version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/RELEASES.md b/RELEASES.md index 3707f170a57..8702bb02118 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -43,7 +43,7 @@ Libraries - [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) - [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) - [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) -- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). +- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229) <a id="1.83.0-Stabilized-APIs"></a> diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index f85c30ac7ec..d24b630516a 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -20,14 +20,14 @@ rustc_smir = { path = "../rustc_smir" } stable_mir = { path = "../stable_mir" } # tidy-alphabetical-end -[dependencies.jemalloc-sys] -version = "0.5.0" +[dependencies.tikv-jemalloc-sys] +version = "0.6.0" optional = true features = ['unprefixed_malloc_on_supported_platforms'] [features] # tidy-alphabetical-start -jemalloc = ['dep:jemalloc-sys'] +jemalloc = ['dep:tikv-jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index ccf88d8ff4b..a55a63a7bf1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -43,6 +43,8 @@ fn main() { { use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 2e51753ede6..15a27c0b6ee 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1215,6 +1215,15 @@ impl Scalar { Scalar::Union { .. } => true, } } + + /// Returns `true` if this is a signed integer scalar + #[inline] + pub fn is_signed(&self) -> bool { + match self.primitive() { + Primitive::Int(_, signed) => signed, + _ => false, + } + } } // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. @@ -1401,10 +1410,7 @@ impl BackendRepr { #[inline] pub fn is_signed(&self) -> bool { match self { - BackendRepr::Scalar(scal) => match scal.primitive() { - Primitive::Int(_, signed) => signed, - _ => false, - }, + BackendRepr::Scalar(scal) => scal.is_signed(), _ => panic!("`is_signed` on non-scalar ABI {self:?}"), } } @@ -1499,7 +1505,11 @@ impl BackendRepr { #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> { /// Single enum variants, structs/tuples, unions, and all non-ADTs. - Single { index: VariantIdx }, + Single { + /// Always 0 for non-enums/generators. + /// For enums without a variant, this is an invalid index! + index: VariantIdx, + }, /// Enum-likes with more than one variant: each variant comes with /// a *discriminant* (usually the same as the variant index but the user can @@ -1528,14 +1538,22 @@ pub enum TagEncoding<VariantIdx: Idx> { /// The variant `untagged_variant` contains a niche at an arbitrary /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to - /// `(d - niche_variants.start).wrapping_add(niche_start)`. + /// `(d - niche_variants.start).wrapping_add(niche_start)` + /// (this is wrapping arithmetic using the type of the niche field). /// /// For example, `Option<(usize, &T)>` is represented such that /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). + /// + /// Other variants that are not `untagged_variant` and that are outside the `niche_variants` + /// range cannot be represented; they must be uninhabited. Niche { untagged_variant: VariantIdx, + /// This range *may* contain `untagged_variant`; that is then just a "dead value" and + /// not used to encode anything. niche_variants: RangeInclusive<VariantIdx>, + /// This is inbounds of the type of the niche field + /// (not sign-extended, i.e., all bits beyond the niche field size are 0). niche_start: u128, }, } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ecb6ef5a2a6..ed2a3a507c8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -39,9 +39,7 @@ pub use crate::format::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream}; -use crate::util::parser::{ - AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS, -}; +use crate::util::parser::{AssocOp, ExprPrecedence}; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: @@ -1184,14 +1182,15 @@ pub struct Expr { } impl Expr { - /// Is this expr either `N`, or `{ N }`. + /// Could this expr be either `N`, or `{ N }`, where `N` is a const parameter. /// /// If this is not the case, name resolution does not resolve `N` when using /// `min_const_generics` as more complex expressions are not supported. /// /// Does not ensure that the path resolves to a const param, the caller should check this. - pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool { - let this = if strip_identity_block { self.maybe_unwrap_block() } else { self }; + /// This also does not consider macros, so it's only correct after macro-expansion. + pub fn is_potential_trivial_const_arg(&self) -> bool { + let this = self.maybe_unwrap_block(); if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() @@ -1316,29 +1315,29 @@ impl Expr { Some(P(Ty { kind, id: self.id, span: self.span, tokens: None })) } - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure(..) => PREC_CLOSURE, + ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) | ExprKind::Yeet(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence // ensures that `pprust` will add parentheses in the right places to get the desired // parse. - ExprKind::Range(..) => PREC_RANGE, + ExprKind::Range(..) => ExprPrecedence::Range, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1347,7 +1346,7 @@ impl Expr { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1380,7 +1379,7 @@ impl Expr { | ExprKind::Underscore | ExprKind::While(..) | ExprKind::Err(_) - | ExprKind::Dummy => PREC_UNAMBIGUOUS, + | ExprKind::Dummy => ExprPrecedence::Unambiguous, } } @@ -1732,12 +1731,12 @@ pub enum AttrArgs { /// Delimited arguments: `#[attr()/[]/{}]`. Delimited(DelimArgs), /// Arguments of a key-value attribute: `#[attr = "value"]`. - Eq( + Eq { /// Span of the `=` token. - Span, - /// The "value". - AttrArgsEq, - ), + eq_span: Span, + + value: AttrArgsEq, + }, } // The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro @@ -1749,15 +1748,39 @@ pub enum AttrArgsEq { Hir(MetaItemLit), } +impl AttrArgsEq { + pub fn span(&self) -> Span { + match self { + AttrArgsEq::Ast(p) => p.span, + AttrArgsEq::Hir(lit) => lit.span, + } + } + + pub fn unwrap_ast(&self) -> &Expr { + match self { + AttrArgsEq::Ast(p) => p, + AttrArgsEq::Hir(lit) => { + unreachable!("in literal form when getting inner tokens: {lit:?}") + } + } + } + + pub fn unwrap_ast_mut(&mut self) -> &mut P<Expr> { + match self { + AttrArgsEq::Ast(p) => p, + AttrArgsEq::Hir(lit) => { + unreachable!("in literal form when getting inner tokens: {lit:?}") + } + } + } +} + impl AttrArgs { pub fn span(&self) -> Option<Span> { match self { AttrArgs::Empty => None, AttrArgs::Delimited(args) => Some(args.dspan.entire()), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { - unreachable!("in literal form when getting span: {:?}", lit); - } + AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())), } } @@ -1767,10 +1790,7 @@ impl AttrArgs { match self { AttrArgs::Empty => TokenStream::default(), AttrArgs::Delimited(args) => args.tokens.clone(), - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { - unreachable!("in literal form when getting inner tokens: {:?}", lit) - } + AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()), } } } @@ -1784,10 +1804,10 @@ where match self { AttrArgs::Empty => {} AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher), - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { unreachable!("hash_stable {:?}", expr); } - AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => { eq_span.hash_stable(ctx, hasher); lit.hash_stable(ctx, hasher); } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 888b13efa31..0d79cadef34 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -250,7 +250,7 @@ impl AttrItem { AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => { MetaItemKind::list_from_tokens(args.tokens.clone()) } - AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None, + AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None, } } @@ -268,7 +268,7 @@ impl AttrItem { /// ``` fn value_str(&self) -> Option<Symbol> { match &self.args { - AttrArgs::Eq(_, args) => args.value_str(), + AttrArgs::Eq { value, .. } => value.value_str(), AttrArgs::Delimited(_) | AttrArgs::Empty => None, } } @@ -492,7 +492,7 @@ impl MetaItemKind { MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List) } AttrArgs::Delimited(..) => None, - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind { ExprKind::Lit(token_lit) => { // Turn failures to `None`, we'll get parse errors elsewhere. MetaItemLit::from_token_lit(token_lit, expr.span) @@ -501,7 +501,9 @@ impl MetaItemKind { } _ => None, }, - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + Some(MetaItemKind::NameValue(lit.clone())) + } } } } @@ -702,7 +704,7 @@ pub fn mk_attr_name_value_str( tokens: None, }); let path = Path::from_ident(Ident::new(name, span)); - let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr)); + let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) }; mk_attr(g, style, unsafety, path, args, span) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0aceed45028..196fcc1af30 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -451,13 +451,10 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) { match args { AttrArgs::Empty => {} AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { - vis.visit_expr(expr); + AttrArgs::Eq { eq_span, value } => { + vis.visit_expr(value.unwrap_ast_mut()); vis.visit_span(eq_span); } - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { - unreachable!("in literal form when visiting mac args eq: {:?}", lit) - } } } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index ed9265d5159..e88bf27021a 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -128,21 +128,21 @@ impl AssocOp { } /// Gets the precedence of this operator - pub fn precedence(&self) -> usize { + pub fn precedence(&self) -> ExprPrecedence { use AssocOp::*; match *self { - As => 14, - Multiply | Divide | Modulus => 13, - Add | Subtract => 12, - ShiftLeft | ShiftRight => 11, - BitAnd => 10, - BitXor => 9, - BitOr => 8, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, - LAnd => 6, - LOr => 5, - DotDot | DotDotEq => 4, - Assign | AssignOp(_) => 2, + As => ExprPrecedence::Cast, + Multiply | Divide | Modulus => ExprPrecedence::Product, + Add | Subtract => ExprPrecedence::Sum, + ShiftLeft | ShiftRight => ExprPrecedence::Shift, + BitAnd => ExprPrecedence::BitAnd, + BitXor => ExprPrecedence::BitXor, + BitOr => ExprPrecedence::BitOr, + Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare, + LAnd => ExprPrecedence::LAnd, + LOr => ExprPrecedence::LOr, + DotDot | DotDotEq => ExprPrecedence::Range, + Assign | AssignOp(_) => ExprPrecedence::Assign, } } @@ -229,17 +229,44 @@ impl AssocOp { } } -pub const PREC_CLOSURE: i8 = -40; -pub const PREC_JUMP: i8 = -30; -pub const PREC_RANGE: i8 = -10; -// The range 2..=14 is reserved for AssocOp binary operator precedences. -pub const PREC_PREFIX: i8 = 50; -pub const PREC_UNAMBIGUOUS: i8 = 60; -pub const PREC_FORCE_PAREN: i8 = 100; +#[derive(Clone, Copy, PartialEq, PartialOrd)] +pub enum ExprPrecedence { + Closure, + // return, break, yield + Jump, + // = += -= *= /= %= &= |= ^= <<= >>= + Assign, + // .. ..= + Range, + // || + LOr, + // && + LAnd, + // == != < > <= >= + Compare, + // | + BitOr, + // ^ + BitXor, + // & + BitAnd, + // << >> + Shift, + // + - + Sum, + // * / % + Product, + // as + Cast, + // unary - * ! & &mut + Prefix, + // paths, loops, function calls, array indexing, field expressions, method calls + Unambiguous, +} /// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`. -pub fn prec_let_scrutinee_needs_par() -> usize { - AssocOp::LAnd.precedence() +pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence { + ExprPrecedence::LAnd } /// Suppose we have `let _ = e` and the `order` of `e`. @@ -247,8 +274,8 @@ pub fn prec_let_scrutinee_needs_par() -> usize { /// /// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`. /// Can we print this as `let _ = a OP b`? -pub fn needs_par_as_let_scrutinee(order: i8) -> bool { - order <= prec_let_scrutinee_needs_par() as i8 +pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool { + order <= prec_let_scrutinee_needs_par() } /// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 718397e8ca0..2f6998783fa 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1273,10 +1273,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - match args { AttrArgs::Empty => {} AttrArgs::Delimited(_args) => {} - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)), - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { - unreachable!("in literal form when walking mac args eq: {:?}", lit) - } + AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())), } V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index ff803e50997..569a15b0e07 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -82,7 +82,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxIndexMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { @@ -222,18 +227,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; // Wrap the expression in an AnonConst. - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); - // HACK(min_generic_const_args): see lower_anon_const - if !expr.is_potential_trivial_const_arg(true) { - self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - *op_sp, - ); - } + self.create_def( + parent_def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + *op_sp, + ); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const_to_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3af29838b72..84e648f4923 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -109,16 +109,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ConstBlock { def_id, hir_id: this.lower_node_id(c.id), - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(c.value.span, Some(&c.value)) - }), + body: this.lower_const_body(c.value.span, Some(&c.value)), } }); hir::ExprKind::ConstBlock(c) } ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); - let count = self.lower_array_length(count); + let count = self.lower_array_length_to_const_arg(count); hir::ExprKind::Repeat(expr, count) } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), @@ -452,15 +450,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = ThinVec::new(); for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); - - // HACK(min_generic_const_args): see lower_anon_const - if !arg.is_potential_trivial_const_arg(true) { - // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); - } - + self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); let mut visitor = WillCreateDefIdsVisitor {}; let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { AstP(Expr { @@ -759,19 +751,17 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime_elision_allowed: false, }); - let body = self.with_def_id_parent(closure_def_id, move |this| { - this.lower_body(move |this| { - this.coroutine_kind = Some(coroutine_kind); + let body = self.lower_body(move |this| { + this.coroutine_kind = Some(coroutine_kind); - let old_ctx = this.task_context; - if task_context.is_some() { - this.task_context = task_context; - } - let res = body(this); - this.task_context = old_ctx; + let old_ctx = this.task_context; + if task_context.is_some() { + this.task_context = task_context; + } + let res = body(this); + this.task_context = old_ctx; - (params, res) - }) + (params, res) }); // `static |<_task_context?>| -> <return_ty> { <body> }`: @@ -1056,26 +1046,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - this.with_def_id_parent(closure_def_id, move |this| { - let mut coroutine_kind = if this - .attrs - .get(&closure_hir_id.local_id) - .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) - { - Some(hir::CoroutineKind::Coroutine(Movability::Movable)) - } else { - None - }; - let body_id = this.lower_fn_body(decl, |this| { - this.coroutine_kind = coroutine_kind; - let e = this.lower_expr_mut(body); - coroutine_kind = this.coroutine_kind; - e - }); - let coroutine_option = - this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); - (body_id, coroutine_option) - }) + let mut coroutine_kind = if this + .attrs + .get(&closure_hir_id.local_id) + .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) + { + Some(hir::CoroutineKind::Coroutine(Movability::Movable)) + } else { + None + }; + let body_id = this.lower_fn_body(decl, |this| { + this.coroutine_kind = coroutine_kind; + let e = this.lower_expr_mut(body); + coroutine_kind = this.coroutine_kind; + e + }); + let coroutine_option = + this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); + (body_id, coroutine_option) }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); @@ -1165,28 +1153,26 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let body = self.with_new_scopes(fn_decl_span, |this| { - this.with_def_id_parent(closure_def_id, |this| { - let inner_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - - // Transform `async |x: u8| -> X { ... }` into - // `|x: u8| || -> X { ... }`. - let body_id = this.lower_body(|this| { - let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - &inner_decl, - |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), - fn_decl_span, - body.span, - coroutine_kind, - hir::CoroutineSource::Closure, - ); + let inner_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + + // Transform `async |x: u8| -> X { ... }` into + // `|x: u8| || -> X { ... }`. + let body_id = this.lower_body(|this| { + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + &inner_decl, + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + fn_decl_span, + body.span, + coroutine_kind, + hir::CoroutineSource::Closure, + ); - this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); + this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); - (parameters, expr) - }); - body_id - }) + (parameters, expr) + }); + body_id }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 65e387de800..c3ff7b4b897 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -235,8 +235,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_anon_const(&mut self, constant: &'hir AnonConst) { - // FIXME: use real span? - self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant)); + self.insert(constant.span, constant.hir_id, Node::AnonConst(constant)); self.with_parent(constant.hir_id, |this| { intravisit::walk_anon_const(this, constant); @@ -252,8 +251,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) { - // FIXME: use real span? - self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg)); + self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg)); self.with_parent(const_arg.hir_id, |this| { intravisit::walk_const_arg(this, const_arg); @@ -387,13 +385,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_array_length(&mut self, len: &'hir ArrayLen<'hir>) { - match len { - ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), - ArrayLen::Body(..) => intravisit::walk_array_len(self, len), - } - } - fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) { self.visit_pat(p) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dae816663e0..bac3f974cca 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -117,18 +117,6 @@ struct LoweringContext<'a, 'hir> { is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, - /// Why do we need this in addition to [`Self::current_hir_id_owner`]? - /// - /// Currently (as of June 2024), anonymous constants are not HIR owners; however, - /// they do get their own DefIds. Some of these DefIds have to be created during - /// AST lowering, rather than def collection, because we can't tell until after - /// name resolution whether an anonymous constant will end up instead being a - /// [`hir::ConstArgKind::Path`]. However, to compute which generics are - /// available to an anonymous constant nested inside another, we need to make - /// sure that the parent is recorded as the parent anon const, not the enclosing - /// item. So we need to track parent defs differently from HIR owners, since they - /// will be finer-grained in the case of anon consts. - current_def_id_parent: LocalDefId, item_local_id_counter: hir::ItemLocalId, trait_map: ItemLocalMap<Box<[TraitCandidate]>>, @@ -161,7 +149,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: SortedMap::default(), children: Vec::default(), current_hir_id_owner: hir::CRATE_OWNER_ID, - current_def_id_parent: CRATE_DEF_ID, item_local_id_counter: hir::ItemLocalId::ZERO, ident_and_label_to_local_id: Default::default(), #[cfg(debug_assertions)] @@ -565,7 +552,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_eq!(_old, None); } - let item = self.with_def_id_parent(def_id, f); + let item = f(self); debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); @@ -590,13 +577,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.children.push((def_id, hir::MaybeOwner::Owner(info))); } - fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T { - let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent); - let result = f(self); - self.current_def_id_parent = current_def_id_parent; - result - } - fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); @@ -773,7 +753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, kind, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? + self.current_hir_id_owner.def_id, param, kw::UnderscoreLifetime, DefKind::LifetimeParam, @@ -909,7 +889,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { + &AttrArgs::Eq { eq_span, ref value } => { + let expr = value.unwrap_ast(); // In valid code the value always ends up as a single literal. Otherwise, a dummy // literal suffices because the error is handled elsewhere. let lit = if let ExprKind::Lit(token_lit) = expr.kind @@ -925,10 +906,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: DUMMY_SP, } }; - AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit)) - } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { - unreachable!("in literal form when lowering mac args eq: {:?}", lit) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } } } } @@ -1277,9 +1255,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - TyKind::Array(ty, length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) - } + TyKind::Array(ty, length) => hir::TyKind::Array( + self.lower_ty(ty, itctx), + self.lower_array_length_to_const_arg(length), + ), TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)), TyKind::TraitObject(bounds, kind) => { let mut lifetime_bound = None; @@ -1466,17 +1445,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id); debug!(?opaque_ty_def_id, ?opaque_ty_hir_id); - let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| { - let bounds = lower_item_bounds(this); - let opaque_ty_def = hir::OpaqueTy { - hir_id: opaque_ty_hir_id, - def_id: opaque_ty_def_id, - bounds, - origin, - span: this.lower_span(opaque_ty_span), - }; - this.arena.alloc(opaque_ty_def) - }); + let bounds = lower_item_bounds(self); + let opaque_ty_def = hir::OpaqueTy { + hir_id: opaque_ty_hir_id, + def_id: opaque_ty_def_id, + bounds, + origin, + span: self.lower_span(opaque_ty_span), + }; + let opaque_ty_def = self.arena.alloc(opaque_ty_def); hir::TyKind::OpaqueDef(opaque_ty_def) } @@ -2029,14 +2006,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr_block(block) } - fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> { + fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer() { - hir::ArrayLen::Infer(hir::InferArg { - hir_id: self.lower_node_id(c.id), - span: self.lower_span(c.value.span), - }) + let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); + self.arena + .alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) } else { feature_err( &self.tcx.sess, @@ -2045,10 +2021,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fluent_generated::ast_lowering_underscore_array_length_unstable, ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)) + self.lower_anon_const_to_const_arg(c) } } - _ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)), + _ => self.lower_anon_const_to_const_arg(c), } } @@ -2084,7 +2060,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { // Construct an AnonConst where the expr is the "ty"'s path. - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); let span = self.lower_span(span); @@ -2108,9 +2084,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::AnonConst { def_id, hir_id, - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(path_expr.span, Some(&path_expr)) - }), + body: this.lower_const_body(path_expr.span, Some(&path_expr)), span, }) }); @@ -2159,7 +2133,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, ); - return ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) }; + return ConstArg { + hir_id: self.lower_node_id(anon.id), + kind: hir::ConstArgKind::Path(qpath), + }; } let lowered_anon = self.lower_anon_const_to_anon_const(anon); @@ -2169,29 +2146,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if c.value.is_potential_trivial_const_arg(true) { - // HACK(min_generic_const_args): see DefCollector::visit_anon_const - // Over there, we guess if this is a bare param and only create a def if - // we think it's not. However we may can guess wrong (see there for example) - // in which case we have to create the def here. - self.create_def( - self.current_def_id_parent, - c.id, - kw::Empty, - DefKind::AnonConst, - c.value.span, - ); - } - self.arena.alloc(self.with_new_scopes(c.value.span, |this| { let def_id = this.local_def_id(c.id); let hir_id = this.lower_node_id(c.id); hir::AnonConst { def_id, hir_id, - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(c.value.span, Some(&c.value)) - }), + body: this.lower_const_body(c.value.span, Some(&c.value)), span: this.lower_span(c.value.span), } })) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 8cdc7133cc0..89311516081 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token}; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue}; use rustc_session::Session; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::symbol::{Symbol, sym}; use rustc_target::spec::abi; use thin_vec::ThinVec; @@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "async closures are unstable", "to use an async block, remove the `||`: `async {`" ); + gate_all!( + async_trait_bounds, + "`async` trait bounds are unstable", + "use the desugared name of the async trait, such as `AsyncFn`" + ); gate_all!(async_for_loop, "`for await` loops are experimental"); gate_all!( closure_lifetime_binder, @@ -690,6 +695,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) { .find(|feat| feat.gate_name == sym::generic_const_exprs) .map(|feat| feat.attr_sp) { + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] sess.dcx().emit_err(errors::IncompatibleFeatures { spans: vec![gce_span], f1: Symbol::intern("-Znext-solver=globally"), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d7c531f3760..479677b0a5a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -648,14 +648,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere AttrArgs::Empty => { self.print_path(&item.path, false, 0); } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); let token_str = self.expr_to_string(expr); self.word(token_str); } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 04ec135c428..c239cb249c3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -5,7 +5,7 @@ use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::util::classify; use rustc_ast::util::literal::escape_byte_str_symbol; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign, FormatTrait, token, @@ -58,10 +58,6 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8, fixup: FixupContext) { - self.print_expr_cond_paren(expr, expr.precedence() < prec, fixup); - } - /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in /// `if cond { ... }`. fn print_expr_as_cond(&mut self, expr: &ast::Expr) { @@ -216,9 +212,9 @@ impl<'a> State<'a> { } fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) { - let prec = match func.kind { - ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_UNAMBIGUOUS, + let needs_paren = match func.kind { + ast::ExprKind::Field(..) => true, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; // Independent of parenthesization related to precedence, we must @@ -237,7 +233,7 @@ impl<'a> State<'a> { // because the latter is valid syntax but with the incorrect meaning. // It's a match-expression followed by tuple-expression, not a function // call. - self.print_expr_maybe_paren(func, prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren(func, needs_paren, fixup.leftmost_subexpression()); self.print_call_post(args) } @@ -258,7 +254,11 @@ impl<'a> State<'a> { // boundaries, `$receiver.method()` can be parsed back as a statement // containing an expression if and only if `$receiver` can be parsed as // a statement containing an expression. - self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + receiver, + receiver.precedence() < ExprPrecedence::Unambiguous, + fixup, + ); self.word("."); self.print_ident(segment.ident); @@ -276,21 +276,22 @@ impl<'a> State<'a> { fixup: FixupContext, ) { let assoc_op = AssocOp::from_ast_binop(op.node); - let prec = assoc_op.precedence() as i8; - let fixity = assoc_op.fixity(); - - let (left_prec, right_prec) = match fixity { - Fixity::Left => (prec, prec + 1), - Fixity::Right => (prec + 1, prec), - Fixity::None => (prec + 1, prec + 1), + let binop_prec = assoc_op.precedence(); + let left_prec = lhs.precedence(); + let right_prec = rhs.precedence(); + + let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() { + Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), + Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), + Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - let left_prec = match (&lhs.kind, op.node) { + match (&lhs.kind, op.node) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => { - parser::PREC_FORCE_PAREN + left_needs_paren = true; } // We are given `(let _ = a) OP b`. // @@ -300,23 +301,25 @@ impl<'a> State<'a> { // - Otherwise, e.g. when we have `(let a = b) < c` in AST, // parens are required since the parser would interpret `let a = b < c` as // `let a = (b < c)`. To achieve this, we force parens. - (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => { - parser::PREC_FORCE_PAREN + (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => { + left_needs_paren = true; } - _ => left_prec, - }; - - self.print_expr_maybe_paren(lhs, left_prec, fixup.leftmost_subexpression()); + _ => {} + } + self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); self.space(); self.word_space(op.node.as_str()); - - self.print_expr_maybe_paren(rhs, right_prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) { self.word(op.as_str()); - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Prefix, + fixup.subsequent_subexpression(), + ); } fn print_expr_addr_of( @@ -334,7 +337,11 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Prefix, + fixup.subsequent_subexpression(), + ); } pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) { @@ -416,8 +423,11 @@ impl<'a> State<'a> { self.print_token_literal(lit, expr.span) } ast::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(expr, prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Cast, + fixup.leftmost_subexpression(), + ); self.space(); self.word_space("as"); self.print_type(ty); @@ -490,7 +500,11 @@ impl<'a> State<'a> { self.space(); } MatchKind::Postfix => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Unambiguous, + fixup, + ); self.word_nbsp(".match"); } } @@ -550,33 +564,57 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Await(expr, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Unambiguous, + fixup, + ); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + lhs, + // Ranges are allowed on the right-hand side of assignment, + // but not the left. `(a..b) = c` needs parentheses. + lhs.precedence() <= ExprPrecedence::Range, + fixup.leftmost_subexpression(), + ); self.space(); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + rhs, + rhs.precedence() < ExprPrecedence::Assign, + fixup.subsequent_subexpression(), + ); } ast::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + lhs, + lhs.precedence() <= ExprPrecedence::Range, + fixup.leftmost_subexpression(), + ); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + rhs, + rhs.precedence() < ExprPrecedence::Assign, + fixup.subsequent_subexpression(), + ); } ast::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < ExprPrecedence::Unambiguous, + fixup, + ); self.word("."); self.print_ident(*ident); } ast::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup.leftmost_subexpression(), ); self.word("["); @@ -588,16 +626,24 @@ impl<'a> State<'a> { // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`. // Here we use a fake precedence value so that any child with lower precedence than // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) - let fake_prec = AssocOp::LOr.precedence() as i8; + let fake_prec = ExprPrecedence::LOr; if let Some(e) = start { - self.print_expr_maybe_paren(e, fake_prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + e, + e.precedence() < fake_prec, + fixup.leftmost_subexpression(), + ); } match limits { ast::RangeLimits::HalfOpen => self.word(".."), ast::RangeLimits::Closed => self.word("..="), } if let Some(e) = end { - self.print_expr_maybe_paren(e, fake_prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + e, + e.precedence() < fake_prec, + fixup.subsequent_subexpression(), + ); } } ast::ExprKind::Underscore => self.word("_"), @@ -615,7 +661,7 @@ impl<'a> State<'a> { expr, // Parenthesize if required by precedence, or in the // case of `break 'inner: loop { break 'inner 1 } + 1` - expr.precedence() < parser::PREC_JUMP + expr.precedence() < ExprPrecedence::Jump || (opt_label.is_none() && classify::leading_labeled_expr(expr)), fixup.subsequent_subexpression(), ); @@ -632,9 +678,9 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -645,9 +691,9 @@ impl<'a> State<'a> { self.word("yeet"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -655,9 +701,9 @@ impl<'a> State<'a> { ast::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( result, - parser::PREC_JUMP, + result.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -709,15 +755,15 @@ impl<'a> State<'a> { if let Some(expr) = e { self.space(); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } } ast::ExprKind::Try(e) => { - self.print_expr_maybe_paren(e, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 16a4f699177..9b7474c2208 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -34,6 +34,7 @@ use rustc_infer::infer::{ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ @@ -502,7 +503,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) { // HIR typeck did not infer the regions of the opaque, so we instantiate // them with fresh inference variables. - let (key, hidden_ty) = tcx.fold_regions(data, |_, _| { + let (key, hidden_ty) = fold_regions(tcx, data, |_, _| { self.next_nll_region_var_in_universe( NllRegionVariableOrigin::Existential { from_forall: false }, ty::UniverseIndex::ROOT, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0ddb4e110e3..99af5500ac6 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,6 +18,7 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; @@ -1100,7 +1101,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let ty = ty.fold_with(&mut OpaqueFolder { tcx }); let mut failed = false; - let ty = tcx.fold_regions(ty, |r, _depth| { + let ty = fold_regions(tcx, ty, |r, _depth| { let r_vid = self.to_region_vid(r); let r_scc = self.constraint_sccs.scc(r_vid); @@ -1273,7 +1274,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - tcx.fold_regions(value, |r, _db| { + fold_regions(tcx, value, |r, _db| { let vid = self.to_region_vid(r); let scc = self.constraint_sccs.scc(vid); let repr = self.scc_representative(scc); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 993d5d86333..7164a129235 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -3,6 +3,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_macros::extension; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, @@ -117,7 +118,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); debug!(?opaque_type_key, ?arg_regions); - let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| { + let concrete_type = fold_regions(infcx.tcx, concrete_type, |region, _| { arg_regions .iter() .find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid)) @@ -204,7 +205,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - tcx.fold_regions(ty, |region, _| match *region { + fold_regions(tcx, ty, |region, _| match *region { ty::ReVar(vid) => { let scc = self.constraint_sccs.scc(vid); @@ -442,7 +443,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let mut seen = vec![tcx.lifetimes.re_static]; - let canonical_args = tcx.fold_regions(args, |r1, _| { + let canonical_args = fold_regions(tcx, args, |r1, _| { if r1.is_error() { r1 } else if let Some(&r2) = seen.iter().find(|&&r2| { diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index b7aef71eb54..d83d6ade203 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -2,6 +2,7 @@ use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::{Body, ConstOperand, Location, Promoted}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable}; use rustc_span::Symbol; use tracing::{debug, instrument}; @@ -68,7 +69,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> { F: Fn() -> RegionCtxt, { let origin = NllRegionVariableOrigin::Existential { from_forall: false }; - self.infcx.tcx.fold_regions(value, |_region, _depth| { + fold_regions(self.infcx.tcx, value, |_region, _depth| { self.infcx.next_nll_region_var(origin, || region_ctxt_fn()) }) } diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 68b843d4d0d..585d0eabf5b 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast}; use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_trait_selection::solve::NoSolution; use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; @@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.infcx.next_trait_solver() { let body = self.body; let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? self.fully_perform_op( location.to_locations(), ConstraintCategory::Boring, @@ -214,6 +216,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] + pub(super) fn structurally_resolve( + &mut self, + ty: Ty<'tcx>, + location: impl NormalizeLocation, + ) -> Ty<'tcx> { + if self.infcx.next_trait_solver() { + let body = self.body; + let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? + self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + CustomTypeOp::new( + |ocx| { + ocx.structurally_normalize( + &ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ), + param_env, + ty, + ) + .map_err(|_| NoSolution) + }, + "normalizing struct tail", + ), + ) + .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar)) + } else { + self.normalize(ty, location) + } + } + + #[instrument(skip(self), level = "debug")] pub(super) fn ascribe_user_type( &mut self, mir_ty: Ty<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 67915371b1f..918efac2a20 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,6 +8,7 @@ use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::traits::ScrubbedTraitError; @@ -216,7 +217,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { /// are dealt with during trait solving. fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T { if value.has_placeholders() { - self.tcx.fold_regions(value, |r, _| match *r { + fold_regions(self.tcx, value, |r, _| match *r { ty::RePlaceholder(placeholder) => { self.constraints.placeholder_region(self.infcx, placeholder) } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3a7ed711f68..89e683b8ae3 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -26,6 +26,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, @@ -213,7 +214,7 @@ pub(crate) fn type_check<'a, 'tcx>( // Convert all regions to nll vars. let (opaque_type_key, hidden_type) = - infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| { + fold_regions(infcx.tcx, (opaque_type_key, hidden_type), |region, _| { match region.kind() { ty::ReVar(_) => region, ty::RePlaceholder(placeholder) => { @@ -1064,7 +1065,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.infcx.tcx; for proj in &user_ty.projs { - if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { + if !self.infcx.next_trait_solver() + && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() + { // There is nothing that we can compare here if we go through an opaque type. // We're always in its defining scope as we can otherwise not project through // it, so we're constraining it anyways. @@ -1075,7 +1078,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { proj, |this, field, ()| { let ty = this.field_ty(tcx, field); - self.normalize(ty, locations) + self.structurally_resolve(ty, locations) }, |_, _| unreachable!(), ); @@ -2071,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let is_implicit_coercion = coercion_source == CoercionSource::Implicit; - let unsize_to = tcx.fold_regions(ty, |r, _| { + let unsize_to = fold_regions(tcx, ty, |r, _| { if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r } }); self.prove_trait_ref( diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f1c23aa26a9..bb64d646ff3 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -26,15 +26,15 @@ use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_macros::extension; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; +use rustc_span::ErrorGuaranteed; use rustc_span::symbol::{kw, sym}; -use rustc_span::{ErrorGuaranteed, Symbol}; use tracing::{debug, instrument}; use crate::BorrowckInferCtxt; @@ -524,7 +524,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let reg_vid = self .infcx - .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic"))) + .next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic)) .as_var(); let region = ty::Region::new_var(self.infcx.tcx, reg_vid); @@ -540,10 +540,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } - let fr_fn_body = self - .infcx - .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body"))) - .as_var(); + let fr_fn_body = + self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var(); let num_universals = self.infcx.num_region_vars(); @@ -824,7 +822,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - self.infcx.tcx.fold_regions(value, |region, _depth| { + fold_regions(self.infcx.tcx, value, |region, _depth| { let name = region.get_name_or_anon(); debug!(?region, ?name); @@ -906,7 +904,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region))) + fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region))) } } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9eee92164cf..cc4a974e757 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,10 +5,10 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(autodiff)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 0d62a13b472..ae9578eeffb 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -74,7 +74,7 @@ fn create_jit_module( jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); - let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name")); + let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); crate::allocator::codegen(tcx, &mut jit_module); @@ -276,12 +276,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> jit_module.module.prepare_for_function_redefine(func_id).unwrap(); - let mut cx = crate::CodegenCx::new( - tcx, - jit_module.isa(), - false, - Symbol::intern("dummy_cgu_name"), - ); + let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); assert!(cx.global_asm.is_empty()); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 7bc500b1814..d74c366a87f 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -476,9 +476,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { let mut new_slot = |x| new_slot_fn(&mut slot_size, x); // Allocate stack slots for saving clobbered registers - let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C) - .unwrap() - .clobbered_regs(); + let abi_clobber = InlineAsmClobberAbi::parse( + self.arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + sym::C, + ) + .unwrap() + .clobbered_regs(); for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { let mut need_save = true; // If the register overlaps with a register clobbered by function call, then diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index f787b8a6fd9..e0ebe30752a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -415,7 +415,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_fma => { + // FIXME: simd_relaxed_fma doesn't relax to non-fused multiply-add + sym::simd_fma | sym::simd_relaxed_fma => { intrinsic_args!(fx, args => (a, b, c); intrinsic); if !a.layout().ty.is_simd() { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index e6f6ae30581..cac9975f04c 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -189,18 +189,13 @@ impl CodegenBackend for CraneliftCodegenBackend { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support - vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")] + vec![sym::fsxr, sym::sse, sym::sse2] } else if sess.target.arch == "aarch64" { match &*sess.target.os { "none" => vec![], // On macOS the aes, sha2 and sha3 features are enabled by default and ring // fails to compile on macOS when they are not present. - "macos" => vec![ - sym::neon, - Symbol::intern("aes"), - Symbol::intern("sha2"), - Symbol::intern("sha3"), - ], + "macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3], // AArch64 mandates Neon support _ => vec![sym::neon], } diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index ab4fdb78bb0..a1f9eab10e7 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -634,6 +634,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", @@ -653,9 +656,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -720,6 +723,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl cx.type_vector(cx.type_i64(), 2) } InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), @@ -730,9 +736,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + cx.type_vector(cx.type_i32(), 4) + } InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 604678a9af4..79d1a06dd46 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -772,6 +772,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_flog => "log", sym::simd_floor => "floor", sym::simd_fma => "fma", + sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary sym::simd_fpowi => "__builtin_powi", sym::simd_fpow => "pow", sym::simd_fsin => "sin", diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 6ee80c08d4a..d1804cb49ad 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -645,6 +645,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> | Arm(ArmInlineAsmRegClass::qreg_low4) => "x", Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w", Hexagon(HexagonInlineAsmRegClass::reg) => "r", + Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => "r", LoongArch(LoongArchInlineAsmRegClass::freg) => "f", Mips(MipsInlineAsmRegClass::reg) => "r", @@ -655,9 +656,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> PowerPC(PowerPCInlineAsmRegClass::reg) => "r", PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", PowerPC(PowerPCInlineAsmRegClass::freg) => "f", - PowerPC(PowerPCInlineAsmRegClass::cr) - | PowerPC(PowerPCInlineAsmRegClass::xer) - | PowerPC(PowerPCInlineAsmRegClass::vreg) => { + PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", + PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -813,6 +813,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' | Arm(ArmInlineAsmRegClass::qreg_low8) | Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2), Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), @@ -823,9 +824,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), - PowerPC(PowerPCInlineAsmRegClass::cr) - | PowerPC(PowerPCInlineAsmRegClass::xer) - | PowerPC(PowerPCInlineAsmRegClass::vreg) => { + PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4), + PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), @@ -1040,6 +1040,26 @@ fn llvm_fixup_input<'ll, 'tcx>( let value = bx.or(value, bx.const_u32(0xFFFF_0000)); bx.bitcast(value, bx.type_f32()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f32(), 4)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f64(), 2)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)) + } _ => value, } } @@ -1175,6 +1195,18 @@ fn llvm_fixup_output<'ll, 'tcx>( let value = bx.trunc(value, bx.type_i16()); bx.bitcast(value, bx.type_f16()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)); + bx.extract_element(value, bx.const_usize(0)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)); + bx.extract_element(value, bx.const_usize(0)) + } _ => value, } } @@ -1299,6 +1331,16 @@ fn llvm_fixup_output_type<'ll, 'tcx>( { cx.type_f32() } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + cx.type_vector(cx.type_f32(), 4) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + cx.type_vector(cx.type_f64(), 2) + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 48beb9be2b2..f6d2ec24da6 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -148,7 +148,7 @@ fn prepare_lto( // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to // __llvm_profile_runtime, therefore we won't know until link time if this symbol // should have default visibility. - symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap()); + symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned()); Ok((symbols_below_threshold, upstream_modules)) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 00f7b479fa7..bde6668929c 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -61,6 +61,7 @@ fn write_output_file<'ll>( dwo_output: Option<&Path>, file_type: llvm::FileType, self_profiler_ref: &SelfProfilerRef, + verify_llvm_ir: bool, ) -> Result<(), FatalError> { debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output); unsafe { @@ -79,6 +80,7 @@ fn write_output_file<'ll>( output_c.as_ptr(), dwo_output_ptr, file_type, + verify_llvm_ir, ); // Record artifact sizes for self-profiling @@ -507,7 +509,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> { } fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> { - config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap()) + config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned()) } pub(crate) unsafe fn llvm_optimize( @@ -840,6 +842,7 @@ pub(crate) unsafe fn codegen( None, llvm::FileType::AssemblyFile, &cgcx.prof, + config.verify_llvm_ir, ) })?; } @@ -877,6 +880,7 @@ pub(crate) unsafe fn codegen( dwo_out, llvm::FileType::ObjectFile, &cgcx.prof, + config.verify_llvm_ir, ) })?; } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index e0a2de3366c..ec77f32caf4 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -104,7 +104,10 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t let is_hidden = if is_generic { // This is a monomorphization of a generic function. - if !cx.tcx.sess.opts.share_generics() { + if !(cx.tcx.sess.opts.share_generics() + || tcx.codegen_fn_attrs(instance_def_id).inline + == rustc_attr::InlineAttr::Never) + { // When not sharing generics, all instances are in the same // crate and have hidden visibility. true diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 841c110b3c8..8218126ea29 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -82,8 +82,8 @@ pub(crate) struct CodegenCx<'ll, 'tcx> { pub isize_ty: &'ll Type, - /// Extra codegen state needed when coverage instrumentation is enabled. - pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>, + /// Extra per-CGU codegen state needed when coverage instrumentation is enabled. + pub coverage_cx: Option<coverageinfo::CguCoverageContext<'ll, 'tcx>>, pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>, eh_personality: Cell<Option<&'ll Value>>, @@ -525,7 +525,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); let coverage_cx = - tcx.sess.instrument_coverage().then(coverageinfo::CrateCoverageContext::new); + tcx.sess.instrument_coverage().then(coverageinfo::CguCoverageContext::new); let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CodegenUnitDebugContext::new(llmod); @@ -576,7 +576,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Extra state that is only available when coverage instrumentation is enabled. #[inline] #[track_caller] - pub(crate) fn coverage_cx(&self) -> &coverageinfo::CrateCoverageContext<'ll, 'tcx> { + pub(crate) fn coverage_cx(&self) -> &coverageinfo::CguCoverageContext<'ll, 'tcx> { self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled") } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 19d6726002c..a6e07ea2a60 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,6 @@ -use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion}; + +use crate::coverageinfo::mapgen::LocalFileId; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -124,23 +126,37 @@ pub(crate) struct CoverageSpan { /// Local index into the function's local-to-global file ID table. /// The value at that index is itself an index into the coverage filename /// table in the CGU's `__llvm_covmap` section. - pub(crate) file_id: u32, + file_id: u32, /// 1-based starting line of the source code span. - pub(crate) start_line: u32, + start_line: u32, /// 1-based starting column of the source code span. - pub(crate) start_col: u32, + start_col: u32, /// 1-based ending line of the source code span. - pub(crate) end_line: u32, + end_line: u32, /// 1-based ending column of the source code span. High bit must be unset. - pub(crate) end_col: u32, + end_col: u32, +} + +impl CoverageSpan { + pub(crate) fn from_source_region( + local_file_id: LocalFileId, + code_region: &SourceRegion, + ) -> Self { + let file_id = local_file_id.as_u32(); + let &SourceRegion { start_line, start_col, end_line, end_col } = code_region; + // Internally, LLVM uses the high bit of `end_col` to distinguish between + // code regions and gap regions, so it can't be used by the column number. + assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); + Self { file_id, start_line, start_col, end_line, end_col } + } } /// Must match the layout of `LLVMRustCoverageCodeRegion`. #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct CodeRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) counter: Counter, } @@ -148,7 +164,7 @@ pub(crate) struct CodeRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct BranchRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) true_counter: Counter, pub(crate) false_counter: Counter, } @@ -157,7 +173,7 @@ pub(crate) struct BranchRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct MCDCBranchRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) true_counter: Counter, pub(crate) false_counter: Counter, pub(crate) mcdc_branch_params: mcdc::BranchParameters, @@ -167,6 +183,6 @@ pub(crate) struct MCDCBranchRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct MCDCDecisionRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) mcdc_decision_params: mcdc::DecisionParameters, } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 95746b88ced..0752c718c70 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,12 +1,13 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::CoverageIdsInfo; use rustc_middle::mir::coverage::{ CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, + SourceRegion, }; use rustc_middle::ty::Instance; -use rustc_span::Span; -use tracing::{debug, instrument}; +use tracing::debug; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -16,17 +17,8 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; pub(crate) struct FunctionCoverageCollector<'tcx> { /// Coverage info that was attached to this function by the instrumentor. function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, - - /// Tracks which counters have been seen, so that we can identify mappings - /// to counters that were optimized out, and set them to zero. - counters_seen: BitSet<CounterId>, - /// Contains all expression IDs that have been seen in an `ExpressionUsed` - /// coverage statement, plus all expression IDs that aren't directly used - /// by any mappings (and therefore do not have expression-used statements). - /// After MIR traversal is finished, we can conclude that any IDs missing - /// from this set must have had their statements deleted by MIR opts. - expressions_seen: BitSet<ExpressionId>, } impl<'tcx> FunctionCoverageCollector<'tcx> { @@ -34,21 +26,24 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { pub(crate) fn new( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, ) -> Self { - Self::create(instance, function_coverage_info, true) + Self::create(instance, function_coverage_info, ids_info, true) } /// Creates a new set of coverage data for an unused (never called) function. pub(crate) fn unused( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, ) -> Self { - Self::create(instance, function_coverage_info, false) + Self::create(instance, function_coverage_info, ids_info, false) } fn create( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, ) -> Self { let num_counters = function_coverage_info.num_counters; @@ -58,44 +53,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}" ); - // Create a filled set of expression IDs, so that expressions not - // directly used by mappings will be treated as "seen". - // (If they end up being unused, LLVM will delete them for us.) - let mut expressions_seen = BitSet::new_filled(num_expressions); - // For each expression ID that is directly used by one or more mappings, - // mark it as not-yet-seen. This indicates that we expect to see a - // corresponding `ExpressionUsed` statement during MIR traversal. - for mapping in function_coverage_info.mappings.iter() { - // Currently we only worry about ordinary code mappings. - // For branch and MC/DC mappings, expressions might not correspond - // to any particular point in the control-flow graph. - // (Keep this in sync with the injection of `ExpressionUsed` - // statements in the `InstrumentCoverage` MIR pass.) - if let MappingKind::Code(term) = mapping.kind - && let CovTerm::Expression(id) = term - { - expressions_seen.remove(id); - } - } - - Self { - function_coverage_info, - is_used, - counters_seen: BitSet::new_empty(num_counters), - expressions_seen, - } - } - - /// Marks a counter ID as having been seen in a counter-increment statement. - #[instrument(level = "debug", skip(self))] - pub(crate) fn mark_counter_id_seen(&mut self, id: CounterId) { - self.counters_seen.insert(id); - } - - /// Marks an expression ID as having been seen in an expression-used statement. - #[instrument(level = "debug", skip(self))] - pub(crate) fn mark_expression_id_seen(&mut self, id: ExpressionId) { - self.expressions_seen.insert(id); + Self { function_coverage_info, ids_info, is_used } } /// Identify expressions that will always have a value of zero, and note @@ -117,7 +75,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { // (By construction, expressions can only refer to other expressions // that have lower IDs, so one pass is sufficient.) for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { - if !self.expressions_seen.contains(id) { + if !self.is_used || !self.ids_info.expressions_seen.contains(id) { // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. zero_expressions.insert(id); @@ -146,7 +104,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { assert_operand_expression_is_lower(id); } - if is_zero_term(&self.counters_seen, &zero_expressions, *operand) { + if is_zero_term(&self.ids_info.counters_seen, &zero_expressions, *operand) { *operand = CovTerm::Zero; } }; @@ -172,17 +130,17 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { pub(crate) fn into_finished(self) -> FunctionCoverage<'tcx> { let zero_expressions = self.identify_zero_expressions(); - let FunctionCoverageCollector { function_coverage_info, is_used, counters_seen, .. } = self; + let FunctionCoverageCollector { function_coverage_info, ids_info, is_used, .. } = self; - FunctionCoverage { function_coverage_info, is_used, counters_seen, zero_expressions } + FunctionCoverage { function_coverage_info, ids_info, is_used, zero_expressions } } } pub(crate) struct FunctionCoverage<'tcx> { pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, - counters_seen: BitSet<CounterId>, zero_expressions: ZeroExpressions, } @@ -220,16 +178,16 @@ impl<'tcx> FunctionCoverage<'tcx> { }) } - /// Yields all this function's coverage mappings, after simplifying away - /// unused counters and counter expressions. - pub(crate) fn mapping_spans( + /// Converts this function's coverage mappings into an intermediate form + /// that will be used by `mapgen` when preparing for FFI. + pub(crate) fn counter_regions( &self, - ) -> impl Iterator<Item = (MappingKind, Span)> + ExactSizeIterator + Captures<'_> { + ) -> impl Iterator<Item = (MappingKind, &SourceRegion)> + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let &Mapping { ref kind, span } = mapping; + let Mapping { kind, source_region } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, span) + (kind, source_region) }) } @@ -238,7 +196,7 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn is_zero_term(&self, term: CovTerm) -> bool { - is_zero_term(&self.counters_seen, &self.zero_expressions, term) + !self.is_used || is_zero_term(&self.ids_info.counters_seen, &self.zero_expressions, term) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index ed881418cb0..8c24579fa7c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,14 +1,12 @@ -mod spans; - use std::ffi::CString; -use std::sync::Arc; +use std::iter; use itertools::Itertools as _; use rustc_abi::Align; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; use rustc_middle::mir::coverage::MappingKind; @@ -17,7 +15,7 @@ use rustc_middle::{bug, mir}; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::def_id::DefIdSet; -use rustc_span::{SourceFile, StableSourceFileId}; +use rustc_span::{Span, Symbol}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -74,11 +72,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { .map(|(instance, function_coverage)| (instance, function_coverage.into_finished())) .collect::<Vec<_>>(); - let all_files = function_coverage_entries + let all_file_names = function_coverage_entries .iter() .map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span) - .map(|span| tcx.sess.source_map().lookup_source_file(span.lo())); - let global_file_table = GlobalFileTable::new(all_files); + .map(|span| span_file_name(tcx, span)); + let global_file_table = GlobalFileTable::new(all_file_names); // Encode all filenames referenced by coverage mappings in this CGU. let filenames_buffer = global_file_table.make_filenames_buffer(tcx); @@ -105,8 +103,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { encode_mappings_for_function(tcx, &global_file_table, &function_coverage); if coverage_mapping_buffer.is_empty() { - debug!("function has no mappings to embed; skipping"); - continue; + if function_coverage.is_used() { + bug!( + "A used function should have had coverage mapping data but did not: {}", + mangled_function_name + ); + } else { + debug!("unused function had no coverage mapping data: {}", mangled_function_name); + continue; + } } if !is_used { @@ -143,34 +148,29 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { } } -/// Maps "global" (per-CGU) file ID numbers to their underlying source files. +/// Maps "global" (per-CGU) file ID numbers to their underlying filenames. struct GlobalFileTable { - /// This "raw" table doesn't include the working dir, so a file's + /// This "raw" table doesn't include the working dir, so a filename's /// global ID is its index in this set **plus one**. - raw_file_table: FxIndexMap<StableSourceFileId, Arc<SourceFile>>, + raw_file_table: FxIndexSet<Symbol>, } impl GlobalFileTable { - fn new(all_files: impl IntoIterator<Item = Arc<SourceFile>>) -> Self { - // Collect all of the files into a set. Files usually come in contiguous - // runs, so we can dedup adjacent ones to save work. - let mut raw_file_table = all_files - .into_iter() - .dedup_by(|a, b| a.stable_id == b.stable_id) - .map(|f| (f.stable_id, f)) - .collect::<FxIndexMap<StableSourceFileId, Arc<SourceFile>>>(); + fn new(all_file_names: impl IntoIterator<Item = Symbol>) -> Self { + // Collect all of the filenames into a set. Filenames usually come in + // contiguous runs, so we can dedup adjacent ones to save work. + let mut raw_file_table = all_file_names.into_iter().dedup().collect::<FxIndexSet<Symbol>>(); - // Sort the file table by its underlying filenames. - raw_file_table.sort_unstable_by(|_, a, _, b| { - Ord::cmp(&a.name, &b.name).then_with(|| Ord::cmp(&a.stable_id, &b.stable_id)) - }); + // Sort the file table by its actual string values, not the arbitrary + // ordering of its symbols. + raw_file_table.sort_unstable_by(|a, b| a.as_str().cmp(b.as_str())); Self { raw_file_table } } - fn global_file_id_for_file(&self, file: &SourceFile) -> GlobalFileId { - let raw_id = self.raw_file_table.get_index_of(&file.stable_id).unwrap_or_else(|| { - bug!("file not found in prepared global file table: {:?}", file.name); + fn global_file_id_for_file_name(&self, file_name: Symbol) -> GlobalFileId { + let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| { + bug!("file name not found in prepared global file table: {file_name}"); }); // The raw file table doesn't include an entry for the working dir // (which has ID 0), so add 1 to get the correct ID. @@ -178,27 +178,24 @@ impl GlobalFileTable { } fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec<u8> { - let mut table = Vec::with_capacity(self.raw_file_table.len() + 1); - // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) // requires setting the first filename to the compilation directory. // Since rustc generates coverage maps with relative paths, the // compilation directory can be combined with the relative paths // to get absolute paths, if needed. - table.push( - tcx.sess - .opts - .working_dir - .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) - .to_string_lossy(), - ); - - // Add the regular entries after the base directory. - table.extend(self.raw_file_table.values().map(|file| { - file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy() - })); - - llvm_cov::write_filenames_to_buffer(table.iter().map(|f| f.as_ref())) + use rustc_session::RemapFileNameExt; + use rustc_session::config::RemapPathScopeComponents; + let working_dir: &str = &tcx + .sess + .opts + .working_dir + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy(); + + // Insert the working dir at index 0, before the other filenames. + let filenames = + iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)); + llvm_cov::write_filenames_to_buffer(filenames) } } @@ -211,7 +208,7 @@ rustc_index::newtype_index! { /// An index into a function's list of global file IDs. That underlying list /// of local-to-global mappings will be embedded in the function's record in /// the `__llvm_covfun` linker section. - struct LocalFileId {} + pub(crate) struct LocalFileId {} } /// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) @@ -237,6 +234,13 @@ impl VirtualFileMapping { } } +fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { + let source_file = tcx.sess.source_map().lookup_source_file(span.lo()); + let name = + source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(); + Symbol::intern(&name) +} + /// Using the expressions and counter regions collected for a single function, /// generate the variable-sized payload of its corresponding `__llvm_covfun` /// entry. The payload is returned as a vector of bytes. @@ -247,13 +251,11 @@ fn encode_mappings_for_function( global_file_table: &GlobalFileTable, function_coverage: &FunctionCoverage<'_>, ) -> Vec<u8> { - let mapping_spans = function_coverage.mapping_spans(); - if mapping_spans.is_empty() { + let counter_regions = function_coverage.counter_regions(); + if counter_regions.is_empty() { return Vec::new(); } - let fn_cov_info = function_coverage.function_coverage_info; - let expressions = function_coverage.counter_expressions().collect::<Vec<_>>(); let mut virtual_file_mapping = VirtualFileMapping::default(); @@ -263,39 +265,34 @@ fn encode_mappings_for_function( let mut mcdc_decision_regions = vec![]; // Currently a function's mappings must all be in the same file as its body span. - let source_map = tcx.sess.source_map(); - let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo()); + let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span); - // Look up the global file ID for that file. - let global_file_id = global_file_table.global_file_id_for_file(&source_file); + // Look up the global file ID for that filename. + let global_file_id = global_file_table.global_file_id_for_file_name(file_name); // Associate that global file ID with a local file ID for this function. let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); + debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); - let make_cov_span = |span| { - spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span) - }; - - // For each coverage mapping span in this function+file, convert it to a + // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. - for (mapping_kind, span) in mapping_spans { - debug!("Adding counter {mapping_kind:?} to map for {span:?}"); - let Some(cov_span) = make_cov_span(span) else { continue }; + for (mapping_kind, region) in counter_regions { + debug!("Adding counter {mapping_kind:?} to map for {region:?}"); + let span = ffi::CoverageSpan::from_source_region(local_file_id, region); match mapping_kind { MappingKind::Code(term) => { - code_regions - .push(ffi::CodeRegion { cov_span, counter: ffi::Counter::from_term(term) }); + code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); } MappingKind::Branch { true_term, false_term } => { branch_regions.push(ffi::BranchRegion { - cov_span, + span, true_counter: ffi::Counter::from_term(true_term), false_counter: ffi::Counter::from_term(false_term), }); } MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { mcdc_branch_regions.push(ffi::MCDCBranchRegion { - cov_span, + span, true_counter: ffi::Counter::from_term(true_term), false_counter: ffi::Counter::from_term(false_term), mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), @@ -303,7 +300,7 @@ fn encode_mappings_for_function( } MappingKind::MCDCDecision(mcdc_decision_params) => { mcdc_decision_regions.push(ffi::MCDCDecisionRegion { - cov_span, + span, mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params), }); } @@ -538,9 +535,12 @@ fn add_unused_function_coverage<'tcx>( }), ); - // An unused function's mappings will automatically be rewritten to map to - // zero, because none of its counters/expressions are marked as seen. - let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info); + // An unused function's mappings will all be rewritten to map to zero. + let function_coverage = FunctionCoverageCollector::unused( + instance, + function_coverage_info, + tcx.coverage_ids_info(instance.def), + ); cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage); } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs deleted file mode 100644 index 4a7721879fd..00000000000 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs +++ /dev/null @@ -1,124 +0,0 @@ -use rustc_middle::mir::coverage::FunctionCoverageInfo; -use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, Pos, SourceFile, Span}; -use tracing::debug; - -use crate::coverageinfo::ffi; -use crate::coverageinfo::mapgen::LocalFileId; - -/// Converts the span into its start line and column, and end line and column. -/// -/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by -/// the compiler, these column numbers are denoted in **bytes**, because that's what -/// LLVM's `llvm-cov` tool expects to see in coverage maps. -/// -/// Returns `None` if the conversion failed for some reason. This shouldn't happen, -/// but it's hard to rule out entirely (especially in the presence of complex macros -/// or other expansions), and if it does happen then skipping a span or function is -/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -pub(crate) fn make_coverage_span( - file_id: LocalFileId, - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - file: &SourceFile, - span: Span, -) -> Option<ffi::CoverageSpan> { - let span = ensure_non_empty_span(source_map, fn_cov_info, span)?; - - let lo = span.lo(); - let hi = span.hi(); - - // Column numbers need to be in bytes, so we can't use the more convenient - // `SourceMap` methods for looking up file coordinates. - let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { - let rpos = file.relative_position(pos); - let line_index = file.lookup_line(rpos)?; - let line_start = file.lines()[line_index]; - // Line numbers and column numbers are 1-based, so add 1 to each. - Some((line_index + 1, (rpos - line_start).to_usize() + 1)) - }; - - let (mut start_line, start_col) = line_and_byte_column(lo)?; - let (mut end_line, end_col) = line_and_byte_column(hi)?; - - // Apply an offset so that code in doctests has correct line numbers. - // FIXME(#79417): Currently we have no way to offset doctest _columns_. - start_line = source_map.doctest_offset_line(&file.name, start_line); - end_line = source_map.doctest_offset_line(&file.name, end_line); - - check_coverage_span(ffi::CoverageSpan { - file_id: file_id.as_u32(), - start_line: start_line as u32, - start_col: start_col as u32, - end_line: end_line as u32, - end_col: end_col as u32, - }) -} - -fn ensure_non_empty_span( - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - span: Span, -) -> Option<Span> { - if !span.is_empty() { - return Some(span); - } - - let lo = span.lo(); - let hi = span.hi(); - - // The span is empty, so try to expand it to cover an adjacent '{' or '}', - // but only within the bounds of the body span. - let try_next = hi < fn_cov_info.body_span.hi(); - let try_prev = fn_cov_info.body_span.lo() < lo; - if !(try_next || try_prev) { - return None; - } - - source_map - .span_to_source(span, |src, start, end| try { - // We're only checking for specific ASCII characters, so we don't - // have to worry about multi-byte code points. - if try_next && src.as_bytes()[end] == b'{' { - Some(span.with_hi(hi + BytePos(1))) - } else if try_prev && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(lo - BytePos(1))) - } else { - None - } - }) - .ok()? -} - -/// If `llvm-cov` sees a source region that is improperly ordered (end < start), -/// it will immediately exit with a fatal error. To prevent that from happening, -/// discard regions that are improperly ordered, or might be interpreted in a -/// way that makes them improperly ordered. -fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> { - let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span; - - // Line/column coordinates are supposed to be 1-based. If we ever emit - // coordinates of 0, `llvm-cov` might misinterpret them. - let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); - // Coverage mappings use the high bit of `end_col` to indicate that a - // region is actually a "gap" region, so make sure it's unset. - let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; - // If a region is improperly ordered (end < start), `llvm-cov` will exit - // with a fatal error, which is inconvenient for users and hard to debug. - let is_ordered = (start_line, start_col) <= (end_line, end_col); - - if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(cov_span) - } else { - debug!( - ?cov_span, - ?all_nonzero, - ?end_col_has_high_bit_unset, - ?is_ordered, - "Skipping source region that would be misinterpreted or rejected by LLVM" - ); - // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper source region: {cov_span:?}"); - None - } -} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index bf773cd2667..c2fcb33f98b 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -21,8 +21,8 @@ mod llvm_cov; pub(crate) mod map_data; mod mapgen; -/// A context object for maintaining all state needed by the coverageinfo module. -pub(crate) struct CrateCoverageContext<'ll, 'tcx> { +/// Extra per-CGU context/state needed for coverage instrumentation. +pub(crate) struct CguCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, @@ -32,7 +32,7 @@ pub(crate) struct CrateCoverageContext<'ll, 'tcx> { covfun_section_name: OnceCell<CString>, } -impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { +impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> { pub(crate) fn new() -> Self { Self { function_coverage_map: Default::default(), @@ -143,6 +143,13 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let bx = self; + // Due to LocalCopy instantiation or MIR inlining, coverage statements + // can end up in a crate that isn't doing coverage instrumentation. + // When that happens, we currently just discard those statements, so + // the corresponding code will be undercounted. + // FIXME(Zalathar): Find a better solution for mixed-coverage builds. + let Some(coverage_cx) = &bx.cx.coverage_cx else { return }; + let Some(function_coverage_info) = bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref() else { @@ -150,32 +157,28 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - // FIXME(#132395): Unwrapping `coverage_cx` here has led to ICEs in the - // wild, so keep this early-return until we understand why. - let mut coverage_map = match bx.coverage_cx { - Some(ref cx) => cx.function_coverage_map.borrow_mut(), - None => return, - }; - let func_coverage = coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); + // Mark the instance as used in this CGU, for coverage purposes. + // This includes functions that were not partitioned into this CGU, + // but were MIR-inlined into one of this CGU's functions. + coverage_cx.function_coverage_map.borrow_mut().entry(instance).or_insert_with(|| { + FunctionCoverageCollector::new( + instance, + function_coverage_info, + bx.tcx.coverage_ids_info(instance.def), + ) + }); match *kind { CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( "marker statement {kind:?} should have been removed by CleanupPostBorrowck" ), CoverageKind::CounterIncrement { id } => { - func_coverage.mark_counter_id_seen(id); - // We need to explicitly drop the `RefMut` before calling into - // `instrprof_increment`, as that needs an exclusive borrow. - drop(coverage_map); - // The number of counters passed to `llvm.instrprof.increment` might // be smaller than the number originally inserted by the instrumentor, // if some high-numbered counters were removed by MIR optimizations. // If so, LLVM's profiler runtime will use fewer physical counters. let num_counters = - bx.tcx().coverage_ids_info(instance.def).max_counter_id.as_u32() + 1; + bx.tcx().coverage_ids_info(instance.def).num_counters_after_mir_opts(); assert!( num_counters as usize <= function_coverage_info.num_counters, "num_counters disagreement: query says {num_counters} but function info only has {}", @@ -192,23 +195,23 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { ); bx.instrprof_increment(fn_name, hash, num_counters, index); } - CoverageKind::ExpressionUsed { id } => { - func_coverage.mark_expression_id_seen(id); + CoverageKind::ExpressionUsed { id: _ } => { + // Expression-used statements are markers that are handled by + // `coverage_ids_info`, so there's nothing to codegen here. } CoverageKind::CondBitmapUpdate { index, decision_depth } => { - drop(coverage_map); - let cond_bitmap = bx - .coverage_cx() + let cond_bitmap = coverage_cx .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); let cond_index = bx.const_i32(index as i32); bx.mcdc_condbitmap_update(cond_index, cond_bitmap); } CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { - drop(coverage_map); - let cond_bitmap = bx.coverage_cx() - .try_get_mcdc_condition_bitmap(&instance, decision_depth) - .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); + let cond_bitmap = + coverage_cx.try_get_mcdc_condition_bitmap(&instance, decision_depth).expect( + "mcdc cond bitmap should have been allocated for merging \ + into the global bitmap", + ); assert!( bitmap_idx as usize <= function_coverage_info.mcdc_bitmap_bits, "bitmap index of the decision out of range" diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ef16e5bb459..dee67baaee9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -203,6 +203,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &ptr_type_debuginfo_name, + None, cx.size_and_align_of(ptr_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -259,6 +260,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( layout.fields.offset(abi::WIDE_PTR_ADDR), DIFlags::FlagZero, data_ptr_type_di_node, + None, ), build_field_di_node( cx, @@ -268,6 +270,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( layout.fields.offset(abi::WIDE_PTR_EXTRA), DIFlags::FlagZero, type_di_node(cx, extra_field.ty), + None, ), ] }, @@ -369,6 +372,7 @@ fn build_dyn_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + None, cx.size_and_align_of(dyn_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -722,6 +726,14 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation // `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`. let float_ty = cx.tcx.types.f16; let bits_ty = cx.tcx.types.u16; + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + match float_ty.kind() { + ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))), + _ => None, + } + } else { + None + }; type_map::build_type_with_children( cx, type_map::stub( @@ -729,12 +741,21 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation Stub::Struct, UniqueTypeId::for_ty(cx.tcx, float_ty), "f16", + def_location, cx.size_and_align_of(float_ty), NO_SCOPE_METADATA, DIFlags::FlagZero, ), // Fields: |cx, float_di_node| { + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + match bits_ty.kind() { + ty::Adt(def, _) => Some(def.did()), + _ => None, + } + } else { + None + }; smallvec![build_field_di_node( cx, float_di_node, @@ -743,6 +764,7 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation Size::ZERO, DIFlags::FlagZero, type_di_node(cx, bits_ty), + def_id, )] }, NO_GENERICS, @@ -839,6 +861,7 @@ fn build_foreign_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, t, false), + None, cx.size_and_align_of(t), Some(get_namespace_for_item(cx, def_id)), DIFlags::FlagZero, @@ -989,15 +1012,22 @@ fn build_field_di_node<'ll, 'tcx>( offset: Size, flags: DIFlags, type_di_node: &'ll DIType, + def_id: Option<DefId>, ) -> &'ll DIType { + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), owner, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size_and_align.0.bits(), size_and_align.1.bits() as u32, offset.bits(), @@ -1041,6 +1071,11 @@ fn build_struct_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, adt_def.did()); let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(adt_def.did()))) + } else { + None + }; type_map::build_type_with_children( cx, @@ -1049,6 +1084,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, struct_type, false), + def_location, size_and_align_of(struct_type_and_layout), Some(containing_scope), visibility_di_flags(cx, adt_def.did(), adt_def.did()), @@ -1068,6 +1104,11 @@ fn build_struct_type_di_node<'ll, 'tcx>( Cow::Borrowed(f.name.as_str()) }; let field_layout = struct_type_and_layout.field(cx, i); + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(f.did) + } else { + None + }; build_field_di_node( cx, owner, @@ -1076,6 +1117,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( struct_type_and_layout.fields.offset(i), visibility_di_flags(cx, f.did, adt_def.did()), type_di_node(cx, field_layout.ty), + def_id, ) }) .collect() @@ -1125,6 +1167,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, up_var_ty), + None, ) }) .collect() @@ -1150,6 +1193,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + None, size_and_align_of(tuple_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -1168,6 +1212,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>( tuple_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, component_type), + None, ) }) .collect() @@ -1189,6 +1234,12 @@ fn build_closure_env_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, def_id); let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -1196,6 +1247,7 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + def_location, cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, @@ -1219,6 +1271,11 @@ fn build_union_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, union_def_id); let union_ty_and_layout = cx.layout_of(union_type); let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(union_def_id))) + } else { + None + }; type_map::build_type_with_children( cx, @@ -1227,6 +1284,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Stub::Union, unique_type_id, &type_name, + def_location, size_and_align_of(union_ty_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -1239,6 +1297,11 @@ fn build_union_type_di_node<'ll, 'tcx>( .enumerate() .map(|(i, f)| { let field_layout = union_ty_and_layout.field(cx, i); + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(f.did) + } else { + None + }; build_field_di_node( cx, owner, @@ -1247,6 +1310,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Size::ZERO, DIFlags::FlagZero, type_di_node(cx, field_layout.ty), + def_id, ) }) .collect() @@ -1321,14 +1385,7 @@ pub(crate) fn build_global_var_di_node<'ll>( // We may want to remove the namespace scope if we're in an extern block (see // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). let var_scope = get_namespace_for_item(cx, def_id); - let span = hygiene::walk_chain_collapsed(tcx.def_span(def_id), DUMMY_SP); - - let (file_metadata, line_number) = if !span.is_dummy() { - let loc = cx.lookup_debug_loc(span.lo()); - (file_metadata(cx, &loc.file), loc.line) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id)); let is_local_to_unit = is_node_local_to_unit(cx, def_id); @@ -1418,6 +1475,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( Stub::VTableTy { vtable_holder }, unique_type_id, &vtable_type_name, + None, (size, pointer_align), NO_SCOPE_METADATA, DIFlags::FlagArtificial, @@ -1455,6 +1513,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( field_offset, DIFlags::FlagZero, field_type_di_node, + None, )) }) .collect() @@ -1606,3 +1665,20 @@ fn tuple_field_name(field_index: usize) -> Cow<'static, str> { .map(|s| Cow::from(*s)) .unwrap_or_else(|| Cow::from(format!("__{field_index}"))) } + +pub(crate) type DefinitionLocation<'ll> = (&'ll DIFile, c_uint); + +pub(crate) fn file_metadata_from_def_id<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: Option<DefId>, +) -> DefinitionLocation<'ll> { + if let Some(def_id) = def_id + && let span = hygiene::walk_chain_collapsed(cx.tcx.def_span(def_id), DUMMY_SP) + && !span.is_dummy() + { + let loc = cx.lookup_debug_loc(span.lo()); + (file_metadata(cx, &loc.file), loc.line) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + } +} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 100b046cee2..d374767f187 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -4,7 +4,7 @@ use libc::c_uint; use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; -use rustc_codegen_ssa::traits::ConstCodegenMethods; +use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods}; use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; @@ -16,8 +16,8 @@ use crate::debuginfo::metadata::enums::DiscrResult; use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER, - build_field_di_node, file_metadata, size_and_align_of, type_di_node, unknown_file_metadata, - visibility_di_flags, + build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node, + unknown_file_metadata, visibility_di_flags, }; use crate::debuginfo::utils::DIB; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -192,6 +192,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -199,6 +205,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &enum_type_name, + def_location, cx.size_and_align_of(enum_type), NO_SCOPE_METADATA, visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()), @@ -262,6 +269,14 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let coroutine_type = unique_type_id.expect_ty(); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else { + bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) + }; + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))) + } else { + None + }; let coroutine_type_and_layout = cx.layout_of(coroutine_type); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); @@ -274,6 +289,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, + def_location, size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -321,6 +337,12 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let tag_base_type_di_node = type_di_node(cx, tag_base_type); let tag_base_type_align = cx.align_of(tag_base_type); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(enum_adt_def.did()) + } else { + None + }; + let variant_names_type_di_node = build_variant_names_type_di_node( cx, enum_type_di_node, @@ -328,6 +350,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( variant_index, Cow::from(enum_adt_def.variant(variant_index).name.as_str()), )), + enum_adt_def_id, ); let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( @@ -341,6 +364,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, DiscrResult::NoDiscriminant, + None, ); smallvec![ @@ -354,6 +378,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( Size::ZERO, visibility_flags, variant_struct_type_wrapper_di_node, + None, ), unsafe { llvm::LLVMRustDIBuilderCreateStaticMemberType( @@ -383,6 +408,12 @@ fn build_union_fields_for_enum<'ll, 'tcx>( ) -> SmallVec<&'ll DIType> { let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(enum_adt_def.did()) + } else { + None + }; + let variant_names_type_di_node = build_variant_names_type_di_node( cx, enum_type_di_node, @@ -390,6 +421,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (variant_index, variant_name) }), + enum_adt_def_id, ); let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()); @@ -447,6 +479,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, containing_scope: &'ll DIType, variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>, + enum_def_id: Option<rustc_span::def_id::DefId>, ) -> &'ll DIType { // Create an enumerator for each variant. super::build_enumeration_type_di_node( @@ -454,6 +487,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( "VariantNames", variant_names_enum_base_type(cx), variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())), + enum_def_id, containing_scope, ) } @@ -469,6 +503,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( tag_base_type_di_node: &'ll DIType, tag_base_type: Ty<'tcx>, discr: DiscrResult, + source_info: Option<(&'ll DIFile, c_uint)>, ) -> &'ll DIType { type_map::build_type_with_children( cx, @@ -481,6 +516,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( variant_index, ), &variant_struct_wrapper_type_name(variant_index), + source_info, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_or_coroutine_type_and_layout), Some(enum_or_coroutine_type_di_node), @@ -530,6 +566,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( Size::ZERO, DIFlags::FlagZero, variant_struct_type_di_node, + None, )); let build_assoc_const = @@ -684,6 +721,11 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( variant_range .clone() .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))), + if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(coroutine_def_id) + } else { + None + }, ); let discriminants: IndexVec<VariantIdx, DiscrResult> = { @@ -776,6 +818,11 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, variant_member_info.discr, + if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + variant_member_info.source_info + } else { + None + }, ); // We use LLVMRustDIBuilderCreateMemberType() member type directly because @@ -831,6 +878,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( lo_offset, di_flags, type_di_node, + None, )); unions_fields.push(build_field_di_node( @@ -841,6 +889,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( hi_offset, DIFlags::FlagZero, type_di_node, + None, )); } else { unions_fields.push(build_field_di_node( @@ -851,6 +900,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( enum_type_and_layout.fields.offset(tag_field), di_flags, tag_base_type_di_node, + None, )); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index b3d4a6642a1..65ab22ad89e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_abi::{FieldIdx, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo}; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; +use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_hir::def::CtorKind; use rustc_index::IndexSlice; use rustc_middle::bug; @@ -16,8 +17,8 @@ use super::{SmallVec, size_and_align_of}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::{self, Stub}; use crate::debuginfo::metadata::{ - UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, type_di_node, - unknown_file_metadata, + UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, + file_metadata_from_def_id, type_di_node, unknown_file_metadata, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::llvm::debuginfo::{DIFlags, DIType}; @@ -68,6 +69,11 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( enum_type_and_layout: TyAndLayout<'tcx>, ) -> DINodeCreationResult<'ll> { let containing_scope = get_namespace_for_item(cx, enum_adt_def.did()); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(enum_adt_def.did()) + } else { + None + }; DINodeCreationResult { di_node: build_enumeration_type_di_node( cx, @@ -77,6 +83,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (name, discr.val) }), + enum_adt_def_id, containing_scope, ), already_stored_in_typemap: false, @@ -92,6 +99,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( type_name: &str, base_type: Ty<'tcx>, enumerators: impl Iterator<Item = (Cow<'tcx, str>, u128)>, + def_id: Option<rustc_span::def_id::DefId>, containing_scope: &'ll DIType, ) -> &'ll DIType { let is_unsigned = match base_type.kind() { @@ -115,14 +123,21 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( }) .collect(); + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), containing_scope, type_name.as_c_char_ptr(), type_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, create_DIArray(DIB(cx), &enumerator_di_nodes[..]), @@ -193,6 +208,12 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( ) -> &'ll DIType { assert_eq!(variant_layout.ty, enum_type_and_layout.ty); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(variant_def.def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -204,6 +225,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), + def_location, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), @@ -231,6 +253,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_layout.fields.offset(field_index), di_flags, type_di_node(cx, field_layout.ty), + None, ) }) .collect::<SmallVec<_>>() @@ -286,6 +309,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &variant_name, + None, size_and_align_of(coroutine_type_and_layout), Some(coroutine_type_di_node), DIFlags::FlagZero, @@ -312,6 +336,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( variant_layout.fields.offset(field_index), DIFlags::FlagZero, type_di_node(cx, field_type), + None, ) }) .collect(); @@ -331,6 +356,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( coroutine_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, upvar_ty), + None, ) }) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index d4006691d37..241bf167a81 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -4,7 +4,7 @@ use libc::c_uint; use rustc_abi::{Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; -use rustc_codegen_ssa::traits::ConstCodegenMethods; +use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self}; @@ -14,7 +14,8 @@ use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, - size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags, + file_metadata_from_def_id, size_and_align_of, type_di_node, unknown_file_metadata, + visibility_di_flags, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -55,6 +56,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -62,6 +69,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &enum_type_name, + def_location, size_and_align_of(enum_type_and_layout), Some(containing_scope), visibility_flags, @@ -84,14 +92,27 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_and_layout.for_variant(cx, variant_index), visibility_flags, ), - source_info: None, + source_info: if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id( + cx, + Some(enum_adt_def.variant(variant_index).def_id), + )) + } else { + None + }, }) .collect(); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(enum_adt_def.did()) + } else { + None + }; smallvec![build_enum_variant_part_di_node( cx, enum_type_and_layout, enum_type_di_node, + enum_adt_def_id, &variant_member_infos[..], )] }, @@ -134,6 +155,12 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -141,6 +168,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, + def_location, size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -197,10 +225,16 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( }) .collect(); + let coroutine_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(coroutine_def_id) + } else { + None + }; smallvec![build_enum_variant_part_di_node( cx, coroutine_type_and_layout, coroutine_type_di_node, + coroutine_def_id, &variant_struct_type_di_nodes[..], )] }, @@ -228,6 +262,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, enum_type_di_node: &'ll DIType, + enum_type_def_id: Option<rustc_span::def_id::DefId>, variant_member_infos: &[VariantMemberInfo<'_, 'll>], ) -> &'ll DIType { let tag_member_di_node = @@ -236,6 +271,13 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let variant_part_unique_type_id = UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty); + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, enum_type_def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + let stub = StubInfo::new( cx, variant_part_unique_type_id, @@ -246,8 +288,8 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( enum_type_di_node, variant_part_name.as_c_char_ptr(), variant_part_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, enum_type_and_layout.size.bits(), enum_type_and_layout.align.abi.bits() as u32, DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 4e461476040..a37e719d43f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -8,7 +8,7 @@ use rustc_macros::HashStable; use rustc_middle::bug; use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt}; -use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; +use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::utils::{DIB, create_DIArray, debug_context}; use crate::llvm::debuginfo::{DIFlags, DIScope, DIType}; @@ -186,6 +186,7 @@ pub(super) fn stub<'ll, 'tcx>( kind: Stub<'ll>, unique_type_id: UniqueTypeId<'tcx>, name: &str, + def_location: Option<DefinitionLocation<'ll>>, (size, align): (Size, Align), containing_scope: Option<&'ll DIScope>, flags: DIFlags, @@ -193,6 +194,12 @@ pub(super) fn stub<'ll, 'tcx>( let empty_array = create_DIArray(DIB(cx), &[]); let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx); + let (file_metadata, line_number) = if let Some(def_location) = def_location { + (def_location.0, def_location.1) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + let metadata = match kind { Stub::Struct | Stub::VTableTy { .. } => { let vtable_holder = match kind { @@ -205,8 +212,8 @@ pub(super) fn stub<'ll, 'tcx>( containing_scope, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, flags, @@ -225,8 +232,8 @@ pub(super) fn stub<'ll, 'tcx>( containing_scope, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, flags, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index da7f94e8cf7..d8b055137b3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1534,6 +1534,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), + sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), @@ -1572,6 +1573,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( | sym::simd_fpowi | sym::simd_fsin | sym::simd_fsqrt + | sym::simd_relaxed_fma | sym::simd_round | sym::simd_trunc ) { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 9f398107fc6..3dfb86d422d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -17,7 +17,6 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] -#![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 17b0ec4b936..b1ace0033ba 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2240,6 +2240,7 @@ unsafe extern "C" { Output: *const c_char, DwoOutput: *const c_char, FileType: FileType, + VerifyIR: bool, ) -> LLVMRustResult; pub fn LLVMRustOptimize<'a>( M: &'a Module, diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 93d90cd16b2..d9c5c3e5af9 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -97,7 +97,7 @@ fn minimum_deployment_target(target: &Target) -> OSVersion { } /// Name of the environment variable used to fetch the deployment target on the given OS. -fn deployment_target_env_var(os: &str) -> &'static str { +pub fn deployment_target_env_var(os: &str) -> &'static str { match os { "macos" => "MACOSX_DEPLOYMENT_TARGET", "ios" => "IPHONEOS_DEPLOYMENT_TARGET", diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 651485a1876..ad81ff272c6 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1386,7 +1386,7 @@ fn link_sanitizer_runtime( let filename = format!("rustc{channel}_rt.{name}"); let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); - linker.cc_args(&["-Wl,-rpath", "-Xlinker", rpath]); + linker.link_args(&["-rpath", rpath]); linker.link_dylib_by_name(&filename, false, true); } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" { // MSVC provides the `/INFERASANLIBS` argument to automatically find the @@ -2210,7 +2210,7 @@ fn add_rpath_args( is_like_osx: sess.target.is_like_osx, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; - cmd.cc_args(&rpath::get_rpath_flags(&rpath_config)); + cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config)); } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 6ee599c9964..05dfbd40a0a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -24,6 +24,9 @@ use super::command::Command; use super::symbol_export; use crate::errors; +#[cfg(test)] +mod tests; + /// Disables non-English messages from localized linkers. /// Such messages may cause issues with text encoding on Windows (#35785) /// and prevent inspection of linker output in case of errors, which we occasionally do. @@ -178,23 +181,42 @@ fn verbatim_args<L: Linker + ?Sized>( } l } +/// Add underlying linker arguments to C compiler command, by wrapping them in +/// `-Wl` or `-Xlinker`. +fn convert_link_args_to_cc_args(cmd: &mut Command, args: impl IntoIterator<Item: AsRef<OsStr>>) { + let mut combined_arg = OsString::from("-Wl"); + for arg in args { + // If the argument itself contains a comma, we need to emit it + // as `-Xlinker`, otherwise we can use `-Wl`. + if arg.as_ref().as_encoded_bytes().contains(&b',') { + // Emit current `-Wl` argument, if any has been built. + if combined_arg != OsStr::new("-Wl") { + cmd.arg(combined_arg); + // Begin next `-Wl` argument. + combined_arg = OsString::from("-Wl"); + } + + // Emit `-Xlinker` argument. + cmd.arg("-Xlinker"); + cmd.arg(arg); + } else { + // Append to `-Wl` argument. + combined_arg.push(","); + combined_arg.push(arg); + } + } + // Emit final `-Wl` argument. + if combined_arg != OsStr::new("-Wl") { + cmd.arg(combined_arg); + } +} /// Arguments for the underlying linker. /// Add options to pass them through cc wrapper if `Linker` is a cc wrapper. -fn link_args<L: Linker + ?Sized>( - l: &mut L, - args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>, -) -> &mut L { - let args = args.into_iter(); +fn link_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L { if !l.is_cc() { verbatim_args(l, args); - } else if args.len() != 0 { - // FIXME: Support arguments with commas, see `rpaths_to_flags` for the example. - let mut combined_arg = OsString::from("-Wl"); - for arg in args { - combined_arg.push(","); - combined_arg.push(arg); - } - l.cmd().arg(combined_arg); + } else { + convert_link_args_to_cc_args(l.cmd(), args); } l } @@ -224,7 +246,7 @@ macro_rules! generate_arg_methods { verbatim_args(self, iter::once(arg)) } #[allow(unused)] - pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>) -> &mut Self { + pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { link_args(self, args) } #[allow(unused)] diff --git a/compiler/rustc_codegen_ssa/src/back/linker/tests.rs b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs new file mode 100644 index 00000000000..bf3e8c90200 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs @@ -0,0 +1,32 @@ +use super::*; + +#[test] +fn test_rpaths_to_args() { + let mut cmd = Command::new("foo"); + convert_link_args_to_cc_args(&mut cmd, &["-rpath", "path1", "-rpath", "path2"]); + assert_eq!(cmd.get_args(), [OsStr::new("-Wl,-rpath,path1,-rpath,path2")]); +} + +#[test] +fn test_xlinker() { + let mut cmd = Command::new("foo"); + convert_link_args_to_cc_args(&mut cmd, &[ + "arg1", + "arg2", + "arg3,with,comma", + "arg4,with,comma", + "arg5", + "arg6,with,comma", + ]); + + assert_eq!(cmd.get_args(), [ + OsStr::new("-Wl,arg1,arg2"), + OsStr::new("-Xlinker"), + OsStr::new("arg3,with,comma"), + OsStr::new("-Xlinker"), + OsStr::new("arg4,with,comma"), + OsStr::new("-Wl,arg5"), + OsStr::new("-Xlinker"), + OsStr::new("arg6,with,comma"), + ]); +} diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 56a808df6b0..d633cc98ac8 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -13,39 +13,27 @@ pub(super) struct RPathConfig<'a> { pub linker_is_gnu: bool, } -pub(super) fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec<OsString> { +pub(super) fn get_rpath_linker_args(config: &RPathConfig<'_>) -> Vec<OsString> { debug!("preparing the RPATH!"); let rpaths = get_rpaths(config); - let mut flags = rpaths_to_flags(rpaths); + let mut args = Vec::with_capacity(rpaths.len() * 2); // the minimum needed capacity + + for rpath in rpaths { + args.push("-rpath".into()); + args.push(rpath); + } if config.linker_is_gnu { // Use DT_RUNPATH instead of DT_RPATH if available - flags.push("-Wl,--enable-new-dtags".into()); + args.push("--enable-new-dtags".into()); // Set DF_ORIGIN for substitute $ORIGIN - flags.push("-Wl,-z,origin".into()); - } - - flags -} - -fn rpaths_to_flags(rpaths: Vec<OsString>) -> Vec<OsString> { - let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity - - for rpath in rpaths { - if rpath.to_string_lossy().contains(',') { - ret.push("-Wl,-rpath".into()); - ret.push("-Xlinker".into()); - ret.push(rpath); - } else { - let mut single_arg = OsString::from("-Wl,-rpath,"); - single_arg.push(rpath); - ret.push(single_arg); - } + args.push("-z".into()); + args.push("origin".into()); } - ret + args } fn get_rpaths(config: &RPathConfig<'_>) -> Vec<OsString> { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index 39034842d10..f1a30105c59 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -1,13 +1,4 @@ -use std::ffi::OsString; -use std::path::{Path, PathBuf}; - -use super::{RPathConfig, get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags}; - -#[test] -fn test_rpaths_to_flags() { - let flags = rpaths_to_flags(vec!["path1".into(), "path2".into()]); - assert_eq!(flags, ["-Wl,-rpath,path1", "-Wl,-rpath,path2"]); -} +use super::*; #[test] fn test_minimize1() { @@ -69,15 +60,3 @@ fn test_rpath_relative_issue_119571() { // Should not panic when lib only contains filename. let _ = get_rpath_relative_to_output(config, Path::new("libstd.so")); } - -#[test] -fn test_xlinker() { - let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]); - - assert_eq!(args, vec![ - OsString::from("-Wl,-rpath,a/normal/path"), - OsString::from("-Wl,-rpath"), - OsString::from("-Xlinker"), - OsString::from("a,comma,path") - ]); -} diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d9152c5d080..788a8a13b3e 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -282,7 +282,7 @@ fn exported_symbols_provider_local( })); } - if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() { + if tcx.local_crate_exports_generics() { use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; use rustc_middle::ty::InstanceKind; @@ -310,6 +310,16 @@ fn exported_symbols_provider_local( continue; } + if !tcx.sess.opts.share_generics() { + if tcx.codegen_fn_attrs(mono_item.def_id()).inline == rustc_attr::InlineAttr::Never + { + // this is OK, we explicitly allow sharing inline(never) across crates even + // without share-generics. + } else { + continue; + } + } + match *mono_item { MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => { if args.non_erasable_generics().next().is_some() { diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index b8fa8c0351b..c38484109d2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,5 +1,6 @@ use rustc_abi::Primitive::{Int, Pointer}; -use rustc_abi::{Align, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; +use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -385,15 +386,22 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { if variant_index != untagged_variant { let niche = self.project_field(bx, tag_field); let niche_llty = bx.cx().immediate_backend_type(niche.layout); + let BackendRepr::Scalar(scalar) = niche.layout.backend_repr else { + bug!("expected a scalar placeref for the niche"); + }; + // We are supposed to compute `niche_value.wrapping_add(niche_start)` wrapping + // around the `niche`'s type. + // The easiest way to do that is to do wrapping arithmetic on `u128` and then + // masking off any extra bits that occur because we did the arithmetic with too many bits. let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); - // FIXME(eddyb): check the actual primitive type here. - let niche_llval = if niche_value == 0 { - // HACK(eddyb): using `c_null` as it works on all types. - bx.cx().const_null(niche_llty) - } else { - bx.cx().const_uint_big(niche_llty, niche_value) - }; + let niche_value = niche_value & niche.layout.size.unsigned_int_max(); + + let niche_llval = bx.cx().scalar_to_backend( + Scalar::from_uint(niche_value, niche.layout.size), + scalar, + niche_llty, + ); OperandValue::Immediate(niche_llval).store(bx, niche); } } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index cbf214763b4..7eab889edf0 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -71,11 +71,11 @@ pub trait CodegenBackend { need_metadata_module: bool, ) -> Box<dyn Any>; - /// This is called on the returned `Box<dyn Any>` from `codegen_backend` + /// This is called on the returned `Box<dyn Any>` from [`codegen_crate`](Self::codegen_crate) /// /// # Panics /// - /// Panics when the passed `Box<dyn Any>` was not returned by `codegen_backend`. + /// Panics when the passed `Box<dyn Any>` was not returned by [`codegen_crate`](Self::codegen_crate). fn join_codegen( &self, ongoing_codegen: Box<dyn Any>, @@ -83,7 +83,7 @@ pub trait CodegenBackend { outputs: &OutputFilenames, ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>); - /// This is called on the returned `CodegenResults` from `join_codegen` + /// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen). fn link( &self, sess: &Session, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index f93f4d36e45..c31c94495d0 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -110,7 +110,7 @@ const_eval_extern_type_field = `extern type` field does not have a known offset const_eval_fn_ptr_call = function pointers need an RFC before allowed to be called in {const_eval_const_context}s const_eval_for_loop_into_iter_non_const = - cannot convert `{$ty}` into an iterator in {const_eval_const_context}s + cannot use `for` loop on `{$ty}` in {const_eval_const_context}s const_eval_frame_note = {$times -> [0] {const_eval_frame_note_inner} @@ -324,11 +324,11 @@ const_eval_ptr_as_bytes_1 = this code performed an operation that depends on the underlying bytes representing a pointer const_eval_ptr_as_bytes_2 = the absolute address of a pointer is not known at compile-time, so such operations are not supported -const_eval_question_branch_non_const = - `?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s +const_eval_question_branch_non_const = + `?` is not allowed on `{$ty}` in {const_eval_const_context}s const_eval_question_from_residual_non_const = - `?` cannot convert from residual of `{$ty}` in {const_eval_const_context}s + `?` is not allowed on `{$ty}` in {const_eval_const_context}s const_eval_range = in the range {$lo}..={$hi} const_eval_range_lower = greater or equal to {$lo} diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ab81e60a33f..489bb54a6f9 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -180,8 +180,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }; } - let mut err = match kind { - CallDesugaringKind::ForLoopIntoIter => { + // Don't point at the trait if this is a desugaring... + // FIXME(const_trait_impl): we could perhaps do this for `Iterator`. + match kind { + CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => { error!(NonConstForLoopIntoIter) } CallDesugaringKind::QuestionBranch => { @@ -196,10 +198,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { CallDesugaringKind::Await => { error!(NonConstAwait) } - }; - - diag_trait(&mut err, self_ty, kind.trait_def_id(tcx)); - err + } } CallKind::FnCall { fn_trait_id, self_ty } => { let note = match self_ty.kind() { diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 1271d9d2d0d..3cb77d1dcb5 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -139,12 +139,14 @@ where match error { // Don't emit a new diagnostic for these errors, they are already reported elsewhere or // should remain silent. + err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span), err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { ErrorHandled::TooGeneric(span) } - err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span), err_inval!(Layout(LayoutError::ReferencesError(guar))) => { - ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span) + // This can occur in infallible promoteds e.g. when a non-existent type or field is + // encountered. + ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span) } // Report remaining errors. _ => { @@ -152,7 +154,12 @@ where let span = span.substitute_dummy(our_span); let err = mk(span, frames); let mut err = tcx.dcx().create_err(err); - let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_)); + // We allow invalid programs in infallible promoteds since invalid layouts can occur + // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time. + let allowed_in_infallible = matches!( + error, + InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) + ); let msg = error.diagnostic_message(); error.add_args(&mut err); @@ -160,8 +167,8 @@ where // Use *our* span to label the interp error err.span_label(our_span, msg); let g = err.emit(); - let reported = if can_be_spurious { - ReportedErrorInfo::spurious(g) + let reported = if allowed_in_infallible { + ReportedErrorInfo::allowed_in_infallible(g) } else { ReportedErrorInfo::from(g) }; diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 8cbdcd68e13..34f795bda75 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -2,6 +2,7 @@ use rustc_abi::VariantIdx; use rustc_middle::query::{Key, TyCtxtAt}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use tracing::instrument; @@ -85,5 +86,6 @@ pub fn tag_for_variant_provider<'tcx>( crate::const_eval::DummyMachine, ); - ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag) + let layout = ecx.layout_of(ty).unwrap(); + ecx.tag_for_variant(layout, variant_index).unwrap().map(|(tag, _tag_field)| tag) } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index f94d0cbb42b..6faac1582ab 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,7 +1,7 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants}; -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_middle::{mir, span_bug}; use tracing::{instrument, trace}; @@ -21,17 +21,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { variant_index: VariantIdx, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - // Layout computation excludes uninhabited variants from consideration - // therefore there's no way to represent those variants in the given layout. - // Essentially, uninhabited variants do not have a tag that corresponds to their - // discriminant, so we cannot do anything here. - // When evaluating we will always error before even getting here, but ConstProp 'executes' - // dead code, so we cannot ICE here. - if dest.layout().for_variant(self, variant_index).is_uninhabited() { - throw_ub!(UninhabitedEnumVariantWritten(variant_index)) - } - - match self.tag_for_variant(dest.layout().ty, variant_index)? { + match self.tag_for_variant(dest.layout(), variant_index)? { Some((tag, tag_field)) => { // No need to validate that the discriminant here because the // `TyAndLayout::for_variant()` call earlier already checks the @@ -80,7 +70,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if ty.is_enum() { // Hilariously, `Single` is used even for 0-variant enums. // (See https://github.com/rust-lang/rust/issues/89765). - if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) { + if ty.ty_adt_def().unwrap().variants().is_empty() { throw_ub!(UninhabitedEnumVariantRead(index)) } // For consistency with `write_discriminant`, and to make sure that @@ -188,6 +178,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let variants = ty.ty_adt_def().expect("tagged layout for non adt").variants(); assert!(variant_index < variants.next_index()); + if variant_index == untagged_variant { + // The untagged variant can be in the niche range, but even then it + // is not a valid encoding. + throw_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))) + } variant_index } else { untagged_variant @@ -236,10 +231,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// given field index. pub(crate) fn tag_for_variant( &self, - ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, variant_index: VariantIdx, ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> { - match self.layout_of(ty)?.variants { + // Layout computation excludes uninhabited variants from consideration. + // Therefore, there's no way to represent those variants in the given layout. + // Essentially, uninhabited variants do not have a tag that corresponds to their + // discriminant, so we have to bail out here. + if layout.for_variant(self, variant_index).is_uninhabited() { + throw_ub!(UninhabitedEnumVariantWritten(variant_index)) + } + + match layout.variants { abi::Variants::Single { .. } => { // The tag of a `Single` enum is like the tag of the niched // variant: there's no tag as the discriminant is encoded @@ -260,7 +263,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let discr = self.discriminant_for_variant(ty, variant_index)?; + let discr = self.discriminant_for_variant(layout.ty, variant_index)?; let discr_size = discr.layout.size; let discr_val = discr.to_scalar().to_bits(discr_size)?; let tag_size = tag_layout.size(self); @@ -286,11 +289,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .. } => { assert!(variant_index != untagged_variant); + // We checked that this variant is inhabited, so it must be in the niche range. + assert!( + niche_variants.contains(&variant_index), + "invalid variant index for this enum" + ); let variants_start = niche_variants.start().as_u32(); - let variant_index_relative = variant_index - .as_u32() - .checked_sub(variants_start) - .expect("overflow computing relative variant idx"); + let variant_index_relative = variant_index.as_u32().strict_sub(variants_start); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index fe93a48c2f2..241be5e175c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // do not continue if typeck errors occurred (can only occur in local crate) if let Some(err) = body.tainted_by_errors { - throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err))); + throw_inval!(AlreadyReported(ReportedErrorInfo::from(err))); } interp_ok(body) } @@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { match err { ErrorHandled::TooGeneric(..) => {}, ErrorHandled::Reported(reported, span) => { - if reported.is_tainted_by_errors() { - // const-eval will return "tainted" errors if e.g. the layout cannot - // be computed as the type references non-existing names. - // See <https://github.com/rust-lang/rust/issues/124348>. - } else if reported.can_be_spurious() { + if reported.is_allowed_in_infallible() { // These errors can just sometimes happen, even when the expression - // is nominally "infallible", e.g. when running out of memory. + // is nominally "infallible", e.g. when running out of memory + // or when some layout could not be computed. } else { // Looks like the const is not captured by `required_consts`, that's bad. span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts"); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 2a7408f1c70..b5adf06b300 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(slice_ptr_get)] +#![feature(strict_overflow_ops)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unqualified_local_imports)] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 34a2464972a..78d69a66edc 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -415,6 +415,10 @@ impl<O: ForestObligation> ObligationForest<O> { .collect() } + pub fn has_pending_obligations(&self) -> bool { + self.nodes.iter().any(|node| node.state.get() == NodeState::Pending) + } + fn insert_into_error_cache(&mut self, index: usize) { let node = &self.nodes[index]; self.error_cache diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 005053e4508..5b472bb9b81 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -418,7 +418,9 @@ fn run_compiler( return early_exit(); } - if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() { + if sess.opts.unstable_opts.parse_crate_root_only + || sess.opts.unstable_opts.show_span.is_some() + { return early_exit(); } @@ -865,8 +867,9 @@ fn print_crate_info( DeploymentTarget => { if sess.target.is_like_osx { println_info!( - "deployment_target={}", - apple::pretty_version(apple::deployment_target(sess)) + "{}={}", + apple::deployment_target_env_var(&sess.target.os), + apple::pretty_version(apple::deployment_target(sess)), ) } else { #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0060.md b/compiler/rustc_error_codes/src/error_codes/E0060.md index 54b10c886cc..a6831c881e3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0060.md +++ b/compiler/rustc_error_codes/src/error_codes/E0060.md @@ -15,7 +15,7 @@ unsafe { printf(); } // error! Using this declaration, it must be called with at least one argument, so simply calling `printf()` is invalid. But the following uses are allowed: -``` +```rust,edition2021 # use std::os::raw::{c_char, c_int}; # #[cfg_attr(all(windows, target_env = "msvc"), # link(name = "legacy_stdio_definitions", @@ -23,16 +23,11 @@ simply calling `printf()` is invalid. But the following uses are allowed: # extern "C" { fn printf(_: *const c_char, ...) -> c_int; } # fn main() { unsafe { - use std::ffi::CString; - - let fmt = CString::new("test\n").unwrap(); - printf(fmt.as_ptr()); + printf(c"test\n".as_ptr()); - let fmt = CString::new("number = %d\n").unwrap(); - printf(fmt.as_ptr(), 3); + printf(c"number = %d\n".as_ptr(), 3); - let fmt = CString::new("%d, %d\n").unwrap(); - printf(fmt.as_ptr(), 10, 5); + printf(c"%d, %d\n".as_ptr(), 10, 5); } # } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index 5d71ee9949d..4cb605b636d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -7,10 +7,11 @@ Erroneous code example: #![allow(internal_features)] extern "rust-intrinsic" { - pub static breakpoint: fn(); // error: intrinsic must be a function + pub static atomic_singlethreadfence_seqcst: fn(); + // error: intrinsic must be a function } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` An intrinsic is a function available for use in a given programming language @@ -22,8 +23,8 @@ error, just declare a function. Example: #![allow(internal_features)] extern "rust-intrinsic" { - pub fn breakpoint(); // ok! + pub fn atomic_singlethreadfence_seqcst(); // ok! } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 798668b8bc1..b4510371323 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::process::ExitStatus; use rustc_abi::TargetDataLayoutErrors; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast_pretty::pprust; use rustc_macros::Subdiagnostic; use rustc_span::Span; @@ -298,6 +299,12 @@ impl IntoDiagArg for hir::def::Namespace { } } +impl IntoDiagArg for ExprPrecedence { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Number(self as i32) + } +} + #[derive(Clone)] pub struct DiagSymbolList<S = Symbol>(Vec<S>); diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 19c2d466f7c..e5500c8bba1 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -732,7 +732,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => item.to_tokens(), }; let attr_item = attr.unwrap_normal_item(); - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { self.cx.dcx().emit_err(UnsupportedKeyValue { span }); } let inner_tokens = attr_item.args.inner_tokens(); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e910415c345..53362cb2529 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -193,6 +193,9 @@ declare_features! ( (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), + /// Allows using `efiapi`, `aapcs`, `sysv64` and `win64` as calling + /// convention for functions with varargs. + (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. @@ -225,7 +228,7 @@ declare_features! ( /// Allows the use of `if let` expressions. (accepted, if_let, "1.0.0", None), /// Rescoping temporaries in `if let` to align with Rust 2024. - (accepted, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), + (accepted, if_let_rescope, "1.84.0", Some(124085)), /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. (accepted, if_while_or_patterns, "1.33.0", Some(48215)), /// Allows lifetime elision in `impl` headers. For example: @@ -357,7 +360,7 @@ declare_features! ( (accepted, repr_transparent, "1.28.0", Some(43036)), /// Allows enums like Result<T, E> to be used across FFI, if T's niche value can /// be used to describe E or vice-versa. - (accepted, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)), + (accepted, result_ffi_guarantees, "1.84.0", Some(110503)), /// Allows return-position `impl Trait` in traits. (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611)), /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). @@ -367,7 +370,7 @@ declare_features! ( /// Allows `Self` struct constructor (RFC 2302). (accepted, self_struct_ctor, "1.32.0", Some(51994)), /// Shortern the tail expression lifetime - (accepted, shorter_tail_lifetimes, "CURRENT_RUSTC_VERSION", Some(123739)), + (accepted, shorter_tail_lifetimes, "1.84.0", Some(123739)), /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254)), /// Allows use of `&foo[a..b]` as a slicing syntax. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 6ff70044eed..8b4f441dafe 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -101,7 +101,7 @@ declare_features! ( /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None), /// Uses generic effect parameters for ~const bounds - (removed, effects, "CURRENT_RUSTC_VERSION", Some(102090), + (removed, effects, "1.84.0", Some(102090), Some("removed, redundant with `#![feature(const_trait_impl)]`")), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), @@ -119,6 +119,13 @@ declare_features! ( (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), /// Allows defining generators. (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")), + /// An extension to the `generic_associated_types` feature, allowing incomplete features. + (removed, generic_associated_types_extended, "CURRENT_RUSTC_VERSION", Some(95451), + Some( + "feature needs overhaul and reimplementation pending \ + better implied higher-ranked implied bounds support" + ) + ), /// Allows `impl Trait` in bindings (`let`, `const`, `static`). (removed, impl_trait_in_bindings, "1.55.0", Some(63065), Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index aa2e451ef39..abc7200699c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -338,7 +338,7 @@ declare_features! ( (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), - (unstable, sparc_target_feature, "CURRENT_RUSTC_VERSION", Some(132783)), + (unstable, sparc_target_feature, "1.84.0", Some(132783)), (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), @@ -394,6 +394,8 @@ declare_features! ( (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. (unstable, async_for_loop, "1.77.0", Some(118898)), + /// Allows `async` trait bound modifier. + (unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg(<true/false>)]`. @@ -475,9 +477,6 @@ declare_features! ( (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), - /// Allows using `efiapi`, `sysv64` and `win64` as calling convention - /// for functions with varargs. - (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), /// Allows defining `extern type`s. (unstable, extern_types, "1.23.0", Some(43467)), /// Allow using 128-bit (quad precision) floating point numbers. @@ -500,8 +499,6 @@ declare_features! ( (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. (unstable, generic_arg_infer, "1.55.0", Some(85077)), - /// An extension to the `generic_associated_types` feature, allowing incomplete features. - (incomplete, generic_associated_types_extended, "1.61.0", Some(95451)), /// Allows non-trivial generic constants which have to have wfness manually propagated to callers (incomplete, generic_const_exprs, "1.56.0", Some(76560)), /// Allows generic parameters and where-clauses on free & associated const items. @@ -538,7 +535,7 @@ declare_features! ( /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Enables the generic const args MVP (only bare paths, not arbitrary computation). - (incomplete, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980)), + (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 3276f516a52..0b7ffc4af45 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,7 +109,16 @@ pub enum DefKind { Use, /// An `extern` block. ForeignMod, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`. + /// + /// Not all anon-consts are actually still relevant in the HIR. We lower + /// trivial const-arguments directly to `hir::ConstArgKind::Path`, at which + /// point the definition for the anon-const ends up unused and incomplete. + /// + /// We do not provide any a `Span` for the definition and pretty much all other + /// queries also ICE when using this `DefId`. Given that the `DefId` of such + /// constants should only be reachable by iterating all definitions of a + /// given crate, you should not have to worry about this. AnonConst, /// An inline constant, e.g. `const { 1 + 2 }` InlineConst, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12dec75e65c..a9696627f11 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence}; use rustc_ast::{ self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind, TraitObjectSyntax, UintTy, @@ -275,6 +275,7 @@ impl<'hir> ConstArg<'hir> { match self.kind { ConstArgKind::Path(path) => path.span(), ConstArgKind::Anon(anon) => anon.span, + ConstArgKind::Infer(span) => span, } } } @@ -289,6 +290,11 @@ pub enum ConstArgKind<'hir> { /// However, in the future, we'll be using it for all of those. Path(QPath<'hir>), Anon(&'hir AnonConst), + /// **Note:** Not all inferred consts are represented as + /// `ConstArgKind::Infer`. In cases where it is ambiguous whether + /// a generic arg is a type or a const, inference variables are + /// represented as `GenericArg::Infer` instead. + Infer(Span), } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -308,6 +314,10 @@ pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), Const(&'hir ConstArg<'hir>), + /// **Note:** Inference variables are only represented as + /// `GenericArg::Infer` in cases where it is ambiguous whether + /// a generic arg is a type or a const. Otherwise, inference variables + /// are represented as `TyKind::Infer` or `ConstArgKind::Infer`. Infer(InferArg), } @@ -1645,29 +1655,6 @@ impl fmt::Display for ConstContext { /// A literal. pub type Lit = Spanned<LitKind>; -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum ArrayLen<'hir> { - Infer(InferArg), - Body(&'hir ConstArg<'hir>), -} - -impl ArrayLen<'_> { - pub fn span(self) -> Span { - match self { - ArrayLen::Infer(arg) => arg.span, - ArrayLen::Body(body) => body.span(), - } - } - - pub fn hir_id(self) -> HirId { - match self { - ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(&ConstArg { hir_id, .. }) => { - hir_id - } - } - } -} - /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1708,22 +1695,22 @@ pub struct Expr<'hir> { } impl Expr<'_> { - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure { .. } => PREC_CLOSURE, + ExprKind::Closure { .. } => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1732,7 +1719,7 @@ impl Expr<'_> { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1753,7 +1740,7 @@ impl Expr<'_> { | ExprKind::Struct(..) | ExprKind::Tup(_) | ExprKind::Type(..) - | ExprKind::Err(_) => PREC_UNAMBIGUOUS, + | ExprKind::Err(_) => ExprPrecedence::Unambiguous, ExprKind::DropTemps(ref expr, ..) => expr.precedence(), } @@ -2115,7 +2102,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, ArrayLen<'hir>), + Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>), /// A suspension point for coroutines (i.e., `yield <expr>`). Yield(&'hir Expr<'hir>, YieldSource), @@ -2625,7 +2612,7 @@ impl<'hir> Ty<'hir> { TyKind::Infer => true, TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Array(ty, length) => { - ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(..)) + ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..)) } TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty), TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(), @@ -2834,7 +2821,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, ArrayLen<'hir>), + Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2861,6 +2848,11 @@ pub enum TyKind<'hir> { Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. + /// + /// **Note:** Not all inferred types are represented as + /// `TyKind::Infer`. In cases where it is ambiguous whether + /// a generic arg is a type or a const, inference variables are + /// represented as `GenericArg::Infer` instead. Infer, /// Placeholder for a type that has failed to be defined. Err(rustc_span::ErrorGuaranteed), @@ -3801,8 +3793,6 @@ pub enum Node<'hir> { Crate(&'hir Mod<'hir>), Infer(&'hir InferArg), WherePredicate(&'hir WherePredicate<'hir>), - // FIXME: Merge into `Node::Infer`. - ArrayLenInfer(&'hir InferArg), PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, @@ -3856,7 +3846,6 @@ impl<'hir> Node<'hir> { | Node::OpaqueTy(..) | Node::Infer(..) | Node::WherePredicate(..) - | Node::ArrayLenInfer(..) | Node::Synthetic | Node::Err(..) => None, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index faaea41047f..602aa8be740 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -343,9 +343,6 @@ pub trait Visitor<'v>: Sized { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } - fn visit_array_length(&mut self, len: &'v ArrayLen<'v>) -> Self::Result { - walk_array_len(self, len) - } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) } @@ -710,14 +707,6 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } -pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>) -> V::Result { - match len { - // FIXME: Use `visit_infer` here. - ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), - ArrayLen::Body(c) => visitor.visit_const_arg(c), - } -} - pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result { try_visit!(visitor.visit_id(constant.hir_id)); visitor.visit_nested_body(constant.body) @@ -739,6 +728,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( match &const_arg.kind { ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), + ConstArgKind::Infer(..) => V::Result::output(), } } @@ -753,7 +743,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } ExprKind::Repeat(ref element, ref count) => { try_visit!(visitor.visit_expr(element)); - try_visit!(visitor.visit_array_length(count)); + try_visit!(visitor.visit_const_arg(count)); } ExprKind::Struct(ref qpath, fields, ref optional_base) => { try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); @@ -901,7 +891,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul } TyKind::Array(ref ty, ref length) => { try_visit!(visitor.visit_ty(ty)); - try_visit!(visitor.visit_array_length(length)); + try_visit!(visitor.visit_const_arg(length)); } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { for bound in bounds { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 49b4a1fabec..070d63b48b7 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -113,8 +113,6 @@ hir_analysis_const_param_ty_impl_on_unsized = the trait `ConstParamTy` may not be implemented for this type .label = type is not `Sized` -hir_analysis_const_specialize = cannot specialize on const impl with non-const impl - hir_analysis_copy_impl_on_non_adt = the trait `Copy` cannot be implemented for this type .label = type is not a structure or enumeration @@ -590,7 +588,7 @@ hir_analysis_value_of_associated_struct_already_specified = .label = re-bound here .previous_bound_label = `{$item_name}` bound here first -hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions} +hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` .label = C-variadic function must have a compatible calling convention hir_analysis_variances_of = {$variances} diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c66572a9377..022a6d457ec 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -17,7 +17,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; use rustc_middle::ty::{ @@ -33,7 +33,7 @@ use tracing::{debug, instrument}; use ty::TypingMode; use {rustc_attr as attr, rustc_hir as hir}; -use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty}; +use super::compare_impl_item::check_type_bounds; use super::*; use crate::check::intrinsicck::InlineAsmCtxt; @@ -103,7 +103,7 @@ fn allowed_union_or_unsafe_field<'tcx>( // Fallback case: allow `ManuallyDrop` and things that are `Copy`, // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx, typing_env) + || tcx.type_is_copy_modulo_regions(typing_env, ty) || ty.references_error() } }; @@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - // FIXME(#132279): This should eventually use the already defined hidden types. - let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); + // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed. + let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() { + TypingMode::post_borrowck_analysis(tcx, defining_use_anchor) + } else { + TypingMode::analysis_in_body(tcx, defining_use_anchor) + }); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let args = match origin { @@ -346,7 +350,7 @@ fn check_opaque_meets_bounds<'tcx>( // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it // here rather than using ReErased. let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args); - let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() { + let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() { ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)), _ => re, }); @@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>( let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; - if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin { + if infcx.next_trait_solver() { + Ok(()) + } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = + origin + { // HACK: this should also fall through to the hidden type check below, but the original // implementation had a bug where equivalent lifetimes are not identical. This caused us // to reject existing stable code that is otherwise completely fine. The real fix is to @@ -1036,18 +1044,23 @@ fn check_impl_items_against_trait<'tcx>( tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait"); continue; }; - match ty_impl_item.kind { - ty::AssocKind::Const => { - tcx.ensure().compare_impl_const(( - impl_item.expect_local(), - ty_impl_item.trait_item_def_id.unwrap(), - )); - } - ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); - } - ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); + + let res = tcx.ensure().compare_impl_item(impl_item.expect_local()); + + if res.is_ok() { + match ty_impl_item.kind { + ty::AssocKind::Fn => { + compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait( + tcx, + ty_impl_item, + ty_trait_item, + tcx.impl_trait_ref(ty_impl_item.container_id(tcx)) + .unwrap() + .instantiate_identity(), + ); + } + ty::AssocKind::Const => {} + ty::AssocKind::Type => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2891b48a154..e176fc58999 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -33,7 +33,25 @@ use tracing::{debug, instrument}; use super::potentially_plural_count; use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; -mod refine; +pub(super) mod refine; + +/// Call the query `tcx.compare_impl_item()` directly instead. +pub(super) fn compare_impl_item( + tcx: TyCtxt<'_>, + impl_item_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + let impl_item = tcx.associated_item(impl_item_def_id); + let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap()); + let impl_trait_ref = + tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity(); + debug!(?impl_trait_ref); + + match impl_item.kind { + ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref), + } +} /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. @@ -44,22 +62,15 @@ mod refine; /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation #[instrument(level = "debug", skip(tcx))] -pub(super) fn compare_impl_method<'tcx>( +fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, trait_m: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, -) { - let _: Result<_, ErrorGuaranteed> = try { - check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; - compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; - refine::check_refining_return_position_impl_trait_in_trait( - tcx, - impl_m, - trait_m, - impl_trait_ref, - ); - }; +) -> Result<(), ErrorGuaranteed> { + check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; + compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; + Ok(()) } /// Checks a bunch of different properties of the impl/trait methods for @@ -523,8 +534,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_sig = ocx.normalize( &misc_cause, param_env, - tcx.liberate_late_bound_regions( - impl_m.def_id, + infcx.instantiate_binder_with_fresh_vars( + return_span, + infer::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity(), ), ); @@ -536,10 +548,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // them with inference variables. // We will use these inference variables to collect the hidden types of RPITITs. let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id); - let unnormalized_trait_sig = infcx - .instantiate_binder_with_fresh_vars( - return_span, - infer::HigherRankedType, + let unnormalized_trait_sig = tcx + .liberate_late_bound_regions( + impl_m.def_id, tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args), ) .fold_with(&mut collector); @@ -702,8 +713,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let mut remapped_types = DefIdMap::default(); for (def_id, (ty, args)) in collected_types { - match infcx.fully_resolve((ty, args)) { - Ok((ty, args)) => { + match infcx.fully_resolve(ty) { + Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the // trait fn signature. However, projection normalization expects `ty` to // contains `def_id`'s early-bound regions. @@ -883,33 +894,27 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { self.tcx } - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { - if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() { - let mut mapped_args = Vec::with_capacity(args.len()); - for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) { - mapped_args.push(match (arg.unpack(), v) { - // Skip uncaptured opaque args - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, - _ => arg.try_fold_with(self)?, - }); - } - Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args))) - } else { - t.try_super_fold_with(self) - } - } - fn try_fold_region( &mut self, region: ty::Region<'tcx>, ) -> Result<ty::Region<'tcx>, Self::Error> { match region.kind() { - // Remap late-bound regions from the function. + // Never remap bound regions or `'static` + ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region), + // We always remap liberated late-bound regions from the function. ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyParam(ebr) if ebr.index as usize >= self.num_impl_args => {} - _ => return Ok(region), + ty::ReEarlyParam(ebr) => { + if ebr.index as usize >= self.num_impl_args { + // Remap + } else { + return Ok(region); + } + } + ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!( + "should not have leaked vars or placeholders into hidden type of RPITIT" + ), } let e = if let Some(id_region) = self.map.get(®ion) { @@ -1727,17 +1732,12 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -/// Use `tcx.compare_impl_const` instead -pub(super) fn compare_impl_const_raw( - tcx: TyCtxt<'_>, - (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), +fn compare_impl_const<'tcx>( + tcx: TyCtxt<'tcx>, + impl_const_item: ty::AssocItem, + trait_const_item: ty::AssocItem, + impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let impl_const_item = tcx.associated_item(impl_const_item_def); - let trait_const_item = tcx.associated_item(trait_const_item_def); - let impl_trait_ref = - tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity(); - debug!(?impl_trait_ref); - compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?; compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?; check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?; @@ -1868,19 +1868,17 @@ fn compare_const_predicate_entailment<'tcx>( } #[instrument(level = "debug", skip(tcx))] -pub(super) fn compare_impl_ty<'tcx>( +fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: ty::AssocItem, trait_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, -) { - let _: Result<(), ErrorGuaranteed> = try { - compare_number_of_generics(tcx, impl_ty, trait_ty, false)?; - compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?; - check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; - compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?; - check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?; - }; +) -> Result<(), ErrorGuaranteed> { + compare_number_of_generics(tcx, impl_ty, trait_ty, false)?; + compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?; + check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; + compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?; + check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref) } /// The equivalent of [compare_method_predicate_entailment], but for associated types diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 67cbcc1566a..6eac4ac3baf 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error}; /// Check that an implementation does not refine an RPITIT from a trait method signature. -pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( +pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, trait_m: ty::AssocItem, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 3e33120901f..2e6b511412b 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid + | sym::breakpoint | sym::size_of | sym::min_align_of | sym::needs_drop @@ -641,7 +642,9 @@ pub fn check_intrinsic_type( | sym::simd_round | sym::simd_trunc => (1, 0, vec![param(0)], param(0)), sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)), - sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), + sym::simd_fma | sym::simd_relaxed_fma => { + (1, 0, vec![param(0), param(0), param(0)], param(0)) + } sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index b96469f503c..df4da03f0f5 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { let msg = "arguments for inline assembly must be copyable"; self.tcx .dcx() diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 375cbfd1c4f..61e203a1ff6 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -108,7 +108,7 @@ pub fn provide(providers: &mut Providers) { adt_async_destructor, region_scope_tree, collect_return_position_impl_trait_in_trait_tys, - compare_impl_const: compare_impl_item::compare_impl_const_raw, + compare_impl_item: compare_impl_item::compare_impl_item, check_coroutine_obligations: check::check_coroutine_obligations, ..*providers }; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8fa797db246..2b33da3c49a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_macros::LintDiagnostic; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -116,13 +117,12 @@ where } f(&mut wfcx)?; - let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; - let errors = wfcx.select_all_or_error(); if !errors.is_empty() { return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; debug!(?assumed_wf_types); let infcx_compat = infcx.fork(); @@ -1170,19 +1170,13 @@ fn check_type_defn<'tcx>( // Explicit `enum` discriminant values must const-evaluate successfully. if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr { - let cause = traits::ObligationCause::new( - tcx.def_span(discr_def_id), - wfcx.body_def_id, - ObligationCauseCode::Misc, - ); - wfcx.register_obligation(Obligation::new( - tcx, - cause, - wfcx.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable( - ty::Const::from_anon_const(tcx, discr_def_id.expect_local()), - ))), - )); + match tcx.const_eval_poly(discr_def_id) { + Ok(_) => {} + Err(ErrorHandled::Reported(..)) => {} + Err(ErrorHandled::TooGeneric(sp)) => { + span_bug!(sp, "enum variant discr was too generic to eval") + } + } } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 93be3e06e5d..8d5824130d8 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,6 +34,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; @@ -150,11 +151,11 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { _ => {} } } - fn visit_array_length(&mut self, length: &'v hir::ArrayLen<'v>) { - if let hir::ArrayLen::Infer(inf) = length { - self.0.push(inf.span); + fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) { + if let hir::ConstArgKind::Infer(span) = const_arg.kind { + self.0.push(span); } - intravisit::walk_array_len(self, length) + intravisit::walk_const_arg(self, const_arg) } } @@ -1415,7 +1416,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( GenericParamKind::Lifetime { .. } => true, _ => false, }); - let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r { + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { ty::ReErased => { if has_region_params { ty::Region::new_error_with_message( diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 8648a7d1e32..f1022d95753 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -1,6 +1,6 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::intravisit; -use rustc_middle::hir::nested_filter::OnlyBodies; +use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::sym; @@ -42,7 +42,8 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { } pub(crate) fn def_parents(tcx: TyCtxt<'_>) { - for did in tcx.hir().body_owners() { + for iid in tcx.hir().items() { + let did = iid.owner_id.def_id; if tcx.has_attr(did, sym::rustc_dump_def_parents) { struct AnonConstFinder<'tcx> { tcx: TyCtxt<'tcx>, @@ -50,7 +51,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> { - type NestedFilter = OnlyBodies; + type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() @@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } } - // Look for any anon consts inside of this body owner as there is no way to apply + // Look for any anon consts inside of this item as there is no way to apply // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible // to see what its def parent is. let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] }; - intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value); + intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid)); for did in [did].into_iter().chain(anon_ct_finder.anon_consts) { let span = tcx.def_span(did); diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c31bff28fd3..1d9114b0ef3 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -181,7 +181,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // expressions' count (i.e. `N` in `[x; N]`), and explicit // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // as they shouldn't be able to cause query cycle errors. - Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. }) + Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. }) if ct.anon_const_hir_id() == Some(hir_id) => { Some(parent_did) @@ -419,7 +419,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if let Node::ConstBlock(_) = node { own_params.push(ty::GenericParamDef { index: next_index(), - name: Symbol::intern("<const_ty>"), + name: rustc_span::sym::const_ty_placeholder, def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index bfee5d33598..ca2597e79fd 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,12 +1,13 @@ use std::assert_matches::assert_matches; -use hir::{HirId, Node}; +use hir::Node; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{ + self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, +}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span}; @@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } if tcx.features().generic_const_exprs() { - predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); + predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates)); } let mut predicates: Vec<_> = predicates.into_iter().collect(); @@ -369,32 +370,48 @@ fn compute_bidirectional_outlives_predicates<'tcx>( } } -fn const_evaluatable_predicates_of( - tcx: TyCtxt<'_>, +#[instrument(level = "debug", skip(tcx, predicates), ret)] +fn const_evaluatable_predicates_of<'tcx>( + tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> FxIndexSet<(ty::Clause<'_>, Span)> { + predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>, +) -> FxIndexSet<(ty::Clause<'tcx>, Span)> { struct ConstCollector<'tcx> { tcx: TyCtxt<'tcx>, preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, } - impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { - fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { - let ct = ty::Const::from_anon_const(self.tcx, c.def_id); - if let ty::ConstKind::Unevaluated(_) = ct.kind() { - let span = self.tcx.def_span(c.def_id); - self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span)); - } - } + fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool { + let hir_id = tcx.local_def_id_to_hir_id(def); + let (_, parent_node) = tcx + .hir() + .parent_iter(hir_id) + .skip_while(|(_, n)| matches!(n, Node::ConstArg(..))) + .next() + .unwrap(); + matches!( + parent_node, + Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. }) + ) + } - fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) { - // Do not look into const param defaults, - // these get checked when they are actually instantiated. - // - // We do not want the following to error: - // - // struct Foo<const N: usize, const M: usize = { N + 1 }>; - // struct Bar<const N: usize>(Foo<N, 3>); + impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> { + fn visit_const(&mut self, c: ty::Const<'tcx>) { + if let ty::ConstKind::Unevaluated(uv) = c.kind() { + if is_const_param_default(self.tcx, uv.def.expect_local()) { + // Do not look into const param defaults, + // these get checked when they are actually instantiated. + // + // We do not want the following to error: + // + // struct Foo<const N: usize, const M: usize = { N + 1 }>; + // struct Bar<const N: usize>(Foo<N, 3>); + return; + } + + let span = self.tcx.def_span(uv.def); + self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span)); + } } } @@ -402,28 +419,31 @@ fn const_evaluatable_predicates_of( let node = tcx.hir_node(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; + + for (clause, _sp) in predicates { + clause.visit_with(&mut collector); + } + if let hir::Node::Item(item) = node - && let hir::ItemKind::Impl(impl_) = item.kind + && let hir::ItemKind::Impl(_) = item.kind { - if let Some(of_trait) = &impl_.of_trait { - debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); - collector.visit_trait_ref(of_trait); + if let Some(of_trait) = tcx.impl_trait_ref(def_id) { + debug!("visit impl trait_ref"); + of_trait.instantiate_identity().visit_with(&mut collector); } - debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); - collector.visit_ty(impl_.self_ty); - } - - if let Some(generics) = node.generics() { - debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id); - collector.visit_generics(generics); + debug!("visit self_ty"); + let self_ty = tcx.type_of(def_id); + self_ty.instantiate_identity().visit_with(&mut collector); } - if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) { - debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id); - collector.visit_fn_decl(fn_sig.decl); + if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) { + debug!("visit fn sig"); + let fn_sig = tcx.fn_sig(def_id); + let fn_sig = fn_sig.instantiate_identity(); + debug!(?fn_sig); + fn_sig.visit_with(&mut collector); } - debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds); collector.preds } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 74729ebe488..74f381d2661 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2060,48 +2060,37 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; match path.res { Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => { - // Get the generics of this type's hir owner. This is *different* - // from the generics of the parameter's definition, since we want - // to be able to resolve an RTN path on a nested body (e.g. method - // inside an impl) using the where clauses on the method. - // FIXME(return_type_notation): Think of some better way of doing this. - let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics() - else { - return; - }; - - // Look for the first bound that contains an associated type that - // matches the segment that we're looking for. We ignore any subsequent - // bounds since we'll be emitting a hard error in HIR lowering, so this - // is purely speculative. - let one_bound = generics.predicates.iter().find_map(|predicate| { - let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind - else { - return None; - }; - let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = - predicate.bounded_ty.kind - else { - return None; - }; - if bounded_path.res != path.res { - return None; - } - predicate.bounds.iter().find_map(|bound| { - let hir::GenericBound::Trait(trait_) = bound else { - return None; - }; + let mut bounds = + self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| { BoundVarContext::supertrait_hrtb_vars( self.tcx, - trait_.trait_ref.trait_def_id()?, + trait_def_id, item_segment.ident, ty::AssocKind::Fn, ) - }) - }); - let Some((bound_vars, assoc_item)) = one_bound else { + }); + + let Some((bound_vars, assoc_item)) = bounds.next() else { + // This will error in HIR lowering. + self.tcx + .dcx() + .span_delayed_bug(path.span, "no resolution for RTN path"); return; }; + + // Don't bail if we have identical bounds, which may be collected from + // something like `T: Bound + Bound`, or via elaborating supertraits. + for (second_vars, second_assoc_item) in bounds { + if second_vars != bound_vars || second_assoc_item != assoc_item { + // This will error in HIR lowering. + self.tcx.dcx().span_delayed_bug( + path.span, + "ambiguous resolution for RTN path", + ); + return; + } + } + (bound_vars, assoc_item.def_id, item_segment) } // If we have a self type alias (in an impl), try to resolve an @@ -2167,6 +2156,92 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { existing_bound_vars.extend(bound_vars); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); } + + /// Walk the generics of the item for a trait bound whose self type + /// corresponds to the expected res, and return the trait def id. + fn for_each_trait_bound_on_res( + &self, + expected_res: Res, + ) -> impl Iterator<Item = DefId> + use<'tcx, '_> { + std::iter::from_coroutine( + #[coroutine] + move || { + let mut scope = self.scope; + loop { + let hir_id = match *scope { + Scope::Binder { hir_id, .. } => Some(hir_id), + Scope::Root { opt_parent_item: Some(parent_def_id) } => { + Some(self.tcx.local_def_id_to_hir_id(parent_def_id)) + } + Scope::Body { .. } + | Scope::ObjectLifetimeDefault { .. } + | Scope::Supertrait { .. } + | Scope::TraitRefBoundary { .. } + | Scope::LateBoundary { .. } + | Scope::Opaque { .. } + | Scope::Root { opt_parent_item: None } => None, + }; + + if let Some(hir_id) = hir_id { + let node = self.tcx.hir_node(hir_id); + // If this is a `Self` bound in a trait, yield the trait itself. + // Specifically, we don't need to look at any supertraits since + // we already do that in `BoundVarContext::supertrait_hrtb_vars`. + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(..) = item.kind + { + // Yield the trait's def id. Supertraits will be + // elaborated from that. + yield item.owner_id.def_id.to_def_id(); + } else if let Some(generics) = node.generics() { + for pred in generics.predicates { + let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind + else { + continue; + }; + let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = + pred.bounded_ty.kind + else { + continue; + }; + // Match the expected res. + if bounded_path.res != expected_res { + continue; + } + for pred in pred.bounds { + match pred { + hir::GenericBound::Trait(poly_trait_ref) => { + if let Some(def_id) = + poly_trait_ref.trait_ref.trait_def_id() + { + yield def_id; + } + } + hir::GenericBound::Outlives(_) + | hir::GenericBound::Use(_, _) => {} + } + } + } + } + } + + match *scope { + Scope::Binder { s, .. } + | Scope::Body { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s } + | Scope::LateBoundary { s, .. } + | Scope::Opaque { s, .. } => { + scope = s; + } + Scope::Root { .. } => break, + } + } + }, + ) + } } /// Detects late-bound lifetimes and inserts them into diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 816761fd00f..7cf99bebd36 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,6 +5,7 @@ use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::plumbing::CyclePlaceholder; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; @@ -113,7 +114,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // so no need for ConstArg. Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id)); - let ty = tcx.fold_regions(ty, |r, _| { + let ty = fold_regions(tcx, ty, |r, _| { if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } }); let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) { @@ -144,7 +145,7 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span // Easy case: arrays repeat expressions. Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id() == arg_hir_id => + if constant.hir_id == arg_hir_id => { return tcx.types.usize; } @@ -578,8 +579,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ x => bug!("unexpected non-type Node::GenericParam: {:?}", x), }, - Node::ArrayLenInfer(_) => tcx.types.usize, - x => { bug!("unexpected sort of node in type_of(): {:?}", x); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 0b2e9ed6052..4142dcff226 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -672,11 +672,10 @@ pub(crate) struct MainFunctionGenericParameters { #[derive(Diagnostic)] #[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] -pub(crate) struct VariadicFunctionCompatibleConvention<'a> { +pub(crate) struct VariadicFunctionCompatibleConvention { #[primary_span] #[label] pub span: Span, - pub conventions: &'a str, } #[derive(Diagnostic)] @@ -1081,13 +1080,6 @@ pub(crate) struct EmptySpecialization { } #[derive(Diagnostic)] -#[diag(hir_analysis_const_specialize)] -pub(crate) struct ConstSpecialize { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_static_specialize)] pub(crate) struct StaticSpecialize { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9d60759ae48..0404e38a293 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -703,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// It might actually be possible that we can already support early-bound generic params /// in such types if we just lifted some more checks in other places, too, for example -/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should +/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should /// probably gate this behind another feature flag. /// /// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index cab04ee0987..321a8aba7f7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -219,11 +219,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id)); } - self.complain_about_missing_assoc_tys( + if let Err(guar) = self.check_for_required_assoc_tys( associated_types, potential_assoc_types, hir_trait_bounds, - ); + ) { + return Ty::new_error(tcx, guar); + } // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as // `dyn Trait + Send`. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 0b58b807090..ff449a858d6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -714,14 +714,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// reasonable suggestion on how to write it. For the case of multiple associated types in the /// same trait bound have the same name (as they come from different supertraits), we instead /// emit a generic note suggesting using a `where` clause to constraint instead. - pub(crate) fn complain_about_missing_assoc_tys( + pub(crate) fn check_for_required_assoc_tys( &self, associated_types: FxIndexMap<Span, FxIndexSet<DefId>>, potential_assoc_types: Vec<usize>, trait_bounds: &[hir::PolyTraitRef<'_>], - ) { + ) -> Result<(), ErrorGuaranteed> { if associated_types.values().all(|v| v.is_empty()) { - return; + return Ok(()); } let tcx = self.tcx(); @@ -739,7 +739,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. let mut trait_bound_spans: Vec<Span> = vec![]; - let mut dyn_compatibility_violations = false; + let mut dyn_compatibility_violations = Ok(()); for (span, items) in &associated_types { if !items.is_empty() { trait_bound_spans.push(*span); @@ -752,13 +752,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let violations = dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); if !violations.is_empty() { - report_dyn_incompatibility(tcx, *span, None, trait_def_id, &violations).emit(); - dyn_compatibility_violations = true; + dyn_compatibility_violations = Err(report_dyn_incompatibility( + tcx, + *span, + None, + trait_def_id, + &violations, + ) + .emit()); } } } - if dyn_compatibility_violations { - return; + + if let Err(guar) = dyn_compatibility_violations { + return Err(guar); } // related to issue #91997, turbofishes added only when in an expr or pat @@ -965,7 +972,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - err.emit(); + Err(err.emit()) } /// On ambiguous associated type, look for an associated function whose name matches the diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index ae1279d428c..c3f4fc8699a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -104,7 +104,7 @@ fn generic_arg_mismatch_err( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), GenericParamDefKind::Const { .. }, ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => { - let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id())); + let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); if let Ok(snippet) = snippet { err.span_suggestion( arg.span(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 01276abec22..cb4209116ac 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -37,6 +37,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, @@ -1569,7 +1570,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); - let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); + let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { return false; @@ -2088,7 +2089,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qpath.span(), format!("Const::lower_const_arg: invalid qpath {qpath:?}"), ), - hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id), + hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id), + hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), } } @@ -2175,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + /// Literals and const generic parameters are eagerly converted to a constant, everything else + /// becomes `Unevaluated`. + #[instrument(skip(self), level = "debug")] + fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> { + let tcx = self.tcx(); + + let body_id = match tcx.hir_node_by_def_id(def) { + hir::Node::AnonConst(ac) => ac.body, + node => span_bug!( + tcx.def_span(def.to_def_id()), + "from_anon_const can only process anonymous constants, not {node:?}" + ), + }; + + let expr = &tcx.hir().body(body_id).value; + debug!(?expr); + + let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); + + match self.try_lower_anon_const_lit(ty, expr) { + Some(v) => v, + None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { + def: def.to_def_id(), + args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()), + }), + } + } + + #[instrument(skip(self), level = "debug")] + fn try_lower_anon_const_lit( + &self, + ty: Ty<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Option<Const<'tcx>> { + let tcx = self.tcx(); + + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + + if let hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + )) = expr.kind + { + span_bug!( + expr.span, + "try_lower_anon_const_lit: received const param which shouldn't be possible" + ); + }; + + let lit_input = match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), + _ => None, + }, + _ => None, + }; + + if let Some(lit_input) = lit_input { + // If an error occurred, ignore that it's a literal and leave reporting the error up to + // mir. + match tcx.at(expr.span).lit_to_const(lit_input) { + Ok(c) => return Some(c), + Err(_) if lit_input.ty.has_aliases() => { + // allow the `ty` to be an alias type, though we cannot handle it here + return None; + } + Err(e) => { + tcx.dcx().span_delayed_bug( + expr.span, + format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"), + ); + } + } + } + + None + } + fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { @@ -2309,13 +2397,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.at(span).type_of(def_id).instantiate(tcx, args) } hir::TyKind::Array(ty, length) => { - let length = match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), - hir::ArrayLen::Body(constant) => { - self.lower_const_arg(constant, FeedConstTy::No) - } - }; - + let length = self.lower_const_arg(length, FeedConstTy::No); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 5b0165bf993..c0fb94d2cb2 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -75,7 +76,7 @@ fn diagnostic_hir_wf_check<'tcx>( // This visitor can walk into binders, resulting in the `tcx_ty` to // potentially reference escaping bound variables. We simply erase // those here. - let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| { + let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| { if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } }); let cause = traits::ObligationCause::new( diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 246643d8074..ee55e1bc21a 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -66,7 +66,6 @@ //! on traits with methods can. use rustc_data_structures::fx::FxHashSet; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::outlives::env::OutlivesEnvironment; @@ -134,7 +133,6 @@ fn check_always_applicable( unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) }; - res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span)); res = res.and(check_static_lifetimes(tcx, &parent_args, span)); res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span)); res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span)); @@ -157,30 +155,6 @@ fn check_has_items( Ok(()) } -/// Check that the specializing impl `impl1` is at least as const as the base -/// impl `impl2` -fn check_constness( - tcx: TyCtxt<'_>, - impl1_def_id: LocalDefId, - impl2_node: Node, - span: Span, -) -> Result<(), ErrorGuaranteed> { - if impl2_node.is_from_trait() { - // This isn't a specialization - return Ok(()); - } - - let impl1_constness = tcx.constness(impl1_def_id.to_def_id()); - let impl2_constness = tcx.constness(impl2_node.def_id()); - - if let hir::Constness::Const = impl2_constness { - if let hir::Constness::NotConst = impl1_constness { - return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span })); - } - } - Ok(()) -} - /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two /// generic parameters `(S1, S2)` that equate their trait references. /// The returned types are expressed in terms of the generics of `impl1`. diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0a26b6776bb..87fd4de26a5 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -62,7 +62,9 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(coroutines)] #![feature(if_let_guard)] +#![feature(iter_from_coroutine)] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] @@ -98,9 +100,7 @@ use rustc_middle::middle; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; -use rustc_session::parse::feature_err; use rustc_span::Span; -use rustc_span::symbol::sym; use rustc_trait_selection::traits; use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; @@ -113,34 +113,9 @@ fn require_c_abi_if_c_variadic( abi: ExternAbi, span: Span, ) { - const CONVENTIONS_UNSTABLE: &str = - "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; - const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; - const UNSTABLE_EXPLAIN: &str = - "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; - - if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { - return; + if decl.c_variadic && !abi.supports_varargs() { + tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span }); } - - let extended_abi_support = tcx.features().extended_varargs_abi_support(); - let conventions = match (extended_abi_support, abi.supports_varargs()) { - // User enabled additional ABI support for varargs and function ABI matches those ones. - (true, true) => return, - - // Using this ABI would be ok, if the feature for additional ABI support was enabled. - // Return CONVENTIONS_STABLE, because we want the other error to look the same. - (false, true) => { - feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) - .emit(); - CONVENTIONS_STABLE - } - - (false, false) => CONVENTIONS_STABLE, - (true, false) => CONVENTIONS_UNSTABLE, - }; - - tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions }); } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 64c6969d4b9..0f3dcebc092 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use std::cell::Cell; use std::vec; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; @@ -118,7 +118,6 @@ impl<'a> State<'a> { Node::LetStmt(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), Node::WherePredicate(pred) => self.print_where_predicate(pred), - Node::ArrayLenInfer(_) => self.word("_"), Node::Synthetic => unreachable!(), Node::Err(_) => self.word("/*ERROR*/"), } @@ -315,7 +314,7 @@ impl<'a> State<'a> { self.word("["); self.print_type(ty); self.word("; "); - self.print_array_length(length); + self.print_const_arg(length); self.word("]"); } hir::TyKind::Typeof(ref e) => { @@ -986,13 +985,6 @@ impl<'a> State<'a> { self.print_else(elseopt) } - fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) { - match len { - hir::ArrayLen::Infer(..) => self.word("_"), - hir::ArrayLen::Body(ct) => self.print_const_arg(ct), - } - } - fn print_anon_const(&mut self, constant: &hir::AnonConst) { self.ann.nested(self, Nested::Body(constant.body)) } @@ -1001,6 +993,7 @@ impl<'a> State<'a> { match &const_arg.kind { ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Anon(anon) => self.print_anon_const(anon), + ConstArgKind::Infer(..) => self.word("_"), } } @@ -1010,10 +1003,6 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_maybe_paren(&mut self, expr: &hir::Expr<'_>, prec: i8) { - self.print_expr_cond_paren(expr, expr.precedence() < prec) - } - /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in /// `if cond { ... }`. fn print_expr_as_cond(&mut self, expr: &hir::Expr<'_>) { @@ -1077,12 +1066,12 @@ impl<'a> State<'a> { self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen<'_>) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ConstArg<'_>) { self.ibox(INDENT_UNIT); self.word("["); self.print_expr(element); self.word_space(";"); - self.print_array_length(count); + self.print_const_arg(count); self.word("]"); self.end() } @@ -1136,12 +1125,12 @@ impl<'a> State<'a> { } fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let prec = match func.kind { - hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_UNAMBIGUOUS, + let needs_paren = match func.kind { + hir::ExprKind::Field(..) => true, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; - self.print_expr_maybe_paren(func, prec); + self.print_expr_cond_paren(func, needs_paren); self.print_call_post(args) } @@ -1152,7 +1141,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(segment.ident); @@ -1166,37 +1155,38 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { let assoc_op = AssocOp::from_ast_binop(op.node); - let prec = assoc_op.precedence() as i8; - let fixity = assoc_op.fixity(); - - let (left_prec, right_prec) = match fixity { - Fixity::Left => (prec, prec + 1), - Fixity::Right => (prec + 1, prec), - Fixity::None => (prec + 1, prec + 1), + let binop_prec = assoc_op.precedence(); + let left_prec = lhs.precedence(); + let right_prec = rhs.precedence(); + + let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() { + Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), + Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), + Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - let left_prec = match (&lhs.kind, op.node) { + match (&lhs.kind, op.node) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt | hir::BinOpKind::Shl) => { - parser::PREC_FORCE_PAREN + left_needs_paren = true; } - (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => { - parser::PREC_FORCE_PAREN + (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => { + left_needs_paren = true; } - _ => left_prec, - }; + _ => {} + } - self.print_expr_maybe_paren(lhs, left_prec); + self.print_expr_cond_paren(lhs, left_needs_paren); self.space(); self.word_space(op.node.as_str()); - self.print_expr_maybe_paren(rhs, right_prec) + self.print_expr_cond_paren(rhs, right_needs_paren); } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { self.word(op.as_str()); - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_expr_addr_of( @@ -1213,7 +1203,7 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_literal(&mut self, lit: &hir::Lit) { @@ -1351,8 +1341,7 @@ impl<'a> State<'a> { self.print_literal(lit); } hir::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(expr, prec); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast); self.space(); self.word_space("as"); self.print_type(ty); @@ -1453,27 +1442,25 @@ impl<'a> State<'a> { self.print_block(blk); } hir::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("["); self.print_expr(index); self.word("]"); @@ -1487,7 +1474,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Continue(destination) => { @@ -1501,13 +1488,13 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_maybe_paren(result, parser::PREC_JUMP); + self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump); } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); @@ -1532,7 +1519,7 @@ impl<'a> State<'a> { } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } hir::ExprKind::Err(_) => { self.popen(); diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 3669100ed91..b27f7215ae4 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer = .label = used more than once .previous_use_label = first use of `{$ident}` +hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function + .suggestion = use a function pointer instead + .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html + hir_typeck_fru_expr = this expression does not end in a comma... hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression @@ -141,7 +146,6 @@ hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value in hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function .suggestion = cast the value to `{$cast_ty}` - .help = cast the value to `{$cast_ty}` .teach_help = certain types, like `{$ty}`, must be casted before passing them to a variadic function, because of arcane ABI rules dictated by the C standard hir_typeck_ptr_cast_add_auto_to_object = adding {$traits_len -> diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a92482e6a0e..b430f48965a 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -1,10 +1,10 @@ use std::iter; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, HirId, LangItem}; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer; use rustc_infer::traits::{self, Obligation, ObligationCause, ObligationCauseCode}; @@ -428,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { ty::FnDef(def_id, args) => { - self.enforce_context_effects(call_expr.span, def_id, args); + self.enforce_context_effects(Some(call_expr.hir_id), call_expr.span, def_id, args); let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); // Unit testing: function items annotated with @@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Ok(rest_snippet) = rest_snippet { - let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS { + let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous { vec![ (up_to_rcvr_span, "".to_string()), (rest_span, format!(".{}({rest_snippet}", segment.ident)), @@ -837,6 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self, span))] pub(super) fn enforce_context_effects( &self, + call_hir_id: Option<HirId>, span: Span, callee_did: DefId, callee_args: GenericArgsRef<'tcx>, @@ -867,10 +868,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.is_conditionally_const(callee_did) { let q = self.tcx.const_conditions(callee_did); // FIXME(const_trait_impl): Use this span with a better cause code. - for (cond, _) in q.instantiate(self.tcx, callee_args) { + for (idx, (cond, pred_span)) in + q.instantiate(self.tcx, callee_args).into_iter().enumerate() + { + let cause = self.cause( + span, + if let Some(hir_id) = call_hir_id { + ObligationCauseCode::HostEffectInExpr(callee_did, pred_span, hir_id, idx) + } else { + ObligationCauseCode::WhereClause(callee_did, pred_span) + }, + ); self.register_predicate(Obligation::new( self.tcx, - self.misc(span), + cause, self.param_env, cond.to_host_effect_clause(self.tcx, host), )); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0c3f21d540d..80b91c21598 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -28,6 +28,7 @@ //! expression, `e as U2` is not necessarily so (in fact it will only be valid if //! `U1` coerces to `U2`). +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; @@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { let expr_prec = self.expr.precedence(); - let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS; + let needs_parens = expr_prec < ExprPrecedence::Unambiguous; let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 11e03229265..bf41dcbe4a3 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -215,7 +215,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - // Examine the supertype and consider auto-borrowing. + // Examine the supertype and consider type-specific coercions, such + // as auto-borrowing, coercing pointer mutability, a `dyn*` coercion, + // or pin-ergonomics. match *b.kind() { ty::RawPtr(_, b_mutbl) => { return self.coerce_unsafe_ptr(a, b, b_mutbl); @@ -230,7 +232,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if self.tcx.features().pin_ergonomics() && self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => { - return self.coerce_pin(a, b); + let pin_coerce = self.commit_if_ok(|_| self.coerce_pin_ref(a, b)); + if pin_coerce.is_ok() { + return pin_coerce; + } } _ => {} } @@ -797,7 +802,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { /// - `Pin<Box<T>>` as `Pin<&T>` /// - `Pin<Box<T>>` as `Pin<&mut T>` #[instrument(skip(self), level = "trace")] - fn coerce_pin(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { + fn coerce_pin_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { // We need to make sure the two types are compatible for coercion. // Then we will build a ReborrowPin adjustment and return that as an InferOk. diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 4f579b05d83..a2e00859307 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -789,11 +789,20 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> { pub span: Span, pub ty: Ty<'tcx>, pub cast_ty: &'a str, - #[suggestion(code = "{replace}", applicability = "machine-applicable")] - pub sugg_span: Option<Span>, - pub replace: String, - #[help] - pub help: bool, + #[suggestion(code = " as {cast_ty}", applicability = "machine-applicable", style = "verbose")] + pub sugg_span: Span, #[note(hir_typeck_teach_help)] pub(crate) teach: bool, } + +#[derive(Diagnostic)] +#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] +#[help] +#[note] +pub(crate) struct PassFnItemToVariadicFunction { + #[primary_span] + pub span: Span, + #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")] + pub sugg_span: Span, + pub replace: String, +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b4715839cf5..4699b342cec 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -19,7 +19,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; -use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; +use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCause; @@ -425,7 +425,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::Node::Crate(_) | hir::Node::Infer(_) | hir::Node::WherePredicate(_) - | hir::Node::ArrayLenInfer(_) | hir::Node::PreciseCapturingNonLifetimeArg(_) | hir::Node::OpaqueTy(_) => { unreachable!("no sub-expr expected for {parent_node:?}") @@ -1673,9 +1672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { else { return; }; - if let hir::TyKind::Array(_, length) = ty.peel_refs().kind - && let hir::ArrayLen::Body(ct) = length - { + if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind { let span = ct.span(); self.dcx().try_steal_modify_and_emit_err( span, @@ -1713,13 +1710,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::ArrayLen<'tcx>, + count: &'tcx hir::ConstArg<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let count_span = count.span(); - let count = self.try_structurally_resolve_const(count_span, self.lower_array_length(count)); + let count = self.try_structurally_resolve_const( + count_span, + self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)), + ); if let Some(count) = count.try_to_target_usize(tcx) { self.suggest_array_len(expr, count); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 2a00530c434..774d00edea0 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env()) + self.0.type_is_copy_modulo_regions(ty) } fn body_owner_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 7719facccc7..ddd146fe785 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -705,7 +705,8 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) -> Self::Result { // For a local, try suggest annotating the type if it's missing. - if let None = local.ty + if let hir::LocalSource::Normal = local.source + && let None = local.ty && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(local.hir_id) && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 47af8c681da..863be3bdcb2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -185,7 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, method: MethodCallee<'tcx>, ) { - self.enforce_context_effects(span, method.def_id, method.args); + self.enforce_context_effects(Some(hir_id), span, method.def_id, method.args); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_args(hir_id, method.args); } @@ -263,6 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Adjust::Deref(Some(overloaded_deref)) => { self.enforce_context_effects( + None, expr.span, overloaded_deref.method_call(self.tcx), self.tcx.mk_args(&[a.target.into()]), @@ -486,24 +487,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { - match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), - hir::ArrayLen::Body(const_arg) => { - let span = const_arg.span(); - let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No); - self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None)); - self.normalize(span, c) - } - } - } - pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, - param_def_id: DefId, + feed: FeedConstTy, ) -> ty::Const<'tcx> { - let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id)); + let ct = self.lowerer().lower_const_arg(const_arg, feed); self.register_wf_obligation( ct.into(), self.tcx.hir().span(const_arg.hir_id), @@ -1278,7 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.fcx.lower_const_arg(ct, param.def_id).into() + self.fcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.fcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index b09d78614c3..6eaba641888 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -11,26 +11,56 @@ use rustc_trait_selection::traits; use crate::FnCtxt; +enum ClauseFlavor { + /// Predicate comes from `predicates_of`. + Where, + /// Predicate comes from `const_conditions`. + Const, +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn adjust_fulfillment_error_for_expr_obligation( &self, error: &mut traits::FulfillmentError<'tcx>, ) -> bool { - let ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) = - *error.obligation.cause.code().peel_derives() - else { - return false; + let (def_id, hir_id, idx, flavor) = match *error.obligation.cause.code().peel_derives() { + ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) => { + (def_id, hir_id, idx, ClauseFlavor::Where) + } + ObligationCauseCode::HostEffectInExpr(def_id, _, hir_id, idx) => { + (def_id, hir_id, idx, ClauseFlavor::Const) + } + _ => return false, }; - let Some(uninstantiated_pred) = self - .tcx - .predicates_of(def_id) - .instantiate_identity(self.tcx) - .predicates - .into_iter() - .nth(idx) - else { - return false; + let uninstantiated_pred = match flavor { + ClauseFlavor::Where => { + if let Some(pred) = self + .tcx + .predicates_of(def_id) + .instantiate_identity(self.tcx) + .predicates + .into_iter() + .nth(idx) + { + pred + } else { + return false; + } + } + ClauseFlavor::Const => { + if let Some((pred, _)) = self + .tcx + .const_conditions(def_id) + .instantiate_identity(self.tcx) + .into_iter() + .nth(idx) + { + pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe) + } else { + return false; + } + } }; let generics = self.tcx.generics_of(def_id); @@ -39,6 +69,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClauseKind::Trait(pred) => { (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) } + ty::ClauseKind::HostEffect(pred) => { + (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) + } ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None), ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None), ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None), @@ -94,39 +127,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate); } - let (expr, qpath) = match self.tcx.hir_node(hir_id) { - hir::Node::Expr(expr) => { - if self.closure_span_overlaps_error(error, expr.span) { - return false; + match self.tcx.hir_node(hir_id) { + hir::Node::Expr(expr) => self.point_at_expr_if_possible( + error, + def_id, + expr, + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ), + + hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => { + for param in [ + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, def_id, param, &qpath) { + return true; + } } - let qpath = - if let hir::ExprKind::Path(qpath) = expr.kind { Some(qpath) } else { None }; - (Some(&expr.kind), qpath) + false } - hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => (None, Some(*qpath)), - _ => return false, - }; - if let Some(qpath) = qpath { - // Prefer pointing at the turbofished arg that corresponds to the - // self type of the failing predicate over anything else. - if let Some(param) = predicate_self_type_to_point_at - && self.point_at_path_if_possible(error, def_id, param, &qpath) - { - return true; - } + _ => false, + } + } - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Call(callee, args), - hir_id: call_hir_id, - span: call_span, - .. - }) = self.tcx.parent_hir_node(hir_id) - && callee.hir_id == hir_id - { - if self.closure_span_overlaps_error(error, *call_span) { - return false; + fn point_at_expr_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + callee_def_id: DefId, + expr: &'tcx hir::Expr<'tcx>, + predicate_self_type_to_point_at: Option<ty::GenericArg<'tcx>>, + param_to_point_at: Option<ty::GenericArg<'tcx>>, + fallback_param_to_point_at: Option<ty::GenericArg<'tcx>>, + self_param_to_point_at: Option<ty::GenericArg<'tcx>>, + ) -> bool { + if self.closure_span_overlaps_error(error, expr.span) { + return false; + } + + match expr.kind { + hir::ExprKind::Call( + hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. }, + args, + ) => { + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_path_if_possible(error, callee_def_id, param, &qpath) + { + return true; } for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] @@ -135,32 +191,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if self.blame_specific_arg_if_possible( error, - def_id, + callee_def_id, param, - *call_hir_id, - callee.span, + expr.hir_id, + *callee_span, None, args, ) { return true; } } + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) { + return true; + } + } } + hir::ExprKind::Path(qpath) => { + // If the parent is an call, then process this as a call. + // + // This is because the `WhereClauseInExpr` obligations come from + // the well-formedness of the *path* expression, but we care to + // point at the call expression (namely, its args). + if let hir::Node::Expr( + call_expr @ hir::Expr { kind: hir::ExprKind::Call(callee, ..), .. }, + ) = self.tcx.parent_hir_node(expr.hir_id) + && callee.hir_id == expr.hir_id + { + return self.point_at_expr_if_possible( + error, + callee_def_id, + call_expr, + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ); + } - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.point_at_path_if_possible(error, def_id, param, &qpath) { + // Otherwise, just try to point at path components. + + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_path_if_possible(error, callee_def_id, param, &qpath) + { return true; } - } - } - match expr { - Some(hir::ExprKind::MethodCall(segment, receiver, args, ..)) => { + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) { + return true; + } + } + } + hir::ExprKind::MethodCall(segment, receiver, args, ..) => { if let Some(param) = predicate_self_type_to_point_at - && self.point_at_generic_if_possible(error, def_id, param, segment) + && self.point_at_generic_if_possible(error, callee_def_id, param, segment) { // HACK: This is not correct, since `predicate_self_type_to_point_at` might // not actually correspond to the receiver of the method call. But we @@ -170,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error.obligation.cause.map_code(|parent_code| { ObligationCauseCode::FunctionArg { arg_hir_id: receiver.hir_id, - call_hir_id: hir_id, + call_hir_id: expr.hir_id, parent_code, } }); @@ -183,9 +275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if self.blame_specific_arg_if_possible( error, - def_id, + callee_def_id, param, - hir_id, + expr.hir_id, segment.ident.span, Some(receiver), args, @@ -194,7 +286,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if let Some(param_to_point_at) = param_to_point_at - && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment) + && self.point_at_generic_if_possible( + error, + callee_def_id, + param_to_point_at, + segment, + ) { return true; } @@ -208,17 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - Some(hir::ExprKind::Struct(qpath, fields, ..)) => { + hir::ExprKind::Struct(qpath, fields, ..) => { if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = - self.typeck_results.borrow().qpath_res(qpath, hir_id) + self.typeck_results.borrow().qpath_res(qpath, expr.hir_id) { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() .flatten() { - let refined_expr = - self.point_at_field_if_possible(def_id, param, variant_def_id, fields); + let refined_expr = self.point_at_field_if_possible( + callee_def_id, + param, + variant_def_id, + fields, + ); match refined_expr { None => {} @@ -242,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .flatten() { - if self.point_at_path_if_possible(error, def_id, param, qpath) { + if self.point_at_path_if_possible(error, callee_def_id, param, qpath) { return true; } } @@ -525,7 +626,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> { match obligation_cause_code { - traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) => { + traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) + | ObligationCauseCode::HostEffectInExpr(..) => { // This is the "root"; we assume that the `expr` is already pointing here. // Therefore, we return `Ok` so that this `expr` can be refined further. Ok(expr) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f8f6564cf14..30c838b74af 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -440,20 +440,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, cast_ty: &str, ) { - let (sugg_span, replace, help) = - if let Ok(snippet) = sess.source_map().span_to_snippet(span) { - (Some(span), format!("{snippet} as {cast_ty}"), false) - } else { - (None, "".to_string(), true) - }; - sess.dcx().emit_err(errors::PassToVariadicFunction { span, ty, cast_ty, - help, - replace, - sugg_span, + sugg_span: span.shrink_to_hi(), teach: sess.teach(E0617), }); } @@ -472,9 +463,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } ty::FnDef(..) => { - let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); - let ptr_ty = self.resolve_vars_if_possible(ptr_ty); - variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); + let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); + let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string(); + + let fn_item_spa = arg.span; + tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction { + span: fn_item_spa, + sugg_span: fn_item_spa.shrink_to_hi(), + replace: fn_ptr, + }); } _ => {} } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 3940d138deb..aacdcf027b6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -307,7 +307,11 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) if !ty.has_escaping_bound_vars() => { - self.normalize(span, ty).ty_adt_def() + if self.next_trait_solver() { + self.try_structurally_resolve_type(span, ty).ty_adt_def() + } else { + self.normalize(span, ty).ty_adt_def() + } } _ => None, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b493a61b9f4..61260dbd16c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2,7 +2,7 @@ use core::cmp::min; use core::iter; use hir::def_id::LocalDefId; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir as hir; @@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we remove the user's `clone` call. { vec![(receiver_method.ident.span, conversion_method.name.to_string())] - } else if expr.precedence() < PREC_UNAMBIGUOUS { + } else if expr.precedence() < ExprPrecedence::Unambiguous { vec![ (expr.span.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)), @@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); - let mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS { + let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); - let close_paren = if expr.precedence() < PREC_UNAMBIGUOUS { + let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); ")" } else { @@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = src.trim_end_matches(&checked_ty.to_string()).len(); expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) }, - if expr.precedence() < PREC_UNAMBIGUOUS { + if expr.precedence() < ExprPrecedence::Unambiguous { // Readd `)` format!("{expected_ty})") } else { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 3754fd02428..b31ee1a55d6 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -7,7 +7,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, + FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; @@ -429,7 +429,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.cfcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.cfcx.lower_const_arg(ct, param.def_id).into() + self.cfcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.cfcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 640729576fc..039c117c099 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Thus we need to prevent them from trying to match the `&_` autoref // candidates that get created for `&self` trait methods. ty::Alias(ty::Opaque, alias_ty) - if self.infcx.can_define_opaque_ty(alias_ty.def_id) + if !self.next_trait_solver() + && self.infcx.can_define_opaque_ty(alias_ty.def_id) && !xform_self_ty.is_ty_var() => { return ProbeResult::NoMatch; @@ -1642,6 +1643,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + // FIXME(-Znext-solver): See the linked issue below. + // <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134> + // + // In the new solver, check the well-formedness of the return type. + // This emulates, in a way, the predicates that fall out of + // normalizing the return type in the old solver. + // + // We alternatively could check the predicates of the method itself hold, + // but we intentionally do not do this in the old solver b/c of cycles, + // and doing it in the new solver would be stronger. This should be fixed + // in the future, since it likely leads to much better method winnowing. + if let Some(xform_ret_ty) = xform_ret_ty + && self.infcx.next_trait_solver() + { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::ClauseKind::WellFormed(xform_ret_ty.into()), + )); + } + // Evaluate those obligations to see if they might possibly hold. for error in ocx.select_where_possible() { result = ProbeResult::NoMatch; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cff2aa68993..6b1a288510a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) - }) && item_name.name == Symbol::intern("write_fmt"); + }) && item_name.name == sym::write_fmt; let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 3d401cef76f..7c667511aa9 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -296,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); }; *deref = OverloadedDeref { mutbl, span: deref.span }; - self.enforce_context_effects(expr.span, method.def_id, method.args); + self.enforce_context_effects(None, expr.span, method.def_id, method.args); // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). // This helps avoid accidental drops. if inside_union diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 2f436ce77a4..e17a68c8692 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, fold_regions}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable}; use rustc_span::Span; @@ -827,7 +827,10 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // no reason to keep regions around. They will be repopulated during MIR // borrowck, and specifically region constraints will be populated during // MIR typeck which is run on the new body. - value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased); + // + // We're not using `tcx.erase_regions` as that also anonymizes bound variables, + // regressing borrowck diagnostics. + value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased); // Normalize consts in writeback, because GCE doesn't normalize eagerly. if tcx.features().generic_const_exprs() { diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index f7d18f84e34..33e8e2824c7 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -arrayvec = { version = "0.7", default-features = false } rustc_index_macros = { path = "../rustc_index_macros", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index a9239489222..de6fa132ca0 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -4,7 +4,6 @@ use std::rc::Rc; use std::{fmt, iter, mem, slice}; use Chunk::*; -use arrayvec::ArrayVec; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_Generic, Encodable_Generic}; use smallvec::{SmallVec, smallvec}; @@ -240,45 +239,6 @@ impl<T: Idx> BitSet<T> { BitIter::new(&self.words) } - /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at - /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). - /// - /// This is an optimization for union of a hybrid bitset. - fn reverse_union_sparse(&mut self, sparse: &SparseBitSet<T>) -> bool { - assert!(sparse.domain_size == self.domain_size); - self.clear_excess_bits(); - - let mut not_already = false; - // Index of the current word not yet merged. - let mut current_index = 0; - // Mask of bits that came from the sparse set in the current word. - let mut new_bit_mask = 0; - for (word_index, mask) in sparse.iter().map(|x| word_index_and_mask(*x)) { - // Next bit is in a word not inspected yet. - if word_index > current_index { - self.words[current_index] |= new_bit_mask; - // Were there any bits in the old word that did not occur in the sparse set? - not_already |= (self.words[current_index] ^ new_bit_mask) != 0; - // Check all words we skipped for any set bit. - not_already |= self.words[current_index + 1..word_index].iter().any(|&x| x != 0); - // Update next word. - current_index = word_index; - // Reset bit mask, no bits have been merged yet. - new_bit_mask = 0; - } - // Add bit and mark it as coming from the sparse set. - // self.words[word_index] |= mask; - new_bit_mask |= mask; - } - self.words[current_index] |= new_bit_mask; - // Any bits in the last inspected word that were not in the sparse set? - not_already |= (self.words[current_index] ^ new_bit_mask) != 0; - // Any bits in the tail? Note `clear_excess_bits` before. - not_already |= self.words[current_index + 1..].iter().any(|&x| x != 0); - - not_already - } - pub fn last_set_in(&self, range: impl RangeBounds<T>) -> Option<T> { let (start, end) = inclusive_start_end(range, self.domain_size)?; let (start_word_index, _) = word_index_and_mask(start); @@ -369,9 +329,11 @@ pub struct ChunkedBitSet<T> { #[derive(Clone, Debug, PartialEq, Eq)] enum Chunk { /// A chunk that is all zeros; we don't represent the zeros explicitly. + /// The `ChunkSize` is always non-zero. Zeros(ChunkSize), /// A chunk that is all ones; we don't represent the ones explicitly. + /// `ChunkSize` is always non-zero. Ones(ChunkSize), /// A chunk that has a mix of zeros and ones, which are represented @@ -381,11 +343,12 @@ enum Chunk { /// turns out to be both simpler and have better performance than /// allocating the minimum number of words, largely because we avoid having /// to store the length, which would make this type larger. These excess - /// words are always be zero, as are any excess bits in the final in-use - /// word. + /// words are always zero, as are any excess bits in the final in-use word. /// - /// The second field is the count of 1s set in the chunk, and must satisfy - /// `0 < count < chunk_domain_size`. + /// The first `ChunkSize` field is always non-zero. + /// + /// The second `ChunkSize` field is the count of 1s set in the chunk, and + /// must satisfy `0 < count < chunk_domain_size`. /// /// The words are within an `Rc` because it's surprisingly common to /// duplicate an entire chunk, e.g. in `ChunkedBitSet::clone_from()`, or @@ -450,6 +413,11 @@ impl<T: Idx> ChunkedBitSet<T> { ChunkedBitSet::new(domain_size, /* is_empty */ false) } + pub fn clear(&mut self) { + let domain_size = self.domain_size(); + *self = ChunkedBitSet::new_empty(domain_size); + } + #[cfg(test)] fn chunks(&self) -> &[Chunk] { &self.chunks @@ -461,7 +429,7 @@ impl<T: Idx> ChunkedBitSet<T> { } pub fn is_empty(&self) -> bool { - self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..) | Chunk::Ones(0))) + self.chunks.iter().all(|chunk| matches!(chunk, Zeros(..))) } /// Returns `true` if `self` contains `elem`. @@ -610,6 +578,18 @@ impl<T: Idx> ChunkedBitSet<T> { } } + fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> { + match self.chunks.get(chunk_index) { + Some(Zeros(_chunk_domain_size)) => ChunkIter::Zeros, + Some(Ones(chunk_domain_size)) => ChunkIter::Ones(0..*chunk_domain_size as usize), + Some(Mixed(chunk_domain_size, _, ref words)) => { + let num_words = num_words(*chunk_domain_size as usize); + ChunkIter::Mixed(BitIter::new(&words[0..num_words])) + } + None => ChunkIter::Finished, + } + } + bit_relations_inherent_impls! {} } @@ -809,30 +789,6 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> { } } -impl<T: Idx> BitRelations<HybridBitSet<T>> for ChunkedBitSet<T> { - fn union(&mut self, other: &HybridBitSet<T>) -> bool { - // FIXME: This is slow if `other` is dense, but it hasn't been a problem - // in practice so far. - // If a faster implementation of this operation is required, consider - // reopening https://github.com/rust-lang/rust/pull/94625 - assert_eq!(self.domain_size, other.domain_size()); - sequential_update(|elem| self.insert(elem), other.iter()) - } - - fn subtract(&mut self, other: &HybridBitSet<T>) -> bool { - // FIXME: This is slow if `other` is dense, but it hasn't been a problem - // in practice so far. - // If a faster implementation of this operation is required, consider - // reopening https://github.com/rust-lang/rust/pull/94625 - assert_eq!(self.domain_size, other.domain_size()); - sequential_update(|elem| self.remove(elem), other.iter()) - } - - fn intersect(&mut self, _other: &HybridBitSet<T>) -> bool { - unimplemented!("implement if/when necessary"); - } -} - impl<T: Idx> BitRelations<ChunkedBitSet<T>> for BitSet<T> { fn union(&mut self, other: &ChunkedBitSet<T>) -> bool { sequential_update(|elem| self.insert(elem), other.iter()) @@ -851,7 +807,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for BitSet<T> { words = &mut words[..CHUNK_WORDS]; } match chunk { - Chunk::Zeros(..) => { + Zeros(..) => { for word in words { if *word != 0 { changed = true; @@ -859,8 +815,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for BitSet<T> { } } } - Chunk::Ones(..) => (), - Chunk::Mixed(_, _, data) => { + Ones(..) => (), + Mixed(_, _, data) => { for (i, word) in words.iter_mut().enumerate() { let new_val = *word & data[i]; if new_val != *word { @@ -897,78 +853,44 @@ impl<T> Clone for ChunkedBitSet<T> { } pub struct ChunkedBitIter<'a, T: Idx> { - index: usize, - bitset: &'a ChunkedBitSet<T>, + bit_set: &'a ChunkedBitSet<T>, + + // The index of the current chunk. + chunk_index: usize, + + // The sub-iterator for the current chunk. + chunk_iter: ChunkIter<'a>, } impl<'a, T: Idx> ChunkedBitIter<'a, T> { #[inline] - fn new(bitset: &'a ChunkedBitSet<T>) -> ChunkedBitIter<'a, T> { - ChunkedBitIter { index: 0, bitset } + fn new(bit_set: &'a ChunkedBitSet<T>) -> ChunkedBitIter<'a, T> { + ChunkedBitIter { bit_set, chunk_index: 0, chunk_iter: bit_set.chunk_iter(0) } } } impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> { type Item = T; - fn next(&mut self) -> Option<T> { - while self.index < self.bitset.domain_size() { - let elem = T::new(self.index); - let chunk = &self.bitset.chunks[chunk_index(elem)]; - match &chunk { - Zeros(chunk_domain_size) => { - self.index += *chunk_domain_size as usize; - } - Ones(_chunk_domain_size) => { - self.index += 1; - return Some(elem); - } - Mixed(_chunk_domain_size, _, words) => loop { - let elem = T::new(self.index); - self.index += 1; - let (word_index, mask) = chunk_word_index_and_mask(elem); - if (words[word_index] & mask) != 0 { - return Some(elem); - } - if self.index % CHUNK_BITS == 0 { - break; - } - }, - } - } - None - } - fn fold<B, F>(mut self, mut init: B, mut f: F) -> B - where - F: FnMut(B, Self::Item) -> B, - { - // If `next` has already been called, we may not be at the start of a chunk, so we first - // advance the iterator to the start of the next chunk, before proceeding in chunk sized - // steps. - while self.index % CHUNK_BITS != 0 { - let Some(item) = self.next() else { return init }; - init = f(init, item); - } - let start_chunk = self.index / CHUNK_BITS; - let chunks = &self.bitset.chunks[start_chunk..]; - for (i, chunk) in chunks.iter().enumerate() { - let base = (start_chunk + i) * CHUNK_BITS; - match chunk { - Chunk::Zeros(_) => (), - Chunk::Ones(limit) => { - for j in 0..(*limit as usize) { - init = f(init, T::new(base + j)); + fn next(&mut self) -> Option<T> { + loop { + match &mut self.chunk_iter { + ChunkIter::Zeros => {} + ChunkIter::Ones(iter) => { + if let Some(next) = iter.next() { + return Some(T::new(next + self.chunk_index * CHUNK_BITS)); } } - Chunk::Mixed(_, _, words) => { - init = BitIter::new(&**words).fold(init, |val, mut item: T| { - item.increment_by(base); - f(val, item) - }); + ChunkIter::Mixed(iter) => { + if let Some(next) = iter.next() { + return Some(T::new(next + self.chunk_index * CHUNK_BITS)); + } } + ChunkIter::Finished => return None, } + self.chunk_index += 1; + self.chunk_iter = self.bit_set.chunk_iter(self.chunk_index); } - init } } @@ -1005,7 +927,7 @@ impl Chunk { } fn new(chunk_domain_size: usize, is_empty: bool) -> Self { - debug_assert!(chunk_domain_size <= CHUNK_BITS); + debug_assert!(0 < chunk_domain_size && chunk_domain_size <= CHUNK_BITS); let chunk_domain_size = chunk_domain_size as ChunkSize; if is_empty { Zeros(chunk_domain_size) } else { Ones(chunk_domain_size) } } @@ -1020,6 +942,13 @@ impl Chunk { } } +enum ChunkIter<'a> { + Zeros, + Ones(Range<usize>), + Mixed(BitIter<'a, usize>), + Finished, +} + // Applies a function to mutate a bitset, and returns true if any // of the applications return true fn sequential_update<T: Idx>( @@ -1029,176 +958,6 @@ fn sequential_update<T: Idx>( it.fold(false, |changed, elem| self_update(elem) | changed) } -// Optimization of intersection for SparseBitSet that's generic -// over the RHS -fn sparse_intersect<T: Idx>( - set: &mut SparseBitSet<T>, - other_contains: impl Fn(&T) -> bool, -) -> bool { - let size = set.elems.len(); - set.elems.retain(|elem| other_contains(elem)); - set.elems.len() != size -} - -// Optimization of dense/sparse intersection. The resulting set is -// guaranteed to be at most the size of the sparse set, and hence can be -// represented as a sparse set. Therefore the sparse set is copied and filtered, -// then returned as the new set. -fn dense_sparse_intersect<T: Idx>( - dense: &BitSet<T>, - sparse: &SparseBitSet<T>, -) -> (SparseBitSet<T>, bool) { - let mut sparse_copy = sparse.clone(); - sparse_intersect(&mut sparse_copy, |el| dense.contains(*el)); - let n = sparse_copy.len(); - (sparse_copy, n != dense.count()) -} - -// hybrid REL dense -impl<T: Idx> BitRelations<BitSet<T>> for HybridBitSet<T> { - fn union(&mut self, other: &BitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => { - // `self` is sparse and `other` is dense. To - // merge them, we have two available strategies: - // * Densify `self` then merge other - // * Clone other then integrate bits from `self` - // The second strategy requires dedicated method - // since the usual `union` returns the wrong - // result. In the dedicated case the computation - // is slightly faster if the bits of the sparse - // bitset map to only few words of the dense - // representation, i.e. indices are near each - // other. - // - // Benchmarking seems to suggest that the second - // option is worth it. - let mut new_dense = other.clone(); - let changed = new_dense.reverse_union_sparse(sparse); - *self = HybridBitSet::Dense(new_dense); - changed - } - - HybridBitSet::Dense(dense) => dense.union(other), - } - } - - fn subtract(&mut self, other: &BitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| sparse.remove(elem), other.iter()) - } - HybridBitSet::Dense(dense) => dense.subtract(other), - } - } - - fn intersect(&mut self, other: &BitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => sparse_intersect(sparse, |elem| other.contains(*elem)), - HybridBitSet::Dense(dense) => dense.intersect(other), - } - } -} - -// dense REL hybrid -impl<T: Idx> BitRelations<HybridBitSet<T>> for BitSet<T> { - fn union(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| self.insert(elem), sparse.iter().cloned()) - } - HybridBitSet::Dense(dense) => self.union(dense), - } - } - - fn subtract(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| self.remove(elem), sparse.iter().cloned()) - } - HybridBitSet::Dense(dense) => self.subtract(dense), - } - } - - fn intersect(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - let (updated, changed) = dense_sparse_intersect(self, sparse); - - // We can't directly assign the SparseBitSet to the BitSet, and - // doing `*self = updated.to_dense()` would cause a drop / reallocation. Instead, - // the BitSet is cleared and `updated` is copied into `self`. - self.clear(); - for elem in updated.iter() { - self.insert(*elem); - } - changed - } - HybridBitSet::Dense(dense) => self.intersect(dense), - } - } -} - -// hybrid REL hybrid -impl<T: Idx> BitRelations<HybridBitSet<T>> for HybridBitSet<T> { - fn union(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(_) => { - match other { - HybridBitSet::Sparse(other_sparse) => { - // Both sets are sparse. Add the elements in - // `other_sparse` to `self` one at a time. This - // may or may not cause `self` to be densified. - let mut changed = false; - for elem in other_sparse.iter() { - changed |= self.insert(*elem); - } - changed - } - - HybridBitSet::Dense(other_dense) => self.union(other_dense), - } - } - - HybridBitSet::Dense(self_dense) => self_dense.union(other), - } - } - - fn subtract(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(self_sparse) => { - sequential_update(|elem| self_sparse.remove(elem), other.iter()) - } - HybridBitSet::Dense(self_dense) => self_dense.subtract(other), - } - } - - fn intersect(&mut self, other: &HybridBitSet<T>) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(self_sparse) => { - sparse_intersect(self_sparse, |elem| other.contains(*elem)) - } - HybridBitSet::Dense(self_dense) => match other { - HybridBitSet::Sparse(other_sparse) => { - let (updated, changed) = dense_sparse_intersect(self_dense, other_sparse); - *self = HybridBitSet::Sparse(updated); - changed - } - HybridBitSet::Dense(other_dense) => self_dense.intersect(other_dense), - }, - } - } -} - impl<T> Clone for BitSet<T> { fn clone(&self) -> Self { BitSet { domain_size: self.domain_size, words: self.words.clone(), marker: PhantomData } @@ -1298,15 +1057,13 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> { // Get the position of the next set bit in the current word, // then clear the bit. let bit_pos = self.word.trailing_zeros() as usize; - let bit = 1 << bit_pos; - self.word ^= bit; + self.word ^= 1 << bit_pos; return Some(T::new(bit_pos + self.offset)); } // Move onto the next word. `wrapping_add()` is needed to handle // the degenerate initial value given to `offset` in `new()`. - let word = self.iter.next()?; - self.word = *word; + self.word = *self.iter.next()?; self.offset = self.offset.wrapping_add(WORD_BITS); } } @@ -1349,286 +1106,6 @@ where false } -const SPARSE_MAX: usize = 8; - -/// A fixed-size bitset type with a sparse representation and a maximum of -/// `SPARSE_MAX` elements. The elements are stored as a sorted `ArrayVec` with -/// no duplicates. -/// -/// This type is used by `HybridBitSet`; do not use directly. -#[derive(Clone, Debug)] -pub struct SparseBitSet<T> { - domain_size: usize, - elems: ArrayVec<T, SPARSE_MAX>, -} - -impl<T: Idx> SparseBitSet<T> { - fn new_empty(domain_size: usize) -> Self { - SparseBitSet { domain_size, elems: ArrayVec::new() } - } - - fn len(&self) -> usize { - self.elems.len() - } - - fn is_empty(&self) -> bool { - self.elems.len() == 0 - } - - fn contains(&self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - self.elems.contains(&elem) - } - - fn insert(&mut self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - let changed = if let Some(i) = self.elems.iter().position(|&e| e.index() >= elem.index()) { - if self.elems[i] == elem { - // `elem` is already in the set. - false - } else { - // `elem` is smaller than one or more existing elements. - self.elems.insert(i, elem); - true - } - } else { - // `elem` is larger than all existing elements. - self.elems.push(elem); - true - }; - assert!(self.len() <= SPARSE_MAX); - changed - } - - fn remove(&mut self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - if let Some(i) = self.elems.iter().position(|&e| e == elem) { - self.elems.remove(i); - true - } else { - false - } - } - - fn to_dense(&self) -> BitSet<T> { - let mut dense = BitSet::new_empty(self.domain_size); - for elem in self.elems.iter() { - dense.insert(*elem); - } - dense - } - - fn iter(&self) -> slice::Iter<'_, T> { - self.elems.iter() - } - - bit_relations_inherent_impls! {} -} - -impl<T: Idx + Ord> SparseBitSet<T> { - pub fn last_set_in(&self, range: impl RangeBounds<T>) -> Option<T> { - let mut last_leq = None; - for e in self.iter() { - if range.contains(e) { - last_leq = Some(*e); - } - } - last_leq - } -} - -/// A fixed-size bitset type with a hybrid representation: sparse when there -/// are up to a `SPARSE_MAX` elements in the set, but dense when there are more -/// than `SPARSE_MAX`. -/// -/// This type is especially efficient for sets that typically have a small -/// number of elements, but a large `domain_size`, and are cleared frequently. -/// -/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also -/// just be `usize`. -/// -/// All operations that involve an element will panic if the element is equal -/// to or greater than the domain size. All operations that involve two bitsets -/// will panic if the bitsets have differing domain sizes. -#[derive(Clone)] -pub enum HybridBitSet<T> { - Sparse(SparseBitSet<T>), - Dense(BitSet<T>), -} - -impl<T: Idx> fmt::Debug for HybridBitSet<T> { - fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Sparse(b) => b.fmt(w), - Self::Dense(b) => b.fmt(w), - } - } -} - -impl<T: Idx> HybridBitSet<T> { - pub fn new_empty(domain_size: usize) -> Self { - HybridBitSet::Sparse(SparseBitSet::new_empty(domain_size)) - } - - pub fn domain_size(&self) -> usize { - match self { - HybridBitSet::Sparse(sparse) => sparse.domain_size, - HybridBitSet::Dense(dense) => dense.domain_size, - } - } - - pub fn clear(&mut self) { - let domain_size = self.domain_size(); - *self = HybridBitSet::new_empty(domain_size); - } - - pub fn contains(&self, elem: T) -> bool { - match self { - HybridBitSet::Sparse(sparse) => sparse.contains(elem), - HybridBitSet::Dense(dense) => dense.contains(elem), - } - } - - pub fn superset(&self, other: &HybridBitSet<T>) -> bool { - match (self, other) { - (HybridBitSet::Dense(self_dense), HybridBitSet::Dense(other_dense)) => { - self_dense.superset(other_dense) - } - _ => { - assert!(self.domain_size() == other.domain_size()); - other.iter().all(|elem| self.contains(elem)) - } - } - } - - pub fn is_empty(&self) -> bool { - match self { - HybridBitSet::Sparse(sparse) => sparse.is_empty(), - HybridBitSet::Dense(dense) => dense.is_empty(), - } - } - - /// Returns the previous element present in the bitset from `elem`, - /// inclusively of elem. That is, will return `Some(elem)` if elem is in the - /// bitset. - pub fn last_set_in(&self, range: impl RangeBounds<T>) -> Option<T> - where - T: Ord, - { - match self { - HybridBitSet::Sparse(sparse) => sparse.last_set_in(range), - HybridBitSet::Dense(dense) => dense.last_set_in(range), - } - } - - pub fn insert(&mut self, elem: T) -> bool { - // No need to check `elem` against `self.domain_size` here because all - // the match cases check it, one way or another. - match self { - HybridBitSet::Sparse(sparse) if sparse.len() < SPARSE_MAX => { - // The set is sparse and has space for `elem`. - sparse.insert(elem) - } - HybridBitSet::Sparse(sparse) if sparse.contains(elem) => { - // The set is sparse and does not have space for `elem`, but - // that doesn't matter because `elem` is already present. - false - } - HybridBitSet::Sparse(sparse) => { - // The set is sparse and full. Convert to a dense set. - let mut dense = sparse.to_dense(); - let changed = dense.insert(elem); - assert!(changed); - *self = HybridBitSet::Dense(dense); - changed - } - HybridBitSet::Dense(dense) => dense.insert(elem), - } - } - - pub fn insert_range(&mut self, elems: impl RangeBounds<T>) { - // No need to check `elem` against `self.domain_size` here because all - // the match cases check it, one way or another. - let start = match elems.start_bound().cloned() { - Bound::Included(start) => start.index(), - Bound::Excluded(start) => start.index() + 1, - Bound::Unbounded => 0, - }; - let end = match elems.end_bound().cloned() { - Bound::Included(end) => end.index() + 1, - Bound::Excluded(end) => end.index(), - Bound::Unbounded => self.domain_size() - 1, - }; - let Some(len) = end.checked_sub(start) else { return }; - match self { - HybridBitSet::Sparse(sparse) if sparse.len() + len < SPARSE_MAX => { - // The set is sparse and has space for `elems`. - for elem in start..end { - sparse.insert(T::new(elem)); - } - } - HybridBitSet::Sparse(sparse) => { - // The set is sparse and full. Convert to a dense set. - let mut dense = sparse.to_dense(); - dense.insert_range(elems); - *self = HybridBitSet::Dense(dense); - } - HybridBitSet::Dense(dense) => dense.insert_range(elems), - } - } - - pub fn insert_all(&mut self) { - let domain_size = self.domain_size(); - match self { - HybridBitSet::Sparse(_) => { - *self = HybridBitSet::Dense(BitSet::new_filled(domain_size)); - } - HybridBitSet::Dense(dense) => dense.insert_all(), - } - } - - pub fn remove(&mut self, elem: T) -> bool { - // Note: we currently don't bother going from Dense back to Sparse. - match self { - HybridBitSet::Sparse(sparse) => sparse.remove(elem), - HybridBitSet::Dense(dense) => dense.remove(elem), - } - } - - /// Converts to a dense set, consuming itself in the process. - pub fn to_dense(self) -> BitSet<T> { - match self { - HybridBitSet::Sparse(sparse) => sparse.to_dense(), - HybridBitSet::Dense(dense) => dense, - } - } - - pub fn iter(&self) -> HybridIter<'_, T> { - match self { - HybridBitSet::Sparse(sparse) => HybridIter::Sparse(sparse.iter()), - HybridBitSet::Dense(dense) => HybridIter::Dense(dense.iter()), - } - } - - bit_relations_inherent_impls! {} -} - -pub enum HybridIter<'a, T: Idx> { - Sparse(slice::Iter<'a, T>), - Dense(BitIter<'a, T>), -} - -impl<'a, T: Idx> Iterator for HybridIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option<T> { - match self { - HybridIter::Sparse(sparse) => sparse.next().copied(), - HybridIter::Dense(dense) => dense.next(), - } - } -} - /// A resizable bitset type with a dense representation. /// /// `T` is an index type, typically a newtyped `usize` wrapper, but it can also @@ -1897,7 +1374,7 @@ impl<R: Idx, C: Idx> fmt::Debug for BitMatrix<R, C> { /// sparse representation. /// /// Initially, every row has no explicit representation. If any bit within a -/// row is set, the entire row is instantiated as `Some(<HybridBitSet>)`. +/// row is set, the entire row is instantiated as `Some(<ChunkedBitSet>)`. /// Furthermore, any previously uninstantiated rows prior to it will be /// instantiated as `None`. Those prior rows may themselves become fully /// instantiated later on if any of their bits are set. @@ -1911,7 +1388,7 @@ where C: Idx, { num_columns: usize, - rows: IndexVec<R, Option<HybridBitSet<C>>>, + rows: IndexVec<R, Option<ChunkedBitSet<C>>>, } impl<R: Idx, C: Idx> SparseBitMatrix<R, C> { @@ -1920,10 +1397,10 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> { Self { num_columns, rows: IndexVec::new() } } - fn ensure_row(&mut self, row: R) -> &mut HybridBitSet<C> { - // Instantiate any missing rows up to and including row `row` with an empty HybridBitSet. - // Then replace row `row` with a full HybridBitSet if necessary. - self.rows.get_or_insert_with(row, || HybridBitSet::new_empty(self.num_columns)) + fn ensure_row(&mut self, row: R) -> &mut ChunkedBitSet<C> { + // Instantiate any missing rows up to and including row `row` with an empty ChunkedBitSet. + // Then replace row `row` with a full ChunkedBitSet if necessary. + self.rows.get_or_insert_with(row, || ChunkedBitSet::new_empty(self.num_columns)) } /// Sets the cell at `(row, column)` to true. Put another way, insert @@ -1997,17 +1474,17 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> { self.row(row).into_iter().flat_map(|r| r.iter()) } - pub fn row(&self, row: R) -> Option<&HybridBitSet<C>> { + pub fn row(&self, row: R) -> Option<&ChunkedBitSet<C>> { self.rows.get(row)?.as_ref() } /// Intersects `row` with `set`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. /// /// Returns true if the row was changed. pub fn intersect_row<Set>(&mut self, row: R, set: &Set) -> bool where - HybridBitSet<C>: BitRelations<Set>, + ChunkedBitSet<C>: BitRelations<Set>, { match self.rows.get_mut(row) { Some(Some(row)) => row.intersect(set), @@ -2016,12 +1493,12 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> { } /// Subtracts `set` from `row`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. /// /// Returns true if the row was changed. pub fn subtract_row<Set>(&mut self, row: R, set: &Set) -> bool where - HybridBitSet<C>: BitRelations<Set>, + ChunkedBitSet<C>: BitRelations<Set>, { match self.rows.get_mut(row) { Some(Some(row)) => row.subtract(set), @@ -2030,12 +1507,12 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> { } /// Unions `row` with `set`. `set` can be either `BitSet` or - /// `HybridBitSet`. + /// `ChunkedBitSet`. /// /// Returns true if the row was changed. pub fn union_row<Set>(&mut self, row: R, set: &Set) -> bool where - HybridBitSet<C>: BitRelations<Set>, + ChunkedBitSet<C>: BitRelations<Set>, { self.ensure_row(row).union(set) } diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index 21e681d63f6..3f9198ce37f 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -76,96 +76,6 @@ fn union_two_sets() { } #[test] -fn hybrid_bitset() { - let mut sparse038: HybridBitSet<usize> = HybridBitSet::new_empty(256); - assert!(sparse038.is_empty()); - assert!(sparse038.insert(0)); - assert!(sparse038.insert(1)); - assert!(sparse038.insert(8)); - assert!(sparse038.insert(3)); - assert!(!sparse038.insert(3)); - assert!(sparse038.remove(1)); - assert!(!sparse038.is_empty()); - assert_eq!(sparse038.iter().collect::<Vec<_>>(), [0, 3, 8]); - - for i in 0..256 { - if i == 0 || i == 3 || i == 8 { - assert!(sparse038.contains(i)); - } else { - assert!(!sparse038.contains(i)); - } - } - - let mut sparse01358 = sparse038.clone(); - assert!(sparse01358.insert(1)); - assert!(sparse01358.insert(5)); - assert_eq!(sparse01358.iter().collect::<Vec<_>>(), [0, 1, 3, 5, 8]); - - let mut dense10 = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(dense10.insert(i)); - } - assert!(!dense10.is_empty()); - assert_eq!(dense10.iter().collect::<Vec<_>>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - - let mut dense256 = HybridBitSet::new_empty(256); - assert!(dense256.is_empty()); - dense256.insert_all(); - assert!(!dense256.is_empty()); - for i in 0..256 { - assert!(dense256.contains(i)); - } - - assert!(sparse038.superset(&sparse038)); // sparse + sparse (self) - assert!(sparse01358.superset(&sparse038)); // sparse + sparse - assert!(dense10.superset(&sparse038)); // dense + sparse - assert!(dense10.superset(&dense10)); // dense + dense (self) - assert!(dense256.superset(&dense10)); // dense + dense - - let mut hybrid = sparse038.clone(); - assert!(!sparse01358.union(&hybrid)); // no change - assert!(hybrid.union(&sparse01358)); - assert!(hybrid.superset(&sparse01358) && sparse01358.superset(&hybrid)); - assert!(!dense256.union(&dense10)); - - // dense / sparse where dense superset sparse - assert!(!dense10.clone().union(&sparse01358)); - assert!(sparse01358.clone().union(&dense10)); - assert!(dense10.clone().intersect(&sparse01358)); - assert!(!sparse01358.clone().intersect(&dense10)); - assert!(dense10.clone().subtract(&sparse01358)); - assert!(sparse01358.clone().subtract(&dense10)); - - // dense / sparse where sparse superset dense - let dense038 = sparse038.to_dense(); - assert!(!sparse01358.clone().union(&dense038)); - assert!(dense038.clone().union(&sparse01358)); - assert!(sparse01358.clone().intersect(&dense038)); - assert!(!dense038.clone().intersect(&sparse01358)); - assert!(sparse01358.clone().subtract(&dense038)); - assert!(dense038.clone().subtract(&sparse01358)); - - let mut dense = dense10.clone(); - assert!(dense.union(&dense256)); - assert!(dense.superset(&dense256) && dense256.superset(&dense)); - assert!(hybrid.union(&dense256)); - assert!(hybrid.superset(&dense256) && dense256.superset(&hybrid)); - - assert!(!dense10.clone().intersect(&dense256)); - assert!(dense256.clone().intersect(&dense10)); - assert!(dense10.clone().subtract(&dense256)); - assert!(dense256.clone().subtract(&dense10)); - - assert_eq!(dense256.iter().count(), 256); - let mut dense0 = dense256; - for i in 0..256 { - assert!(dense0.remove(i)); - } - assert!(!dense0.remove(0)); - assert!(dense0.is_empty()); -} - -#[test] fn chunked_bitset() { let mut b0 = ChunkedBitSet::<usize>::new_empty(0); let b0b = b0.clone(); @@ -593,15 +503,15 @@ fn sparse_matrix_operations() { matrix.insert(2, 99); matrix.insert(4, 0); - let mut disjoint: HybridBitSet<usize> = HybridBitSet::new_empty(100); + let mut disjoint: ChunkedBitSet<usize> = ChunkedBitSet::new_empty(100); disjoint.insert(33); - let mut superset = HybridBitSet::new_empty(100); + let mut superset = ChunkedBitSet::new_empty(100); superset.insert(22); superset.insert(75); superset.insert(33); - let mut subset = HybridBitSet::new_empty(100); + let mut subset = ChunkedBitSet::new_empty(100); subset.insert(22); // SparseBitMatrix::remove @@ -746,90 +656,6 @@ fn dense_last_set_before() { } } -/// Merge dense hybrid set into empty sparse hybrid set. -#[bench] -fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet<usize> = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let pre_sparse: HybridBitSet<usize> = HybridBitSet::new_empty(256); - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set with same indices. -#[bench] -fn union_hybrid_sparse_full_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet<usize> = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet<usize> = HybridBitSet::new_empty(256); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set with indices over the whole domain. -#[bench] -fn union_hybrid_sparse_domain_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX * 64); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX * 64); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i * 64)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into empty hybrid set where the domain is very small. -#[bench] -fn union_hybrid_sparse_empty_small_domain(b: &mut Bencher) { - let mut pre_dense: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_dense.insert(i)); - } - let pre_sparse: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX); - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set where the domain is very small. -#[bench] -fn union_hybrid_sparse_full_small_domain(b: &mut Bencher) { - let mut pre_dense: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet<usize> = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - #[bench] fn bench_insert(b: &mut Bencher) { let mut bs = BitSet::new_filled(99999usize); diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 1968ed34752..5fc9b679c8a 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, ErrorGuaranteed}; -use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin}; +use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; @@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } + fn next_region_infer(&self) -> ty::Region<'tcx> { + self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) + } + fn next_ty_infer(&self) -> Ty<'tcx> { self.next_ty_var(DUMMY_SP) } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 6af49accc84..e454a88e847 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -9,7 +9,7 @@ use rustc_data_structures::graph::implementation::{ use rustc_data_structures::intern::Interned; use rustc_data_structures::unord::UnordSet; use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::{ self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt, @@ -974,7 +974,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r)) + fold_regions(tcx, value, |r, _db| self.resolve_region(tcx, r)) } fn value(&self, rid: RegionVid) -> &VarValue<'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 555c1022a8a..544f941dda5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -33,7 +33,7 @@ use rustc_middle::traits::select; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{ - BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, + BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, }; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ @@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> { #[inline(always)] pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool { + debug_assert!(!self.next_trait_solver()); match self.typing_mode() { TypingMode::Analysis { defining_opaque_types } => { id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) } - TypingMode::Coherence | TypingMode::PostAnalysis => false, + // FIXME(#132279): This function is quite weird in post-analysis + // and post-borrowck analysis mode. We may need to modify its uses + // to support PostBorrowckAnalysis in the old solver as well. + TypingMode::Coherence + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => false, } } @@ -1165,7 +1171,7 @@ impl<'tcx> InferCtxt<'tcx> { } if value.has_infer_regions() { let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved")); - Ok(self.tcx.fold_regions(value, |re, _| { + Ok(fold_regions(self.tcx, value, |re, _| { if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } })) } else { @@ -1276,7 +1282,6 @@ impl<'tcx> InferCtxt<'tcx> { /// using canonicalization or carrying this inference context around. pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> { let typing_mode = match self.typing_mode() { - ty::TypingMode::Coherence => ty::TypingMode::Coherence, // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible // to handle them without proper canonicalization. This means we may cause cycle // errors and fail to reveal opaques while inside of bodies. We should rename this @@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> { ty::TypingMode::Analysis { defining_opaque_types: _ } => { TypingMode::non_body_analysis() } - ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis, + mode @ (ty::TypingMode::Coherence + | ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::PostAnalysis) => mode, }; ty::TypingEnv { typing_mode, param_env } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index a608ea1ad57..b64686afd23 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> { + debug_assert!(!self.next_trait_solver()); let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); @@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> { ); } } - ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"), + mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => { + bug!("insert hidden type in {mode:?}") + } } Ok(()) diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index ba1516655b0..51282b900ed 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -84,6 +84,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { self.collect_remaining_errors(infcx) } + fn has_pending_obligations(&self) -> bool; + fn pending_obligations(&self) -> PredicateObligations<'tcx>; /// Among all pending obligations, collect those are stalled on a inference variable which has diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2905fe688b5..06e27ed8060 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -830,7 +830,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); tcx.ensure().check_mod_unstable_api_usage(module); - tcx.ensure().check_mod_const_bodies(module); }); }, { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 6beae14100d..9384ed925c7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -712,7 +712,7 @@ fn test_unstable_options_tracking_hash() { untracked!(no_analysis, true); untracked!(no_leak_check, true); untracked!(no_parallel_backend, true); - untracked!(parse_only, true); + untracked!(parse_crate_root_only, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); @@ -771,6 +771,7 @@ fn test_unstable_options_tracking_hash() { tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); + tracked!(debug_info_type_line_numbers, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b584e7afd98..6caeec1b5cc 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -707,17 +707,7 @@ impl Cursor<'_> { self.bump(); self.bump(); self.eat_while(is_id_continue); - match self.first() { - '\'' => { - // Check if after skipping literal contents we've met a closing - // single quote (which means that user attempted to create a - // string with single quotes). - self.bump(); - let kind = Char { terminated: true }; - return Literal { kind, suffix_start: self.pos_within_token() }; - } - _ => return RawLifetime, - } + return RawLifetime; } // Either a lifetime or a character literal with diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fd7f2d8b2..40ffed48038 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -450,15 +450,15 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - .label = casting happend here + .label = casting happened here lint_invalid_reference_casting_bigger_layout = casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused - .label = casting happend here + .label = casting happened here .alloc = backing allocation comes from here .layout = casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes) lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - .label = casting happend here + .label = casting happened here lint_invalid_reference_casting_note_book = for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html> @@ -733,6 +733,9 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_reserved_multihash = reserved token in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 + lint_reserved_prefix = prefix `{$prefix}` is unknown .label = unknown prefix .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 @@ -772,6 +775,9 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type +lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal + .help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs` + lint_trailing_semi_macro = trailing semicolon in macro used in expression position .note1 = macro invocations at the end of a block are treated as expressions .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e130cfc1d73..ec085198922 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -586,7 +586,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) { + if cx.type_is_copy_modulo_regions(ty) { return; } if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7248b192763..44c7888a530 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -710,6 +710,10 @@ impl<'tcx> LateContext<'tcx> { TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } } + pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { + self.tcx.type_is_copy_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>> { diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 565c3c04252..a3731e31c2b 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -176,8 +176,12 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } .decorate_lint(diag); } - BuiltinLintDiag::ReservedString(suggestion) => { - lints::ReservedString { suggestion }.decorate_lint(diag); + BuiltinLintDiag::ReservedString { is_string, suggestion } => { + if is_string { + lints::ReservedString { suggestion }.decorate_lint(diag); + } else { + lints::ReservedMultihash { suggestion }.decorate_lint(diag); + } } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 8fe86738658..ce23892508b 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) { let arg_ty = cx.typeck_results().expr_ty(arg); - let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + let is_copy = cx.type_is_copy_modulo_regions(arg_ty); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let let_underscore_ignore_sugg = || { if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 0e874669043..2db229ed133 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -103,8 +103,11 @@ fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { } fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { - let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else { - return false; + let mut parents = tcx.hir().parent_iter(hir_id); + let stmt = match parents.next() { + Some((_, hir::Node::Stmt(stmt))) => stmt, + Some((_, hir::Node::Block(_) | hir::Node::Arm(_))) => return true, + _ => return false, }; let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false }; expr.hir_id == hir_id diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 38c38b59bc5..482650e04e8 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -17,8 +17,9 @@ use tracing::debug; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified, - TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag, + NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, + SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, + UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -242,17 +243,10 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> { } // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait. Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => { - if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() { - if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did()) - { - // NOTE: This path is currently unreachable as `Ty<'tcx>` is - // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>` - // is not actually allowed. - // - // I(@lcnr) still kept this branch in so we don't miss this - // if we ever change it in the future. - return Some(format!("{}<{}>", name, args[0])); - } + if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() + && let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did()) + { + return Some(format!("{}<{}>", name, args[0])); } } _ => (), @@ -657,3 +651,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => false, } } + +declare_tool_lint! { + /// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal + pub rustc::SYMBOL_INTERN_STRING_LITERAL, + // rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols; + // bootstrap will deny this manually + Allow, + "Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead", + report_in_external_macro: true +} + +declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]); + +impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) + && let ExprKind::Lit(kind) = arg.kind + && let rustc_ast::LitKind::Str(_, _) = kind.node + { + cx.emit_span_lint( + SYMBOL_INTERN_STRING_LITERAL, + kind.span, + SymbolInternStringLiteralDiag, + ); + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4cf5c7b4ff9..a99c94592b3 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(PassByValue)); store.register_lints(&SpanUseEqCtxt::lint_vec()); store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt)); + store.register_lints(&SymbolInternStringLiteral::lint_vec()); + store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index dce6010a2c1..e6eae7e7368 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -908,6 +908,11 @@ pub(crate) struct QueryUntracked { pub(crate) struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] +#[diag(lint_symbol_intern_string_literal)] +#[help] +pub(crate) struct SymbolInternStringLiteralDiag; + +#[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] pub(crate) struct TykindKind { #[suggestion(code = "ty", applicability = "maybe-incorrect")] @@ -3059,3 +3064,10 @@ pub(crate) struct ReservedString { #[suggestion(code = " ", applicability = "machine-applicable")] pub suggestion: Span, } + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_multihash)] +pub(crate) struct ReservedMultihash { + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e1a0e1ec579..b775cd37409 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1563,7 +1563,7 @@ impl UnusedImportBraces { } rename.unwrap_or(orig_ident).name } - ast::UseTreeKind::Glob => Symbol::intern("*"), + ast::UseTreeKind::Glob => sym::asterisk, ast::UseTreeKind::Nested { .. } => return, }; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3b406c7e161..d2b7ae620e2 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -179,7 +179,7 @@ declare_lint! { Warn, "applying forbid to lint-groups", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>", }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c74fceeedba..eb761bd6475 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -663,8 +663,11 @@ pub enum BuiltinLintDiag { ReservedPrefix(Span, String), /// `'r#` in edition < 2021. RawPrefix(Span), - /// `##` or `#"` is edition < 2024. - ReservedString(Span), + /// `##` or `#"` in edition < 2024. + ReservedString { + is_string: bool, + suggestion: Span, + }, TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 489c911d7ee..20859b167bc 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -552,7 +552,7 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, LLVMModuleRef M, const char *Path, const char *DwoPath, - LLVMRustFileType RustFileType) { + LLVMRustFileType RustFileType, bool VerifyIR) { llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR); auto FileType = fromRust(RustFileType); @@ -577,10 +577,10 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Failure; } auto DBOS = buffer_ostream(DOS); - unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR); PM->run(*unwrap(M)); } else { - unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR); PM->run(*unwrap(M)); } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index a18c6baec00..29dba2bca61 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -861,8 +861,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // First up we check for global allocators. Look at the crate graph here // and see what's a global allocator, including if we ourselves are a // global allocator. - let mut global_allocator = - self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + let this_crate = Symbol::intern("this crate"); + + let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate); for (_, data) in self.cstore.iter_crate_data() { if data.has_global_allocator() { match global_allocator { @@ -876,8 +878,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } } - let mut alloc_error_handler = - self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate")); + let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate); for (_, data) in self.cstore.iter_crate_data() { if data.has_alloc_error_handler() { match alloc_error_handler { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index ace46891f83..8bd2281981b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -54,9 +54,13 @@ pub fn walk_native_lib_search_dirs<R>( // The targets here should be in sync with `copy_third_party_objects` in bootstrap. // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind // and sanitizers to self-contained directory, and stop adding this search path. + // FIXME: On AIX this also has the side-effect of making the list of library search paths + // non-empty, which is needed or the linker may decide to record the LIBPATH env, if + // defined, as the search path instead of appending the default search paths. if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + || sess.target.is_like_aix || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { f(&sess.target_tlib_path.dir, false)?; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 56beff5aa64..f3f5af49412 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -872,6 +872,7 @@ impl MetadataBlob { let def_kind = root.tables.def_kind.get(blob, item).unwrap(); let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob); + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] let def_name = if item == CRATE_DEF_INDEX { rustc_span::symbol::kw::Crate } else { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dd149af5205..a34ea18f716 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1383,6 +1383,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); self.tables.def_kind.set_some(def_id.index, def_kind); + + // The `DefCollector` will sometimes create unnecessary `DefId`s + // for trivial const arguments which are directly lowered to + // `ConstArgKind::Path`. We never actually access this `DefId` + // anywhere so we don't need to encode it for other crates. + if def_kind == DefKind::AnonConst + && match tcx.hir_node_by_def_id(local_id) { + hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind { + // Skip encoding defs for these as they should not have had a `DefId` created + hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true, + hir::ConstArgKind::Anon(..) => false, + }, + _ => false, + } + { + continue; + } + if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4900575c36e..0c701c834f2 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -948,7 +948,6 @@ impl<'hir> Map<'hir> { Node::LetStmt(local) => local.span, Node::Crate(item) => item.spans.inner_span, Node::WherePredicate(pred) => pred.span, - Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::Synthetic => unreachable!(), Node::Err(span) => span, @@ -1226,7 +1225,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { } Node::Crate(..) => String::from("(root_crate)"), Node::WherePredicate(_) => node_str("where predicate"), - Node::ArrayLenInfer(_) => node_str("array len infer"), Node::Synthetic => unreachable!(), Node::Err(_) => node_str("error"), Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 33f9a2bdca6..b7410ca5f18 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -28,7 +28,6 @@ rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] #[orderable] - #[max = 0xFFFF_FFFF] #[debug_format = "CounterId({})"] pub struct CounterId {} } @@ -46,7 +45,6 @@ rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] #[orderable] - #[max = 0xFFFF_FFFF] #[debug_format = "ExpressionId({})"] pub struct ExpressionId {} } @@ -155,6 +153,22 @@ impl Debug for CoverageKind { } } +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct SourceRegion { + pub start_line: u32, + pub start_col: u32, + pub end_line: u32, + pub end_col: u32, +} + +impl Debug for SourceRegion { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + let &Self { start_line, start_col, end_line, end_col } = self; + write!(fmt, "{start_line}:{start_col} - {end_line}:{end_col}") + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum Op { @@ -216,7 +230,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub span: Span, + pub source_region: SourceRegion, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 08afa33c6b4..ad5d678178d 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -46,7 +46,7 @@ impl ErrorHandled { pub fn emit_note(&self, tcx: TyCtxt<'_>) { match self { &ErrorHandled::Reported(err, span) => { - if !err.is_tainted_by_errors && !span.is_dummy() { + if !err.allowed_in_infallible && !span.is_dummy() { tcx.dcx().emit_note(error::ErroneousConstant { span }); } } @@ -58,34 +58,26 @@ impl ErrorHandled { #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub struct ReportedErrorInfo { error: ErrorGuaranteed, - is_tainted_by_errors: bool, - /// Whether this is the kind of error that can sometimes occur, and sometimes not. - /// Used for resource exhaustion errors. - can_be_spurious: bool, + /// Whether this error is allowed to show up even in otherwise "infallible" promoteds. + /// This is for things like overflows during size computation or resource exhaustion. + allowed_in_infallible: bool, } impl ReportedErrorInfo { #[inline] - pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error } - } - #[inline] - pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error } + pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo { + ReportedErrorInfo { allowed_in_infallible: true, error } } - pub fn is_tainted_by_errors(&self) -> bool { - self.is_tainted_by_errors - } - pub fn can_be_spurious(&self) -> bool { - self.can_be_spurious + pub fn is_allowed_in_infallible(&self) -> bool { + self.allowed_in_infallible } } impl From<ErrorGuaranteed> for ReportedErrorInfo { #[inline] fn from(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error } + ReportedErrorInfo { allowed_in_infallible: false, error } } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 244d22d082f..161716610fe 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -111,6 +111,13 @@ impl<'tcx> MonoItem<'tcx> { return InstantiationMode::GloballyShared { may_conflict: false }; } + if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline + && self.is_generic_fn() + { + // Upgrade inline(never) to a globally shared instance. + return InstantiationMode::GloballyShared { may_conflict: true }; + } + // At this point we don't have explicit linkage and we're an // inlined function. If we're inlining into all CGUs then we'll // be creating a local copy per CGU. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ece468947c2..2bfcd0a6227 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -603,8 +603,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, span } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {span:?};")?; + for coverage::Mapping { kind, source_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 86abeb50382..80dfcbf2e69 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -8,7 +8,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::BitMatrix; +use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; @@ -17,6 +17,7 @@ use smallvec::SmallVec; use super::{ConstValue, SourceInfo}; use crate::mir; +use crate::ty::fold::fold_regions; use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt}; rustc_index::newtype_index! { @@ -315,7 +316,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { /// All regions of `ty` must be of kind `ReVar` and must represent /// universal regions *external* to the closure. pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { + let inner = fold_regions(tcx, ty, |r, depth| match r.kind() { ty::ReVar(vid) => { let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), @@ -334,7 +335,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { tcx: TyCtxt<'tcx>, mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx> { - tcx.fold_regions(self.inner, |r, depth| match r.kind() { + fold_regions(tcx, self.inner, |r, depth| match r.kind() { ty::ReBound(debruijn, br) => { debug_assert_eq!(debruijn, depth); map(ty::RegionVid::new(br.var.index())) @@ -358,12 +359,22 @@ pub struct DestructuredConstant<'tcx> { /// Used by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] pub struct CoverageIdsInfo { - /// Coverage codegen needs to know the highest counter ID that is ever + pub counters_seen: BitSet<mir::coverage::CounterId>, + pub expressions_seen: BitSet<mir::coverage::ExpressionId>, +} + +impl CoverageIdsInfo { + /// Coverage codegen needs to know how many coverage counters are ever /// incremented within a function, so that it can set the `num-counters` /// argument of the `llvm.instrprof.increment` intrinsic. /// /// This may be less than the highest counter ID emitted by the /// InstrumentCoverage MIR pass, if the highest-numbered counter increments /// were removed by MIR optimizations. - pub max_counter_id: mir::coverage::CounterId, + pub fn num_counters_after_mir_opts(&self) -> u32 { + // FIXME(Zalathar): Currently this treats an unused counter as "used" + // if its ID is less than that of the highest counter that really is + // used. Fixing this would require adding a renumbering step somewhere. + self.counters_seen.last_set_in(..).map_or(0, |max| max.as_u32() + 1) + } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f2a6d598a0..df110fdc20a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -958,11 +958,6 @@ rustc_queries! { desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } } - /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`). - query check_mod_const_bodies(key: LocalModDefId) { - desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) } - } - /// Checks the loops in the module. query check_mod_loops(key: LocalModDefId) { desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } @@ -1086,6 +1081,8 @@ rustc_queries! { } /// Computes the tag (if any) for a given type and variant. + /// `None` means that the variant doesn't need a tag (because it is niched). + /// Will panic for uninhabited variants. query tag_for_variant( key: (Ty<'tcx>, abi::VariantIdx) ) -> Option<ty::ScalarInt> { @@ -2311,10 +2308,13 @@ rustc_queries! { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } - query compare_impl_const( - key: (LocalDefId, DefId) - ) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) } + /// This takes the def-id of an associated item from a impl of a trait, + /// and checks its validity against the trait item it corresponds to. + /// + /// Any other def id will ICE. + query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } + ensure_forwards_result_if_red } query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d61ef7641ee..0a77c3bc42f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -204,6 +204,10 @@ pub enum ObligationCauseCode<'tcx> { /// list of the item. WhereClauseInExpr(DefId, Span, HirId, usize), + /// Like `WhereClauseinExpr`, but indexes into the `const_conditions` + /// rather than the `predicates_of`. + HostEffectInExpr(DefId, Span, HirId, usize), + /// A type like `&'a T` is WF only if `T: 'a`. ReferenceOutlivesReferent(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index d27205e26ab..31055276422 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,15 +2,11 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::{self as hir}; use rustc_macros::HashStable; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; -use tracing::{debug, instrument}; -use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt}; +use crate::mir::interpret::Scalar; +use crate::ty::{self, Ty, TyCtxt}; mod int; mod kind; @@ -181,82 +177,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> { } impl<'tcx> Const<'tcx> { - // FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg - /// Literals and const generic parameters are eagerly converted to a constant, everything else - /// becomes `Unevaluated`. - #[instrument(skip(tcx), level = "debug")] - pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self { - let body_id = match tcx.hir_node_by_def_id(def) { - hir::Node::AnonConst(ac) => ac.body, - node => span_bug!( - tcx.def_span(def.to_def_id()), - "from_anon_const can only process anonymous constants, not {node:?}" - ), - }; - - let expr = &tcx.hir().body(body_id).value; - debug!(?expr); - - let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - - match Self::try_from_lit(tcx, ty, expr) { - Some(v) => v, - None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { - def: def.to_def_id(), - args: GenericArgs::identity_for_item(tcx, def.to_def_id()), - }), - } - } - - #[instrument(skip(tcx), level = "debug")] - fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> { - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - - if let hir::ExprKind::Path(hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - )) = expr.kind - { - span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible"); - }; - - let lit_input = match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), - _ => None, - }, - _ => None, - }; - - if let Some(lit_input) = lit_input { - // If an error occurred, ignore that it's a literal and leave reporting the error up to - // mir. - match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return Some(c), - Err(_) if lit_input.ty.has_aliases() => { - // allow the `ty` to be an alias type, though we cannot handle it here - return None; - } - Err(e) => { - tcx.dcx().span_delayed_bug( - expr.span, - format!("Const::try_from_lit: couldn't lit_to_const {e:?}"), - ); - } - } - } - - None - } - /// Creates a constant with the given integer value and interns it. #[inline] pub fn from_bits( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2c867e6b8ca..3cbb2a3acf5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1955,8 +1955,6 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn local_crate_exports_generics(self) -> bool { - debug_assert!(self.sess.opts.share_generics()); - self.crate_types().iter().any(|crate_type| { match crate_type { CrateType::Executable diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 7adbd556141..1b073d3c466 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -2,9 +2,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; pub use rustc_type_ir::fold::{ - FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region, shift_vars, + FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, shift_region, + shift_vars, }; -use tracing::{debug, instrument}; use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt}; @@ -51,85 +51,6 @@ where } /////////////////////////////////////////////////////////////////////////// -// Region folder - -impl<'tcx> TyCtxt<'tcx> { - /// Folds the escaping and free regions in `value` using `f`. - pub fn fold_regions<T>( - self, - value: T, - mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, - ) -> T - where - T: TypeFoldable<TyCtxt<'tcx>>, - { - value.fold_with(&mut RegionFolder::new(self, &mut f)) - } -} - -/// Folds over the substructure of a type, visiting its component -/// types and all regions that occur *free* within it. -/// -/// That is, function pointer types and trait object can introduce -/// new bound regions which are not visited by this visitors as -/// they are not free; only regions that occur free will be -/// visited by `fld_r`. -pub struct RegionFolder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - - /// Stores the index of a binder *just outside* the stuff we have - /// visited. So this begins as INNERMOST; when we pass through a - /// binder, it is incremented (via `shift_in`). - current_index: ty::DebruijnIndex, - - /// Callback invokes for each free region. The `DebruijnIndex` - /// points to the binder *just outside* the ones we have passed - /// through. - fold_region_fn: - &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a), -} - -impl<'a, 'tcx> RegionFolder<'a, 'tcx> { - #[inline] - pub fn new( - tcx: TyCtxt<'tcx>, - fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, - ) -> RegionFolder<'a, 'tcx> { - RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn } - } -} - -impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - #[instrument(skip(self), level = "debug", ret)] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReBound(debruijn, _) if debruijn < self.current_index => { - debug!(?self.current_index, "skipped bound region"); - r - } - _ => { - debug!(?self.current_index, "folding free region"); - (self.fold_region_fn)(r, self.current_index) - } - } - } -} - -/////////////////////////////////////////////////////////////////////////// // Bound vars replacer /// A delegate used when instantiating bound vars. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 73fd8aa5b6c..3d4ce112a64 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -190,19 +190,23 @@ impl<'tcx> Instance<'tcx> { /// This method already takes into account the global `-Zshare-generics` /// setting, always returning `None` if `share-generics` is off. pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> { - // If we are not in share generics mode, we don't link to upstream - // monomorphizations but always instantiate our own internal versions - // instead. - if !tcx.sess.opts.share_generics() { - return None; - } - // If this is an item that is defined in the local crate, no upstream // crate can know about it/provide a monomorphization. if self.def_id().is_local() { return None; } + // If we are not in share generics mode, we don't link to upstream + // monomorphizations but always instantiate our own internal versions + // instead. + if !tcx.sess.opts.share_generics() + // However, if the def_id is marked inline(never), then it's fine to just reuse the + // upstream monomorphization. + && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr::InlineAttr::Never + { + return None; + } + // If this a non-generic instance, it cannot be a shared monomorphization. self.args.non_erasable_generics().next()?; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 55a7a837b6d..57054bd1a0b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -21,6 +21,7 @@ use tracing::{debug, instrument}; use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::Providers; +use crate::ty::fold::fold_regions; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, @@ -171,6 +172,24 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Checks whether `ty: Copy` holds while ignoring region constraints. + /// + /// This impacts whether values of `ty` are *moved* or *copied* + /// when referenced. This means that we may generate MIR which + /// does copies even when the type actually doesn't satisfy the + /// full requirements for the `Copy` trait (cc #29149) -- this + /// winds up being reported as an error during NLL borrow check. + /// + /// This function should not be used if there is an `InferCtxt` available. + /// Use `InferCtxt::type_is_copy_modulo_regions` instead. + pub fn type_is_copy_modulo_regions( + self, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + ty.is_trivially_pure_clone_copy() || self.is_copy_raw(typing_env.as_query_input(ty)) + } + /// Returns the deeply last field of nested structures, or the same type if /// not a structure at all. Corresponds to the only possible unsized field, /// and its type can be used to determine unsizing strategy. @@ -735,7 +754,7 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|decl| !decl.ignore_for_traits) .map(move |decl| { let mut vars = vec![]; - let ty = self.fold_regions(decl.ty, |re, debruijn| { + let ty = fold_regions(self, decl.ty, |re, debruijn| { assert_eq!(re, self.lifetimes.re_erased); let var = ty::BoundVar::from_usize(vars.len()); vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); @@ -1173,21 +1192,6 @@ impl<'tcx> Ty<'tcx> { .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } - /// Checks whether values of this type `T` are *moved* or *copied* - /// when referenced -- this amounts to a check for whether `T: - /// Copy`, but note that we **don't** consider lifetimes when - /// doing this check. This means that we may generate MIR which - /// does copies even when the type actually doesn't satisfy the - /// full requirements for the `Copy` trait (cc #29149) -- this - /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions( - self, - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - ) -> bool { - self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self)) - } - /// Checks whether values of this type `T` have a size known at /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored /// for the purposes of this check, so it can be an diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index acfb78b3f6e..df5b73ac1bd 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -14,6 +14,8 @@ use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, Typing pub enum CallDesugaringKind { /// for _ in x {} calls x.into_iter() ForLoopIntoIter, + /// for _ in x {} calls iter.next() + ForLoopNext, /// x? calls x.branch() QuestionBranch, /// x? calls type_of(x)::from_residual() @@ -28,6 +30,7 @@ impl CallDesugaringKind { pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId { match self { Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(), + Self::ForLoopNext => tcx.require_lang_item(LangItem::Iterator, None), Self::QuestionBranch | Self::TryBlockFromOutput => { tcx.require_lang_item(LangItem::Try, None) } @@ -121,6 +124,10 @@ pub fn call_kind<'tcx>( && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop) { Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0))) + } else if tcx.is_lang_item(method_did, LangItem::IteratorNext) + && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop) + { + Some((CallDesugaringKind::ForLoopNext, method_args.type_at(0))) } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) { if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) { Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0))) diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 0cab853196b..777ff9e68f0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty = expr.ty; if !ty.is_sized(tcx, this.typing_env()) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env())); + assert!(!tcx.type_is_copy_modulo_regions(this.typing_env(), ty)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f89e337781..c66af118453 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr }; let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> { - // We can use `ty::TypingEnv::fully_monomorphized()`` here + // We can use `ty::TypingEnv::fully_monomorphized()` here // as we only need it to compute the layout of a primitive. let range_val = Const::from_bits( this.tcx, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e55cd35e243..a13b00e1921 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -780,7 +780,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: return; }; - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env); + let is_binding_by_move = |ty: Ty<'tcx>| !cx.tcx.type_is_copy_modulo_regions(cx.typing_env, ty); let sess = cx.tcx.sess; diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index 11cf8c3e898..4a9bcdaddb3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -15,7 +15,6 @@ pub enum ResultsHandle<'a, 'tcx, A> where A: Analysis<'tcx>, { - Borrowed(&'a Results<'tcx, A>), BorrowedMut(&'a mut Results<'tcx, A>), Owned(Results<'tcx, A>), } @@ -28,7 +27,6 @@ where fn deref(&self) -> &Results<'tcx, A> { match self { - ResultsHandle::Borrowed(borrowed) => borrowed, ResultsHandle::BorrowedMut(borrowed) => borrowed, ResultsHandle::Owned(owned) => owned, } @@ -41,9 +39,6 @@ where { fn deref_mut(&mut self) -> &mut Results<'tcx, A> { match self { - ResultsHandle::Borrowed(_borrowed) => { - panic!("tried to deref_mut a `ResultsHandle::Borrowed") - } ResultsHandle::BorrowedMut(borrowed) => borrowed, ResultsHandle::Owned(owned) => owned, } diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs index c177d98106f..dc176ba2d03 100644 --- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -4,7 +4,7 @@ use std::fmt; use rustc_index::Idx; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use super::lattice::MaybeReachable; @@ -85,8 +85,8 @@ where let size = self.domain_size(); assert_eq!(size, old.domain_size()); - let mut set_in_self = HybridBitSet::new_empty(size); - let mut cleared_in_self = HybridBitSet::new_empty(size); + let mut set_in_self = ChunkedBitSet::new_empty(size); + let mut cleared_in_self = ChunkedBitSet::new_empty(size); for i in (0..size).map(T::new) { match (self.contains(i), old.contains(i)) { @@ -112,8 +112,8 @@ where let size = self.domain_size(); assert_eq!(size, old.domain_size()); - let mut set_in_self = HybridBitSet::new_empty(size); - let mut cleared_in_self = HybridBitSet::new_empty(size); + let mut set_in_self = ChunkedBitSet::new_empty(size); + let mut cleared_in_self = ChunkedBitSet::new_empty(size); for i in (0..size).map(T::new) { match (self.contains(i), old.contains(i)) { @@ -159,8 +159,8 @@ where } fn fmt_diff<T, C>( - inserted: &HybridBitSet<T>, - removed: &HybridBitSet<T>, + inserted: &ChunkedBitSet<T>, + removed: &ChunkedBitSet<T>, ctxt: &C, f: &mut fmt::Formatter<'_>, ) -> fmt::Result diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 6e4994af8b4..561229cf725 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -47,7 +47,7 @@ where { pub(crate) fn new( body: &'mir Body<'tcx>, - results: &'mir Results<'tcx, A>, + results: &'mir mut Results<'tcx, A>, style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 6d2a7a099a0..e2b56aedca3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -40,7 +40,7 @@ use std::iter; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{Idx, IndexVec}; use crate::framework::BitSetExt; @@ -227,20 +227,6 @@ impl<T, S: BitSetExt<T>> BitSetExt<T> for MaybeReachable<S> { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet<T>) { - match self { - MaybeReachable::Unreachable => {} - MaybeReachable::Reachable(set) => set.union(other), - } - } - - fn subtract(&mut self, other: &HybridBitSet<T>) { - match self { - MaybeReachable::Unreachable => {} - MaybeReachable::Reachable(set) => set.subtract(other), - } - } } impl<V: Clone> Clone for MaybeReachable<V> { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index bb652a75caa..b9407882ec5 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -35,7 +35,7 @@ use std::cmp::Ordering; use rustc_data_structures::work_queue::WorkQueue; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{Idx, IndexVec}; use rustc_middle::bug; use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal}; @@ -63,36 +63,18 @@ pub use self::visitor::{ResultsVisitor, visit_results}; /// operations needed by all of them. pub trait BitSetExt<T> { fn contains(&self, elem: T) -> bool; - fn union(&mut self, other: &HybridBitSet<T>); - fn subtract(&mut self, other: &HybridBitSet<T>); } impl<T: Idx> BitSetExt<T> for BitSet<T> { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet<T>) { - self.union(other); - } - - fn subtract(&mut self, other: &HybridBitSet<T>) { - self.subtract(other); - } } impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet<T>) { - self.union(other); - } - - fn subtract(&mut self, other: &HybridBitSet<T>) { - self.subtract(other); - } } /// A dataflow problem with an arbitrarily complex transfer function. @@ -299,10 +281,10 @@ pub trait Analysis<'tcx> { ); } - let results = Results { analysis: self, entry_sets }; + let mut results = Results { analysis: self, entry_sets }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let res = write_graphviz_results(tcx, body, &results, pass_name); + let res = write_graphviz_results(tcx, body, &mut results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 8493a7aa44b..c4321c454e6 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -37,18 +37,9 @@ impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { - /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`, - /// which is appropriate when the `Results` is used outside the cursor. + /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the + /// `Results` is also used outside the cursor. pub fn as_results_cursor<'mir>( - &'mir self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A> { - ResultsCursor::new(body, ResultsHandle::Borrowed(self)) - } - - /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`, - /// which is appropriate when the `Results` is used outside the cursor. - pub fn as_results_cursor_mut<'mir>( &'mir mut self, body: &'mir mir::Body<'tcx>, ) -> ResultsCursor<'mir, 'tcx, A> { @@ -95,7 +86,7 @@ where pub(super) fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, - results: &Results<'tcx, A>, + results: &mut Results<'tcx, A>, pass_name: Option<&'static str>, ) -> std::io::Result<()> where diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 9b9aeccf890..858752a3f01 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -680,7 +680,7 @@ fn locals_live_across_suspend_points<'tcx>( let mut requires_storage_results = MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) .iterate_to_fixpoint(tcx, body, None); - let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body); + let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 02fd289b6ef..e8b3d80be02 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,15 +13,16 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; -use rustc_span::Span; use rustc_span::def_id::LocalDefId; +use rustc_span::source_map::SourceMap; +use rustc_span::{BytePos, Pos, SourceFile, Span}; use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; @@ -96,7 +97,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: let coverage_counters = CoverageCounters::make_bcb_counters(&basic_coverage_blocks, &bcbs_with_counter_mappings); - let mappings = create_mappings(&extracted_mappings, &coverage_counters); + let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters); if mappings.is_empty() { // No spans could be converted into valid mappings, so skip this function. debug!("no spans could be converted into valid mappings; skipping"); @@ -135,12 +136,18 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: /// /// Precondition: All BCBs corresponding to those spans have been given /// coverage counters. -fn create_mappings( +fn create_mappings<'tcx>( + tcx: TyCtxt<'tcx>, + hir_info: &ExtractedHirInfo, extracted_mappings: &ExtractedMappings, coverage_counters: &CoverageCounters, ) -> Vec<Mapping> { + let source_map = tcx.sess.source_map(); + let file = source_map.lookup_source_file(hir_info.body_span.lo()); + let term_for_bcb = |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); + let region_for_span = |span: Span| make_source_region(source_map, hir_info, &file, span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -153,20 +160,22 @@ fn create_mappings( } = extracted_mappings; let mut mappings = Vec::new(); - mappings.extend(code_mappings.iter().map( + mappings.extend(code_mappings.iter().filter_map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { + let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Mapping { kind, span } + Some(Mapping { kind, source_region }) }, )); - mappings.extend(branch_pairs.iter().map( + mappings.extend(branch_pairs.iter().filter_map( |&mappings::BranchPair { span, true_bcb, false_bcb }| { let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - Mapping { kind, span } + let source_region = region_for_span(span)?; + Some(Mapping { kind, source_region }) }, )); @@ -174,7 +183,7 @@ fn create_mappings( |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); // MCDC branch mappings are appended with their decisions in case decisions were ignored. - mappings.extend(mcdc_degraded_branches.iter().map( + mappings.extend(mcdc_degraded_branches.iter().filter_map( |&mappings::MCDCBranch { span, true_bcb, @@ -183,9 +192,10 @@ fn create_mappings( true_index: _, false_index: _, }| { + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Mapping { kind: MappingKind::Branch { true_term, false_term }, span } + Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region }) }, )); @@ -193,7 +203,7 @@ fn create_mappings( let num_conditions = branches.len() as u16; let conditions = branches .into_iter() - .map( + .filter_map( |&mappings::MCDCBranch { span, true_bcb, @@ -202,29 +212,31 @@ fn create_mappings( true_index: _, false_index: _, }| { + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Mapping { + Some(Mapping { kind: MappingKind::MCDCBranch { true_term, false_term, mcdc_params: condition_info, }, - span, - } + source_region, + }) }, ) .collect::<Vec<_>>(); - if conditions.len() == num_conditions as usize { + if conditions.len() == num_conditions as usize + && let Some(source_region) = region_for_span(decision.span) + { // LLVM requires end index for counter mapping regions. let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, num_conditions, }); mappings.extend( - std::iter::once(Mapping { kind, span: decision.span }) - .chain(conditions.into_iter()), + std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()), ); } else { mappings.extend(conditions.into_iter().map(|mapping| { @@ -233,7 +245,10 @@ fn create_mappings( else { unreachable!("all mappings here are MCDCBranch as shown above"); }; - Mapping { kind: MappingKind::Branch { true_term, false_term }, span: mapping.span } + Mapping { + kind: MappingKind::Branch { true_term, false_term }, + source_region: mapping.source_region, + } })) } } @@ -376,6 +391,121 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } +fn ensure_non_empty_span( + source_map: &SourceMap, + hir_info: &ExtractedHirInfo, + span: Span, +) -> Option<Span> { + if !span.is_empty() { + return Some(span); + } + + let lo = span.lo(); + let hi = span.hi(); + + // The span is empty, so try to expand it to cover an adjacent '{' or '}', + // but only within the bounds of the body span. + let try_next = hi < hir_info.body_span.hi(); + let try_prev = hir_info.body_span.lo() < lo; + if !(try_next || try_prev) { + return None; + } + + source_map + .span_to_source(span, |src, start, end| try { + // We're only checking for specific ASCII characters, so we don't + // have to worry about multi-byte code points. + if try_next && src.as_bytes()[end] == b'{' { + Some(span.with_hi(hi + BytePos(1))) + } else if try_prev && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(lo - BytePos(1))) + } else { + None + } + }) + .ok()? +} + +/// Converts the span into its start line and column, and end line and column. +/// +/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by +/// the compiler, these column numbers are denoted in **bytes**, because that's what +/// LLVM's `llvm-cov` tool expects to see in coverage maps. +/// +/// Returns `None` if the conversion failed for some reason. This shouldn't happen, +/// but it's hard to rule out entirely (especially in the presence of complex macros +/// or other expansions), and if it does happen then skipping a span or function is +/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. +fn make_source_region( + source_map: &SourceMap, + hir_info: &ExtractedHirInfo, + file: &SourceFile, + span: Span, +) -> Option<SourceRegion> { + let span = ensure_non_empty_span(source_map, hir_info, span)?; + + let lo = span.lo(); + let hi = span.hi(); + + // Column numbers need to be in bytes, so we can't use the more convenient + // `SourceMap` methods for looking up file coordinates. + let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { + let rpos = file.relative_position(pos); + let line_index = file.lookup_line(rpos)?; + let line_start = file.lines()[line_index]; + // Line numbers and column numbers are 1-based, so add 1 to each. + Some((line_index + 1, (rpos - line_start).to_usize() + 1)) + }; + + let (mut start_line, start_col) = line_and_byte_column(lo)?; + let (mut end_line, end_col) = line_and_byte_column(hi)?; + + // Apply an offset so that code in doctests has correct line numbers. + // FIXME(#79417): Currently we have no way to offset doctest _columns_. + start_line = source_map.doctest_offset_line(&file.name, start_line); + end_line = source_map.doctest_offset_line(&file.name, end_line); + + check_source_region(SourceRegion { + start_line: start_line as u32, + start_col: start_col as u32, + end_line: end_line as u32, + end_col: end_col as u32, + }) +} + +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), +/// it will immediately exit with a fatal error. To prevent that from happening, +/// discard regions that are improperly ordered, or might be interpreted in a +/// way that makes them improperly ordered. +fn check_source_region(source_region: SourceRegion) -> Option<SourceRegion> { + let SourceRegion { start_line, start_col, end_line, end_col } = source_region; + + // Line/column coordinates are supposed to be 1-based. If we ever emit + // coordinates of 0, `llvm-cov` might misinterpret them. + let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); + // Coverage mappings use the high bit of `end_col` to indicate that a + // region is actually a "gap" region, so make sure it's unset. + let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; + // If a region is improperly ordered (end < start), `llvm-cov` will exit + // with a fatal error, which is inconvenient for users and hard to debug. + let is_ordered = (start_line, start_col) <= (end_line, end_col); + + if all_nonzero && end_col_has_high_bit_unset && is_ordered { + Some(source_region) + } else { + debug!( + ?source_region, + ?all_nonzero, + ?end_col_has_high_bit_unset, + ?is_ordered, + "Skipping source region that would be misinterpreted or rejected by LLVM" + ); + // If this happens in a debug build, ICE to make it easier to notice. + debug_assert!(false, "Improper source region: {source_region:?}"); + None + } +} + /// Function information extracted from HIR by the coverage instrumentor. #[derive(Debug)] struct ExtractedHirInfo { diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index df151f8cca3..0090f6f3040 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,6 +1,7 @@ use rustc_data_structures::captures::Captures; +use rustc_index::bit_set::BitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::coverage::{CovTerm, CoverageKind, MappingKind}; use rustc_middle::mir::{Body, CoverageIdsInfo, Statement, StatementKind}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::{self, TyCtxt}; @@ -86,15 +87,43 @@ fn coverage_ids_info<'tcx>( ) -> CoverageIdsInfo { let mir_body = tcx.instance_mir(instance_def); - let max_counter_id = all_coverage_in_mir_body(mir_body) - .filter_map(|kind| match *kind { - CoverageKind::CounterIncrement { id } => Some(id), - _ => None, - }) - .max() - .unwrap_or(CounterId::ZERO); + let Some(fn_cov_info) = mir_body.function_coverage_info.as_ref() else { + return CoverageIdsInfo { + counters_seen: BitSet::new_empty(0), + expressions_seen: BitSet::new_empty(0), + }; + }; + + let mut counters_seen = BitSet::new_empty(fn_cov_info.num_counters); + let mut expressions_seen = BitSet::new_filled(fn_cov_info.expressions.len()); + + // For each expression ID that is directly used by one or more mappings, + // mark it as not-yet-seen. This indicates that we expect to see a + // corresponding `ExpressionUsed` statement during MIR traversal. + for mapping in fn_cov_info.mappings.iter() { + // Currently we only worry about ordinary code mappings. + // For branch and MC/DC mappings, expressions might not correspond + // to any particular point in the control-flow graph. + // (Keep this in sync with the injection of `ExpressionUsed` + // statements in the `InstrumentCoverage` MIR pass.) + if let MappingKind::Code(CovTerm::Expression(id)) = mapping.kind { + expressions_seen.remove(id); + } + } + + for kind in all_coverage_in_mir_body(mir_body) { + match *kind { + CoverageKind::CounterIncrement { id } => { + counters_seen.insert(id); + } + CoverageKind::ExpressionUsed { id } => { + expressions_seen.insert(id); + } + _ => {} + } + } - CoverageIdsInfo { max_counter_id } + CoverageIdsInfo { counters_seen, expressions_seen } } fn all_coverage_in_mir_body<'a, 'tcx>( diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0878fa26a92..79c38b50459 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -220,15 +220,7 @@ impl<'tcx> Inliner<'tcx> { // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. - if !validate_types( - self.tcx, - MirPhase::Runtime(RuntimePhase::Optimized), - self.typing_env, - &callee_body, - &caller_body, - ) - .is_empty() - { + if !validate_types(self.tcx, self.typing_env, &callee_body, &caller_body).is_empty() { return Err("failed to validate callee body"); } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 779e7f22101..8a45ce0762d 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -292,7 +292,7 @@ fn run_passes_inner<'tcx>( } pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { - validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); + validate::Validator { when }.run_pass(tcx, body); } fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 51e5c49cea1..404fbb6b839 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -29,12 +29,6 @@ enum EdgeKind { pub(super) struct Validator { /// Describes at which point in the pipeline this validation is happening. pub when: String, - /// The phase for which we are upholding the dialect. If the given phase forbids a specific - /// element, this validator will now emit errors if that specific element is encountered. - /// Note that phases that change the dialect cause all *following* phases to check the - /// invariants of the new dialect. A phase that changes dialects never checks the new invariants - /// itself. - pub mir_phase: MirPhase, } impl<'tcx> crate::MirPass<'tcx> for Validator { @@ -46,11 +40,9 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) { return; } - debug_assert_eq!(self.mir_phase, body.phase); let def_id = body.source.def_id(); - let mir_phase = body.phase; let typing_env = body.typing_env(tcx); - let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) { + let can_unwind = if body.phase <= MirPhase::Runtime(RuntimePhase::Initial) { // In this case `AbortUnwindingCalls` haven't yet been executed. true } else if !tcx.def_kind(def_id).is_fn_like() { @@ -64,9 +56,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { ty::Coroutine(..) => ExternAbi::Rust, // No need to do MIR validation on error bodies ty::Error(_) => return, - _ => { - span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) - } + _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"), }; ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi) @@ -76,7 +66,6 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { when: &self.when, body, tcx, - mir_phase, unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), value_cache: FxHashSet::default(), @@ -86,7 +75,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { cfg_checker.check_cleanup_control_flow(); // Also run the TypeChecker. - for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) { + for (location, msg) in validate_types(tcx, typing_env, body, body) { cfg_checker.fail(location, msg); } @@ -107,7 +96,6 @@ struct CfgChecker<'a, 'tcx> { when: &'a str, body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - mir_phase: MirPhase, unwind_edge_count: usize, reachable_blocks: BitSet<BasicBlock>, value_cache: FxHashSet<u128>, @@ -294,7 +282,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match &statement.kind { StatementKind::AscribeUserType(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`AscribeUserType` should have been removed after drop lowering phase", @@ -302,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::FakeRead(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FakeRead` should have been removed after drop lowering phase", @@ -310,17 +298,17 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::SetDiscriminant { .. } => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } } StatementKind::Deinit(..) => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Deinit`is not allowed until deaggregation"); } } StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.mir_phase < + // FIXME(JakobDegen) The validator should check that `self.body.phase < // DropsLowered`. However, this causes ICEs with generation of drop shims, which // seem to fail to set their `MirPhase` correctly. if matches!(kind, RetagKind::TwoPhase) { @@ -328,7 +316,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::Coverage(kind) => { - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind { self.fail( @@ -391,7 +379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { // the return edge from the call. FIXME(tmiasko): Since this is a strictly code // generation concern, the code generation should be responsible for handling // it. - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized) + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) && self.is_critical_call_edge(target, unwind) { self.fail( @@ -440,7 +428,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`Yield` cannot appear outside coroutine bodies"); } - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Yield` should have been replaced by coroutine lowering"); } self.check_edge(location, *resume, EdgeKind::Normal); @@ -449,7 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } TerminatorKind::FalseEdge { real_target, imaginary_target } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FalseEdge` should have been removed after drop elaboration", @@ -459,7 +447,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_edge(location, *imaginary_target, EdgeKind::Normal); } TerminatorKind::FalseUnwind { real_target, unwind } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FalseUnwind` should have been removed after drop elaboration", @@ -478,7 +466,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies"); } - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`CoroutineDrop` should have been replaced by coroutine lowering", @@ -532,13 +520,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { /// `optimized_mir` is available. pub(super) fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, - mir_phase: MirPhase, typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, caller_body: &Body<'tcx>, ) -> Vec<(Location, String)> { - let mut type_checker = - TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() }; + let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() }; type_checker.visit_body(body); type_checker.failures } @@ -548,7 +534,6 @@ struct TypeChecker<'a, 'tcx> { caller_body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - mir_phase: MirPhase, failures: Vec<(Location, String)>, } @@ -577,7 +562,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // After borrowck subtyping should be fully explicit via // `Subtype` projections. - let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + let variance = if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { Variance::Invariant } else { Variance::Covariant @@ -618,13 +603,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed. if self.tcx.sess.opts.unstable_opts.validate_mir - && self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) + && self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { // `Operand::Copy` is only supposed to be used with `Copy` types. if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } @@ -642,7 +627,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) { match elem { ProjectionElem::OpaqueCast(ty) - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) => + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) => { self.fail( location, @@ -656,7 +641,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } ProjectionElem::Deref - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => + if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => { let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; @@ -856,7 +841,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // Set off any `bug!`s in the type computation code let _ = place.ty(&self.body.local_decls, self.tcx); - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) && place.projection.len() > 1 && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo) && place.projection[1..].contains(&ProjectionElem::Deref) @@ -974,7 +959,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } AggregateKind::RawPtr(pointee_ty, mutability) => { - if !matches!(self.mir_phase, MirPhase::Runtime(_)) { + if !matches!(self.body.phase, MirPhase::Runtime(_)) { // It would probably be fine to support this in earlier phases, but at the // time of writing it's only ever introduced from intrinsic lowering, so // earlier things just `bug!` on it. @@ -1016,7 +1001,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } }, Rvalue::Ref(_, BorrowKind::Fake(_), _) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`Assign` statement with a `Fake` borrow should have been removed in runtime MIR", @@ -1130,7 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } UnOp::PtrMetadata => { - if !matches!(self.mir_phase, MirPhase::Runtime(_)) { + if !matches!(self.body.phase, MirPhase::Runtime(_)) { // It would probably be fine to support this in earlier phases, but at // the time of writing it's only ever introduced from intrinsic // lowering or other runtime-phase optimization passes, so earlier @@ -1206,7 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { "CastKind::{kind:?} output must be a raw const pointer, not {:?}", ty::RawPtr(_, Mutability::Not) ); - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { self.fail(location, format!("After borrowck, MIR disallows {kind:?}")); } } @@ -1222,7 +1207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { "CastKind::{kind:?} output must be a raw pointer, not {:?}", ty::RawPtr(..) ); - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { self.fail(location, format!("After borrowck, MIR disallows {kind:?}")); } } @@ -1288,7 +1273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - if let MirPhase::Runtime(..) = self.mir_phase { + if let MirPhase::Runtime(..) = self.body.phase { // Unlike `mem::transmute`, a MIR `Transmute` is well-formed // for any two `Sized` types, just potentially UB to run. @@ -1317,7 +1302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location, format!( "Transmute is not supported in non-runtime phase {:?}.", - self.mir_phase + self.body.phase ), ); } @@ -1404,7 +1389,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::AscribeUserType(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`AscribeUserType` should have been removed after drop lowering phase", @@ -1412,7 +1397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::FakeRead(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FakeRead` should have been removed after drop lowering phase", @@ -1463,7 +1448,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::SetDiscriminant { place, .. } => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind(); @@ -1477,12 +1462,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::Deinit(..) => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Deinit`is not allowed until deaggregation"); } } StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.mir_phase < + // FIXME(JakobDegen) The validator should check that `self.body.phase < // DropsLowered`. However, this causes ICEs with generation of drop shims, which // seem to fail to set their `MirPhase` correctly. if matches!(kind, RetagKind::TwoPhase) { diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 6c881fd7e06..e18441ea7fc 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } +rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7240cfce0f7..7ea4ded2b05 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -208,8 +208,8 @@ where // available to downstream crates. This depends on whether we are in // share-generics mode and whether the current crate can even have // downstream crates. - let export_generics = - cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics(); + let can_export_generics = cx.tcx.local_crate_exports_generics(); + let always_export_generics = can_export_generics && cx.tcx.sess.opts.share_generics(); let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx); let cgu_name_cache = &mut UnordMap::default(); @@ -249,7 +249,8 @@ where cx.tcx, &mono_item, &mut can_be_internalized, - export_generics, + can_export_generics, + always_export_generics, ); if visibility == Visibility::Hidden && can_be_internalized { internalization_candidates.insert(mono_item); @@ -739,12 +740,19 @@ fn mono_item_linkage_and_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, - export_generics: bool, + can_export_generics: bool, + always_export_generics: bool, ) -> (Linkage, Visibility) { if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) { return (explicit_linkage, Visibility::Default); } - let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics); + let vis = mono_item_visibility( + tcx, + mono_item, + can_be_internalized, + can_export_generics, + always_export_generics, + ); (Linkage::External, vis) } @@ -767,7 +775,8 @@ fn mono_item_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, - export_generics: bool, + can_export_generics: bool, + always_export_generics: bool, ) -> Visibility { let instance = match mono_item { // This is pretty complicated; see below. @@ -826,7 +835,11 @@ fn mono_item_visibility<'tcx>( // Upstream `DefId` instances get different handling than local ones. let Some(def_id) = def_id.as_local() else { - return if export_generics && is_generic { + return if is_generic + && (always_export_generics + || (can_export_generics + && tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never)) + { // If it is an upstream monomorphization and we export generics, we must make // it available to downstream crates. *can_be_internalized = false; @@ -837,7 +850,10 @@ fn mono_item_visibility<'tcx>( }; if is_generic { - if export_generics { + if always_export_generics + || (can_export_generics + && tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never) + { if tcx.is_unreachable_local_definition(def_id) { // This instance cannot be used from another crate. Visibility::Hidden diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index adac35b57cd..198ccb000f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -339,7 +339,9 @@ where match self.typing_mode() { TypingMode::Coherence => {} - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => { self.discard_impls_shadowed_by_env(goal, &mut candidates); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 40d1576256e..70ceb22bfea 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -644,6 +644,12 @@ where } } + pub(super) fn next_region_var(&mut self) -> I::Region { + let region = self.delegate.next_region_infer(); + self.inspect.add_var_value(region); + region + } + pub(super) fn next_ty_infer(&mut self) -> I::Ty { let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 5c54656cc59..ebf1013db1e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -23,7 +23,7 @@ mod trait_goals; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; @@ -321,6 +321,19 @@ where Ok(ct) } } + + fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool { + match self.typing_mode() { + // Opaques are never rigid outside of analysis mode. + TypingMode::Coherence | TypingMode::PostAnalysis => false, + // During analysis, opaques are rigid unless they may be defined by + // the current body. + TypingMode::Analysis { defining_opaque_types: non_rigid_opaques } + | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => { + !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id)) + } + } + } } fn response_no_constraints_raw<I: Interner>( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 33bd1cf2f56..f5b1b23b8e9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -6,7 +6,7 @@ mod weak_types; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _}; +use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -71,21 +71,10 @@ where Ok(()) } ty::AliasTermKind::OpaqueTy => { - match self.typing_mode() { - // Opaques are never rigid outside of analysis mode. - TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution), - // During analysis, opaques are only rigid if we may not define it. - TypingMode::Analysis { defining_opaque_types } => { - if rigid_alias - .def_id - .as_local() - .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) - { - Err(NoSolution) - } else { - Ok(()) - } - } + if self.opaque_type_is_rigid(rigid_alias.def_id) { + Ok(()) + } else { + Err(NoSolution) } } // FIXME(generic_const_exprs): we would need to support generic consts here diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 336bcb9df33..26a8a22d77e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -2,6 +2,7 @@ //! behaves differently depending on the current `TypingMode`. use rustc_index::bit_set::GrowableBitSet; +use rustc_type_ir::fold::fold_regions; use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner, TypingMode}; @@ -95,6 +96,26 @@ where ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } + TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { + let Some(def_id) = opaque_ty.def_id.as_local() else { + return Err(NoSolution); + }; + + if !defined_opaque_types.contains(&def_id) { + return Err(NoSolution); + } + + let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); + // FIXME: Actually use a proper binder here instead of relying on `ReErased`. + // + // This is also probably unsound or sth :shrug: + let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() { + ty::ReErased => self.next_region_var(), + _ => re, + }); + self.eq(goal.param_env, expected, actual)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } TypingMode::PostAnalysis => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 096dc32ccc9..6641d2bf924 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -69,7 +69,9 @@ where // it's not a real impl. (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() { TypingMode::Coherence => Certainty::AMBIGUOUS, - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => return Err(NoSolution), }, // Impl matches polarity @@ -174,20 +176,7 @@ where // ideally we want to avoid, since we can make progress on this goal // via an alias bound or a locally-inferred hidden type instead. if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { - match ecx.typing_mode() { - TypingMode::Coherence | TypingMode::PostAnalysis => { - unreachable!("rigid opaque outside of analysis: {goal:?}"); - } - TypingMode::Analysis { defining_opaque_types } => { - if opaque_ty - .def_id - .as_local() - .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) - { - return Err(NoSolution); - } - } - } + debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id)); } ecx.probe_and_evaluate_goal_for_constituent_tys( diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 8c4f669c332..b9a325eddd8 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -716,6 +716,10 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow .label = the label .suggestion = add `:` after the label +parse_reserved_multihash = reserved multi-hash token is forbidden + .note = sequences of two or more # are reserved for future use since Rust 2024 + .suggestion_whitespace = consider inserting whitespace here + parse_reserved_string = invalid string literal .note = unprefixed guarded string literals are reserved for future use since Rust 2024 .suggestion_whitespace = consider inserting whitespace here diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9bdb99dc000..2579e4c1f25 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ @@ -2152,6 +2153,15 @@ pub(crate) enum UnknownPrefixSugg { } #[derive(Diagnostic)] +#[diag(parse_reserved_multihash)] +#[note] +pub(crate) struct ReservedMultihash { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: Option<GuardedStringSugg>, +} +#[derive(Diagnostic)] #[diag(parse_reserved_string)] #[note] pub(crate) struct ReservedString { @@ -2611,8 +2621,9 @@ pub(crate) enum InvalidMutInPattern { #[diag(parse_repeated_mut_in_pattern)] pub(crate) struct RepeatedMutInPattern { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] pub span: Span, + #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] @@ -2676,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern { /// Was a `RangePatternBound` expected? pub is_bound: bool, /// The unexpected expr's precedence (used in match arm guard suggestions). - pub expr_precedence: i8, + pub expr_precedence: ExprPrecedence, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 8db3b174a89..d97f05dc7eb 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -300,6 +300,26 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let prefix_span = self.mk_sp(start, ident_start); if prefix_span.at_least_rust_2021() { + // If the raw lifetime is followed by \' then treat it a normal + // lifetime followed by a \', which is to interpret it as a character + // literal. In this case, it's always an invalid character literal + // since the literal must necessarily have >3 characters (r#...) inside + // of it, which is invalid. + if self.cursor.as_str().starts_with('\'') { + let lit_span = self.mk_sp(start, self.pos + BytePos(1)); + let contents = self.str_from_to(start + BytePos(1), self.pos); + emit_unescape_error( + self.dcx(), + contents, + lit_span, + lit_span, + Mode::Char, + 0..contents.len(), + EscapeError::MoreThanOneChar, + ) + .expect("expected error"); + } + let span = self.mk_sp(start, self.pos); let lifetime_name_without_tick = @@ -371,8 +391,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::Unknown - | rustc_lexer::TokenKind::InvalidIdent => { + rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { // Don't emit diagnostics for sequences of the same invalid token if swallow_next_invalid > 0 { swallow_next_invalid -= 1; @@ -816,7 +835,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let mut cursor = Cursor::new(str_before); - let (span, unterminated) = match cursor.guarded_double_quoted_string() { + let (is_string, span, unterminated) = match cursor.guarded_double_quoted_string() { Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => { let end = start + BytePos(token_len); let span = self.mk_sp(start, end); @@ -829,13 +848,13 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let unterminated = if terminated { None } else { Some(str_start) }; - (span, unterminated) + (true, span, unterminated) } - _ => { + None => { // We should only get here in the `##+` case. debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##"); - (span, None) + (false, span, None) } }; if edition2024 { @@ -857,7 +876,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> { }; // In Edition 2024 and later, emit a hard error. - let err = self.dcx().emit_err(errors::ReservedString { span, sugg }); + let err = if is_string { + self.dcx().emit_err(errors::ReservedString { span, sugg }) + } else { + self.dcx().emit_err(errors::ReservedMultihash { span, sugg }) + }; token::Literal(token::Lit { kind: token::Err(err), @@ -870,7 +893,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::ReservedString(space_span), + BuiltinLintDiag::ReservedString { is_string, suggestion: space_span }, ); // For backwards compatibility, roll back to after just the first `#` diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a1fe5508970..34131e3af6e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1990,7 +1990,6 @@ impl<'a> Parser<'a> { /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`. pub(super) fn recover_incorrect_await_syntax( &mut self, - lo: Span, await_sp: Span, ) -> PResult<'a, P<Expr>> { let (hi, expr, is_question) = if self.token == token::Not { @@ -1999,8 +1998,8 @@ impl<'a> Parser<'a> { } else { self.recover_await_prefix(await_sp)? }; - let (sp, guar) = self.error_on_incorrect_await(lo, hi, &expr, is_question); - let expr = self.mk_expr_err(lo.to(sp), guar); + let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, &expr, is_question); + let expr = self.mk_expr_err(await_sp.to(sp), guar); self.maybe_recover_from_bad_qpath(expr) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index aa5e9586daf..8d16d44b0a2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,7 +1,7 @@ // ignore-tidy-filelength use core::mem; -use core::ops::ControlFlow; +use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; use ast::token::IdentIsRaw; @@ -10,7 +10,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::util::classify; -use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, @@ -120,7 +120,7 @@ impl<'a> Parser<'a> { r: Restrictions, attrs: AttrWrapper, ) -> PResult<'a, (P<Expr>, bool)> { - self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) + self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { /// followed by a subexpression (e.g. `1 + 2`). pub(super) fn parse_expr_assoc_with( &mut self, - min_prec: usize, + min_prec: Bound<ExprPrecedence>, attrs: AttrWrapper, ) -> PResult<'a, (P<Expr>, bool)> { let lhs = if self.token.is_range_separator() { @@ -144,7 +144,7 @@ impl<'a> Parser<'a> { /// was actually parsed. pub(super) fn parse_expr_assoc_rest_with( &mut self, - min_prec: usize, + min_prec: Bound<ExprPrecedence>, starts_stmt: bool, mut lhs: P<Expr>, ) -> PResult<'a, (P<Expr>, bool)> { @@ -163,7 +163,11 @@ impl<'a> Parser<'a> { self.restrictions }; let prec = op.node.precedence(); - if prec < min_prec { + if match min_prec { + Bound::Included(min_prec) => prec < min_prec, + Bound::Excluded(min_prec) => prec <= min_prec, + Bound::Unbounded => false, + } { break; } // Check for deprecated `...` syntax @@ -276,16 +280,16 @@ impl<'a> Parser<'a> { } let fixity = op.fixity(); - let prec_adjustment = match fixity { - Fixity::Right => 0, - Fixity::Left => 1, + let min_prec = match fixity { + Fixity::Right => Bound::Included(prec), + Fixity::Left => Bound::Excluded(prec), // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. - Fixity::None => 1, + Fixity::None => Bound::Excluded(prec), }; let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(prec + prec_adjustment, attrs) + this.parse_expr_assoc_with(min_prec, attrs) })?; let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); @@ -451,7 +455,7 @@ impl<'a> Parser<'a> { /// The other two variants are handled in `parse_prefix_range_expr` below. fn parse_expr_range( &mut self, - prec: usize, + prec: ExprPrecedence, lhs: P<Expr>, op: AssocOp, cur_op_span: Span, @@ -460,7 +464,7 @@ impl<'a> Parser<'a> { let maybe_lt = self.token.clone(); let attrs = self.parse_outer_attributes()?; Some( - self.parse_expr_assoc_with(prec + 1, attrs) + self.parse_expr_assoc_with(Bound::Excluded(prec), attrs) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))? .0, ) @@ -518,7 +522,7 @@ impl<'a> Parser<'a> { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) + this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs) .map(|(x, _)| (lo.to(x.span), Some(x))) .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { @@ -1446,34 +1450,31 @@ impl<'a> Parser<'a> { this.parse_expr_closure() } else { assert!(this.eat_keyword(kw::For)); - this.parse_expr_for(None, this.prev_token.span) + this.parse_expr_for(None, lo) } } else if this.eat_keyword(kw::While) { - this.parse_expr_while(None, this.prev_token.span) + this.parse_expr_while(None, lo) } else if let Some(label) = this.eat_label() { this.parse_expr_labeled(label, true) } else if this.eat_keyword(kw::Loop) { - let sp = this.prev_token.span; - this.parse_expr_loop(None, this.prev_token.span).map_err(|mut err| { - err.span_label(sp, "while parsing this `loop` expression"); + this.parse_expr_loop(None, lo).map_err(|mut err| { + err.span_label(lo, "while parsing this `loop` expression"); err }) } else if this.eat_keyword(kw::Match) { - let match_sp = this.prev_token.span; this.parse_expr_match().map_err(|mut err| { - err.span_label(match_sp, "while parsing this `match` expression"); + err.span_label(lo, "while parsing this `match` expression"); err }) } else if this.eat_keyword(kw::Unsafe) { - let sp = this.prev_token.span; this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err( |mut err| { - err.span_label(sp, "while parsing this `unsafe` expression"); + err.span_label(lo, "while parsing this `unsafe` expression"); err }, ) } else if this.check_inline_const(0) { - this.parse_const_block(lo.to(this.token.span), false) + this.parse_const_block(lo, false) } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { @@ -1514,7 +1515,7 @@ impl<'a> Parser<'a> { this.parse_expr_closure() } } else if this.eat_keyword_noexpect(kw::Await) { - this.recover_incorrect_await_syntax(lo, this.prev_token.span) + this.recover_incorrect_await_syntax(lo) } else { this.parse_expr_lit() } @@ -2646,7 +2647,8 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let (expr, _) = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; + let (expr, _) = + self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ed8d152d2d..37556c064d8 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> { AttrArgs::Delimited(args) } else if self.eat(&token::Eq) { let eq_span = self.prev_token.span; - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?)) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) } } else { AttrArgs::Empty }) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 004b5b34813..e08b925f008 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,12 +1,13 @@ +use std::ops::Bound; + use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, - Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, - StmtKind, + self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability, + Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind, }; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey}; @@ -435,8 +436,9 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - let Ok((expr, _)) = - snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) + let Ok((expr, _)) = snapshot + .parse_expr_assoc_rest_with(Bound::Unbounded, false, expr) + .map_err(|err| err.cancel()) else { // We got a trailing method/operator, but that wasn't an expression. return None; @@ -545,10 +547,7 @@ impl<'a> Parser<'a> { // HACK: a neater way would be preferable. let expr = match &err.args["expr_precedence"] { DiagArgValue::Number(expr_precedence) => { - if *expr_precedence - <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence() - as i32 - { + if *expr_precedence <= ExprPrecedence::Compare as i32 { format!("({expr})") } else { format!("{expr}") @@ -570,9 +569,7 @@ impl<'a> Parser<'a> { } Some(guard) => { // Are parentheses required around the old guard? - let wrap_guard = guard.precedence() - <= AssocOp::from_ast_binop(BinOpKind::And).precedence() - as i8; + let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd; err.subdiagnostic( UnexpectedExpressionInPatternSugg::UpdateGuard { @@ -1089,7 +1086,9 @@ impl<'a> Parser<'a> { return; } - self.dcx().emit_err(RepeatedMutInPattern { span: lo.to(self.prev_token.span) }); + let span = lo.to(self.prev_token.span); + let suggestion = span.with_hi(self.token.span.lo()); + self.dcx().emit_err(RepeatedMutInPattern { span, suggestion }); } /// Parse macro invocation diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 190cd9ed061..5fa2e01fc86 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::mem; +use std::ops::Bound; use ast::Label; use rustc_ast as ast; @@ -207,7 +208,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens` closure, since our // outer attributes do not apply to this part of the expression. let (expr, _) = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc_rest_with(0, true, expr) + this.parse_expr_assoc_rest_with(Bound::Unbounded, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -240,7 +241,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let (e, _) = self.parse_expr_assoc_rest_with(0, false, e)?; + let (e, _) = self.parse_expr_assoc_rest_with(Bound::Unbounded, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c561ea3823d..8cff23c2e32 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -9,7 +9,7 @@ use rustc_ast::{ }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span}; use thin_vec::{ThinVec, thin_vec}; use super::{Parser, PathStyle, SeqSep, TokenType, Trailing}; @@ -274,7 +274,6 @@ impl<'a> Parser<'a> { // Function pointer type self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)? } else if self.check_keyword(kw::For) { - let for_span = self.token.span; // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` @@ -302,7 +301,7 @@ impl<'a> Parser<'a> { kw: kw.name.as_str(), sugg: errors::TransposeDynOrImplSugg { removal_span, - insertion_span: for_span.shrink_to_lo(), + insertion_span: lo.shrink_to_lo(), kw: kw.name.as_str(), }, }); @@ -345,16 +344,14 @@ impl<'a> Parser<'a> { // FIXME(c_variadic): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? // NOTE: This may regress certain MBE calls if done incorrectly. - let guar = self - .dcx() - .emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); + let guar = self.dcx().emit_err(NestedCVariadicType { span: lo }); TyKind::Err(guar) } } } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); - let mut err = self.dcx().struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected type"); + let mut err = self.dcx().struct_span_err(lo, msg); + err.span_label(lo, "expected type"); return Err(err); }; @@ -943,7 +940,7 @@ impl<'a> Parser<'a> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Async) { - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else if self.may_recover() && self.token.uninterpolated_span().is_rust_2015() @@ -954,7 +951,7 @@ impl<'a> Parser<'a> { span: self.prev_token.span, help: HelpUseLatestEdition::new(), }); - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else { BoundAsyncness::Normal @@ -1139,7 +1136,7 @@ impl<'a> Parser<'a> { Some(ast::Path { span: fn_token_span.to(self.prev_token.span), segments: thin_vec![ast::PathSegment { - ident: Ident::new(Symbol::intern("Fn"), fn_token_span), + ident: Ident::new(sym::Fn, fn_token_span), id: DUMMY_NODE_ID, args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs { span: args_lo.to(self.prev_token.span), diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index f3174e7dea2..aab3f10bc66 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -43,7 +43,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } _ => { - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { Ok(_) => {} @@ -70,7 +70,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; MetaItemKind::List(nmis) } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { if let ast::ExprKind::Lit(token_lit) = expr.kind { let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span); let res = match res { @@ -116,7 +116,9 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met return Err(err); } } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => MetaItemKind::NameValue(lit.clone()), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + MetaItemKind::NameValue(lit.clone()) + } }, }) } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 0712af422ad..7a0a518bb51 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -709,8 +709,6 @@ passes_should_be_applied_to_trait = attribute should be applied to a trait .label = not a trait -passes_skipping_const_checks = skipping const checks - passes_stability_promotable = attribute cannot be applied to an expression diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs deleted file mode 100644 index f5ece513956..00000000000 --- a/compiler/rustc_passes/src/check_const.rs +++ /dev/null @@ -1,236 +0,0 @@ -//! This pass checks HIR bodies that may be evaluated at compile-time (e.g., `const`, `static`, -//! `const fn`) for structured control flow (e.g. `if`, `while`), which is forbidden in a const -//! context. -//! -//! By the time the MIR const-checker runs, these high-level constructs have been lowered to -//! control-flow primitives (e.g., `Goto`, `SwitchInt`), making it tough to properly attribute -//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips -//! through, but errors for structured control flow in a `const` should be emitted here. - -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_middle::hir::nested_filter; -use rustc_middle::query::Providers; -use rustc_middle::span_bug; -use rustc_middle::ty::TyCtxt; -use rustc_session::parse::feature_err; -use rustc_span::{Span, Symbol, sym}; -use {rustc_attr as attr, rustc_hir as hir}; - -use crate::errors::SkippingConstChecks; - -/// An expression that is not *always* legal in a const context. -#[derive(Clone, Copy)] -enum NonConstExpr { - Loop(hir::LoopSource), - Match(hir::MatchSource), -} - -impl NonConstExpr { - fn name(self) -> String { - match self { - Self::Loop(src) => format!("`{}`", src.name()), - Self::Match(src) => format!("`{}`", src.name()), - } - } - - fn required_feature_gates(self) -> Option<&'static [Symbol]> { - use hir::LoopSource::*; - use hir::MatchSource::*; - - let gates: &[_] = match self { - Self::Match(AwaitDesugar) => { - return None; - } - - Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for], - - Self::Match(TryDesugar(_)) => &[sym::const_try], - - // All other expressions are allowed. - Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[], - }; - - Some(gates) - } -} - -fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - let mut vis = CheckConstVisitor::new(tcx); - tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis); -} - -pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_const_bodies, ..*providers }; -} - -#[derive(Copy, Clone)] -struct CheckConstVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - const_kind: Option<hir::ConstContext>, - def_id: Option<LocalDefId>, -} - -impl<'tcx> CheckConstVisitor<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Self { - CheckConstVisitor { tcx, const_kind: None, def_id: None } - } - - /// Emits an error when an unsupported expression is found in a const context. - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn const_check_violated(&self, expr: NonConstExpr, span: Span) { - let Self { tcx, def_id, const_kind } = *self; - - let features = tcx.features(); - let required_gates = expr.required_feature_gates(); - - let is_feature_allowed = |feature_gate| { - // All features require that the corresponding gate be enabled, - // even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`. - if !tcx.features().enabled(feature_gate) { - return false; - } - - // If `def_id` is `None`, we don't need to consider stability attributes. - let def_id = match def_id { - Some(x) => x, - None => return true, - }; - - // If the function belongs to a trait, then it must enable the const_trait_impl - // feature to use that trait function (with a const default body). - if tcx.trait_of_item(def_id.to_def_id()).is_some() { - return true; - } - - // If this crate is not using stability attributes, or this function is not claiming to be a - // stable `const fn`, that is all that is required. - if !tcx.features().staged_api() || tcx.has_attr(def_id, sym::rustc_const_unstable) { - return true; - } - - // However, we cannot allow stable `const fn`s to use unstable features without an explicit - // opt-in via `rustc_allow_const_fn_unstable`. - let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id)); - attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate) - }; - - match required_gates { - // Don't emit an error if the user has enabled the requisite feature gates. - Some(gates) if gates.iter().copied().all(is_feature_allowed) => return, - - // `-Zunleash-the-miri-inside-of-you` only works for expressions that don't have a - // corresponding feature gate. This encourages nightly users to use feature gates when - // possible. - None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => { - tcx.dcx().emit_warn(SkippingConstChecks { span }); - return; - } - - _ => {} - } - - let const_kind = - const_kind.expect("`const_check_violated` may only be called inside a const context"); - - let required_gates = required_gates.unwrap_or(&[]); - let missing_gates: Vec<_> = - required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect(); - - match missing_gates.as_slice() { - [] => { - span_bug!( - span, - "we should not have reached this point, since `.await` is denied earlier" - ); - } - - [missing_primary, ref missing_secondary @ ..] => { - let msg = - format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); - let mut err = feature_err(&tcx.sess, *missing_primary, span, msg); - - // If multiple feature gates would be required to enable this expression, include - // them as help messages. Don't emit a separate error for each missing feature gate. - // - // FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This - // is a pretty narrow case, however. - tcx.disabled_nightly_features( - &mut err, - def_id.map(|id| tcx.local_def_id_to_hir_id(id)), - missing_secondary.into_iter().map(|gate| (String::new(), *gate)), - ); - - err.emit(); - } - } - } - - /// Saves the parent `const_kind` before calling `f` and restores it afterwards. - fn recurse_into( - &mut self, - kind: Option<hir::ConstContext>, - def_id: Option<LocalDefId>, - f: impl FnOnce(&mut Self), - ) { - let parent_def_id = self.def_id; - let parent_kind = self.const_kind; - self.def_id = def_id; - self.const_kind = kind; - f(self); - self.def_id = parent_def_id; - self.const_kind = parent_kind; - } -} - -impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { - let kind = Some(hir::ConstContext::Const { inline: false }); - self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); - } - - fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) { - let kind = Some(hir::ConstContext::Const { inline: true }); - self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block)); - } - - fn visit_body(&mut self, body: &hir::Body<'tcx>) { - let owner = self.tcx.hir().body_owner_def_id(body.id()); - let kind = self.tcx.hir().body_const_context(owner); - self.recurse_into(kind, Some(owner), |this| intravisit::walk_body(this, body)); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - match &e.kind { - // Skip the following checks if we are not currently in a const context. - _ if self.const_kind.is_none() => {} - - hir::ExprKind::Loop(_, _, source, _) => { - self.const_check_violated(NonConstExpr::Loop(*source), e.span); - } - - hir::ExprKind::Match(_, _, source) => { - let non_const_expr = match source { - // These are handled by `ExprKind::Loop` above. - hir::MatchSource::ForLoopDesugar => None, - - _ => Some(NonConstExpr::Match(*source)), - }; - - if let Some(expr) = non_const_expr { - self.const_check_violated(expr, e.span); - } - } - - _ => {} - } - - intravisit::walk_expr(self, e); - } -} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index fbf25cb476a..fdc7e1bba2f 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1670,13 +1670,6 @@ pub(crate) struct ProcMacroBadSig { pub kind: ProcMacroKind, } -#[derive(Diagnostic)] -#[diag(passes_skipping_const_checks)] -pub(crate) struct SkippingConstChecks { - #[primary_span] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_unreachable_due_to_uninhabited)] pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> { diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 8f53b71319d..1aa077ad2bb 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -19,7 +19,6 @@ use rustc_middle::query::Providers; pub mod abi_test; mod check_attr; -mod check_const; pub mod dead; mod debugger_visualizer; mod diagnostic_items; @@ -43,7 +42,6 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { check_attr::provide(providers); - check_const::provide(providers); dead::provide(providers); debugger_visualizer::provide(providers); diagnostic_items::provide(providers); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 7536869e2fe..66492842581 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -12,23 +12,16 @@ use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{Symbol, kw, sym}; use tracing::debug; -use crate::{ImplTraitContext, InvocationParent, PendingAnonConstInfo, Resolver}; +use crate::{ImplTraitContext, InvocationParent, Resolver}; pub(crate) fn collect_definitions( resolver: &mut Resolver<'_, '_>, fragment: &AstFragment, expansion: LocalExpnId, ) { - let InvocationParent { parent_def, pending_anon_const_info, impl_trait_context, in_attr } = + let InvocationParent { parent_def, impl_trait_context, in_attr } = resolver.invocation_parents[&expansion]; - let mut visitor = DefCollector { - resolver, - parent_def, - pending_anon_const_info, - expansion, - impl_trait_context, - in_attr, - }; + let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr }; fragment.visit_with(&mut visitor); } @@ -36,13 +29,6 @@ pub(crate) fn collect_definitions( struct DefCollector<'a, 'ra, 'tcx> { resolver: &'a mut Resolver<'ra, 'tcx>, parent_def: LocalDefId, - /// If we have an anon const that consists of a macro invocation, e.g. `Foo<{ m!() }>`, - /// we need to wait until we know what the macro expands to before we create the def for - /// the anon const. That's because we lower some anon consts into `hir::ConstArgKind::Path`, - /// which don't have defs. - /// - /// See `Self::visit_anon_const()`. - pending_anon_const_info: Option<PendingAnonConstInfo>, impl_trait_context: ImplTraitContext, in_attr: bool, expansion: LocalExpnId, @@ -110,61 +96,13 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { fn visit_macro_invoc(&mut self, id: NodeId) { let id = id.placeholder_to_expn_id(); - let pending_anon_const_info = self.pending_anon_const_info.take(); let old_parent = self.resolver.invocation_parents.insert(id, InvocationParent { parent_def: self.parent_def, - pending_anon_const_info, impl_trait_context: self.impl_trait_context, in_attr: self.in_attr, }); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } - - /// Determines whether the const argument `AnonConst` is a simple macro call, optionally - /// surrounded with braces. - /// - /// If this const argument *is* a trivial macro call then the id for the macro call is - /// returned along with the information required to build the anon const's def if - /// the macro call expands to a non-trivial expression. - fn is_const_arg_trivial_macro_expansion( - &self, - anon_const: &'a AnonConst, - ) -> Option<(PendingAnonConstInfo, NodeId)> { - anon_const.value.optionally_braced_mac_call(false).map(|(block_was_stripped, id)| { - ( - PendingAnonConstInfo { - id: anon_const.id, - span: anon_const.value.span, - block_was_stripped, - }, - id, - ) - }) - } - - /// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes - /// surrounded with braces if a set of braces has not already been entered. This is required - /// as `{ N }` is treated as equivalent to a bare parameter `N` whereas `{{ N }}` is treated as - /// a real block expression and is lowered to an anonymous constant which is not allowed to use - /// generic parameters. - /// - /// If this expression is a trivial macro call then the id for the macro call is - /// returned along with the information required to build the anon const's def if - /// the macro call expands to a non-trivial expression. - fn is_const_arg_sub_expr_trivial_macro_expansion( - &self, - const_arg_sub_expr: &'a Expr, - ) -> Option<(PendingAnonConstInfo, NodeId)> { - let pending_anon = self.pending_anon_const_info.unwrap_or_else(|| - panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"), - ); - - const_arg_sub_expr.optionally_braced_mac_call(pending_anon.block_was_stripped).map( - |(block_was_stripped, id)| { - (PendingAnonConstInfo { block_was_stripped, ..pending_anon }, id) - }, - ) - } } impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { @@ -376,78 +314,34 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - // HACK(min_generic_const_args): don't create defs for anon consts if we think they will - // later be turned into ConstArgKind::Path's. because this is before resolve is done, we - // may accidentally identify a construction of a unit struct as a param and not create a - // def. we'll then create a def later in ast lowering in this case. the parent of nested - // items will be messed up, but that's ok because there can't be any if we're just looking - // for bare idents. - - if let Some((pending_anon, macro_invoc)) = - self.is_const_arg_trivial_macro_expansion(constant) - { - self.pending_anon_const_info = Some(pending_anon); - return self.visit_macro_invoc(macro_invoc); - } else if constant.value.is_potential_trivial_const_arg(true) { - return visit::walk_anon_const(self, constant); - } - - let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + let parent = + self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); + self.with_parent(parent, |this| visit::walk_anon_const(this, constant)); } fn visit_expr(&mut self, expr: &'a Expr) { - // If we're visiting the expression of a const argument that was a macro call then - // check if it is *still* unknown whether it is a trivial const arg or not. If so - // recurse into the macro call and delay creating the anon const def until expansion. - if self.pending_anon_const_info.is_some() - && let Some((pending_anon, macro_invoc)) = - self.is_const_arg_sub_expr_trivial_macro_expansion(expr) - { - self.pending_anon_const_info = Some(pending_anon); - return self.visit_macro_invoc(macro_invoc); - } - - // See self.pending_anon_const_info for explanation - let parent_def = self - .pending_anon_const_info - .take() - // If we already stripped away a set of braces then do not do it again when determining - // if the macro expanded to a trivial const arg. This arises in cases such as: - // `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a - // trivial const argument even though `{ N }` by itself *is*. - .filter(|pending_anon| { - !expr.is_potential_trivial_const_arg(!pending_anon.block_was_stripped) - }) - .map(|pending_anon| { - self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span) - }) - .unwrap_or(self.parent_def); - - self.with_parent(parent_def, |this| { - let parent_def = match expr.kind { - ExprKind::MacCall(..) => return this.visit_macro_invoc(expr.id), - ExprKind::Closure(..) | ExprKind::Gen(..) => { - this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) - } - ExprKind::ConstBlock(ref constant) => { - for attr in &expr.attrs { - visit::walk_attribute(this, attr); - } - let def = this.create_def( - constant.id, - kw::Empty, - DefKind::InlineConst, - constant.value.span, - ); - this.with_parent(def, |this| visit::walk_anon_const(this, constant)); - return; + let parent_def = match expr.kind { + ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), + ExprKind::Closure(..) | ExprKind::Gen(..) => { + self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) + } + ExprKind::ConstBlock(ref constant) => { + for attr in &expr.attrs { + visit::walk_attribute(self, attr); } - _ => this.parent_def, - }; + let def = self.create_def( + constant.id, + kw::Empty, + DefKind::InlineConst, + constant.value.span, + ); + self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + return; + } + _ => self.parent_def, + }; - this.with_parent(parent_def, |this| visit::walk_expr(this, expr)) - }) + self.with_parent(parent_def, |this| visit::walk_expr(this, expr)) } fn visit_ty(&mut self, ty: &'a Ty) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 60815ffdb1b..fc92dc8b4ed 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4521,7 +4521,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_anon_const_manual( - constant.value.is_potential_trivial_const_arg(true), + constant.value.is_potential_trivial_const_arg(), anon_const_kind, |this| this.resolve_expr(&constant.value, None), ) @@ -4685,7 +4685,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // that is how they will be later lowered to HIR. if const_args.contains(&idx) { self.resolve_anon_const_manual( - argument.is_potential_trivial_const_arg(true), + argument.is_potential_trivial_const_arg(), AnonConstKind::ConstArg(IsRepeatExpr::No), |this| this.resolve_expr(argument, None), ); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 663c3ac0045..09f3e848766 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3113,6 +3113,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] let existing_name = match &in_scope_lifetimes[..] { [] => Symbol::intern("'a"), [(existing, _)] => existing.name, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e382295b8f6..ca4adce37ce 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -174,7 +174,6 @@ impl<'ra> ParentScope<'ra> { #[derive(Copy, Debug, Clone)] struct InvocationParent { parent_def: LocalDefId, - pending_anon_const_info: Option<PendingAnonConstInfo>, impl_trait_context: ImplTraitContext, in_attr: bool, } @@ -182,24 +181,12 @@ struct InvocationParent { impl InvocationParent { const ROOT: Self = Self { parent_def: CRATE_DEF_ID, - pending_anon_const_info: None, impl_trait_context: ImplTraitContext::Existential, in_attr: false, }; } #[derive(Copy, Debug, Clone)] -struct PendingAnonConstInfo { - // A const arg is only a "trivial" const arg if it has at *most* one set of braces - // around the argument. We track whether we have stripped an outter brace so that - // if a macro expands to a braced expression *and* the macro was itself inside of - // some braces then we can consider it to be a non-trivial const argument. - block_was_stripped: bool, - id: NodeId, - span: Span, -} - -#[derive(Copy, Debug, Clone)] enum ImplTraitContext { Existential, Universal, @@ -2270,7 +2257,7 @@ fn module_to_string(module: Module<'_>) -> Option<String> { collect_mod(names, parent); } } else { - names.push(Symbol::intern("<opaque>")); + names.push(sym::opaque_module_name_placeholder); collect_mod(names, module.parent.unwrap()); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 02e255d7726..65128ceb866 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -220,9 +220,9 @@ pub fn attrs_to_doc_fragments<'a>( fn span_for_value(attr: &ast::Attribute) -> Span { if let ast::AttrKind::Normal(normal) = &attr.kind - && let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args + && let ast::AttrArgs::Eq { value, .. } = &normal.item.args { - meta.span.with_ctxt(attr.span.ctxt()) + value.span().with_ctxt(attr.span.ctxt()) } else { attr.span } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0124397ea46..cb6d539cdf9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1208,7 +1208,7 @@ impl Options { /// Returns `true` if there will be an output file generated. pub fn will_create_output_file(&self) -> bool { - !self.unstable_opts.parse_only && // The file is just being parsed + !self.unstable_opts.parse_crate_root_only && // The file is just being parsed self.unstable_opts.ls.is_empty() // The file is just being queried } @@ -1864,7 +1864,7 @@ fn parse_output_types( matches: &getopts::Matches, ) -> OutputTypes { let mut output_types = BTreeMap::new(); - if !unstable_opts.parse_only { + if !unstable_opts.parse_crate_root_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { let (shorthand, path) = split_out_file_name(output_type); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a2d75917c82..9e95e278325 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1702,6 +1702,8 @@ options! { "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), + debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], + "emit type and line information for additional data types (default: no)"), debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], "compress debug info sections (none, zlib, zstd, default: none)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], @@ -1937,8 +1939,9 @@ options! { "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], "panic strategy for panics in drops"), - parse_only: bool = (false, parse_bool, [UNTRACKED], - "parse only; do not compile, assemble, or link (default: no)"), + parse_crate_root_only: bool = (false, parse_bool, [UNTRACKED], + "parse the crate root file only; do not parse other files, compile, assemble, or link \ + (default: no)"), patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED], "nop padding at function entry"), plt: Option<bool> = (None, parse_opt_bool, [TRACKED], @@ -2036,7 +2039,7 @@ written to standard error output)"), shell_argfiles: bool = (false, parse_bool, [UNTRACKED], "allow argument files to be specified with POSIX \"shell-style\" argument quoting"), show_span: Option<String> = (None, parse_opt_string, [TRACKED], - "show spans for compiler debugging (expr|pat|ty)"), + "show spans in the crate root file, for compiler debugging (expr|pat|ty)"), simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \ to rust's source base directory. only meant for testing purposes"), diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 357d746c184..2b2ba50d3fb 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -87,7 +87,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol { } } - Symbol::intern("rust_out") + sym::rust_out } pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f585410adb9..120ae9946ea 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1358,6 +1358,12 @@ pub struct EarlyDiagCtxt { dcx: DiagCtxt, } +impl Default for EarlyDiagCtxt { + fn default() -> Self { + Self::new(ErrorOutputType::default()) + } +} + impl EarlyDiagCtxt { pub fn new(output: ErrorOutputType) -> Self { let emitter = mk_emitter(output); diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index a9ca5dbe509..a5826137181 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -26,6 +26,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; +use std::collections::hash_set::Entry as SetEntry; use std::fmt; use std::hash::Hash; @@ -1270,7 +1271,7 @@ pub struct HygieneDecodeContext { inner: Lock<HygieneDecodeContextInner>, /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal<RefCell<FxHashMap<u32, ()>>>, + local_in_progress: WorkerLocal<RefCell<FxHashSet<u32>>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1364,14 +1365,14 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext match inner.decoding.entry(raw_id) { Entry::Occupied(ctxt_entry) => { match context.local_in_progress.borrow_mut().entry(raw_id) { - Entry::Occupied(..) => { + SetEntry::Occupied(..) => { // We're decoding this already on the current thread. Return here // and let the function higher up the stack finish decoding to handle // recursive cases. return *ctxt_entry.get(); } - Entry::Vacant(entry) => { - entry.insert(()); + SetEntry::Vacant(entry) => { + entry.insert(); // Some other thread is current decoding this. Race with it. *ctxt_entry.get() @@ -1380,7 +1381,7 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext } Entry::Vacant(entry) => { // We are the first thread to start decoding. Mark the current thread as being progress. - context.local_in_progress.borrow_mut().insert(raw_id, ()); + context.local_in_progress.borrow_mut().insert(raw_id); // Allocate and store SyntaxContext id *before* calling the decoder function, // as the SyntaxContextData may reference itself. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1481e1cbd91..57c645bfaba 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -22,6 +22,7 @@ #![feature(array_windows)] #![feature(cfg_match)] #![feature(core_io_borrowed_buf)] +#![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5252c446e1d..47ceab750cf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -182,6 +182,7 @@ symbols! { ConstParamTy_, Context, Continue, + ControlFlow, Copy, Cow, Debug, @@ -297,6 +298,7 @@ symbols! { Return, Right, Rust, + RustaceansAreAwesome, RustcDecodable, RustcEncodable, RwLock, @@ -315,6 +317,7 @@ symbols! { StructuralPartialEq, SubdiagMessage, Subdiagnostic, + SymbolIntern, Sync, SyncUnsafeCell, T, @@ -376,6 +379,7 @@ symbols! { adt_const_params, advanced_slice_patterns, adx_target_feature, + aes, aggregate_raw_ptr, alias, align, @@ -392,6 +396,7 @@ symbols! { allow_fail, allow_internal_unsafe, allow_internal_unstable, + altivec, alu32, always, and, @@ -438,6 +443,7 @@ symbols! { associated_types, assume, assume_init, + asterisk: "*", async_await, async_call, async_call_mut, @@ -466,6 +472,7 @@ symbols! { async_for_loop, async_iterator, async_iterator_poll_next, + async_trait_bounds, atomic, atomic_mod, atomics, @@ -518,6 +525,7 @@ symbols! { btreeset_iter, builtin_syntax, c, + c_dash_variadic, c_str, c_str_literals, c_unwind, @@ -648,6 +656,7 @@ symbols! { const_trait_bound_opt_out, const_trait_impl, const_try, + const_ty_placeholder: "<const_ty>", constant, constructor, convert_identity, @@ -777,6 +786,7 @@ symbols! { drop_types_in_const, dropck_eyepatch, dropck_parametricity, + dummy_cgu_name, dylib, dyn_compatible_for_dispatch, dyn_metadata, @@ -920,6 +930,7 @@ symbols! { fmuladdf32, fmuladdf64, fn_align, + fn_body, fn_delegation, fn_must_use, fn_mut, @@ -960,6 +971,7 @@ symbols! { fs_create_dir, fsub_algebraic, fsub_fast, + fsxr, full, fundamental, fused_iterator, @@ -1383,6 +1395,7 @@ symbols! { on, on_unimplemented, opaque, + opaque_module_name_placeholder: "<opaque>", open_options_new, ops, opt_out_copy, @@ -1611,6 +1624,7 @@ symbols! { repr_simd, repr_transparent, require, + reserve_x18: "reserve-x18", residual, result, result_ffi_guarantees, @@ -1651,6 +1665,7 @@ symbols! { rust_eh_catch_typeinfo, rust_eh_personality, rust_logo, + rust_out, rustc, rustc_abi, rustc_allocator, @@ -1773,6 +1788,8 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + sha2, + sha3, sha512_sm_x86, shadow_call_stack, shallow, @@ -1841,6 +1858,7 @@ symbols! { simd_reduce_mul_unordered, simd_reduce_or, simd_reduce_xor, + simd_relaxed_fma, simd_rem, simd_round, simd_saturating_add, @@ -1886,6 +1904,7 @@ symbols! { sreg, sreg_low16, sse, + sse2, sse4a_target_feature, stable, staged_api, @@ -2153,6 +2172,7 @@ symbols! { volatile_store, vreg, vreg_low16, + vsx, vtable_align, vtable_size, warn, @@ -2172,6 +2192,7 @@ symbols! { wrapping_sub, wreg, write_bytes, + write_fmt, write_macro, write_str, write_via_move, @@ -2401,6 +2422,7 @@ impl Symbol { } /// Maps a string to its interned representation. + #[rustc_diagnostic_item = "SymbolIntern"] pub fn intern(string: &str) -> Self { with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index b82d327a409..cdccb3e5d72 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexSet; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; @@ -71,18 +71,26 @@ impl AArch64InlineAsmRegClass { } } -pub(crate) fn target_reserves_x18(target: &Target) -> bool { - target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows +pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet<Symbol>) -> bool { + // See isX18ReservedByDefault in LLVM for targets reserve x18 by default: + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/TargetParser/AArch64TargetParser.cpp#L102-L105 + // Note that +reserve-x18 is currently not set for the above targets. + target.os == "android" + || target.os == "fuchsia" + || target.env == "ohos" + || target.is_like_osx + || target.is_like_windows + || target_features.contains(&sym::reserve_x18) } fn reserved_x18( _arch: InlineAsmArch, _reloc_model: RelocModel, - _target_features: &FxIndexSet<Symbol>, + target_features: &FxIndexSet<Symbol>, target: &Target, _is_clobber: bool, ) -> Result<(), &'static str> { - if target_reserves_x18(target) { + if target_reserves_x18(target, target_features) { Err("x18 is a reserved register on this target") } else { Ok(()) diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs index 276f376b297..55d393c81d3 100644 --- a/compiler/rustc_target/src/asm/avr.rs +++ b/compiler/rustc_target/src/asm/avr.rs @@ -105,7 +105,12 @@ def_regs! { #error = ["SP", "SPL", "SPH"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r0", "r1", "r1r0"] => - "r0 and r1 are not available due to an issue in LLVM", + "LLVM reserves r0 (scratch register) and r1 (zero register)", + // If this changes within LLVM, the compiler might use the registers + // in the future. This must be reflected in the set of clobbered + // registers, else the clobber ABI implementation is *unsound*, as + // this generates invalid code (register is not marked as clobbered + // but may change the register content). } } diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs index f7e726c3376..aa14ca3f337 100644 --- a/compiler/rustc_target/src/asm/hexagon.rs +++ b/compiler/rustc_target/src/asm/hexagon.rs @@ -7,6 +7,7 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; def_reg_class! { Hexagon HexagonInlineAsmRegClass { reg, + preg, } } @@ -37,6 +38,7 @@ impl HexagonInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option<Symbol>)] { match self { Self::reg => types! { _: I8, I16, I32, F32; }, + Self::preg => &[], } } } @@ -71,6 +73,10 @@ def_regs! { r26: reg = ["r26"], r27: reg = ["r27"], r28: reg = ["r28"], + p0: preg = ["p0"], + p1: preg = ["p1"], + p2: preg = ["p2"], + p3: preg = ["p3"], #error = ["r19"] => "r19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r29", "sp"] => diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index b1c01d27cad..b4ea6fc592a 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -38,7 +38,7 @@ impl LoongArchInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option<Symbol>)] { match self { Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, - Self::freg => types! { _: F32, F64; }, + Self::freg => types! { f: F32; d: F64; }, } } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index db8d23776e5..204d5d53361 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -928,7 +928,9 @@ pub enum InlineAsmClobberAbi { AArch64, AArch64NoX18, Arm64EC, + Avr, RiscV, + RiscVE, LoongArch, PowerPC, S390x, @@ -941,6 +943,7 @@ impl InlineAsmClobberAbi { pub fn parse( arch: InlineAsmArch, target: &Target, + target_features: &FxIndexSet<Symbol>, name: Symbol, ) -> Result<Self, &'static [&'static str]> { let name = name.as_str(); @@ -963,11 +966,13 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) { - InlineAsmClobberAbi::AArch64NoX18 - } else { - InlineAsmClobberAbi::AArch64 - }), + "C" | "system" | "efiapi" => { + Ok(if aarch64::target_reserves_x18(target, target_features) { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::Arm64EC => match name { @@ -975,9 +980,17 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), + "C" | "system" | "efiapi" => Ok(if riscv::is_e(target_features) { + InlineAsmClobberAbi::RiscVE + } else { + InlineAsmClobberAbi::RiscV + }), _ => Err(&["C", "system", "efiapi"]), }, + InlineAsmArch::Avr => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::Avr), + _ => Err(&["C", "system"]), + }, InlineAsmArch::LoongArch64 => match name { "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), _ => Err(&["C", "system"]), @@ -1125,6 +1138,23 @@ impl InlineAsmClobberAbi { d24, d25, d26, d27, d28, d29, d30, d31, } }, + InlineAsmClobberAbi::Avr => clobbered_regs! { + Avr AvrInlineAsmReg { + // The list of "Call-Used Registers" according to + // https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers + + // Clobbered registers available in inline assembly + r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r30, r31, + // As per the AVR-GCC-ABI documentation linked above, the R0 + // register is a clobbered register as well. Since we don't + // allow the usage of R0 in inline assembly, nothing has to + // be done here. + // Likewise, the T-flag in the SREG should be clobbered, but + // this is not necessary to be listed here, since the SREG + // is considered clobbered anyways unless `preserve_flags` + // is used. + } + }, InlineAsmClobberAbi::RiscV => clobbered_regs! { RiscV RiscVInlineAsmReg { // ra @@ -1148,6 +1178,31 @@ impl InlineAsmClobberAbi { v24, v25, v26, v27, v28, v29, v30, v31, } }, + InlineAsmClobberAbi::RiscVE => clobbered_regs! { + RiscV RiscVInlineAsmReg { + // Refs: + // - ILP32E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#ilp32e-calling-convention + // - LP64E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/299 + + // ra + x1, + // t0-t2 + x5, x6, x7, + // a0-a5 + x10, x11, x12, x13, x14, x15, + // ft0-ft7 + f0, f1, f2, f3, f4, f5, f6, f7, + // fa0-fa7 + f10, f11, f12, f13, f14, f15, f16, f17, + // ft8-ft11 + f28, f29, f30, f31, + + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + } + }, InlineAsmClobberAbi::LoongArch => clobbered_regs! { LoongArch LoongArchInlineAsmReg { // ra diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index aa8b26170be..f3934afa6d9 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -51,7 +51,11 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, - Self::vreg => &[], + // FIXME: vsx also supports integers?: https://github.com/rust-lang/rust/pull/131551#discussion_r1862535963 + Self::vreg => types! { + altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4); + vsx: F32, F64, VecI64(2), VecF64(2); + }, Self::cr | Self::xer => &[], } } diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index cfd573efbc1..d6b30525379 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -54,6 +54,10 @@ impl RiscVInlineAsmRegClass { } } +pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool { + target_features.contains(&sym::e) +} + fn not_e( _arch: InlineAsmArch, _reloc_model: RelocModel, @@ -61,7 +65,7 @@ fn not_e( _target: &Target, _is_clobber: bool, ) -> Result<(), &'static str> { - if target_features.contains(&sym::e) { + if is_e(target_features) { Err("register can't be used with the `e` target feature") } else { Ok(()) diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs index 1869369b9e3..fe37d313294 100644 --- a/compiler/rustc_target/src/spec/base/aix.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs @@ -4,7 +4,7 @@ use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, cr pub(crate) fn opts() -> TargetOptions { TargetOptions { abi: "vec-extabi".into(), - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Large), cpu: "pwr7".into(), os: "aix".into(), vendor: "ibm".into(), diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs new file mode 100644 index 00000000000..206766325aa --- /dev/null +++ b/compiler/rustc_target/src/spec/json.rs @@ -0,0 +1,798 @@ +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::str::FromStr; + +use serde_json::Value; + +use super::{Target, TargetKind, TargetOptions, TargetWarnings}; +use crate::json::{Json, ToJson}; + +impl Target { + /// Loads a target descriptor from a JSON object. + pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> { + // While ugly, this code must remain this way to retain + // compatibility with existing JSON fields and the internal + // expected naming of the Target and TargetOptions structs. + // To ensure compatibility is retained, the built-in targets + // are round-tripped through this code to catch cases where + // the JSON parser is not updated to match the structs. + + let mut obj = match obj { + Value::Object(obj) => obj, + _ => return Err("Expected JSON object for target")?, + }; + + let mut get_req_field = |name: &str| { + obj.remove(name) + .and_then(|j| j.as_str().map(str::to_string)) + .ok_or_else(|| format!("Field {name} in target specification is required")) + }; + + let mut base = Target { + llvm_target: get_req_field("llvm-target")?.into(), + metadata: Default::default(), + pointer_width: get_req_field("target-pointer-width")? + .parse::<u32>() + .map_err(|_| "target-pointer-width must be an integer".to_string())?, + data_layout: get_req_field("data-layout")?.into(), + arch: get_req_field("arch")?.into(), + options: Default::default(), + }; + + // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid. + // That's okay for now, the only use of this is when generating docs, which we don't do for + // custom targets. + if let Some(Json::Object(mut metadata)) = obj.remove("metadata") { + base.metadata.description = metadata + .remove("description") + .and_then(|desc| desc.as_str().map(|desc| desc.to_owned().into())); + base.metadata.tier = metadata + .remove("tier") + .and_then(|tier| tier.as_u64()) + .filter(|tier| (1..=3).contains(tier)); + base.metadata.host_tools = + metadata.remove("host_tools").and_then(|host| host.as_bool()); + base.metadata.std = metadata.remove("std").and_then(|host| host.as_bool()); + } + + let mut incorrect_type = vec![]; + + macro_rules! key { + ($key_name:ident) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { + base.$key_name = s; + } + } ); + ($key_name:ident = $json_name:expr) => ( { + let name = $json_name; + if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { + base.$key_name = s; + } + } ); + ($key_name:ident, bool) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = s; + } + } ); + ($key_name:ident = $json_name:expr, bool) => ( { + let name = $json_name; + if let Some(s) = obj.remove(name).and_then(|b| b.as_bool()) { + base.$key_name = s; + } + } ); + ($key_name:ident, u32) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { + if s < 1 || s > 5 { + return Err("Not a valid DWARF version number".into()); + } + base.$key_name = s as u32; + } + } ); + ($key_name:ident, Option<bool>) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = Some(s); + } + } ); + ($key_name:ident, Option<u64>) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { + base.$key_name = Some(s); + } + } ); + ($key_name:ident, MergeFunctions) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::MergeFunctions>() { + Ok(mergefunc) => base.$key_name = mergefunc, + _ => return Some(Err(format!("'{}' is not a valid value for \ + merge-functions. Use 'disabled', \ + 'trampolines', or 'aliases'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, RelocModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::RelocModel>() { + Ok(relocation_model) => base.$key_name = relocation_model, + _ => return Some(Err(format!("'{}' is not a valid relocation model. \ + Run `rustc --print relocation-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, CodeModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::CodeModel>() { + Ok(code_model) => base.$key_name = Some(code_model), + _ => return Some(Err(format!("'{}' is not a valid code model. \ + Run `rustc --print code-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, TlsModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::TlsModel>() { + Ok(tls_model) => base.$key_name = tls_model, + _ => return Some(Err(format!("'{}' is not a valid TLS model. \ + Run `rustc --print tls-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, SmallDataThresholdSupport) => ( { + obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::SmallDataThresholdSupport>() { + Ok(support) => base.small_data_threshold_support = support, + _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, PanicStrategy) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s { + "unwind" => base.$key_name = super::PanicStrategy::Unwind, + "abort" => base.$key_name = super::PanicStrategy::Abort, + _ => return Some(Err(format!("'{}' is not a valid value for \ + panic-strategy. Use 'unwind' or 'abort'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, RelroLevel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::RelroLevel>() { + Ok(level) => base.$key_name = level, + _ => return Some(Err(format!("'{}' is not a valid value for \ + relro-level. Use 'full', 'partial, or 'off'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, Option<SymbolVisibility>) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::SymbolVisibility>() { + Ok(level) => base.$key_name = Some(level), + _ => return Some(Err(format!("'{}' is not a valid value for \ + symbol-visibility. Use 'hidden', 'protected, or 'interposable'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, DebuginfoKind) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::DebuginfoKind>() { + Ok(level) => base.$key_name = level, + _ => return Some(Err( + format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \ + 'dwarf-dsym' or 'pdb'.") + )), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, SplitDebuginfo) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::SplitDebuginfo>() { + Ok(level) => base.$key_name = level, + _ => return Some(Err(format!("'{}' is not a valid value for \ + split-debuginfo. Use 'off' or 'dsymutil'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(j) = obj.remove(&name) { + if let Some(v) = j.as_array() { + base.$key_name = v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect(); + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, opt_list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(j) = obj.remove(&name) { + if let Some(v) = j.as_array() { + base.$key_name = Some(v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect()); + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, fallible_list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|j| { + if let Some(v) = j.as_array() { + match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() { + Ok(l) => { base.$key_name = l }, + // FIXME: `fallible_list` can't re-use the `key!` macro for list + // elements and the error messages from that macro, so it has a bad + // generic message instead + Err(_) => return Some(Err( + format!("`{:?}` is not a valid value for `{}`", j, name) + )), + } + } else { + incorrect_type.push(name) + } + Some(Ok(())) + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, optional) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + base.$key_name = o + .as_str() + .map(|s| s.to_string().into()); + } + } ); + ($key_name:ident = $json_name:expr, LldFlavor) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + if let Some(flavor) = super::LldFlavor::from_str(&s) { + base.$key_name = flavor; + } else { + return Some(Err(format!( + "'{}' is not a valid value for lld-flavor. \ + Use 'darwin', 'gnu', 'link' or 'wasm'.", + s))) + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident = $json_name:expr, LinkerFlavorCli) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + match super::LinkerFlavorCli::from_str(s) { + Some(linker_flavor) => base.$key_name = linker_flavor, + _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ + Use {}", s, super::LinkerFlavorCli::one_of()))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, StackProbeType) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| match super::StackProbeType::from_json(&o) { + Ok(v) => { + base.$key_name = v; + Some(Ok(())) + }, + Err(s) => Some(Err( + format!("`{:?}` is not a valid value for `{}`: {}", o, name, s) + )), + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, SanitizerSet) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(a) = o.as_array() { + for s in a { + use super::SanitizerSet; + base.$key_name |= match s.as_str() { + Some("address") => SanitizerSet::ADDRESS, + Some("cfi") => SanitizerSet::CFI, + Some("dataflow") => SanitizerSet::DATAFLOW, + Some("kcfi") => SanitizerSet::KCFI, + Some("kernel-address") => SanitizerSet::KERNELADDRESS, + Some("leak") => SanitizerSet::LEAK, + Some("memory") => SanitizerSet::MEMORY, + Some("memtag") => SanitizerSet::MEMTAG, + Some("safestack") => SanitizerSet::SAFESTACK, + Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK, + Some("thread") => SanitizerSet::THREAD, + Some("hwaddress") => SanitizerSet::HWADDRESS, + Some(s) => return Err(format!("unknown sanitizer {}", s)), + _ => return Err(format!("not a string: {:?}", s)), + }; + } + } else { + incorrect_type.push(name) + } + } + Ok::<(), String>(()) + } ); + ($key_name:ident, link_self_contained_components) => ( { + // Skeleton of what needs to be parsed: + // + // ``` + // $name: { + // "components": [ + // <array of strings> + // ] + // } + // ``` + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(o) = o.as_object() { + let component_array = o.get("components") + .ok_or_else(|| format!("{name}: expected a \ + JSON object with a `components` field."))?; + let component_array = component_array.as_array() + .ok_or_else(|| format!("{name}.components: expected a JSON array"))?; + let mut components = super::LinkSelfContainedComponents::empty(); + for s in component_array { + components |= match s.as_str() { + Some(s) => { + super::LinkSelfContainedComponents::from_str(s) + .ok_or_else(|| format!("unknown \ + `-Clink-self-contained` component: {s}"))? + }, + _ => return Err(format!("not a string: {:?}", s)), + }; + } + base.$key_name = super::LinkSelfContainedDefault::WithComponents(components); + } else { + incorrect_type.push(name) + } + } + Ok::<(), String>(()) + } ); + ($key_name:ident = $json_name:expr, link_self_contained_backwards_compatible) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::<super::LinkSelfContainedDefault>() { + Ok(lsc_default) => base.$key_name = lsc_default, + _ => return Some(Err(format!("'{}' is not a valid `-Clink-self-contained` default. \ + Use 'false', 'true', 'musl' or 'mingw'", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident = $json_name:expr, link_objects) => ( { + let name = $json_name; + if let Some(val) = obj.remove(name) { + let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ + JSON object with fields per CRT object kind.", name))?; + let mut args = super::CrtObjects::new(); + for (k, v) in obj { + let kind = super::LinkOutputKind::from_str(&k).ok_or_else(|| { + format!("{}: '{}' is not a valid value for CRT object kind. \ + Use '(dynamic,static)-(nopic,pic)-exe' or \ + '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k) + })?; + + let v = v.as_array().ok_or_else(|| + format!("{}.{}: expected a JSON array", name, k) + )?.iter().enumerate() + .map(|(i,s)| { + let s = s.as_str().ok_or_else(|| + format!("{}.{}[{}]: expected a JSON string", name, k, i))?; + Ok(s.to_string().into()) + }) + .collect::<Result<Vec<_>, String>>()?; + + args.insert(kind, v); + } + base.$key_name = args; + } + } ); + ($key_name:ident = $json_name:expr, link_args) => ( { + let name = $json_name; + if let Some(val) = obj.remove(name) { + let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ + JSON object with fields per linker-flavor.", name))?; + let mut args = super::LinkArgsCli::new(); + for (k, v) in obj { + let flavor = super::LinkerFlavorCli::from_str(&k).ok_or_else(|| { + format!("{}: '{}' is not a valid value for linker-flavor. \ + Use 'em', 'gcc', 'ld' or 'msvc'", name, k) + })?; + + let v = v.as_array().ok_or_else(|| + format!("{}.{}: expected a JSON array", name, k) + )?.iter().enumerate() + .map(|(i,s)| { + let s = s.as_str().ok_or_else(|| + format!("{}.{}[{}]: expected a JSON string", name, k, i))?; + Ok(s.to_string().into()) + }) + .collect::<Result<Vec<_>, String>>()?; + + args.insert(flavor, v); + } + base.$key_name = args; + } + } ); + ($key_name:ident, env) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(a) = o.as_array() { + for o in a { + if let Some(s) = o.as_str() { + if let [k, v] = *s.split('=').collect::<Vec<_>>() { + base.$key_name + .to_mut() + .push((k.to_string().into(), v.to_string().into())) + } + } + } + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, target_families) => ( { + if let Some(value) = obj.remove("target-family") { + if let Some(v) = value.as_array() { + base.$key_name = v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect(); + } else if let Some(v) = value.as_str() { + base.$key_name = vec![v.to_string().into()].into(); + } + } + } ); + ($key_name:ident, Conv) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match super::Conv::from_str(s) { + Ok(c) => { + base.$key_name = c; + Some(Ok(())) + } + Err(e) => Some(Err(e)) + } + })).unwrap_or(Ok(())) + } ); + } + + if let Some(j) = obj.remove("target-endian") { + if let Some(s) = j.as_str() { + base.endian = s.parse()?; + } else { + incorrect_type.push("target-endian".into()) + } + } + + if let Some(fp) = obj.remove("frame-pointer") { + if let Some(s) = fp.as_str() { + base.frame_pointer = s + .parse() + .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?; + } else { + incorrect_type.push("frame-pointer".into()) + } + } + + key!(c_int_width = "target-c-int-width"); + key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width + key!(os); + key!(env); + key!(abi); + key!(vendor); + key!(linker, optional); + key!(linker_flavor_json = "linker-flavor", LinkerFlavorCli)?; + key!(lld_flavor_json = "lld-flavor", LldFlavor)?; + key!(linker_is_gnu_json = "linker-is-gnu", bool); + key!(pre_link_objects = "pre-link-objects", link_objects); + key!(post_link_objects = "post-link-objects", link_objects); + key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); + key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); + // Deserializes the backwards-compatible variants of `-Clink-self-contained` + key!( + link_self_contained = "crt-objects-fallback", + link_self_contained_backwards_compatible + )?; + // Deserializes the components variant of `-Clink-self-contained` + key!(link_self_contained, link_self_contained_components)?; + key!(pre_link_args_json = "pre-link-args", link_args); + key!(late_link_args_json = "late-link-args", link_args); + key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); + key!(late_link_args_static_json = "late-link-args-static", link_args); + key!(post_link_args_json = "post-link-args", link_args); + key!(link_script, optional); + key!(link_env, env); + key!(link_env_remove, list); + key!(asm_args, list); + key!(cpu); + key!(features); + key!(dynamic_linking, bool); + key!(direct_access_external_data, Option<bool>); + key!(dll_tls_export, bool); + key!(only_cdylib, bool); + key!(executables, bool); + key!(relocation_model, RelocModel)?; + key!(code_model, CodeModel)?; + key!(tls_model, TlsModel)?; + key!(disable_redzone, bool); + key!(function_sections, bool); + key!(dll_prefix); + key!(dll_suffix); + key!(exe_suffix); + key!(staticlib_prefix); + key!(staticlib_suffix); + key!(families, target_families); + key!(abi_return_struct_as_int, bool); + key!(is_like_aix, bool); + key!(is_like_osx, bool); + key!(is_like_solaris, bool); + key!(is_like_windows, bool); + key!(is_like_msvc, bool); + key!(is_like_wasm, bool); + key!(is_like_android, bool); + key!(default_dwarf_version, u32); + key!(allows_weak_linkage, bool); + key!(has_rpath, bool); + key!(no_default_libraries, bool); + key!(position_independent_executables, bool); + key!(static_position_independent_executables, bool); + key!(plt_by_default, bool); + key!(relro_level, RelroLevel)?; + key!(archive_format); + key!(allow_asm, bool); + key!(main_needs_argc_argv, bool); + key!(has_thread_local, bool); + key!(obj_is_bitcode, bool); + key!(bitcode_llvm_cmdline); + key!(max_atomic_width, Option<u64>); + key!(min_atomic_width, Option<u64>); + key!(atomic_cas, bool); + key!(panic_strategy, PanicStrategy)?; + key!(crt_static_allows_dylibs, bool); + key!(crt_static_default, bool); + key!(crt_static_respected, bool); + key!(stack_probes, StackProbeType)?; + key!(min_global_align, Option<u64>); + key!(default_codegen_units, Option<u64>); + key!(trap_unreachable, bool); + key!(requires_lto, bool); + key!(singlethread, bool); + key!(no_builtins, bool); + key!(default_visibility, Option<SymbolVisibility>)?; + key!(emit_debug_gdb_scripts, bool); + key!(requires_uwtable, bool); + key!(default_uwtable, bool); + key!(simd_types_indirect, bool); + key!(limit_rdylib_exports, bool); + key!(override_export_symbols, opt_list); + key!(merge_functions, MergeFunctions)?; + key!(mcount = "target-mcount"); + key!(llvm_mcount_intrinsic, optional); + key!(llvm_abiname); + key!(relax_elf_relocations, bool); + key!(llvm_args, list); + key!(use_ctors_section, bool); + key!(eh_frame_header, bool); + key!(has_thumb_interworking, bool); + key!(debuginfo_kind, DebuginfoKind)?; + key!(split_debuginfo, SplitDebuginfo)?; + key!(supported_split_debuginfo, fallible_list)?; + key!(supported_sanitizers, SanitizerSet)?; + key!(generate_arange_section, bool); + key!(supports_stack_protector, bool); + key!(small_data_threshold_support, SmallDataThresholdSupport)?; + key!(entry_name); + key!(entry_abi, Conv)?; + key!(supports_xray, bool); + + base.update_from_cli(); + base.check_consistency(TargetKind::Json)?; + + // Each field should have been read using `Json::remove` so any keys remaining are unused. + let remaining_keys = obj.keys(); + Ok((base, TargetWarnings { + unused_fields: remaining_keys.cloned().collect(), + incorrect_type, + })) + } +} + +impl ToJson for Target { + fn to_json(&self) -> Json { + let mut d = serde_json::Map::new(); + let default: TargetOptions = Default::default(); + let mut target = self.clone(); + target.update_to_cli(); + + macro_rules! target_val { + ($attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + d.insert(name, target.$attr.to_json()); + }}; + } + + macro_rules! target_option_val { + ($attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != target.$attr { + d.insert(name, target.$attr.to_json()); + } + }}; + ($attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + d.insert(name.into(), target.$attr.to_json()); + } + }}; + (link_args - $attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + let obj = target + .$attr + .iter() + .map(|(k, v)| (k.desc().to_string(), v.clone())) + .collect::<BTreeMap<_, _>>(); + d.insert(name.to_string(), obj.to_json()); + } + }}; + (env - $attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != target.$attr { + let obj = target + .$attr + .iter() + .map(|&(ref k, ref v)| format!("{k}={v}")) + .collect::<Vec<_>>(); + d.insert(name, obj.to_json()); + } + }}; + } + + target_val!(llvm_target); + target_val!(metadata); + d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json()); + target_val!(arch); + target_val!(data_layout); + + target_option_val!(endian, "target-endian"); + target_option_val!(c_int_width, "target-c-int-width"); + target_option_val!(os); + target_option_val!(env); + target_option_val!(abi); + target_option_val!(vendor); + target_option_val!(linker); + target_option_val!(linker_flavor_json, "linker-flavor"); + target_option_val!(lld_flavor_json, "lld-flavor"); + target_option_val!(linker_is_gnu_json, "linker-is-gnu"); + target_option_val!(pre_link_objects); + target_option_val!(post_link_objects); + target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); + target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); + target_option_val!(link_args - pre_link_args_json, "pre-link-args"); + target_option_val!(link_args - late_link_args_json, "late-link-args"); + target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); + target_option_val!(link_args - late_link_args_static_json, "late-link-args-static"); + target_option_val!(link_args - post_link_args_json, "post-link-args"); + target_option_val!(link_script); + target_option_val!(env - link_env); + target_option_val!(link_env_remove); + target_option_val!(asm_args); + target_option_val!(cpu); + target_option_val!(features); + target_option_val!(dynamic_linking); + target_option_val!(direct_access_external_data); + target_option_val!(dll_tls_export); + target_option_val!(only_cdylib); + target_option_val!(executables); + target_option_val!(relocation_model); + target_option_val!(code_model); + target_option_val!(tls_model); + target_option_val!(disable_redzone); + target_option_val!(frame_pointer); + target_option_val!(function_sections); + target_option_val!(dll_prefix); + target_option_val!(dll_suffix); + target_option_val!(exe_suffix); + target_option_val!(staticlib_prefix); + target_option_val!(staticlib_suffix); + target_option_val!(families, "target-family"); + target_option_val!(abi_return_struct_as_int); + target_option_val!(is_like_aix); + target_option_val!(is_like_osx); + target_option_val!(is_like_solaris); + target_option_val!(is_like_windows); + target_option_val!(is_like_msvc); + target_option_val!(is_like_wasm); + target_option_val!(is_like_android); + target_option_val!(default_dwarf_version); + target_option_val!(allows_weak_linkage); + target_option_val!(has_rpath); + target_option_val!(no_default_libraries); + target_option_val!(position_independent_executables); + target_option_val!(static_position_independent_executables); + target_option_val!(plt_by_default); + target_option_val!(relro_level); + target_option_val!(archive_format); + target_option_val!(allow_asm); + target_option_val!(main_needs_argc_argv); + target_option_val!(has_thread_local); + target_option_val!(obj_is_bitcode); + target_option_val!(bitcode_llvm_cmdline); + target_option_val!(min_atomic_width); + target_option_val!(max_atomic_width); + target_option_val!(atomic_cas); + target_option_val!(panic_strategy); + target_option_val!(crt_static_allows_dylibs); + target_option_val!(crt_static_default); + target_option_val!(crt_static_respected); + target_option_val!(stack_probes); + target_option_val!(min_global_align); + target_option_val!(default_codegen_units); + target_option_val!(trap_unreachable); + target_option_val!(requires_lto); + target_option_val!(singlethread); + target_option_val!(no_builtins); + target_option_val!(default_visibility); + target_option_val!(emit_debug_gdb_scripts); + target_option_val!(requires_uwtable); + target_option_val!(default_uwtable); + target_option_val!(simd_types_indirect); + target_option_val!(limit_rdylib_exports); + target_option_val!(override_export_symbols); + target_option_val!(merge_functions); + target_option_val!(mcount, "target-mcount"); + target_option_val!(llvm_mcount_intrinsic); + target_option_val!(llvm_abiname); + target_option_val!(relax_elf_relocations); + target_option_val!(llvm_args); + target_option_val!(use_ctors_section); + target_option_val!(eh_frame_header); + target_option_val!(has_thumb_interworking); + target_option_val!(debuginfo_kind); + target_option_val!(split_debuginfo); + target_option_val!(supported_split_debuginfo); + target_option_val!(supported_sanitizers); + target_option_val!(c_enum_min_bits); + target_option_val!(generate_arange_section); + target_option_val!(supports_stack_protector); + target_option_val!(small_data_threshold_support); + target_option_val!(entry_name); + target_option_val!(entry_abi); + target_option_val!(supports_xray); + + // Serializing `-Clink-self-contained` needs a dynamic key to support the + // backwards-compatible variants. + d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); + + Json::Object(d) + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index fead20ec7d1..a2e9430830a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -42,6 +42,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; +use rustc_data_structures::fx::FxHashSet; use rustc_fs_util::try_canonicalize; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -65,6 +66,8 @@ pub mod abi { } mod base; +mod json; + pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. @@ -1605,13 +1608,11 @@ macro_rules! supported_targets { #[cfg(test)] mod tests { - mod tests_impl; - // Cannot put this into a separate file without duplication, make an exception. $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(crate::spec::targets::$module::target()); + crate::spec::targets::$module::target().test_target() } )+ } @@ -1998,6 +1999,14 @@ impl TargetWarnings { } } +/// For the [`Target::check_consistency`] function, determines whether the given target is a builtin or a JSON +/// target. +#[derive(Copy, Clone, Debug, PartialEq)] +enum TargetKind { + Json, + Builtin, +} + /// Everything `rustc` knows about how to compile for a specific target. /// /// Every field here must be specified, and has no default value. @@ -2846,619 +2855,355 @@ impl Target { self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) } - /// Loads a target descriptor from a JSON object. - pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> { - // While ugly, this code must remain this way to retain - // compatibility with existing JSON fields and the internal - // expected naming of the Target and TargetOptions structs. - // To ensure compatibility is retained, the built-in targets - // are round-tripped through this code to catch cases where - // the JSON parser is not updated to match the structs. - - let mut obj = match obj { - Value::Object(obj) => obj, - _ => return Err("Expected JSON object for target")?, - }; - - let mut get_req_field = |name: &str| { - obj.remove(name) - .and_then(|j| j.as_str().map(str::to_string)) - .ok_or_else(|| format!("Field {name} in target specification is required")) - }; - - let mut base = Target { - llvm_target: get_req_field("llvm-target")?.into(), - metadata: Default::default(), - pointer_width: get_req_field("target-pointer-width")? - .parse::<u32>() - .map_err(|_| "target-pointer-width must be an integer".to_string())?, - data_layout: get_req_field("data-layout")?.into(), - arch: get_req_field("arch")?.into(), - options: Default::default(), - }; - - // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid. - // That's okay for now, the only use of this is when generating docs, which we don't do for - // custom targets. - if let Some(Json::Object(mut metadata)) = obj.remove("metadata") { - base.metadata.description = metadata - .remove("description") - .and_then(|desc| desc.as_str().map(|desc| desc.to_owned().into())); - base.metadata.tier = metadata - .remove("tier") - .and_then(|tier| tier.as_u64()) - .filter(|tier| (1..=3).contains(tier)); - base.metadata.host_tools = - metadata.remove("host_tools").and_then(|host| host.as_bool()); - base.metadata.std = metadata.remove("std").and_then(|host| host.as_bool()); - } - - let mut incorrect_type = vec![]; - - macro_rules! key { - ($key_name:ident) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { - base.$key_name = s; - } - } ); - ($key_name:ident = $json_name:expr) => ( { - let name = $json_name; - if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { - base.$key_name = s; - } - } ); - ($key_name:ident, bool) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { - base.$key_name = s; - } - } ); - ($key_name:ident = $json_name:expr, bool) => ( { - let name = $json_name; - if let Some(s) = obj.remove(name).and_then(|b| b.as_bool()) { - base.$key_name = s; + /// Check some basic consistency of the current target. For JSON targets we are less strict; + /// some of these checks are more guidelines than strict rules. + fn check_consistency(&self, kind: TargetKind) -> Result<(), String> { + macro_rules! check { + ($b:expr, $($msg:tt)*) => { + if !$b { + return Err(format!($($msg)*)); } - } ); - ($key_name:ident, u32) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { - if s < 1 || s > 5 { - return Err("Not a valid DWARF version number".into()); - } - base.$key_name = s as u32; - } - } ); - ($key_name:ident, Option<bool>) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { - base.$key_name = Some(s); - } - } ); - ($key_name:ident, Option<u64>) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { - base.$key_name = Some(s); - } - } ); - ($key_name:ident, MergeFunctions) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<MergeFunctions>() { - Ok(mergefunc) => base.$key_name = mergefunc, - _ => return Some(Err(format!("'{}' is not a valid value for \ - merge-functions. Use 'disabled', \ - 'trampolines', or 'aliases'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, RelocModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<RelocModel>() { - Ok(relocation_model) => base.$key_name = relocation_model, - _ => return Some(Err(format!("'{}' is not a valid relocation model. \ - Run `rustc --print relocation-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, CodeModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<CodeModel>() { - Ok(code_model) => base.$key_name = Some(code_model), - _ => return Some(Err(format!("'{}' is not a valid code model. \ - Run `rustc --print code-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, TlsModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<TlsModel>() { - Ok(tls_model) => base.$key_name = tls_model, - _ => return Some(Err(format!("'{}' is not a valid TLS model. \ - Run `rustc --print tls-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, SmallDataThresholdSupport) => ( { - obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { - match s.parse::<SmallDataThresholdSupport>() { - Ok(support) => base.small_data_threshold_support = support, - _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, PanicStrategy) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s { - "unwind" => base.$key_name = PanicStrategy::Unwind, - "abort" => base.$key_name = PanicStrategy::Abort, - _ => return Some(Err(format!("'{}' is not a valid value for \ - panic-strategy. Use 'unwind' or 'abort'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, RelroLevel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<RelroLevel>() { - Ok(level) => base.$key_name = level, - _ => return Some(Err(format!("'{}' is not a valid value for \ - relro-level. Use 'full', 'partial, or 'off'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, Option<SymbolVisibility>) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<SymbolVisibility>() { - Ok(level) => base.$key_name = Some(level), - _ => return Some(Err(format!("'{}' is not a valid value for \ - symbol-visibility. Use 'hidden', 'protected, or 'interposable'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, DebuginfoKind) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<DebuginfoKind>() { - Ok(level) => base.$key_name = level, - _ => return Some(Err( - format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \ - 'dwarf-dsym' or 'pdb'.") - )), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, SplitDebuginfo) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<SplitDebuginfo>() { - Ok(level) => base.$key_name = level, - _ => return Some(Err(format!("'{}' is not a valid value for \ - split-debuginfo. Use 'off' or 'dsymutil'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(j) = obj.remove(&name) { - if let Some(v) = j.as_array() { - base.$key_name = v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect(); - } else { - incorrect_type.push(name) - } + } + } + macro_rules! check_eq { + ($left:expr, $right:expr, $($msg:tt)*) => { + if ($left) != ($right) { + return Err(format!($($msg)*)); } - } ); - ($key_name:ident, opt_list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(j) = obj.remove(&name) { - if let Some(v) = j.as_array() { - base.$key_name = Some(v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect()); - } else { - incorrect_type.push(name) - } + } + } + macro_rules! check_ne { + ($left:expr, $right:expr, $($msg:tt)*) => { + if ($left) == ($right) { + return Err(format!($($msg)*)); } - } ); - ($key_name:ident, fallible_list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|j| { - if let Some(v) = j.as_array() { - match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() { - Ok(l) => { base.$key_name = l }, - // FIXME: `fallible_list` can't re-use the `key!` macro for list - // elements and the error messages from that macro, so it has a bad - // generic message instead - Err(_) => return Some(Err( - format!("`{:?}` is not a valid value for `{}`", j, name) - )), - } - } else { - incorrect_type.push(name) - } - Some(Ok(())) - }).unwrap_or(Ok(())) - } ); - ($key_name:ident, optional) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - base.$key_name = o - .as_str() - .map(|s| s.to_string().into()); + } + } + macro_rules! check_matches { + ($left:expr, $right:pat, $($msg:tt)*) => { + if !matches!($left, $right) { + return Err(format!($($msg)*)); } - } ); - ($key_name:ident = $json_name:expr, LldFlavor) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - if let Some(flavor) = LldFlavor::from_str(&s) { - base.$key_name = flavor; - } else { - return Some(Err(format!( - "'{}' is not a valid value for lld-flavor. \ - Use 'darwin', 'gnu', 'link' or 'wasm'.", - s))) - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident = $json_name:expr, LinkerFlavor) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - match LinkerFlavorCli::from_str(s) { - Some(linker_flavor) => base.$key_name = linker_flavor, - _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ - Use {}", s, LinkerFlavorCli::one_of()))), + } + } + + check_eq!( + self.is_like_osx, + self.vendor == "apple", + "`is_like_osx` must be set if and only if `vendor` is `apple`" + ); + check_eq!( + self.is_like_solaris, + self.os == "solaris" || self.os == "illumos", + "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`" + ); + check_eq!( + self.is_like_windows, + self.os == "windows" || self.os == "uefi", + "`is_like_windows` must be set if and only if `os` is `windows` or `uefi`" + ); + check_eq!( + self.is_like_wasm, + self.arch == "wasm32" || self.arch == "wasm64", + "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`" + ); + if self.is_like_msvc { + check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set"); + } + if self.os == "emscripten" { + check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets"); + } + + // Check that default linker flavor is compatible with some other key properties. + check_eq!( + self.is_like_osx, + matches!(self.linker_flavor, LinkerFlavor::Darwin(..)), + "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set" + ); + check_eq!( + self.is_like_msvc, + matches!(self.linker_flavor, LinkerFlavor::Msvc(..)), + "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set" + ); + check_eq!( + self.is_like_wasm && self.os != "emscripten", + matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)), + "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`", + ); + check_eq!( + self.os == "emscripten", + matches!(self.linker_flavor, LinkerFlavor::EmCc), + "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`" + ); + check_eq!( + self.arch == "bpf", + matches!(self.linker_flavor, LinkerFlavor::Bpf), + "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`" + ); + check_eq!( + self.arch == "nvptx64", + matches!(self.linker_flavor, LinkerFlavor::Ptx), + "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`" + ); + + for args in [ + &self.pre_link_args, + &self.late_link_args, + &self.late_link_args_dynamic, + &self.late_link_args_static, + &self.post_link_args, + ] { + for (&flavor, flavor_args) in args { + check!(!flavor_args.is_empty(), "linker flavor args must not be empty"); + // Check that flavors mentioned in link args are compatible with the default flavor. + match self.linker_flavor { + LinkerFlavor::Gnu(..) => { + check_matches!( + flavor, + LinkerFlavor::Gnu(..), + "mixing GNU and non-GNU linker flavors" + ); } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, StackProbeType) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| match StackProbeType::from_json(&o) { - Ok(v) => { - base.$key_name = v; - Some(Ok(())) - }, - Err(s) => Some(Err( - format!("`{:?}` is not a valid value for `{}`: {}", o, name, s) - )), - }).unwrap_or(Ok(())) - } ); - ($key_name:ident, SanitizerSet) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(a) = o.as_array() { - for s in a { - base.$key_name |= match s.as_str() { - Some("address") => SanitizerSet::ADDRESS, - Some("cfi") => SanitizerSet::CFI, - Some("dataflow") => SanitizerSet::DATAFLOW, - Some("kcfi") => SanitizerSet::KCFI, - Some("kernel-address") => SanitizerSet::KERNELADDRESS, - Some("leak") => SanitizerSet::LEAK, - Some("memory") => SanitizerSet::MEMORY, - Some("memtag") => SanitizerSet::MEMTAG, - Some("safestack") => SanitizerSet::SAFESTACK, - Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK, - Some("thread") => SanitizerSet::THREAD, - Some("hwaddress") => SanitizerSet::HWADDRESS, - Some(s) => return Err(format!("unknown sanitizer {}", s)), - _ => return Err(format!("not a string: {:?}", s)), - }; - } - } else { - incorrect_type.push(name) + LinkerFlavor::Darwin(..) => { + check_matches!( + flavor, + LinkerFlavor::Darwin(..), + "mixing Darwin and non-Darwin linker flavors" + ) } - } - Ok::<(), String>(()) - } ); - ($key_name:ident, link_self_contained_components) => ( { - // Skeleton of what needs to be parsed: - // - // ``` - // $name: { - // "components": [ - // <array of strings> - // ] - // } - // ``` - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(o) = o.as_object() { - let component_array = o.get("components") - .ok_or_else(|| format!("{name}: expected a \ - JSON object with a `components` field."))?; - let component_array = component_array.as_array() - .ok_or_else(|| format!("{name}.components: expected a JSON array"))?; - let mut components = LinkSelfContainedComponents::empty(); - for s in component_array { - components |= match s.as_str() { - Some(s) => { - LinkSelfContainedComponents::from_str(s) - .ok_or_else(|| format!("unknown \ - `-Clink-self-contained` component: {s}"))? - }, - _ => return Err(format!("not a string: {:?}", s)), - }; - } - base.$key_name = LinkSelfContainedDefault::WithComponents(components); - } else { - incorrect_type.push(name) + LinkerFlavor::WasmLld(..) => { + check_matches!( + flavor, + LinkerFlavor::WasmLld(..), + "mixing wasm and non-wasm linker flavors" + ) } - } - Ok::<(), String>(()) - } ); - ($key_name:ident = $json_name:expr, link_self_contained_backwards_compatible) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::<LinkSelfContainedDefault>() { - Ok(lsc_default) => base.$key_name = lsc_default, - _ => return Some(Err(format!("'{}' is not a valid `-Clink-self-contained` default. \ - Use 'false', 'true', 'musl' or 'mingw'", s))), + LinkerFlavor::Unix(..) => { + check_matches!( + flavor, + LinkerFlavor::Unix(..), + "mixing unix and non-unix linker flavors" + ); } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident = $json_name:expr, link_objects) => ( { - let name = $json_name; - if let Some(val) = obj.remove(name) { - let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ - JSON object with fields per CRT object kind.", name))?; - let mut args = CrtObjects::new(); - for (k, v) in obj { - let kind = LinkOutputKind::from_str(&k).ok_or_else(|| { - format!("{}: '{}' is not a valid value for CRT object kind. \ - Use '(dynamic,static)-(nopic,pic)-exe' or \ - '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k) - })?; - - let v = v.as_array().ok_or_else(|| - format!("{}.{}: expected a JSON array", name, k) - )?.iter().enumerate() - .map(|(i,s)| { - let s = s.as_str().ok_or_else(|| - format!("{}.{}[{}]: expected a JSON string", name, k, i))?; - Ok(s.to_string().into()) - }) - .collect::<Result<Vec<_>, String>>()?; - - args.insert(kind, v); + LinkerFlavor::Msvc(..) => { + check_matches!( + flavor, + LinkerFlavor::Msvc(..), + "mixing MSVC and non-MSVC linker flavors" + ); } - base.$key_name = args; - } - } ); - ($key_name:ident = $json_name:expr, link_args) => ( { - let name = $json_name; - if let Some(val) = obj.remove(name) { - let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ - JSON object with fields per linker-flavor.", name))?; - let mut args = LinkArgsCli::new(); - for (k, v) in obj { - let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| { - format!("{}: '{}' is not a valid value for linker-flavor. \ - Use 'em', 'gcc', 'ld' or 'msvc'", name, k) - })?; - - let v = v.as_array().ok_or_else(|| - format!("{}.{}: expected a JSON array", name, k) - )?.iter().enumerate() - .map(|(i,s)| { - let s = s.as_str().ok_or_else(|| - format!("{}.{}[{}]: expected a JSON string", name, k, i))?; - Ok(s.to_string().into()) - }) - .collect::<Result<Vec<_>, String>>()?; - - args.insert(flavor, v); + LinkerFlavor::EmCc + | LinkerFlavor::Bpf + | LinkerFlavor::Ptx + | LinkerFlavor::Llbc => { + check_eq!(flavor, self.linker_flavor, "mixing different linker flavors") } - base.$key_name = args; } - } ); - ($key_name:ident, env) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(a) = o.as_array() { - for o in a { - if let Some(s) = o.as_str() { - if let [k, v] = *s.split('=').collect::<Vec<_>>() { - base.$key_name - .to_mut() - .push((k.to_string().into(), v.to_string().into())) - } + + // Check that link args for cc and non-cc versions of flavors are consistent. + let check_noncc = |noncc_flavor| -> Result<(), String> { + if let Some(noncc_args) = args.get(&noncc_flavor) { + for arg in flavor_args { + if let Some(suffix) = arg.strip_prefix("-Wl,") { + check!( + noncc_args.iter().any(|a| a == suffix), + " link args for cc and non-cc versions of flavors are not consistent" + ); } } - } else { - incorrect_type.push(name) - } - } - } ); - ($key_name:ident, TargetFamilies) => ( { - if let Some(value) = obj.remove("target-family") { - if let Some(v) = value.as_array() { - base.$key_name = v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect(); - } else if let Some(v) = value.as_str() { - base.$key_name = vec![v.to_string().into()].into(); } + Ok(()) + }; + + match self.linker_flavor { + LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?, + LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?, + LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?, + _ => {} } - } ); - ($key_name:ident, Conv) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match Conv::from_str(s) { - Ok(c) => { - base.$key_name = c; - Some(Ok(())) - } - Err(e) => Some(Err(e)) - } - })).unwrap_or(Ok(())) - } ); - } + } - if let Some(j) = obj.remove("target-endian") { - if let Some(s) = j.as_str() { - base.endian = s.parse()?; - } else { - incorrect_type.push("target-endian".into()) + // Check that link args for lld and non-lld versions of flavors are consistent. + for cc in [Cc::No, Cc::Yes] { + check_eq!( + args.get(&LinkerFlavor::Gnu(cc, Lld::No)), + args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + check_eq!( + args.get(&LinkerFlavor::Darwin(cc, Lld::No)), + args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + } + check_eq!( + args.get(&LinkerFlavor::Msvc(Lld::No)), + args.get(&LinkerFlavor::Msvc(Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + } + + if self.link_self_contained.is_disabled() { + check!( + self.pre_link_objects_self_contained.is_empty() + && self.post_link_objects_self_contained.is_empty(), + "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty", + ); + } + + // If your target really needs to deviate from the rules below, + // except it and document the reasons. + // Keep the default "unknown" vendor instead. + check_ne!(self.vendor, "", "`vendor` cannot be empty"); + check_ne!(self.os, "", "`os` cannot be empty"); + if !self.can_use_os_unknown() { + // Keep the default "none" for bare metal targets instead. + check_ne!( + self.os, + "unknown", + "`unknown` os can only be used on particular targets; use `none` for bare-metal targets" + ); + } + + // Check dynamic linking stuff. + // We skip this for JSON targets since otherwise, our default values would fail this test. + // These checks are not critical for correctness, but more like default guidelines. + // FIXME (https://github.com/rust-lang/rust/issues/133459): do we want to change the JSON + // target defaults so that they pass these checks? + if kind == TargetKind::Builtin { + // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. + // hexagon: when targeting QuRT, that OS can load dynamic libraries. + // wasm{32,64}: dynamic linking is inherent in the definition of the VM. + if self.os == "none" + && (self.arch != "bpf" + && self.arch != "hexagon" + && self.arch != "wasm32" + && self.arch != "wasm64") + { + check!( + !self.dynamic_linking, + "dynamic linking is not supported on this OS/architecture" + ); + } + if self.only_cdylib + || self.crt_static_allows_dylibs + || !self.late_link_args_dynamic.is_empty() + { + check!( + self.dynamic_linking, + "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set" + ); + } + // Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs + if self.dynamic_linking && !self.is_like_wasm { + check_eq!( + self.relocation_model, + RelocModel::Pic, + "targets that support dynamic linking must use the `pic` relocation model" + ); + } + if self.position_independent_executables { + check_eq!( + self.relocation_model, + RelocModel::Pic, + "targets that support position-independent executables must use the `pic` relocation model" + ); + } + // The UEFI targets do not support dynamic linking but still require PIC (#101377). + if self.relocation_model == RelocModel::Pic && (self.os != "uefi") { + check!( + self.dynamic_linking || self.position_independent_executables, + "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \ + Set the relocation model to `static` to avoid this requirement" + ); + } + if self.static_position_independent_executables { + check!( + self.position_independent_executables, + "if `static_position_independent_executables` is set, then `position_independent_executables` must be set" + ); } + if self.position_independent_executables { + check!( + self.executables, + "if `position_independent_executables` is set then `executables` must be set" + ); + } + } + + // Check crt static stuff + if self.crt_static_default || self.crt_static_allows_dylibs { + check!( + self.crt_static_respected, + "static CRT can be enabled but `crt_static_respected` is not set" + ); } - if let Some(fp) = obj.remove("frame-pointer") { - if let Some(s) = fp.as_str() { - base.frame_pointer = s - .parse() - .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?; - } else { - incorrect_type.push("frame-pointer".into()) + // Check that RISC-V targets always specify which ABI they use. + match &*self.arch { + "riscv32" => { + check_matches!( + &*self.llvm_abiname, + "ilp32" | "ilp32f" | "ilp32d" | "ilp32e", + "invalid RISC-V ABI name" + ); + } + "riscv64" => { + // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI. + check_matches!( + &*self.llvm_abiname, + "lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e", + "invalid RISC-V ABI name" + ); + } + _ => {} + } + + // Check that the given target-features string makes some basic sense. + if !self.features.is_empty() { + let mut features_enabled = FxHashSet::default(); + let mut features_disabled = FxHashSet::default(); + for feat in self.features.split(',') { + if let Some(feat) = feat.strip_prefix("+") { + features_enabled.insert(feat); + if features_disabled.contains(feat) { + return Err(format!( + "target feature `{feat}` is both enabled and disabled" + )); + } + } else if let Some(feat) = feat.strip_prefix("-") { + features_disabled.insert(feat); + if features_enabled.contains(feat) { + return Err(format!( + "target feature `{feat}` is both enabled and disabled" + )); + } + } else { + return Err(format!( + "target feature `{feat}` is invalid, must start with `+` or `-`" + )); + } } } - key!(c_int_width = "target-c-int-width"); - key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width - key!(os); - key!(env); - key!(abi); - key!(vendor); - key!(linker, optional); - key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?; - key!(lld_flavor_json = "lld-flavor", LldFlavor)?; - key!(linker_is_gnu_json = "linker-is-gnu", bool); - key!(pre_link_objects = "pre-link-objects", link_objects); - key!(post_link_objects = "post-link-objects", link_objects); - key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); - key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); - // Deserializes the backwards-compatible variants of `-Clink-self-contained` - key!( - link_self_contained = "crt-objects-fallback", - link_self_contained_backwards_compatible - )?; - // Deserializes the components variant of `-Clink-self-contained` - key!(link_self_contained, link_self_contained_components)?; - key!(pre_link_args_json = "pre-link-args", link_args); - key!(late_link_args_json = "late-link-args", link_args); - key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); - key!(late_link_args_static_json = "late-link-args-static", link_args); - key!(post_link_args_json = "post-link-args", link_args); - key!(link_script, optional); - key!(link_env, env); - key!(link_env_remove, list); - key!(asm_args, list); - key!(cpu); - key!(features); - key!(dynamic_linking, bool); - key!(direct_access_external_data, Option<bool>); - key!(dll_tls_export, bool); - key!(only_cdylib, bool); - key!(executables, bool); - key!(relocation_model, RelocModel)?; - key!(code_model, CodeModel)?; - key!(tls_model, TlsModel)?; - key!(disable_redzone, bool); - key!(function_sections, bool); - key!(dll_prefix); - key!(dll_suffix); - key!(exe_suffix); - key!(staticlib_prefix); - key!(staticlib_suffix); - key!(families, TargetFamilies); - key!(abi_return_struct_as_int, bool); - key!(is_like_aix, bool); - key!(is_like_osx, bool); - key!(is_like_solaris, bool); - key!(is_like_windows, bool); - key!(is_like_msvc, bool); - key!(is_like_wasm, bool); - key!(is_like_android, bool); - key!(default_dwarf_version, u32); - key!(allows_weak_linkage, bool); - key!(has_rpath, bool); - key!(no_default_libraries, bool); - key!(position_independent_executables, bool); - key!(static_position_independent_executables, bool); - key!(plt_by_default, bool); - key!(relro_level, RelroLevel)?; - key!(archive_format); - key!(allow_asm, bool); - key!(main_needs_argc_argv, bool); - key!(has_thread_local, bool); - key!(obj_is_bitcode, bool); - key!(bitcode_llvm_cmdline); - key!(max_atomic_width, Option<u64>); - key!(min_atomic_width, Option<u64>); - key!(atomic_cas, bool); - key!(panic_strategy, PanicStrategy)?; - key!(crt_static_allows_dylibs, bool); - key!(crt_static_default, bool); - key!(crt_static_respected, bool); - key!(stack_probes, StackProbeType)?; - key!(min_global_align, Option<u64>); - key!(default_codegen_units, Option<u64>); - key!(trap_unreachable, bool); - key!(requires_lto, bool); - key!(singlethread, bool); - key!(no_builtins, bool); - key!(default_visibility, Option<SymbolVisibility>)?; - key!(emit_debug_gdb_scripts, bool); - key!(requires_uwtable, bool); - key!(default_uwtable, bool); - key!(simd_types_indirect, bool); - key!(limit_rdylib_exports, bool); - key!(override_export_symbols, opt_list); - key!(merge_functions, MergeFunctions)?; - key!(mcount = "target-mcount"); - key!(llvm_mcount_intrinsic, optional); - key!(llvm_abiname); - key!(relax_elf_relocations, bool); - key!(llvm_args, list); - key!(use_ctors_section, bool); - key!(eh_frame_header, bool); - key!(has_thumb_interworking, bool); - key!(debuginfo_kind, DebuginfoKind)?; - key!(split_debuginfo, SplitDebuginfo)?; - key!(supported_split_debuginfo, fallible_list)?; - key!(supported_sanitizers, SanitizerSet)?; - key!(generate_arange_section, bool); - key!(supports_stack_protector, bool); - key!(small_data_threshold_support, SmallDataThresholdSupport)?; - key!(entry_name); - key!(entry_abi, Conv)?; - key!(supports_xray, bool); - - base.update_from_cli(); - - // Each field should have been read using `Json::remove` so any keys remaining are unused. - let remaining_keys = obj.keys(); - Ok((base, TargetWarnings { - unused_fields: remaining_keys.cloned().collect(), - incorrect_type, - })) + Ok(()) + } + + /// Test target self-consistency and JSON encoding/decoding roundtrip. + #[cfg(test)] + fn test_target(mut self) { + let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j); + self.update_to_cli(); + self.check_consistency(TargetKind::Builtin).unwrap(); + assert_eq!(recycled_target, Ok(self)); + } + + // Add your target to the whitelist if it has `std` library + // and you certainly want "unknown" for the OS name. + fn can_use_os_unknown(&self) -> bool { + self.llvm_target == "wasm32-unknown-unknown" + || self.llvm_target == "wasm64-unknown-unknown" + || (self.env == "sgx" && self.vendor == "fortanix") } /// Load a built-in target @@ -3563,177 +3308,6 @@ impl Target { } } -impl ToJson for Target { - fn to_json(&self) -> Json { - let mut d = serde_json::Map::new(); - let default: TargetOptions = Default::default(); - let mut target = self.clone(); - target.update_to_cli(); - - macro_rules! target_val { - ($attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - d.insert(name, target.$attr.to_json()); - }}; - } - - macro_rules! target_option_val { - ($attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != target.$attr { - d.insert(name, target.$attr.to_json()); - } - }}; - ($attr:ident, $json_name:expr) => {{ - let name = $json_name; - if default.$attr != target.$attr { - d.insert(name.into(), target.$attr.to_json()); - } - }}; - (link_args - $attr:ident, $json_name:expr) => {{ - let name = $json_name; - if default.$attr != target.$attr { - let obj = target - .$attr - .iter() - .map(|(k, v)| (k.desc().to_string(), v.clone())) - .collect::<BTreeMap<_, _>>(); - d.insert(name.to_string(), obj.to_json()); - } - }}; - (env - $attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != target.$attr { - let obj = target - .$attr - .iter() - .map(|&(ref k, ref v)| format!("{k}={v}")) - .collect::<Vec<_>>(); - d.insert(name, obj.to_json()); - } - }}; - } - - target_val!(llvm_target); - target_val!(metadata); - d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json()); - target_val!(arch); - target_val!(data_layout); - - target_option_val!(endian, "target-endian"); - target_option_val!(c_int_width, "target-c-int-width"); - target_option_val!(os); - target_option_val!(env); - target_option_val!(abi); - target_option_val!(vendor); - target_option_val!(linker); - target_option_val!(linker_flavor_json, "linker-flavor"); - target_option_val!(lld_flavor_json, "lld-flavor"); - target_option_val!(linker_is_gnu_json, "linker-is-gnu"); - target_option_val!(pre_link_objects); - target_option_val!(post_link_objects); - target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); - target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); - target_option_val!(link_args - pre_link_args_json, "pre-link-args"); - target_option_val!(link_args - late_link_args_json, "late-link-args"); - target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); - target_option_val!(link_args - late_link_args_static_json, "late-link-args-static"); - target_option_val!(link_args - post_link_args_json, "post-link-args"); - target_option_val!(link_script); - target_option_val!(env - link_env); - target_option_val!(link_env_remove); - target_option_val!(asm_args); - target_option_val!(cpu); - target_option_val!(features); - target_option_val!(dynamic_linking); - target_option_val!(direct_access_external_data); - target_option_val!(dll_tls_export); - target_option_val!(only_cdylib); - target_option_val!(executables); - target_option_val!(relocation_model); - target_option_val!(code_model); - target_option_val!(tls_model); - target_option_val!(disable_redzone); - target_option_val!(frame_pointer); - target_option_val!(function_sections); - target_option_val!(dll_prefix); - target_option_val!(dll_suffix); - target_option_val!(exe_suffix); - target_option_val!(staticlib_prefix); - target_option_val!(staticlib_suffix); - target_option_val!(families, "target-family"); - target_option_val!(abi_return_struct_as_int); - target_option_val!(is_like_aix); - target_option_val!(is_like_osx); - target_option_val!(is_like_solaris); - target_option_val!(is_like_windows); - target_option_val!(is_like_msvc); - target_option_val!(is_like_wasm); - target_option_val!(is_like_android); - target_option_val!(default_dwarf_version); - target_option_val!(allows_weak_linkage); - target_option_val!(has_rpath); - target_option_val!(no_default_libraries); - target_option_val!(position_independent_executables); - target_option_val!(static_position_independent_executables); - target_option_val!(plt_by_default); - target_option_val!(relro_level); - target_option_val!(archive_format); - target_option_val!(allow_asm); - target_option_val!(main_needs_argc_argv); - target_option_val!(has_thread_local); - target_option_val!(obj_is_bitcode); - target_option_val!(bitcode_llvm_cmdline); - target_option_val!(min_atomic_width); - target_option_val!(max_atomic_width); - target_option_val!(atomic_cas); - target_option_val!(panic_strategy); - target_option_val!(crt_static_allows_dylibs); - target_option_val!(crt_static_default); - target_option_val!(crt_static_respected); - target_option_val!(stack_probes); - target_option_val!(min_global_align); - target_option_val!(default_codegen_units); - target_option_val!(trap_unreachable); - target_option_val!(requires_lto); - target_option_val!(singlethread); - target_option_val!(no_builtins); - target_option_val!(default_visibility); - target_option_val!(emit_debug_gdb_scripts); - target_option_val!(requires_uwtable); - target_option_val!(default_uwtable); - target_option_val!(simd_types_indirect); - target_option_val!(limit_rdylib_exports); - target_option_val!(override_export_symbols); - target_option_val!(merge_functions); - target_option_val!(mcount, "target-mcount"); - target_option_val!(llvm_mcount_intrinsic); - target_option_val!(llvm_abiname); - target_option_val!(relax_elf_relocations); - target_option_val!(llvm_args); - target_option_val!(use_ctors_section); - target_option_val!(eh_frame_header); - target_option_val!(has_thumb_interworking); - target_option_val!(debuginfo_kind); - target_option_val!(split_debuginfo); - target_option_val!(supported_split_debuginfo); - target_option_val!(supported_sanitizers); - target_option_val!(c_enum_min_bits); - target_option_val!(generate_arange_section); - target_option_val!(supports_stack_protector); - target_option_val!(small_data_threshold_support); - target_option_val!(entry_name); - target_option_val!(entry_abi); - target_option_val!(supports_xray); - - // Serializing `-Clink-self-contained` needs a dynamic key to support the - // backwards-compatible variants. - d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); - - Json::Object(d) - } -} - /// Either a target tuple string or a path to a JSON file. #[derive(Clone, Debug)] pub enum TargetTuple { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index 62d6ffbd34f..9817c5a8eb0 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { description: Some("ARM64 Apple visionOS".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index a66c4f6e96b..d411f710540 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { description: Some("ARM64 Apple visionOS simulator".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index 22b3a5f8842..14a22988a09 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -16,7 +16,6 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { - features: "+reserve-x18".into(), mcount: "\u{1}_mcount".into(), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs index 34d8383a604..ae7bfbd0394 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { cpu: "esp32-s2".into(), linker: Some("xtensa-esp32s2-elf-gcc".into()), max_atomic_width: Some(32), + features: "+forced-atomics".into(), ..xtensa::opts() }, } diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs deleted file mode 100644 index 3225cdc759d..00000000000 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ /dev/null @@ -1,208 +0,0 @@ -use std::assert_matches::assert_matches; - -use rustc_data_structures::fx::FxHashSet; - -use super::super::*; - -// Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(mut target: Target) { - let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); - target.update_to_cli(); - target.check_consistency(); - assert_eq!(recycled_target, Ok(target)); -} - -impl Target { - fn check_consistency(&self) { - assert_eq!(self.is_like_osx, self.vendor == "apple"); - assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); - assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); - assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64"); - if self.is_like_msvc { - assert!(self.is_like_windows); - } - if self.os == "emscripten" { - assert!(self.is_like_wasm); - } - - // Check that default linker flavor is compatible with some other key properties. - assert_eq!(self.is_like_osx, matches!(self.linker_flavor, LinkerFlavor::Darwin(..))); - assert_eq!(self.is_like_msvc, matches!(self.linker_flavor, LinkerFlavor::Msvc(..))); - assert_eq!( - self.is_like_wasm && self.os != "emscripten", - matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)) - ); - assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc)); - assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf)); - assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx)); - - for args in [ - &self.pre_link_args, - &self.late_link_args, - &self.late_link_args_dynamic, - &self.late_link_args_static, - &self.post_link_args, - ] { - for (&flavor, flavor_args) in args { - assert!(!flavor_args.is_empty()); - // Check that flavors mentioned in link args are compatible with the default flavor. - match self.linker_flavor { - LinkerFlavor::Gnu(..) => { - assert_matches!(flavor, LinkerFlavor::Gnu(..)); - } - LinkerFlavor::Darwin(..) => { - assert_matches!(flavor, LinkerFlavor::Darwin(..)) - } - LinkerFlavor::WasmLld(..) => { - assert_matches!(flavor, LinkerFlavor::WasmLld(..)) - } - LinkerFlavor::Unix(..) => { - assert_matches!(flavor, LinkerFlavor::Unix(..)); - } - LinkerFlavor::Msvc(..) => { - assert_matches!(flavor, LinkerFlavor::Msvc(..)) - } - LinkerFlavor::EmCc - | LinkerFlavor::Bpf - | LinkerFlavor::Ptx - | LinkerFlavor::Llbc => { - assert_eq!(flavor, self.linker_flavor) - } - } - - // Check that link args for cc and non-cc versions of flavors are consistent. - let check_noncc = |noncc_flavor| { - if let Some(noncc_args) = args.get(&noncc_flavor) { - for arg in flavor_args { - if let Some(suffix) = arg.strip_prefix("-Wl,") { - assert!(noncc_args.iter().any(|a| a == suffix)); - } - } - } - }; - - match self.linker_flavor { - LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld)), - LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No)), - LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No)), - _ => {} - } - } - - // Check that link args for lld and non-lld versions of flavors are consistent. - for cc in [Cc::No, Cc::Yes] { - assert_eq!( - args.get(&LinkerFlavor::Gnu(cc, Lld::No)), - args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)), - ); - assert_eq!( - args.get(&LinkerFlavor::Darwin(cc, Lld::No)), - args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)), - ); - } - assert_eq!( - args.get(&LinkerFlavor::Msvc(Lld::No)), - args.get(&LinkerFlavor::Msvc(Lld::Yes)), - ); - } - - if self.link_self_contained.is_disabled() { - assert!( - self.pre_link_objects_self_contained.is_empty() - && self.post_link_objects_self_contained.is_empty() - ); - } - - // If your target really needs to deviate from the rules below, - // except it and document the reasons. - // Keep the default "unknown" vendor instead. - assert_ne!(self.vendor, ""); - assert_ne!(self.os, ""); - if !self.can_use_os_unknown() { - // Keep the default "none" for bare metal targets instead. - assert_ne!(self.os, "unknown"); - } - - // Check dynamic linking stuff - // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. - // hexagon: when targeting QuRT, that OS can load dynamic libraries. - // wasm{32,64}: dynamic linking is inherent in the definition of the VM. - if self.os == "none" - && (self.arch != "bpf" - && self.arch != "hexagon" - && self.arch != "wasm32" - && self.arch != "wasm64") - { - assert!(!self.dynamic_linking); - } - if self.only_cdylib - || self.crt_static_allows_dylibs - || !self.late_link_args_dynamic.is_empty() - { - assert!(self.dynamic_linking); - } - // Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs - if self.dynamic_linking && !self.is_like_wasm { - assert_eq!(self.relocation_model, RelocModel::Pic); - } - if self.position_independent_executables { - assert_eq!(self.relocation_model, RelocModel::Pic); - } - // The UEFI targets do not support dynamic linking but still require PIC (#101377). - if self.relocation_model == RelocModel::Pic && self.os != "uefi" { - assert!(self.dynamic_linking || self.position_independent_executables); - } - if self.static_position_independent_executables { - assert!(self.position_independent_executables); - } - if self.position_independent_executables { - assert!(self.executables); - } - - // Check crt static stuff - if self.crt_static_default || self.crt_static_allows_dylibs { - assert!(self.crt_static_respected); - } - - // Check that RISC-V targets always specify which ABI they use. - match &*self.arch { - "riscv32" => { - assert_matches!(&*self.llvm_abiname, "ilp32" | "ilp32f" | "ilp32d" | "ilp32e") - } - "riscv64" => { - // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI. - assert_matches!(&*self.llvm_abiname, "lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e") - } - _ => {} - } - - // Check that the given target-features string makes some basic sense. - if !self.features.is_empty() { - let mut features_enabled = FxHashSet::default(); - let mut features_disabled = FxHashSet::default(); - for feat in self.features.split(',') { - if let Some(feat) = feat.strip_prefix("+") { - features_enabled.insert(feat); - if features_disabled.contains(feat) { - panic!("target feature `{feat}` is both enabled and disabled"); - } - } else if let Some(feat) = feat.strip_prefix("-") { - features_disabled.insert(feat); - if features_enabled.contains(feat) { - panic!("target feature `{feat}` is both enabled and disabled"); - } - } else { - panic!("target feature `{feat}` is invalid, must start with `+` or `-`"); - } - } - } - } - - // Add your target to the whitelist if it has `std` library - // and you certainly want "unknown" for the OS name. - fn can_use_os_unknown(&self) -> bool { - self.llvm_target == "wasm32-unknown-unknown" - || self.llvm_target == "wasm64-unknown-unknown" - || (self.env == "sgx" && self.vendor == "fortanix") - } -} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 112eb862663..67c047dddfc 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -228,6 +228,12 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), + // This is needed for inline assembly, but shouldn't be stabilized as-is + // since it should be enabled globally using -Zfixed-x18, not + // #[target_feature]. + // Note that cfg(target_feature = "reserve-x18") is currently not set for + // targets that reserve x18 by default. + ("reserve-x18", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_SB ("sb", Stable, &[]), // FEAT_SHA1 & FEAT_SHA256 diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 0f9d4cb1982..8ba7969207e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1837,11 +1837,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind - && let hir::ArrayLen::Body(ct) = length && let Some((scalar, ty)) = sz.found.try_to_scalar() && ty == self.tcx.types.usize { - let span = ct.span(); + let span = length.span(); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: scalar.to_target_usize(&self.tcx).unwrap(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 75054b22153..218d2e753ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -3,6 +3,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use tracing::instrument; @@ -83,7 +84,7 @@ pub fn find_param_with_region<'tcx>( // May return None; sometimes the tables are not yet populated. let ty = fn_sig.inputs()[index]; let mut found_anon_region = false; - let new_param_ty = tcx.fold_regions(ty, |r, _| { + let new_param_ty = fold_regions(tcx, ty, |r, _| { if r == anon_region { found_anon_region = true; replace_region 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 75191894525..90b18253629 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 @@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { closure_def_id, found_kind, expected_kind, - "async ", + "Async", ); self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); @@ -1731,6 +1731,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); for (sp, label) in [trait_def_id, other_trait_def_id] .iter() + // The current crate-version might depend on another version of the same crate + // (Think "semver-trick"). Do not call `extern_crate` in that case for the local + // crate as that doesn't make sense and ICEs (#133563). + .filter(|def_id| !def_id.is_local()) .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 7f42c932fcf..f10314c1c9e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use std::iter; use std::path::PathBuf; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItemInner}; +use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -639,8 +639,7 @@ impl<'tcx> OnUnimplementedDirective { let report_span = match &item.args { AttrArgs::Empty => item.path.span, AttrArgs::Delimited(args) => args.dspan.entire(), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => eq_span.to(expr.span), - AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span), + AttrArgs::Eq { eq_span, value } => eq_span.to(value.span()), }; if let Some(item_def_id) = item_def_id.as_local() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 27b45f70946..2bb503f17b4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2803,6 +2803,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::WhereClause(item_def_id, span) | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) + | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..) if !span.is_dummy() => { if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code { @@ -2966,7 +2967,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.help(help); } } - ObligationCauseCode::WhereClause(..) | ObligationCauseCode::WhereClauseInExpr(..) => { + ObligationCauseCode::WhereClause(..) + | ObligationCauseCode::WhereClauseInExpr(..) + | ObligationCauseCode::HostEffectInExpr(..) => { // We hold the `DefId` of the item introducing the obligation, but displaying it // doesn't add user usable information. It always point at an associated item. } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 43244eb5dcb..ee708564a80 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -35,7 +35,7 @@ impl<'tcx> InferCtxt<'tcx> { // FIXME(#132279): This should be removed as it causes us to incorrectly // handle opaques in their defining scope. if !(param_env, ty).has_infer() { - return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env)); + return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 09bba24ba61..97cde67799c 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match self.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { .. } => false, + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => false, TypingMode::PostAnalysis => { let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); !poly_trait_ref.still_further_specializable() diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0f90c45d032..2b2623a050e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -199,6 +199,10 @@ where errors } + fn has_pending_obligations(&self) -> bool { + !self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e0a9ddf1876..c9297027519 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{ TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; -use rustc_span::symbol::Symbol; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -329,10 +328,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( .collect(), // Associated types can only be dyn-compatible if they have `Self: Sized` bounds. ty::AssocKind::Type => { - if !tcx.features().generic_associated_types_extended() - && !tcx.generics_of(item.def_id).is_own_empty() - && !item.is_impl_trait_in_trait() - { + if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() { vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)] } else { // We will permit associated types if they are explicitly mentioned in the trait object. @@ -679,7 +675,7 @@ fn receiver_is_dispatchable<'tcx>( // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = - Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); + Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome); // `Receiver[Self => U]` let unsized_receiver_ty = diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 03e483f555d..7529ee128f5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -213,6 +213,10 @@ where } } + fn has_pending_obligations(&self) -> bool { + self.predicates.has_pending_obligations() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 4d3d8c66e62..ad62b456ad4 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -7,6 +7,7 @@ use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; use rustc_macros::extension; +use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, @@ -63,10 +64,18 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { + if fulfill_cx.has_pending_obligations() { + let pending_obligations = fulfill_cx.pending_obligations(); + span_bug!( + pending_obligations[0].cause.span, + "deeply_normalize should not be called with pending obligations: \ + {pending_obligations:#?}" + ); + } let value = self .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); - let errors = fulfill_cx.select_where_possible(self.infcx); + let errors = fulfill_cx.select_all_or_error(self.infcx); let value = self.infcx.resolve_vars_if_possible(value); if errors.is_empty() { Ok(value) } else { Err(errors) } } @@ -118,9 +127,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>( // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`, // so we can ignore those. match infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - flags.remove(ty::TypeFlags::HAS_TY_OPAQUE) - } + // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), TypingMode::PostAnalysis => {} } @@ -213,9 +223,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.selcx.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - ty.super_fold_with(self) - } + // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), TypingMode::PostAnalysis => { let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2864f277df5..49c34550f8e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -14,7 +14,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; @@ -179,35 +179,11 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( ) -> ProjectAndUnifyResult<'tcx> { let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { - let old_universe = infcx.universe(); let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); - let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); match project_and_unify_term(selcx, &placeholder_obligation) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), - ProjectAndUnifyResult::Holds(obligations) - if old_universe != new_universe - && selcx.tcx().features().generic_associated_types_extended() => - { - // If the `generic_associated_types_extended` feature is active, then we ignore any - // obligations references lifetimes from any universe greater than or equal to the - // universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`, - // which isn't quite what we want. Ideally, we want either an implied - // `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we - // instantiate concrete regions. There is design work to be done here; until then, - // however, this allows experimenting potential GAT features without running into - // well-formedness issues. - let new_obligations = obligations - .into_iter() - .filter(|obligation| { - let mut visitor = MaxUniverse::new(); - obligation.predicate.visit_with(&mut visitor); - visitor.max_universe() < new_universe - }) - .collect(); - Ok(ProjectAndUnifyResult::Holds(new_obligations)) - } other => Ok(other), } }); @@ -975,7 +951,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match selcx.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { .. } => { + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => { debug!( assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), ?obligation.predicate, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 22cfbb2c840..2ef9d5421ba 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> { ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - ty.try_super_fold_with(self)? - } + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, TypingMode::PostAnalysis => { let args = data.args.try_fold_with(self)?; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index c6e41e57f0c..fe47e837dfb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -59,12 +59,16 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> { - let normalize_op = |ty| { - let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty); + let normalize_op = |ty| -> Result<_, NoSolution> { + // We must normalize the type so we can compute the right outlives components. + // for example, if we have some constrained param type like `T: Trait<Out = U>`, + // and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`. + let ty = ocx + .deeply_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| NoSolution)?; if !ocx.select_all_or_error().is_empty() { return Err(NoSolution); } - let ty = ocx.infcx.resolve_vars_if_possible(ty); let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty); Ok(ty) }; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 712856e6a8f..19b4125e75c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for assoc_type in assoc_types { let defs: &ty::Generics = tcx.generics_of(assoc_type); - if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended() { + if !defs.own_params.is_empty() { tcx.dcx().span_delayed_bug( obligation.cause.span, "GATs in trait object shouldn't have been considered", diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b64a47181a..41a35c31fe4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -25,6 +25,7 @@ use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; pub use rustc_middle::traits::select::*; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, @@ -1470,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation = &stack.obligation; match self.infcx.typing_mode() { TypingMode::Coherence => {} - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()), + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => return Ok(()), } debug!("is_knowable()"); @@ -1517,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TypingMode::Analysis { defining_opaque_types } => { defining_opaque_types.is_empty() || !pred.has_opaque_types() } + // The hidden types of `defined_opaque_types` is not local to the current + // inference context, so we can freely move this to the global cache. + TypingMode::PostBorrowckAnalysis { .. } => true, // The global cache is only used if there are no opaque types in // the defining scope or we're outside of analysis. // @@ -1537,14 +1543,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) { - Some(res) - } else { - debug_assert_eq!(infcx.selection_cache.get(&(param_env, pred), tcx), None); - None + return Some(res); + } else if cfg!(debug_assertions) { + match infcx.selection_cache.get(&(param_env, pred), tcx) { + None | Some(Err(Overflow(OverflowError::Canonical))) => {} + res => bug!("unexpected local cache result: {res:?}"), + } } - } else { - infcx.selection_cache.get(&(param_env, pred), tcx) } + + // Subtle: we need to check the local cache even if we're able to use the + // global cache as we don't cache overflow in the global cache but need to + // cache it as otherwise rustdoc hangs when compiling diesel. + infcx.selection_cache.get(&(param_env, pred), tcx) } /// Determines whether can we safely cache the result @@ -3209,7 +3220,7 @@ fn bind_coroutine_hidden_types_above<'tcx>( // Only remap erased regions if we use them. if considering_regions { bty = bty.map_bound(|ty| { - tcx.fold_regions(ty, |r, current_depth| match r.kind() { + fold_regions(tcx, ty, |r, current_depth| match r.kind() { ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a9cd705465e..1430cfae51f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -15,6 +15,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_infer::traits::Obligation; use rustc_middle::bug; use rustc_middle::query::LocalCrate; use rustc_middle::ty::print::PrintTraitRefExt as _; @@ -224,21 +225,30 @@ pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool tcx.features().specialization() || tcx.features().min_specialization() } -/// Is `impl1` a specialization of `impl2`? +/// Is `specializing_impl_def_id` a specialization of `parent_impl_def_id`? /// -/// Specialization is determined by the sets of types to which the impls apply; -/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies -/// to. +/// For every type that could apply to `specializing_impl_def_id`, we prove that +/// the `parent_impl_def_id` also applies (i.e. it has a valid impl header and +/// its where-clauses hold). +/// +/// For the purposes of const traits, we also check that the specializing +/// impl is not more restrictive than the parent impl. That is, if the +/// `parent_impl_def_id` is a const impl (conditionally based off of some `~const` +/// bounds), then `specializing_impl_def_id` must also be const for the same +/// set of types. #[instrument(skip(tcx), level = "debug")] -pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool { +pub(super) fn specializes( + tcx: TyCtxt<'_>, + (specializing_impl_def_id, parent_impl_def_id): (DefId, DefId), +) -> bool { // We check that the specializing impl comes from a crate that has specialization enabled, // or if the specializing impl is marked with `allow_internal_unstable`. // // We don't really care if the specialized impl (the parent) is in a crate that has // specialization enabled, since it's not being specialized, and it's already been checked // for coherence. - if !tcx.specialization_enabled_in(impl1_def_id.krate) { - let span = tcx.def_span(impl1_def_id); + if !tcx.specialization_enabled_in(specializing_impl_def_id.krate) { + let span = tcx.def_span(specializing_impl_def_id); if !span.allows_unstable(sym::specialization) && !span.allows_unstable(sym::min_specialization) { @@ -246,7 +256,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, } } - let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap(); + let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap(); // We determine whether there's a subset relationship by: // @@ -261,27 +271,123 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // See RFC 1210 for more details and justification. // Currently we do not allow e.g., a negative impl to specialize a positive one - if impl1_trait_header.polarity != tcx.impl_polarity(impl2_def_id) { + if specializing_impl_trait_header.polarity != tcx.impl_polarity(parent_impl_def_id) { return false; } - // create a parameter environment corresponding to an identity instantiation of impl1, - // i.e. the most generic instantiation of impl1. - let param_env = tcx.param_env(impl1_def_id); + // create a parameter environment corresponding to an identity instantiation of the specializing impl, + // i.e. the most generic instantiation of the specializing impl. + let param_env = tcx.param_env(specializing_impl_def_id); - // Create an infcx, taking the predicates of impl1 as assumptions: + // Create an infcx, taking the predicates of the specializing impl as assumptions: let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - // Attempt to prove that impl2 applies, given all of the above. - fulfill_implication( - &infcx, + let specializing_impl_trait_ref = + specializing_impl_trait_header.trait_ref.instantiate_identity(); + let cause = &ObligationCause::dummy(); + debug!( + "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)", + param_env, specializing_impl_trait_ref, parent_impl_def_id + ); + + // Attempt to prove that the parent impl applies, given all of the above. + + let ocx = ObligationCtxt::new(&infcx); + let specializing_impl_trait_ref = ocx.normalize(cause, param_env, specializing_impl_trait_ref); + + if !ocx.select_all_or_error().is_empty() { + infcx.dcx().span_delayed_bug( + infcx.tcx.def_span(specializing_impl_def_id), + format!("failed to fully normalize {specializing_impl_trait_ref}"), + ); + return false; + } + + let parent_args = infcx.fresh_args_for_item(DUMMY_SP, parent_impl_def_id); + let parent_impl_trait_ref = ocx.normalize( + cause, param_env, - impl1_trait_header.trait_ref.instantiate_identity(), - impl1_def_id, - impl2_def_id, - &ObligationCause::dummy(), - ) - .is_ok() + infcx + .tcx + .impl_trait_ref(parent_impl_def_id) + .expect("expected source impl to be a trait impl") + .instantiate(infcx.tcx, parent_args), + ); + + // do the impls unify? If not, no specialization. + let Ok(()) = ocx.eq(cause, param_env, specializing_impl_trait_ref, parent_impl_trait_ref) + else { + return false; + }; + + // Now check that the source trait ref satisfies all the where clauses of the target impl. + // This is not just for correctness; we also need this to constrain any params that may + // only be referenced via projection predicates. + let predicates = ocx.normalize( + cause, + param_env, + infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args), + ); + let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); + ocx.register_obligations(obligations); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + specializing_impl_trait_ref, + parent_impl_trait_ref, + errors, + param_env.caller_bounds() + ); + return false; + } + + // If the parent impl is const, then the specializing impl must be const, + // and it must not be *more restrictive* than the parent impl (that is, + // it cannot be const in fewer cases than the parent impl). + if tcx.is_conditionally_const(parent_impl_def_id) { + if !tcx.is_conditionally_const(specializing_impl_def_id) { + return false; + } + + let const_conditions = ocx.normalize( + cause, + param_env, + infcx.tcx.const_conditions(parent_impl_def_id).instantiate(infcx.tcx, parent_args), + ); + ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, _)| { + Obligation::new( + infcx.tcx, + cause.clone(), + param_env, + trait_ref.to_host_effect_clause(infcx.tcx, ty::BoundConstness::Maybe), + ) + })); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + specializing_impl_trait_ref, + parent_impl_trait_ref, + errors, + param_env.caller_bounds() + ); + return false; + } + } + + debug!( + "fulfill_implication: an impl for {:?} specializes {:?}", + specializing_impl_trait_ref, parent_impl_trait_ref + ); + + true } /// Query provider for `specialization_graph_of`. diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 57225df0819..e5276e6d515 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -74,12 +74,21 @@ pub(crate) fn codegen_select_candidate<'tcx>( } let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = infcx.tcx.erase_regions(impl_source); - if impl_source.has_infer() { - // Unused lifetimes on an impl get replaced with inference vars, but never resolved, - // causing the return value of a query to contain inference vars. We do not have a concept - // for this and will in fact ICE in stable hashing of the return value. So bail out instead. - infcx.tcx.dcx().has_errors().unwrap(); + let impl_source = tcx.erase_regions(impl_source); + if impl_source.has_non_region_infer() { + // Unused generic types or consts on an impl get replaced with inference vars, + // but never resolved, causing the return value of a query to contain inference + // vars. We do not have a concept for this and will in fact ICE in stable hashing + // of the return value. So bail out instead. + match impl_source { + ImplSource::UserDefined(impl_) => { + tcx.dcx().span_delayed_bug( + tcx.def_span(impl_.impl_def_id), + "this impl has unconstrained generic parameters", + ); + } + _ => unreachable!(), + } return Err(CodegenObligationError::FulfillmentError); } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index f19a567cd84..83463babc4f 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -319,38 +319,35 @@ pub(crate) mod rustc { ) -> Result<Self, Err> { assert!(def.is_enum()); - // Computes the variant of a given index. - let layout_of_variant = |index, encoding: Option<TagEncoding<VariantIdx>>| { - let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index)); - let variant_def = Def::Variant(def.variant(index)); - let variant_layout = ty_variant(cx, (ty, layout), index); - Self::from_variant( - variant_def, - tag.map(|tag| (tag, index, encoding.unwrap())), - (ty, variant_layout), - layout.size, - cx, - ) - }; + // Computes the layout of a variant. + let layout_of_variant = + |index, encoding: Option<TagEncoding<VariantIdx>>| -> Result<Self, Err> { + let variant_layout = ty_variant(cx, (ty, layout), index); + if variant_layout.is_uninhabited() { + return Ok(Self::uninhabited()); + } + let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index)); + let variant_def = Def::Variant(def.variant(index)); + Self::from_variant( + variant_def, + tag.map(|tag| (tag, index, encoding.unwrap())), + (ty, variant_layout), + layout.size, + cx, + ) + }; - // We consider three kinds of enums, each demanding a different - // treatment of their layout computation: - // 1. enums that are uninhabited ZSTs - // 2. enums that delegate their layout to a variant - // 3. enums with multiple variants match layout.variants() { - Variants::Single { .. } if layout.is_uninhabited() && layout.size == Size::ZERO => { - // The layout representation of uninhabited, ZST enums is - // defined to be like that of the `!` type, as opposed of a - // typical enum. Consequently, they cannot be descended into - // as if they typical enums. We therefore special-case this - // scenario and simply return an uninhabited `Tree`. - Ok(Self::uninhabited()) - } Variants::Single { index } => { - // `Variants::Single` on enums with variants denotes that - // the enum delegates its layout to the variant at `index`. - layout_of_variant(*index, None) + // Hilariously, `Single` is used even for 0-variant enums; + // `index` is just junk in that case. + if ty.ty_adt_def().unwrap().variants().is_empty() { + Ok(Self::uninhabited()) + } else { + // `Variants::Single` on enums with variants denotes that + // the enum delegates its layout to the variant at `index`. + layout_of_variant(*index, None) + } } Variants::Multiple { tag, tag_encoding, tag_field, .. } => { // `Variants::Multiple` denotes an enum with multiple @@ -369,7 +366,7 @@ pub(crate) mod rustc { }, )?; - return Ok(Self::def(Def::Adt(def)).then(variants)); + Ok(Self::def(Def::Adt(def)).then(variants)) } } } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 5cd10e90538..c4637f1293c 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -6,6 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -86,7 +87,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' } } // FIXME: This could use a real folder, I guess. - let remapped_wf_tys = tcx.fold_regions( + let remapped_wf_tys = fold_regions( + tcx, tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), |region, _| { // If `region` is a `ReLateParam` that is captured by the diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 8798772e398..eb30169a7d9 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>( // get a result which isn't correct for all monomorphizations. match typing_env.typing_mode { ty::TypingMode::Coherence - | ty::TypingMode::Analysis { defining_opaque_types: _ } => false, + | ty::TypingMode::Analysis { .. } + | ty::TypingMode::PostBorrowckAnalysis { .. } => false, ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), } }; @@ -215,15 +216,15 @@ fn resolve_associated_item<'tcx>( let args = tcx.erase_regions(args); - // Check if we just resolved an associated `const` declaration from - // a `trait` to an associated `const` definition in an `impl`, where - // the definition in the `impl` has the wrong type (for which an - // error has already been/will be emitted elsewhere). - if leaf_def.item.kind == ty::AssocKind::Const - && trait_item_id != leaf_def.item.def_id + // We check that the impl item is compatible with the trait item + // because otherwise we may ICE in const eval due to type mismatches, + // signature incompatibilities, etc. + // NOTE: We could also only enforce this in `PostAnalysis`, which + // is what CTFE and MIR inlining would care about anyways. + if trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.compare_impl_const((leaf_def_item, trait_item_id))?; + tcx.ensure().compare_impl_item(leaf_def_item)?; } Some(ty::Instance::new(leaf_def.item.def_id, args)) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 66134b81b2a..0d656f1b63b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -81,7 +81,7 @@ fn layout_of<'tcx>( record_layout_for_printing(&cx, layout); } - invariant::partially_check_layout(&cx, &layout); + invariant::layout_sanity_check(&cx, &layout); Ok(layout) } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 26ea81daf78..f39b87622f4 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -1,11 +1,11 @@ use std::assert_matches::assert_matches; -use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants}; +use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; /// Enforce some basic invariants on layouts. -pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { +pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. @@ -241,7 +241,17 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa check_layout_abi(cx, layout); - if let Variants::Multiple { variants, .. } = &layout.variants { + if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants { + if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding { + let niche_size = tag.size(cx); + assert!(*niche_start <= niche_size.unsigned_int_max()); + for (idx, variant) in variants.iter_enumerated() { + // Ensure all inhabited variants are accounted for. + if !variant.is_uninhabited() { + assert!(idx == *untagged_variant || niche_variants.contains(&idx)); + } + } + } for variant in variants.iter() { // No nested "multiple". assert_matches!(variant.variants, Variants::Single { .. }); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d85da7d355e..1c85eb2a861 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -202,7 +202,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env) => {} + _ if tcx.type_is_copy_modulo_regions(self.typing_env, component) => {} ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 61f2262dfe8..774f0660258 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -5,6 +5,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, }; @@ -197,7 +198,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { // We have entered some binders as we've walked into the // bounds of the RPITIT. Shift these binders back out when // constructing the top-level projection predicate. - let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| { + let shifted_alias_ty = fold_regions(self.tcx, unshifted_alias_ty, |re, depth| { if let ty::ReBound(index, bv) = re.kind() { if depth != ty::INNERMOST { return ty::Region::new_error_with_message( diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 2c8e47bcbca..81c8a7d4bfa 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -214,27 +214,47 @@ impl<I: Interner> DeepRejectCtxt<I, false, true> { impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool> DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER> { + // Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates + // and small enough to prevent hangs. + const STARTING_DEPTH: usize = 8; + pub fn args_may_unify( self, obligation_args: I::GenericArgs, impl_args: I::GenericArgs, ) -> bool { + self.args_may_unify_inner(obligation_args, impl_args, Self::STARTING_DEPTH) + } + + pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH) + } + + fn args_may_unify_inner( + self, + obligation_args: I::GenericArgs, + impl_args: I::GenericArgs, + depth: usize, + ) -> bool { + // No need to decrement the depth here as this function is only + // recursively reachable via `types_may_unify_inner` which already + // increments the depth for us. iter::zip(obligation_args.iter(), impl_args.iter()).all(|(obl, imp)| { match (obl.kind(), imp.kind()) { // We don't fast reject based on regions. (ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_)) => true, (ty::GenericArgKind::Type(obl), ty::GenericArgKind::Type(imp)) => { - self.types_may_unify(obl, imp) + self.types_may_unify_inner(obl, imp, depth) } (ty::GenericArgKind::Const(obl), ty::GenericArgKind::Const(imp)) => { - self.consts_may_unify(obl, imp) + self.consts_may_unify_inner(obl, imp) } _ => panic!("kind mismatch: {obl:?} {imp:?}"), } }) } - pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + fn types_may_unify_inner(self, lhs: I::Ty, rhs: I::Ty, depth: usize) -> bool { match rhs.kind() { // Start by checking whether the `rhs` type may unify with // pretty much everything. Just return `true` in that case. @@ -273,18 +293,31 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_ | ty::Placeholder(_) => {} }; + // The type system needs to support exponentially large types + // as long as they are self-similar. While most other folders + // use caching to handle them, this folder exists purely as a + // perf optimization and is incredibly hot. In pretty much all + // uses checking the cache is slower than simply recursing, so + // we instead just add an arbitrary depth cutoff. + // + // We only decrement the depth here as the match on `rhs` + // does not recurse. + let Some(depth) = depth.checked_sub(1) else { + return true; + }; + // For purely rigid types, use structural equivalence. match lhs.kind() { ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() { ty::Ref(_, rhs_ty, rhs_mutbl) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth) } _ => false, }, ty::Adt(lhs_def, lhs_args) => match rhs.kind() { ty::Adt(rhs_def, rhs_args) => { - lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) + lhs_def == rhs_def && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, @@ -326,27 +359,28 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_ ty::Tuple(rhs) => { lhs.len() == rhs.len() && iter::zip(lhs.iter(), rhs.iter()) - .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + .all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth)) } _ => false, }, ty::Array(lhs_ty, lhs_len) => match rhs.kind() { ty::Array(rhs_ty, rhs_len) => { - self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) + self.types_may_unify_inner(lhs_ty, rhs_ty, depth) + && self.consts_may_unify_inner(lhs_len, rhs_len) } _ => false, }, ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() { ty::RawPtr(rhs_ty, rhs_mutbl) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth) } _ => false, }, ty::Slice(lhs_ty) => { - matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty)) + matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth)) } ty::Dynamic(lhs_preds, ..) => { @@ -366,7 +400,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_ lhs_hdr == rhs_hdr && lhs_sig_tys.len() == rhs_sig_tys.len() && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter()) - .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + .all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth)) } _ => false, }, @@ -375,49 +409,51 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_ ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() { ty::FnDef(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() { ty::Closure(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() { ty::CoroutineClosure(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() { ty::Coroutine(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() { ty::CoroutineWitness(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Pat(lhs_ty, _) => { // FIXME(pattern_types): take pattern into account - matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty)) + matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth)) } ty::Error(..) => true, } } - pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool { + // Unlike `types_may_unify_inner`, this does not take a depth as + // we never recurse from this function. + fn consts_may_unify_inner(self, lhs: I::Const, rhs: I::Const) -> bool { match rhs.kind() { ty::ConstKind::Param(_) => { if INSTANTIATE_RHS_WITH_INFER { diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 8209d6f5fe3..d337a1a8ad9 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -49,7 +49,7 @@ use std::mem; use rustc_index::{Idx, IndexVec}; use thin_vec::ThinVec; -use tracing::instrument; +use tracing::{debug, instrument}; use crate::data_structures::Lrc; use crate::inherent::*; @@ -431,3 +431,75 @@ where value.fold_with(&mut Shifter::new(cx, amount)) } } + +/////////////////////////////////////////////////////////////////////////// +// Region folder + +pub fn fold_regions<I: Interner, T>( + cx: I, + value: T, + mut f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region, +) -> T +where + T: TypeFoldable<I>, +{ + value.fold_with(&mut RegionFolder::new(cx, &mut f)) +} + +/// Folds over the substructure of a type, visiting its component +/// types and all regions that occur *free* within it. +/// +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be +/// visited by `fld_r`. +pub struct RegionFolder<'a, I: Interner> { + cx: I, + + /// Stores the index of a binder *just outside* the stuff we have + /// visited. So this begins as INNERMOST; when we pass through a + /// binder, it is incremented (via `shift_in`). + current_index: ty::DebruijnIndex, + + /// Callback invokes for each free region. The `DebruijnIndex` + /// points to the binder *just outside* the ones we have passed + /// through. + fold_region_fn: &'a mut (dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region + 'a), +} + +impl<'a, I: Interner> RegionFolder<'a, I> { + #[inline] + pub fn new( + cx: I, + fold_region_fn: &'a mut dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region, + ) -> RegionFolder<'a, I> { + RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn } + } +} + +impl<'a, I: Interner> TypeFolder<I> for RegionFolder<'a, I> { + fn cx(&self) -> I { + self.cx + } + + fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + #[instrument(skip(self), level = "debug", ret)] + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { + debug!(?self.current_index, "skipped bound region"); + r + } + _ => { + debug!(?self.current_index, "folding free region"); + (self.fold_region_fn)(r, self.current_index) + } + } + } +} diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 13ad505bc04..a892b88c2c6 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -63,6 +63,12 @@ pub enum TypingMode<I: Interner> { /// } /// ``` Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, + /// Any analysis after borrowck for a given body should be able to use all the + /// hidden types defined by borrowck, without being able to define any new ones. + /// + /// This is currently only used by the new solver, but should be implemented in + /// the old solver as well. + PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes }, /// After analysis, mostly during codegen and MIR optimizations, we're able to /// reveal all opaque types. As the concrete type should *never* be observable /// directly by the user, this should not be used by checks which may expose @@ -85,6 +91,12 @@ impl<I: Interner> TypingMode<I> { pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } } + + pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { + TypingMode::PostBorrowckAnalysis { + defined_opaque_types: cx.opaque_types_defined_by(body_def_id), + } + } } pub trait InferCtxtLike: Sized { @@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized { vid: ty::RegionVid, ) -> <Self::Interner as Interner>::Region; + fn next_region_infer(&self) -> <Self::Interner as Interner>::Region; fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty; fn next_const_infer(&self) -> <Self::Interner as Interner>::Const; fn fresh_args_for_item( diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index c8abfee314e..d49f8d3093d 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -136,9 +136,9 @@ where relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); Ok(a) } - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { - structurally_relate_tys(relation, a, b) - } + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), } } diff --git a/library/Cargo.lock b/library/Cargo.lock index 197e0a8fedb..f9b0af2c6e8 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "compiler_builtins", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index c1907361f93..2633154318c 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -4,8 +4,7 @@ #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] +#![feature(strict_provenance_lints)] #![feature(test)] #![deny(fuzzy_provenance_casts)] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ee60ec0fbac..e0f94428cfa 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,9 +191,7 @@ use core::error::{self, Error}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -#[cfg(not(bootstrap))] -use core::marker::PointerLike; -use core::marker::{Tuple, Unsize}; +use core::marker::{PointerLike, Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, @@ -227,7 +225,7 @@ pub use thin::ThinBox; #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] // The declaration of the `Box` struct must be kept in sync with the // compiler or ICEs will happen. pub struct Box< @@ -1502,7 +1500,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_mut_ptr(b: &mut Self) -> *mut T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -1551,7 +1549,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_ptr(b: &Self) -> *const T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -2134,6 +2132,5 @@ impl<E: Error> Error for Box<E> { } } -#[cfg(not(bootstrap))] #[unstable(feature = "pointer_like_trait", issue = "none")] impl<T> PointerLike for Box<T> {} diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index 4430fff6677..255cefb1e78 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -110,7 +110,7 @@ impl<T: Clone> From<&[T]> for Box<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl<T: Clone> From<&mut [T]> for Box<[T]> { /// Converts a `&mut [T]` into a `Box<[T]>` /// @@ -171,7 +171,7 @@ impl From<&str> for Box<str> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Box<str> { /// Converts a `&mut str` into a `Box<str>` /// diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 59f10b09c73..5d3997e14e3 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -452,7 +452,7 @@ impl<T: Ord> BinaryHeap<T> { /// /// The binary heap will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the binary heap will not allocate. + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. /// /// # Examples /// @@ -486,7 +486,6 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> { /// heap.push(4); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "125961")] #[must_use] pub const fn new_in(alloc: A) -> BinaryHeap<T, A> { BinaryHeap { data: Vec::new_in(alloc) } @@ -496,7 +495,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> { /// /// The binary heap will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the binary heap will not allocate. + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. /// /// # Examples /// diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 213924d1d02..d1ce4e215ed 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -308,11 +308,38 @@ impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> { alloc: (*map.alloc).clone(), _marker: PhantomData, } - .insert(SetValZST::default()); + .insert(SetValZST); None } } } + + pub(super) fn get_or_insert_with<Q: ?Sized, F>(&mut self, q: &Q, f: F) -> &K + where + K: Borrow<Q> + Ord, + Q: Ord, + F: FnOnce(&Q) -> K, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = + map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut(); + match root_node.search_tree(q) { + Found(handle) => handle.into_kv_mut().0, + GoDown(handle) => { + let key = f(q); + assert!(*key.borrow() == *q, "new value is not equal"); + VacantEntry { + key, + handle: Some(handle), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + } + .insert_entry(SetValZST) + .into_key() + } + } + } } /// An iterator over the entries of a `BTreeMap`. diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 0da6af54bc2..ea8fa363c38 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -449,6 +449,11 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { self.handle.reborrow().into_kv().0 } + /// Converts the entry into a reference to its key. + pub(crate) fn into_key(self) -> &'a K { + self.handle.into_kv_mut().0 + } + /// Take ownership of the key and value from the map. /// /// # Examples diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 8daee6030c2..6f8c3b2d152 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -7,12 +7,17 @@ use core::iter::{FusedIterator, Peekable}; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub}; -use super::map::{BTreeMap, Keys}; +use super::map::{self, BTreeMap, Keys}; use super::merge_iter::MergeIterInner; use super::set_val::SetValZST; use crate::alloc::{Allocator, Global}; use crate::vec::Vec; +mod entry; + +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; + /// An ordered set based on a B-Tree. /// /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance @@ -928,6 +933,109 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> { self.map.replace(value) } + /// Inserts the given `value` into the set if it is not present, then + /// returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.len(), 3); + /// assert_eq!(set.get_or_insert(2), &2); + /// assert_eq!(set.get_or_insert(100), &100); + /// assert_eq!(set.len(), 4); // 100 was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get_or_insert(&mut self, value: T) -> &T + where + T: Ord, + { + self.map.entry(value).insert_entry(SetValZST).into_key() + } + + /// Inserts a value computed from `f` into the set if the given `value` is + /// not present, then returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet<String> = ["cat", "dog", "horse"] + /// .iter().map(|&pet| pet.to_owned()).collect(); + /// + /// assert_eq!(set.len(), 3); + /// for &pet in &["cat", "dog", "fish"] { + /// let value = set.get_or_insert_with(pet, str::to_owned); + /// assert_eq!(value, pet); + /// } + /// assert_eq!(set.len(), 4); // a new "fish" was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T + where + T: Borrow<Q> + Ord, + Q: Ord, + F: FnOnce(&Q) -> T, + { + self.map.get_or_insert_with(value, f) + } + + /// Gets the given value's corresponding entry in the set for in-place manipulation. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry::*; + /// + /// let mut singles = BTreeSet::new(); + /// let mut dupes = BTreeSet::new(); + /// + /// for ch in "a short treatise on fungi".chars() { + /// if let Vacant(dupe_entry) = dupes.entry(ch) { + /// // We haven't already seen a duplicate, so + /// // check if we've at least seen it once. + /// match singles.entry(ch) { + /// Vacant(single_entry) => { + /// // We found a new character for the first time. + /// single_entry.insert() + /// } + /// Occupied(single_entry) => { + /// // We've already seen this once, "move" it to dupes. + /// single_entry.remove(); + /// dupe_entry.insert(); + /// } + /// } + /// } + /// } + /// + /// assert!(!singles.contains(&'t') && dupes.contains(&'t')); + /// assert!(singles.contains(&'u') && !dupes.contains(&'u')); + /// assert!(!singles.contains(&'v') && !dupes.contains(&'v')); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn entry(&mut self, value: T) -> Entry<'_, T, A> + where + T: Ord, + { + match self.map.entry(value) { + map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }), + map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }), + } + } + /// If the set contains an element equal to the value, removes it from the /// set and drops it. Returns whether such an element was present. /// diff --git a/library/alloc/src/collections/btree/set/entry.rs b/library/alloc/src/collections/btree/set/entry.rs new file mode 100644 index 00000000000..a60d22f9ece --- /dev/null +++ b/library/alloc/src/collections/btree/set/entry.rs @@ -0,0 +1,388 @@ +use core::fmt::{self, Debug}; + +use Entry::*; + +use super::{SetValZST, map}; +use crate::alloc::{Allocator, Global}; + +/// A view into a single entry in a set, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: super::BTreeSet +/// [`entry`]: super::BTreeSet::entry +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::BTreeSet; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// assert_eq!(set.len(), 3); +/// +/// // Existing value (insert) +/// let entry = set.entry("a"); +/// let _raw_o = entry.insert(); +/// assert_eq!(set.len(), 3); +/// // Nonexistent value (insert) +/// set.entry("d").insert(); +/// +/// // Existing value (or_insert) +/// set.entry("b").or_insert(); +/// // Nonexistent value (or_insert) +/// set.entry("e").or_insert(); +/// +/// println!("Our BTreeSet: {:?}", set); +/// assert!(set.iter().eq(&["a", "b", "c", "d", "e"])); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub enum Entry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + /// An occupied entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::from(["a", "b"]); + /// + /// match set.entry("a") { + /// Entry::Vacant(_) => unreachable!(), + /// Entry::Occupied(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "133549")] + Occupied(OccupiedEntry<'a, T, A>), + + /// A vacant entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("a") { + /// Entry::Occupied(_) => unreachable!(), + /// Entry::Vacant(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "133549")] + Vacant(VacantEntry<'a, T, A>), +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl<T: Debug + Ord, A: Allocator + Clone> Debug for Entry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), + Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), + } + } +} + +/// A view into an occupied entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// +/// let _entry_o = set.entry("a").insert(); +/// assert_eq!(set.len(), 3); +/// +/// // Existing key +/// match set.entry("a") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.get(), &"a"); +/// } +/// } +/// +/// assert_eq!(set.len(), 3); +/// +/// // Existing key (take) +/// match set.entry("c") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.remove(), "c"); +/// } +/// } +/// assert_eq!(set.get(&"c"), None); +/// assert_eq!(set.len(), 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub struct OccupiedEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl<T: Debug + Ord, A: Allocator + Clone> Debug for OccupiedEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntry").field("value", self.get()).finish() + } +} + +/// A view into a vacant entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::<&str>::new(); +/// +/// let entry_v = match set.entry("a") { +/// Entry::Vacant(view) => view, +/// Entry::Occupied(_) => unreachable!(), +/// }; +/// entry_v.insert(); +/// assert!(set.contains("a") && set.len() == 1); +/// +/// // Nonexistent key (insert) +/// match set.entry("b") { +/// Entry::Vacant(view) => view.insert(), +/// Entry::Occupied(_) => unreachable!(), +/// } +/// assert!(set.contains("b") && set.len() == 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub struct VacantEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl<T: Debug + Ord, A: Allocator + Clone> Debug for VacantEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntry").field(self.get()).finish() + } +} + +impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { + /// Sets the value of the entry, and returns an `OccupiedEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// let entry = set.entry("horseyland").insert(); + /// + /// assert_eq!(entry.get(), &"horseyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn insert(self) -> OccupiedEntry<'a, T, A> { + match self { + Occupied(entry) => entry, + Vacant(entry) => entry.insert_entry(), + } + } + + /// Ensures a value is in the entry by inserting if it was vacant. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// // nonexistent key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// + /// // existing key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn or_insert(self) { + if let Vacant(entry) = self { + entry.insert(); + } + } + + /// Returns a reference to this entry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// // existing key + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// // nonexistent key + /// assert_eq!(set.entry("horseland").get(), &"horseland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + match *self { + Occupied(ref entry) => entry.get(), + Vacant(ref entry) => entry.get(), + } + } +} + +impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> { + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// match set.entry("poneyland") { + /// Entry::Vacant(_) => panic!(), + /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Takes the value out of the entry, and returns it. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// if let Entry::Occupied(o) = set.entry("poneyland") { + /// assert_eq!(o.remove(), "poneyland"); + /// } + /// + /// assert_eq!(set.contains("poneyland"), false); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn remove(self) -> T { + self.inner.remove_entry().0 + } +} + +impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { + /// Gets a reference to the value that would be used when inserting + /// through the `VacantEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Take ownership of the value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("poneyland") { + /// Entry::Occupied(_) => panic!(), + /// Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn into_value(self) -> T { + self.inner.into_key() + } + + /// Sets the value of the entry with the VacantEntry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// + /// if let Entry::Vacant(o) = set.entry("poneyland") { + /// o.insert(); + /// } + /// assert!(set.contains("poneyland")); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn insert(self) { + self.inner.insert(SetValZST); + } + + #[inline] + fn insert_entry(self) -> OccupiedEntry<'a, T, A> { + OccupiedEntry { inner: self.inner.insert_entry(SetValZST) } + } +} diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index d91682b796e..9c074383a5e 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -384,7 +384,7 @@ impl CString { /// fn some_extern_function(s: *mut c_char); /// } /// - /// let c_string = CString::new("Hello!").expect("CString::new failed"); + /// let c_string = CString::from(c"Hello!"); /// let raw = c_string.into_raw(); /// unsafe { /// some_extern_function(raw); @@ -429,7 +429,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// /// let ptr = c_string.into_raw(); /// @@ -487,7 +487,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes(); /// assert_eq!(bytes, vec![b'f', b'o', b'o']); /// ``` @@ -508,7 +508,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes_with_nul(); /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); /// ``` @@ -530,7 +530,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes(); /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` @@ -550,7 +550,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes_with_nul(); /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` @@ -568,7 +568,7 @@ impl CString { /// ``` /// use std::ffi::{CString, CStr}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let cstr = c_string.as_c_str(); /// assert_eq!(cstr, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); @@ -586,12 +586,9 @@ impl CString { /// # Examples /// /// ``` - /// use std::ffi::{CString, CStr}; - /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = c"foo".to_owned(); /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(&*boxed, - /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); + /// assert_eq!(boxed.to_bytes_with_nul(), b"foo\0"); /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] @@ -658,7 +655,7 @@ impl CString { /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) /// .expect("CString::from_vec_with_nul failed"), - /// CString::new(b"abc".to_vec()).expect("CString::new failed") + /// c"abc".to_owned() /// ); /// ``` /// @@ -773,7 +770,7 @@ impl From<&CStr> for Box<CStr> { } #[cfg(not(test))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Box<CStr> { /// Converts a `&mut CStr` into a `Box<CStr>`, /// by copying the contents into a newly allocated [`Box`]. @@ -921,7 +918,7 @@ impl From<&CStr> for Arc<CStr> { } #[cfg(target_has_atomic = "ptr")] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Arc<CStr> { /// Converts a `&mut CStr` into a `Arc<CStr>`, /// by copying the contents into a newly allocated [`Arc`]. @@ -953,7 +950,7 @@ impl From<&CStr> for Rc<CStr> { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Rc<CStr> { /// Converts a `&mut CStr` into a `Rc<CStr>`, /// by copying the contents into a newly allocated [`Rc`]. @@ -1168,11 +1165,12 @@ impl CStr { /// # Examples /// /// ``` - /// use std::ffi::CString; + /// use std::ffi::{CStr, CString}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); - /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed")); + /// let boxed: Box<CStr> = Box::from(c"foo"); + /// let c_string: CString = c"foo".to_owned(); + /// + /// assert_eq!(boxed.into_c_string(), c_string); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs index 8b7172b3f20..d6b797347c2 100644 --- a/library/alloc/src/ffi/c_str/tests.rs +++ b/library/alloc/src/ffi/c_str/tests.rs @@ -159,7 +159,7 @@ fn boxed_default() { #[test] fn test_c_str_clone_into() { - let mut c_string = CString::new("lorem").unwrap(); + let mut c_string = c"lorem".to_owned(); let c_ptr = c_string.as_ptr(); let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap(); c_str.clone_into(&mut c_string); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 041ff37897f..84f4202c02a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -91,8 +91,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] -#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![cfg_attr(test, feature(str_as_str))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -107,13 +105,8 @@ #![feature(box_uninit_write)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] -#![feature(const_align_of_val)] -#![feature(const_box)] #![feature(const_eval_select)] #![feature(const_heap)] -#![feature(const_maybe_uninit_write)] -#![feature(const_size_of_val)] -#![feature(const_vec_string_slice)] #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] #![feature(deref_pure_trait)] @@ -163,8 +156,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] @@ -172,7 +163,6 @@ #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] -#![feature(const_try)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(fundamental)] @@ -188,6 +178,7 @@ #![feature(slice_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 85a9120c7e2..2c7cdcf0cfb 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -103,7 +103,6 @@ impl<T> RawVec<T, Global> { /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. #[must_use] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new() -> Self { Self::new_in(Global) } @@ -179,7 +178,6 @@ impl<T, A: Allocator> RawVec<T, A> { /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new_in(alloc: A) -> Self { Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData } } @@ -409,7 +407,6 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> { impl<A: Allocator> RawVecInner<A> { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] const fn new_in(alloc: A, align: usize) -> Self { let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. @@ -757,7 +754,9 @@ impl<A: Allocator> RawVecInner<A> { } } -#[inline(never)] +// not marked inline(never) since we want optimizers to be able to observe the specifics of this +// function, see tests/codegen/vec-reserve-extend.rs. +#[cold] fn finish_grow<A>( new_layout: Layout, current_memory: Option<(NonNull<u8>, Layout)>, diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3a9bd1b5bf1..7aa1457b1df 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -307,7 +307,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { /// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`. /// /// [get_mut]: Rc::get_mut -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] @@ -2659,7 +2659,7 @@ impl<T: Clone> From<&[T]> for Rc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl<T: Clone> From<&mut [T]> for Rc<[T]> { /// Allocates a reference-counted slice and fills it by cloning `v`'s items. /// @@ -2698,7 +2698,7 @@ impl From<&str> for Rc<str> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Rc<str> { /// Allocates a reference-counted string slice and copies `v` into it. /// diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 333e1bde31c..2210a7c24c0 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -349,9 +349,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Rc<CStr> = Rc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak<CStr> = Rc::downgrade(&x); drop(x); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index da2d6bb3bce..b8bdd298c27 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -235,7 +235,7 @@ macro_rules! acquire { /// counting in general. /// /// [rc_examples]: crate::rc#examples -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] @@ -3618,7 +3618,7 @@ impl<T: Clone> From<&[T]> for Arc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl<T: Clone> From<&mut [T]> for Arc<[T]> { /// Allocates a reference-counted slice and fills it by cloning `v`'s items. /// @@ -3657,7 +3657,7 @@ impl From<&str> for Arc<str> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Arc<str> { /// Allocates a reference-counted `str` and copies `v` into it. /// diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 3f66c889923..de5816fda97 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -412,9 +412,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Arc<CStr> = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Arc<CStr> = Arc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak<CStr> = Arc::downgrade(&x); drop(x); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 990b7e8f761..4b706086e07 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -427,7 +427,7 @@ impl<T> Vec<T> { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -487,7 +487,7 @@ impl<T> Vec<T> { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// # Errors /// @@ -745,7 +745,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -808,7 +808,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// # Errors /// @@ -1662,7 +1662,7 @@ impl<T, A: Allocator> Vec<T, A> { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through @@ -1725,7 +1725,7 @@ impl<T, A: Allocator> Vec<T, A> { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 6a8ba5c92fb..94389cf2de9 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -4,7 +4,7 @@ use core::mem::MaybeUninit; use core::ptr::NonNull; #[test] -#[cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] +#[expect(dangling_pointers_from_temporaries)] fn uninitialized_zero_size_box() { assert_eq!( &*Box::<()>::new_uninit() as *const _, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 699a8e6776e..bcab17e7b2d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -4,8 +4,6 @@ #![feature(assert_matches)] #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] -#![feature(const_heap)] -#![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] #![feature(exact_size_is_empty)] @@ -32,10 +30,9 @@ #![feature(panic_update_hook)] #![feature(pointer_is_aligned_to)] #![feature(thin_box)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(strict_provenance_lints)] #![feature(vec_pop_if)] #![feature(unique_rc_arc)] #![feature(macro_metavar_expr_concat)] diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 94f343d0670..cace4582b48 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -43,8 +43,6 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index f412ca17163..d884fa69efb 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -157,7 +157,6 @@ impl Layout { #[must_use = "this returns the minimum alignment, \ without modifying the layout"] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(ptr_alignment_type))] pub const fn align(&self) -> usize { self.align.as_usize() } @@ -180,6 +179,7 @@ impl Layout { /// or other unsized type like a slice). #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] #[must_use] #[inline] pub const fn for_value<T: ?Sized>(t: &T) -> Self { @@ -216,7 +216,6 @@ impl Layout { /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html #[unstable(feature = "layout_for_ptr", issue = "69835")] - #[rustc_const_unstable(feature = "layout_for_ptr", issue = "69835")] #[must_use] pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller @@ -255,7 +254,7 @@ impl Layout { /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> { if let Some(align) = Alignment::new(align) { @@ -331,7 +330,7 @@ impl Layout { /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[must_use = "this returns a new `Layout`, \ without modifying the original"] #[inline] @@ -431,7 +430,7 @@ impl Layout { /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = Alignment::max(self.align, next.align); @@ -495,7 +494,7 @@ impl Layout { /// `isize::MAX`, returns `LayoutError`. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn array<T>(n: usize) -> Result<Self, LayoutError> { // Reduce the amount of code we need to monomorphize per `T`. diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 57f456c98b3..95d88c7f679 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } + +/// Compiles to a target-specific software breakpoint instruction or equivalent. +/// +/// This will typically abort the program. It may result in a core dump, and/or the system logging +/// debug information. Additional target-specific capabilities may be possible depending on +/// debuggers or other tooling; in particular, a debugger may be able to resume execution. +/// +/// If possible, this will produce an instruction sequence that allows a debugger to resume *after* +/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is +/// target-specific and debugger-specific, and not guaranteed. +/// +/// If the target platform does not have any kind of debug breakpoint instruction, this may compile +/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of +/// target-specific abort that may or may not support convenient resumption. +/// +/// The precise behavior and the precise instruction generated are not guaranteed, except that in +/// normal execution with no debug tooling involved this will not continue executing. +/// +/// - On x86 targets, this produces an `int3` instruction. +/// - On aarch64 targets, this produces a `brk #0xf000` instruction. +// When stabilizing this, update the comment on `core::intrinsics::breakpoint`. +#[unstable(feature = "breakpoint", issue = "133724")] +#[inline(always)] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + core::intrinsics::breakpoint(); +} diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 67fbda34bb9..95c1eb460cd 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -214,8 +214,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] { } } -/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if -/// `slice.len() == N`. +/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. +/// Succeeds if `slice.len() == N`. /// /// ``` /// let bytes: [u8; 3] = [1, 0, 2]; @@ -282,13 +282,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { #[inline] fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_ptr() as *const [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&*ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_array().ok_or(TryFromSliceError(())) } } @@ -310,13 +304,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { #[inline] fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_mut_ptr() as *mut [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&mut *ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_mut_array().ok_or(TryFromSliceError(())) } } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index bfd2a71f97b..cfa4c1fb564 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -587,7 +587,7 @@ impl<T: ?Sized> Cell<T> { #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *mut T { self.value.get() @@ -713,7 +713,6 @@ impl<T, const N: usize> Cell<[T; N]> { /// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells(); /// ``` #[unstable(feature = "as_array_of_cells", issue = "88248")] - #[rustc_const_unstable(feature = "as_array_of_cells", issue = "88248")] pub const fn as_array_of_cells(&self) -> &[Cell<T>; N] { // SAFETY: `Cell<T>` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) } @@ -1150,7 +1149,7 @@ impl<T: ?Sized> RefCell<T> { /// ``` #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub fn as_ptr(&self) -> *mut T { self.value.get() @@ -2133,9 +2132,8 @@ impl<T: ?Sized> UnsafeCell<T> { /// assert_eq!(*uc.get_mut(), 41); /// ``` #[inline(always)] - #[stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] + #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> { // SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)]. unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) } @@ -2160,7 +2158,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell<T>` to `T` because of @@ -2308,7 +2306,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> { /// when casting to `&mut T`, and ensure that there are no mutations /// or mutable aliases going on when casting to `&T` #[inline] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { self.value.get() diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 974e7baccf7..7d33765879f 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -729,7 +729,7 @@ impl char { /// '𝕊'.encode_utf16(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0")] #[inline] pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { encode_utf16_raw(self as u32, dst) @@ -1299,7 +1299,7 @@ impl char { /// /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); @@ -1325,7 +1325,7 @@ impl char { /// /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); @@ -1787,7 +1787,6 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))] #[doc(hidden)] #[inline] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { @@ -1836,10 +1835,6 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { /// Panics if the buffer is not large enough. /// A buffer of length 2 is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION") -)] #[doc(hidden)] #[inline] pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9e32f74227c..8831443a10f 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -138,11 +138,9 @@ enum FromBytesWithNulErrorKind { // FIXME: const stability attributes should not be required here, I think impl FromBytesWithNulError { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn interior_nul(pos: usize) -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } } - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn not_nul_terminated() -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } } @@ -464,8 +462,7 @@ impl CStr { /// /// ```no_run /// # #![allow(unused_must_use)] - /// # #![cfg_attr(bootstrap, expect(temporary_cstring_as_ptr))] - /// # #![cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] + /// # #![expect(dangling_pointers_from_temporaries)] /// use std::ffi::CString; /// /// // Do not do this: @@ -500,7 +497,7 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() @@ -732,7 +729,6 @@ impl AsRef<CStr> for CStr { /// located within `isize::MAX` from `ptr`. #[inline] #[unstable(feature = "cstr_internals", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))] #[rustc_allow_const_fn_unstable(const_eval_select)] const unsafe fn strlen(ptr: *const c_char) -> usize { const_eval_select!( diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 2b1692a195e..7fc9dd21fdd 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -333,10 +333,6 @@ pub struct Arguments<'a> { #[unstable(feature = "fmt_internals", issue = "none")] impl<'a> Arguments<'a> { #[inline] - #[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none") - )] pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self { const { assert!(N <= 1) }; Arguments { pieces, fmt: None, args: &[] } @@ -438,7 +434,7 @@ impl<'a> Arguments<'a> { /// assert_eq!(format_args!("{:?}", std::env::current_dir()).as_str(), None); /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] - #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 234914c20fc..cfbd88bbe79 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -25,7 +25,7 @@ use crate::task::{Context, Poll}; /// [`async`]: ../../std/keyword.async.html /// [`Waker`]: crate::task::Waker #[doc(notable_trait)] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 061690e88dd..84bbf985e8b 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -752,10 +752,10 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<fn() -> H>); impl<H> BuildHasherDefault<H> { /// Creates a new BuildHasherDefault for Hasher `H`. - #[unstable( + #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable( feature = "build_hasher_default_const_new", - issue = "123197", - reason = "recently added" + since = "CURRENT_RUSTC_VERSION" )] pub const fn new() -> Self { BuildHasherDefault(marker::PhantomData) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 78df51f2bc4..c59e4414d37 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -506,7 +506,6 @@ pub const fn black_box<T>(dummy: T) -> T { /// # } /// ``` #[unstable(feature = "hint_must_use", issue = "94745")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "hint_must_use", issue = "94745"))] #[must_use] // <-- :) #[inline(always)] pub const fn must_use<T>(value: T) -> T { diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 6539964bc09..55dcf7cd47e 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -249,6 +249,39 @@ //! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`. //! - [`TailCall`] does not have a return destination or next block, so its syntax is just //! `TailCall(function(arg1, arg2, ...))`. +//! +//! #### Debuginfo +//! +//! Debuginfo associates source code variable names (of variables that may not exist any more) with +//! MIR expressions that indicate where the value of that variable is stored. The syntax to do so +//! is: +//! ```text +//! debug source_var_name => expression; +//! ``` +//! Both places and constants are supported in the `expression`. +//! +//! ```rust +//! #![allow(internal_features)] +//! #![feature(core_intrinsics, custom_mir)] +//! +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! fn debuginfo(arg: Option<&i32>) { +//! mir!( +//! // Debuginfo for a source variable `plain_local` that just duplicates `arg`. +//! debug plain_local => arg; +//! // Debuginfo for a source variable `projection` that can be computed by dereferencing +//! // a field of `arg`. +//! debug projection => *Field::<&i32>(Variant(arg, 1), 0); +//! // Debuginfo for a source variable `constant` that always holds the value `5`. +//! debug constant => 5_usize; +//! { +//! Return() +//! } +//! ) +//! } +//! ``` #![unstable( feature = "custom_mir", diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 2f75bfae988..802b571c510 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + unreachable!() +} + +/// Executes a breakpoint trap, for inspection by a debugger. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[cfg(bootstrap)] pub unsafe fn breakpoint() { unreachable!() } @@ -1431,11 +1443,7 @@ pub fn abort() -> ! { /// reach code marked with this function. /// /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1453,8 +1461,7 @@ pub const unsafe fn unreachable() -> ! { /// own, or if it does not enable any significant optimizations. /// /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -1474,8 +1481,7 @@ pub const unsafe fn assume(b: bool) { /// /// This intrinsic does not have a stable counterpart. #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] -#[cfg(not(bootstrap))] +#[rustc_intrinsic] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] #[cold] @@ -1492,19 +1498,10 @@ pub const fn cold_path() {} /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn likely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { true } else { @@ -1524,19 +1521,10 @@ pub const fn likely(b: bool) -> bool { /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn unlikely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { cold_path(); true @@ -1570,8 +1558,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T { /// This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1583,8 +1570,7 @@ pub const fn assert_inhabited<T>() { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1595,8 +1581,7 @@ pub const fn assert_zero_valid<T>() { /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1612,8 +1597,7 @@ pub const fn assert_mem_uninitialized_valid<T>() { /// any safety invariants. /// /// Consider using [`core::panic::Location::caller`] instead. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1630,8 +1614,7 @@ pub const fn caller_location() -> &'static crate::panic::Location<'static> { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1944,8 +1927,7 @@ pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst { /// /// This is not expected to ever be exposed directly to users, rather it /// may eventually be exposed through some more-constrained API. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1966,8 +1948,7 @@ pub const unsafe fn transmute_unchecked<Src, Dst>(_src: Src) -> Dst { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1992,8 +1973,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool { /// /// The stabilized version of this intrinsic is [`pointer::offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2015,8 +1995,7 @@ pub const unsafe fn offset<Ptr, Delta>(_dst: Ptr, _offset: Delta) -> Ptr { /// /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2039,628 +2018,982 @@ pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T { unreachable!() } -extern "rust-intrinsic" { - /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with - /// a size of `count` * `size_of::<T>()` and an alignment of - /// `min_align_of::<T>()` - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize); - /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with - /// a size of `count * size_of::<T>()` and an alignment of - /// `min_align_of::<T>()` - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize); - /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a - /// size of `count * size_of::<T>()` and an alignment of - /// `min_align_of::<T>()`. - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize); +/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with +/// a size of `count` * `size_of::<T>()` and an alignment of +/// `min_align_of::<T>()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_nonoverlapping_memory<T>(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with +/// a size of `count * size_of::<T>()` and an alignment of +/// `min_align_of::<T>()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_memory<T>(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a +/// size of `count * size_of::<T>()` and an alignment of +/// `min_align_of::<T>()`. +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_set_memory<T>(_dst: *mut T, _val: u8, _count: usize) { + unreachable!() +} - /// Performs a volatile load from the `src` pointer. - /// - /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. - #[rustc_nounwind] - pub fn volatile_load<T>(src: *const T) -> T; - /// Performs a volatile store to the `dst` pointer. - /// - /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. - #[rustc_nounwind] - pub fn volatile_store<T>(dst: *mut T, val: T); +/// Performs a volatile load from the `src` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_load<T>(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_store<T>(_dst: *mut T, _val: T) { + unreachable!() +} - /// Performs a volatile load from the `src` pointer - /// The pointer is not required to be aligned. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] - pub fn unaligned_volatile_load<T>(src: *const T) -> T; - /// Performs a volatile store to the `dst` pointer. - /// The pointer is not required to be aligned. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] - pub fn unaligned_volatile_store<T>(dst: *mut T, val: T); +/// Performs a volatile load from the `src` pointer +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] +pub unsafe fn unaligned_volatile_load<T>(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] +pub unsafe fn unaligned_volatile_store<T>(_dst: *mut T, _val: T) { + unreachable!() +} - /// Returns the square root of an `f16` - /// - /// The stabilized version of this intrinsic is - /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf16(x: f16) -> f16; - /// Returns the square root of an `f32` - /// - /// The stabilized version of this intrinsic is - /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf32(x: f32) -> f32; - /// Returns the square root of an `f64` - /// - /// The stabilized version of this intrinsic is - /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf64(x: f64) -> f64; - /// Returns the square root of an `f128` - /// - /// The stabilized version of this intrinsic is - /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf128(x: f128) -> f128; +/// Returns the square root of an `f16` +/// +/// The stabilized version of this intrinsic is +/// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the square root of an `f32` +/// +/// The stabilized version of this intrinsic is +/// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the square root of an `f64` +/// +/// The stabilized version of this intrinsic is +/// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the square root of an `f128` +/// +/// The stabilized version of this intrinsic is +/// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf128(_x: f128) -> f128 { + unreachable!() +} - /// Raises an `f16` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f16::powi`](../../std/primitive.f16.html#method.powi) - #[rustc_nounwind] - pub fn powif16(a: f16, x: i32) -> f16; - /// Raises an `f32` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f32::powi`](../../std/primitive.f32.html#method.powi) - #[rustc_nounwind] - pub fn powif32(a: f32, x: i32) -> f32; - /// Raises an `f64` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f64::powi`](../../std/primitive.f64.html#method.powi) - #[rustc_nounwind] - pub fn powif64(a: f64, x: i32) -> f64; - /// Raises an `f128` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f128::powi`](../../std/primitive.f128.html#method.powi) - #[rustc_nounwind] - pub fn powif128(a: f128, x: i32) -> f128; +/// Raises an `f16` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powi`](../../std/primitive.f16.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif16(_a: f16, _x: i32) -> f16 { + unreachable!() +} +/// Raises an `f32` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powi`](../../std/primitive.f32.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif32(_a: f32, _x: i32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powi`](../../std/primitive.f64.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif64(_a: f64, _x: i32) -> f64 { + unreachable!() +} +/// Raises an `f128` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powi`](../../std/primitive.f128.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif128(_a: f128, _x: i32) -> f128 { + unreachable!() +} - /// Returns the sine of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::sin`](../../std/primitive.f16.html#method.sin) - #[rustc_nounwind] - pub fn sinf16(x: f16) -> f16; - /// Returns the sine of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::sin`](../../std/primitive.f32.html#method.sin) - #[rustc_nounwind] - pub fn sinf32(x: f32) -> f32; - /// Returns the sine of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::sin`](../../std/primitive.f64.html#method.sin) - #[rustc_nounwind] - pub fn sinf64(x: f64) -> f64; - /// Returns the sine of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::sin`](../../std/primitive.f128.html#method.sin) - #[rustc_nounwind] - pub fn sinf128(x: f128) -> f128; +/// Returns the sine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::sin`](../../std/primitive.f16.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the sine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::sin`](../../std/primitive.f32.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the sine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::sin`](../../std/primitive.f64.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the sine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::sin`](../../std/primitive.f128.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the cosine of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::cos`](../../std/primitive.f16.html#method.cos) - #[rustc_nounwind] - pub fn cosf16(x: f16) -> f16; - /// Returns the cosine of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::cos`](../../std/primitive.f32.html#method.cos) - #[rustc_nounwind] - pub fn cosf32(x: f32) -> f32; - /// Returns the cosine of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::cos`](../../std/primitive.f64.html#method.cos) - #[rustc_nounwind] - pub fn cosf64(x: f64) -> f64; - /// Returns the cosine of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::cos`](../../std/primitive.f128.html#method.cos) - #[rustc_nounwind] - pub fn cosf128(x: f128) -> f128; +/// Returns the cosine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::cos`](../../std/primitive.f16.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the cosine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::cos`](../../std/primitive.f32.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the cosine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::cos`](../../std/primitive.f64.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the cosine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::cos`](../../std/primitive.f128.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf128(_x: f128) -> f128 { + unreachable!() +} - /// Raises an `f16` to an `f16` power. - /// - /// The stabilized version of this intrinsic is - /// [`f16::powf`](../../std/primitive.f16.html#method.powf) - #[rustc_nounwind] - pub fn powf16(a: f16, x: f16) -> f16; - /// Raises an `f32` to an `f32` power. - /// - /// The stabilized version of this intrinsic is - /// [`f32::powf`](../../std/primitive.f32.html#method.powf) - #[rustc_nounwind] - pub fn powf32(a: f32, x: f32) -> f32; - /// Raises an `f64` to an `f64` power. - /// - /// The stabilized version of this intrinsic is - /// [`f64::powf`](../../std/primitive.f64.html#method.powf) - #[rustc_nounwind] - pub fn powf64(a: f64, x: f64) -> f64; - /// Raises an `f128` to an `f128` power. - /// - /// The stabilized version of this intrinsic is - /// [`f128::powf`](../../std/primitive.f128.html#method.powf) - #[rustc_nounwind] - pub fn powf128(a: f128, x: f128) -> f128; +/// Raises an `f16` to an `f16` power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powf`](../../std/primitive.f16.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf16(_a: f16, _x: f16) -> f16 { + unreachable!() +} +/// Raises an `f32` to an `f32` power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powf`](../../std/primitive.f32.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf32(_a: f32, _x: f32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an `f64` power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powf`](../../std/primitive.f64.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf64(_a: f64, _x: f64) -> f64 { + unreachable!() +} +/// Raises an `f128` to an `f128` power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powf`](../../std/primitive.f128.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf128(_a: f128, _x: f128) -> f128 { + unreachable!() +} - /// Returns the exponential of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::exp`](../../std/primitive.f16.html#method.exp) - #[rustc_nounwind] - pub fn expf16(x: f16) -> f16; - /// Returns the exponential of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::exp`](../../std/primitive.f32.html#method.exp) - #[rustc_nounwind] - pub fn expf32(x: f32) -> f32; - /// Returns the exponential of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::exp`](../../std/primitive.f64.html#method.exp) - #[rustc_nounwind] - pub fn expf64(x: f64) -> f64; - /// Returns the exponential of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::exp`](../../std/primitive.f128.html#method.exp) - #[rustc_nounwind] - pub fn expf128(x: f128) -> f128; +/// Returns the exponential of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp`](../../std/primitive.f16.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the exponential of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp`](../../std/primitive.f32.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the exponential of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp`](../../std/primitive.f64.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the exponential of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp`](../../std/primitive.f128.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns 2 raised to the power of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f16(x: f16) -> f16; - /// Returns 2 raised to the power of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f32(x: f32) -> f32; - /// Returns 2 raised to the power of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f64(x: f64) -> f64; - /// Returns 2 raised to the power of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f128(x: f128) -> f128; +/// Returns 2 raised to the power of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns 2 raised to the power of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns 2 raised to the power of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns 2 raised to the power of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the natural logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::ln`](../../std/primitive.f16.html#method.ln) - #[rustc_nounwind] - pub fn logf16(x: f16) -> f16; - /// Returns the natural logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::ln`](../../std/primitive.f32.html#method.ln) - #[rustc_nounwind] - pub fn logf32(x: f32) -> f32; - /// Returns the natural logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::ln`](../../std/primitive.f64.html#method.ln) - #[rustc_nounwind] - pub fn logf64(x: f64) -> f64; - /// Returns the natural logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::ln`](../../std/primitive.f128.html#method.ln) - #[rustc_nounwind] - pub fn logf128(x: f128) -> f128; +/// Returns the natural logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ln`](../../std/primitive.f16.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the natural logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ln`](../../std/primitive.f32.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the natural logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ln`](../../std/primitive.f64.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the natural logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ln`](../../std/primitive.f128.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the base 10 logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::log10`](../../std/primitive.f16.html#method.log10) - #[rustc_nounwind] - pub fn log10f16(x: f16) -> f16; - /// Returns the base 10 logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::log10`](../../std/primitive.f32.html#method.log10) - #[rustc_nounwind] - pub fn log10f32(x: f32) -> f32; - /// Returns the base 10 logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::log10`](../../std/primitive.f64.html#method.log10) - #[rustc_nounwind] - pub fn log10f64(x: f64) -> f64; - /// Returns the base 10 logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::log10`](../../std/primitive.f128.html#method.log10) - #[rustc_nounwind] - pub fn log10f128(x: f128) -> f128; +/// Returns the base 10 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log10`](../../std/primitive.f16.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log10`](../../std/primitive.f32.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log10`](../../std/primitive.f64.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log10`](../../std/primitive.f128.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the base 2 logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::log2`](../../std/primitive.f16.html#method.log2) - #[rustc_nounwind] - pub fn log2f16(x: f16) -> f16; - /// Returns the base 2 logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::log2`](../../std/primitive.f32.html#method.log2) - #[rustc_nounwind] - pub fn log2f32(x: f32) -> f32; - /// Returns the base 2 logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::log2`](../../std/primitive.f64.html#method.log2) - #[rustc_nounwind] - pub fn log2f64(x: f64) -> f64; - /// Returns the base 2 logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::log2`](../../std/primitive.f128.html#method.log2) - #[rustc_nounwind] - pub fn log2f128(x: f128) -> f128; +/// Returns the base 2 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log2`](../../std/primitive.f16.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log2`](../../std/primitive.f32.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log2`](../../std/primitive.f64.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log2`](../../std/primitive.f128.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns `a * b + c` for `f16` values. - /// - /// The stabilized version of this intrinsic is - /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf16(a: f16, b: f16, c: f16) -> f16; - /// Returns `a * b + c` for `f32` values. - /// - /// The stabilized version of this intrinsic is - /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; - /// Returns `a * b + c` for `f64` values. - /// - /// The stabilized version of this intrinsic is - /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; - /// Returns `a * b + c` for `f128` values. - /// - /// The stabilized version of this intrinsic is - /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; +/// Returns `a * b + c` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} - /// Returns `a * b + c` for `f16` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; - /// Returns `a * b + c` for `f32` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; - /// Returns `a * b + c` for `f64` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; - /// Returns `a * b + c` for `f128` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; +/// Returns `a * b + c` for `f16` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} - /// Returns the largest integer less than or equal to an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::floor`](../../std/primitive.f16.html#method.floor) - #[rustc_nounwind] - pub fn floorf16(x: f16) -> f16; - /// Returns the largest integer less than or equal to an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::floor`](../../std/primitive.f32.html#method.floor) - #[rustc_nounwind] - pub fn floorf32(x: f32) -> f32; - /// Returns the largest integer less than or equal to an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::floor`](../../std/primitive.f64.html#method.floor) - #[rustc_nounwind] - pub fn floorf64(x: f64) -> f64; - /// Returns the largest integer less than or equal to an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::floor`](../../std/primitive.f128.html#method.floor) - #[rustc_nounwind] - pub fn floorf128(x: f128) -> f128; +/// Returns the largest integer less than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::floor`](../../std/primitive.f16.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::floor`](../../std/primitive.f32.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::floor`](../../std/primitive.f64.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::floor`](../../std/primitive.f128.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the smallest integer greater than or equal to an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf16(x: f16) -> f16; - /// Returns the smallest integer greater than or equal to an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf32(x: f32) -> f32; - /// Returns the smallest integer greater than or equal to an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf64(x: f64) -> f64; - /// Returns the smallest integer greater than or equal to an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf128(x: f128) -> f128; +/// Returns the smallest integer greater than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the integer part of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc) - #[rustc_nounwind] - pub fn truncf16(x: f16) -> f16; - /// Returns the integer part of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) - #[rustc_nounwind] - pub fn truncf32(x: f32) -> f32; - /// Returns the integer part of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) - #[rustc_nounwind] - pub fn truncf64(x: f64) -> f64; - /// Returns the integer part of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc) - #[rustc_nounwind] - pub fn truncf128(x: f128) -> f128; +/// Returns the integer part of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the integer part of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the integer part of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the integer part of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f16::round`](../../std/primitive.f16.html#method.round) - #[rustc_nounwind] - pub fn roundf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f32::round`](../../std/primitive.f32.html#method.round) - #[rustc_nounwind] - pub fn roundf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f64::round`](../../std/primitive.f64.html#method.round) - #[rustc_nounwind] - pub fn roundf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f128::round`](../../std/primitive.f128.html#method.round) - #[rustc_nounwind] - pub fn roundf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round`](../../std/primitive.f16.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round`](../../std/primitive.f32.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round`](../../std/primitive.f64.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round`](../../std/primitive.f128.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf128(_x: f128) -> f128 { + unreachable!() +} - /// Float addition that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fadd_fast<T: Copy>(a: T, b: T) -> T; +/// Float addition that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fadd_fast<T: Copy>(_a: T, _b: T) -> T { + unreachable!() +} - /// Float subtraction that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fsub_fast<T: Copy>(a: T, b: T) -> T; +/// Float subtraction that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fsub_fast<T: Copy>(_a: T, _b: T) -> T { + unreachable!() +} - /// Float multiplication that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fmul_fast<T: Copy>(a: T, b: T) -> T; +/// Float multiplication that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmul_fast<T: Copy>(_a: T, _b: T) -> T { + unreachable!() +} - /// Float division that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fdiv_fast<T: Copy>(a: T, b: T) -> T; +/// Float division that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fdiv_fast<T: Copy>(_a: T, _b: T) -> T { + unreachable!() +} - /// Float remainder that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn frem_fast<T: Copy>(a: T, b: T) -> T; +/// Float remainder that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn frem_fast<T: Copy>(_a: T, _b: T) -> T { + unreachable!() +} - /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range - /// (<https://github.com/rust-lang/rust/issues/10184>) - /// - /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. - #[rustc_nounwind] - pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; +/// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range +/// (<https://github.com/rust-lang/rust/issues/10184>) +/// +/// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int { + unreachable!() } /// Float addition that allows optimizations based on algebraic rules. @@ -2723,8 +3056,7 @@ pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2768,8 +3100,7 @@ pub const fn ctpop<T: Copy>(_x: T) -> u32 { /// let num_leading = ctlz(x); /// assert_eq!(num_leading, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2794,8 +3125,7 @@ pub const fn ctlz<T: Copy>(_x: T) -> u32 { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2839,8 +3169,7 @@ pub const unsafe fn ctlz_nonzero<T: Copy>(_x: T) -> u32 { /// let num_trailing = cttz(x); /// assert_eq!(num_trailing, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2865,8 +3194,7 @@ pub const fn cttz<T: Copy>(_x: T) -> u32 { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2884,8 +3212,7 @@ pub const unsafe fn cttz_nonzero<T: Copy>(_x: T) -> u32 { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2903,8 +3230,7 @@ pub const fn bswap<T: Copy>(_x: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2919,7 +3245,6 @@ pub const fn bitreverse<T: Copy>(_x: T) -> T { /// large and difficult to optimize. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_three_way_compare", issue = "none"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn three_way_compare<T: Copy>(_lhs: T, _rhss: T) -> crate::cmp::Ordering { @@ -2936,8 +3261,7 @@ pub const fn three_way_compare<T: Copy>(_lhs: T, _rhss: T) -> crate::cmp::Orderi /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2955,8 +3279,7 @@ pub const fn add_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2974,8 +3297,7 @@ pub const fn sub_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2987,7 +3309,6 @@ pub const fn mul_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_exact_div", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3001,8 +3322,7 @@ pub const unsafe fn exact_div<T: Copy>(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3015,8 +3335,7 @@ pub const unsafe fn unchecked_div<T: Copy>(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3030,8 +3349,7 @@ pub const unsafe fn unchecked_rem<T: Copy>(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3044,8 +3362,7 @@ pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(_x: T, _y: U) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3058,8 +3375,7 @@ pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(_x: T, _y: U) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_add` on the various /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3072,8 +3388,7 @@ pub const unsafe fn unchecked_add<T: Copy>(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_sub` on the various /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3086,8 +3401,7 @@ pub const unsafe fn unchecked_sub<T: Copy>(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_mul` on the various /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3105,8 +3419,7 @@ pub const unsafe fn unchecked_mul<T: Copy>(_x: T, _y: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3124,8 +3437,7 @@ pub const fn rotate_left<T: Copy>(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3143,8 +3455,7 @@ pub const fn rotate_right<T: Copy>(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3161,8 +3472,7 @@ pub const fn wrapping_add<T: Copy>(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3179,8 +3489,7 @@ pub const fn wrapping_sub<T: Copy>(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3198,8 +3507,7 @@ pub const fn wrapping_mul<T: Copy>(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3216,8 +3524,7 @@ pub const fn saturating_add<T: Copy>(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3231,8 +3538,7 @@ pub const fn saturating_sub<T: Copy>(_a: T, _b: T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it /// trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3246,8 +3552,7 @@ pub const unsafe fn read_via_copy<T>(_ptr: *const T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3264,8 +3569,7 @@ pub const unsafe fn write_via_move<T>(_ptr: *mut T, _value: T) { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3304,8 +3608,7 @@ extern "rust-intrinsic" { } /// See documentation of `<*const T>::offset_from` for details. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3314,7 +3617,6 @@ pub const unsafe fn ptr_offset_from<T>(_ptr: *const T, _base: *const T) -> isize } /// See documentation of `<*const T>::sub_ptr` for details. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3326,7 +3628,6 @@ pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T) /// Returns `2` if the result is unknown. /// Returns `1` if the pointers are guaranteed equal. /// Returns `0` if the pointers are guaranteed inequal. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] #[rustc_do_not_const_check] @@ -3359,7 +3660,6 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { /// /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3381,10 +3681,6 @@ pub const unsafe fn raw_eq<T>(_a: &T, _b: &T) -> bool { /// that differs. That allows optimizations that can read in large chunks. /// /// [valid]: crate::ptr#safety -#[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none") -)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3395,7 +3691,6 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u /// See documentation of [`std::hint::black_box`] for details. /// /// [`std::hint::black_box`]: crate::hint::black_box -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_black_box", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3627,11 +3922,7 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_is_val_statically_known", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[rustc_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -3673,8 +3964,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] // just for UB checks +#[rustc_intrinsic_const_stable_indirect] // just for UB checks #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { @@ -3757,8 +4047,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { /// The stabilized version of this intrinsic is [`core::mem::size_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn size_of<T>() -> usize { @@ -3775,8 +4064,7 @@ pub const fn size_of<T>() -> usize { /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn min_align_of<T>() -> usize { @@ -3789,7 +4077,6 @@ pub const fn min_align_of<T>() -> usize { /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_pref_align_of", issue = "91971"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn pref_align_of<T>() -> usize { @@ -3807,7 +4094,6 @@ pub const unsafe fn pref_align_of<T>() -> usize { /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "variant_count", issue = "73662"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn variant_count<T>() -> usize { @@ -3823,9 +4109,9 @@ pub const fn variant_count<T>() -> usize { /// See [`crate::mem::size_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_size_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize { unreachable!() } @@ -3839,9 +4125,9 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize { /// See [`crate::mem::align_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_align_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize { unreachable!() } @@ -3856,7 +4142,6 @@ pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize { /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name", issue = "63084"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_name<T: ?Sized>() -> &'static str { @@ -3875,7 +4160,6 @@ pub const fn type_name<T: ?Sized>() -> &'static str { /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_id", issue = "77125"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_id<T: ?Sized + 'static>() -> u128 { @@ -3889,8 +4173,7 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P { @@ -3915,11 +4198,7 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr( - bootstrap, - cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")) -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M { @@ -4025,8 +4304,7 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4132,8 +4410,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4216,8 +4493,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4250,7 +4526,6 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { /// The stabilized version of this intrinsic is /// [`f16::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf16(_x: f16, _y: f16) -> f16 { @@ -4267,11 +4542,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf32(_x: f32, _y: f32) -> f32 { @@ -4288,11 +4559,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf64(_x: f64, _y: f64) -> f64 { @@ -4309,7 +4576,6 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf128(_x: f128, _y: f128) -> f128 { @@ -4326,7 +4592,6 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { @@ -4343,11 +4608,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { @@ -4364,11 +4625,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { @@ -4385,7 +4642,6 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { @@ -4397,7 +4653,6 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::abs`](../../std/primitive.f16.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf16(_x: f16) -> f16 { @@ -4409,11 +4664,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::abs`](../../std/primitive.f32.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf32(_x: f32) -> f32 { @@ -4425,11 +4676,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::abs`](../../std/primitive.f64.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf64(_x: f64) -> f64 { @@ -4441,7 +4688,6 @@ pub const unsafe fn fabsf64(_x: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::abs`](../../std/primitive.f128.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf128(_x: f128) -> f128 { @@ -4453,7 +4699,6 @@ pub const unsafe fn fabsf128(_x: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { @@ -4465,11 +4710,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { @@ -4480,11 +4721,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { @@ -4496,7 +4733,6 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 5ddca9c4dce..f80a60d471c 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -612,6 +612,21 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_fma<T>(x: T, y: T, z: T) -> T; + /// Computes `(x*y) + z` for each element, non-deterministically executing either + /// a fused multiply-add or two operations with rounding of the intermediate result. + /// + /// The operation is fused if the code generator determines that target instruction + /// set has support for a fused operation, and that the fused operation is more efficient + /// than the equivalent, separate pair of mul and add instructions. It is unspecified + /// whether or not a fused operation is selected, and that may depend on optimization + /// level and context, for example. It may even be the case that some SIMD lanes get fused + /// and others do not. + /// + /// `T` must be a vector of floats. + #[cfg(not(bootstrap))] + #[rustc_nounwind] + pub fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T; + // Computes the sine of each element. /// /// `T` must be a vector of floats. diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index ffaf1bc56e9..38dfbbef393 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1553,7 +1553,7 @@ pub trait Iterator { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a + /// Panics if `N` is zero. This check will most probably get changed to a /// compile time error before this method gets stabilized. /// /// ```should_panic @@ -3454,7 +3454,7 @@ pub trait Iterator { /// /// # Panics /// - /// Panics if `N` is 0. + /// Panics if `N` is zero. /// /// # Examples /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a178d101254..ab9c33ee754 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,28 +107,9 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_exact_div))] -#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] -#![cfg_attr(bootstrap, feature(const_ub_checks))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(const_align_of_val)] -#![feature(const_align_of_val_raw)] -#![feature(const_alloc_layout)] -#![feature(const_black_box)] -#![feature(const_eq_ignore_ascii_case)] #![feature(const_eval_select)] -#![feature(const_heap)] -#![feature(const_nonnull_new)] -#![feature(const_ptr_sub_ptr)] -#![feature(const_raw_ptr_comparison)] -#![feature(const_size_of_val)] -#![feature(const_size_of_val_raw)] -#![feature(const_sockaddr_setters)] -#![feature(const_swap)] -#![feature(const_try)] -#![feature(const_type_id)] -#![feature(const_type_name)] #![feature(const_typed_swap)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] @@ -144,6 +125,7 @@ #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] +#![feature(slice_as_array)] #![feature(slice_as_chunks)] #![feature(slice_ptr_get)] #![feature(str_internals)] @@ -158,8 +140,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -169,10 +149,7 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_ub_checks)] -#![feature(const_for)] -#![feature(const_is_char_boundary)] #![feature(const_precise_live_drops)] -#![feature(const_str_split_at)] #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] @@ -209,6 +186,7 @@ #![feature(simd_ffi)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(target_feature_11)] #![feature(trait_alias)] #![feature(transparent_unions)] @@ -258,7 +236,6 @@ pub mod assert_matches { } // We don't export this through #[macro_export] for now, to avoid breakage. -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// Unstable module containing the unstable `autodiff` macro. pub mod autodiff { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 771c2d31b60..ab674b58902 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1554,7 +1554,6 @@ pub(crate) mod builtin { #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro autodiff($item:item) { /* compiler built-in */ } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 27273e4eedf..9b3d6902098 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -485,9 +485,9 @@ impl<T> MaybeUninit<T> { /// } /// } /// ``` - #[stable(feature = "maybe_uninit_write", since = "1.55.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")] #[inline(always)] + #[stable(feature = "maybe_uninit_write", since = "1.55.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "CURRENT_RUSTC_VERSION")] pub const fn write(&mut self, val: T) -> &mut T { *self = MaybeUninit::new(val); // SAFETY: We just initialized this value. @@ -529,7 +529,7 @@ impl<T> MaybeUninit<T> { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_ptr(&self) -> *const T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -571,7 +571,7 @@ impl<T> MaybeUninit<T> { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -911,10 +911,7 @@ impl<T> MaybeUninit<T> { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_assume_init", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.84.0")] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` is initialized. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 4cf52042a57..78ad6880709 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -333,7 +333,7 @@ pub const fn size_of<T>() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer @@ -390,7 +390,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -#[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")] pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::size_of_val(val) } @@ -485,7 +484,7 @@ pub const fn align_of<T>() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] +#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")] #[allow(deprecated)] pub const fn align_of_val<T: ?Sized>(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer @@ -534,7 +533,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -#[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")] pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::min_align_of_val(val) } diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 6746f0b2b31..82f11f0eaac 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1601,8 +1601,8 @@ impl Ipv6Addr { /// ``` #[must_use] #[inline] - #[stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] pub const fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 } @@ -1679,8 +1679,8 @@ impl Ipv6Addr { /// ``` #[must_use] #[inline] - #[stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] pub const fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index abeccb7eea2..4ebeaf04611 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -807,7 +807,6 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// #![feature(num_midpoint)] /// # // Using aarch64 because `reliable_f128_math` is needed /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { /// @@ -817,8 +816,8 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - // #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f128) -> f128 { + #[rustc_const_unstable(feature = "f128", issue = "116909")] + pub const fn midpoint(self, other: f128) -> f128 { const LO: f128 = f128::MIN_POSITIVE * 2.; const HI: f128 = f128::MAX / 2.; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 0d3e9269570..c82f0d7cd4a 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -795,7 +795,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(num_midpoint)] /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 /// /// assert_eq!(1f16.midpoint(4.0), 2.5); @@ -804,8 +803,8 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - // #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f16) -> f16 { + #[rustc_const_unstable(feature = "f16", issue = "116909")] + pub const fn midpoint(self, other: f16) -> f16 { const LO: f16 = f16::MIN_POSITIVE * 2.; const HI: f16 = f16::MAX / 2.; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 47dfce7530f..4c0d95f95e5 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -984,27 +984,27 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] /// assert_eq!(1f32.midpoint(4.0), 2.5); /// assert_eq!((-5.5f32).midpoint(8.0), 1.25); /// ``` #[inline] - #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f32) -> f32 { + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f32) -> f32 { cfg_if! { + // Allow faster implementation that have known good 64-bit float + // implementations. Falling back to the branchy code on targets that don't + // have 64-bit hardware floats or buggy implementations. + // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 if #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", - all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"), - all(target_arch = "arm", target_feature="vfp2"), + all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"), + all(target_arch = "arm", target_feature = "vfp2"), target_arch = "wasm32", target_arch = "wasm64", ))] { - // whitelist the faster implementation to targets that have known good 64-bit float - // implementations. Falling back to the branchy code on targets that don't have - // 64-bit hardware floats or buggy implementations. - // see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 - ((f64::from(self) + f64::from(other)) / 2.0) as f32 + ((self as f64 + other as f64) / 2.0) as f32 } else { const LO: f32 = f32::MIN_POSITIVE * 2.; const HI: f32 = f32::MAX / 2.; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index c89023c1ae4..77ca56df067 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1002,13 +1002,13 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] /// assert_eq!(1f64.midpoint(4.0), 2.5); /// assert_eq!((-5.5f64).midpoint(8.0), 1.25); /// ``` #[inline] - #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f64) -> f64 { + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f64) -> f64 { const LO: f64 = f64::MIN_POSITIVE * 2.; const HI: f64 = f64::MAX / 2.; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 64dcb4c91e6..9a202600988 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1152,7 +1152,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_neg", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_neg(self) -> Self { @@ -1217,7 +1216,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1282,7 +1280,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1340,7 +1337,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1405,7 +1401,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -1613,8 +1608,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1828,7 +1823,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -1986,7 +1981,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2014,7 +2009,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2042,7 +2037,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2069,7 +2064,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2134,7 +2129,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2164,7 +2158,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2526,7 +2519,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2557,7 +2550,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2588,7 +2581,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2619,7 +2612,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2860,8 +2853,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2887,7 +2880,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -2926,7 +2919,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` and /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -2975,7 +2968,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -3019,7 +3012,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9d9897b9cf0..e36f20fd576 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -103,18 +103,18 @@ macro_rules! midpoint_impl { ($SelfT:ty, unsigned) => { /// Calculates the middle point of `self` and `rhs`. /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. /// /// # Examples /// /// ``` - /// #![feature(num_midpoint)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -134,14 +134,14 @@ macro_rules! midpoint_impl { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] + /// #![feature(num_midpoint_signed)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[unstable(feature = "num_midpoint_signed", issue = "110840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -157,18 +157,18 @@ macro_rules! midpoint_impl { ($SelfT:ty, $WideT:ty, unsigned) => { /// Calculates the middle point of `self` and `rhs`. /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. /// /// # Examples /// /// ``` - /// #![feature(num_midpoint)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -186,14 +186,14 @@ macro_rules! midpoint_impl { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] + /// #![feature(num_midpoint_signed)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[unstable(feature = "num_midpoint_signed", issue = "110840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -677,7 +677,7 @@ impl u8 { /// /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); @@ -703,7 +703,7 @@ impl u8 { /// /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); @@ -1449,7 +1449,6 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } #[doc(hidden)] #[inline(always)] #[unstable(issue = "none", feature = "std_internals")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_from_str", since = "1.82.0"))] pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b883a0c2ec7..e97af081143 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -139,9 +139,9 @@ impl_nonzero_fmt! { LowerHex #[stable(feature = "nonzero", since = "1.28.0")] UpperHex - #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] LowerExp - #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] UpperExp } @@ -614,7 +614,6 @@ macro_rules! nonzero_integer { /// ``` /// #[unstable(feature = "non_zero_count_ones", issue = "120287")] - #[rustc_const_unstable(feature = "non_zero_count_ones", issue = "120287")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] #[must_use = "this returns the result of the operation, \ @@ -1509,8 +1508,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] - /// /// # use std::num::NonZero; /// # /// # fn main() { test().unwrap(); } @@ -1524,7 +1521,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Some(()) /// # } /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1587,8 +1585,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Some(()) /// # } /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0383c13fa08..c79b2f7ad8e 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1434,7 +1434,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1499,7 +1498,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1557,7 +1555,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1622,7 +1619,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -1877,7 +1873,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2034,7 +2030,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2063,7 +2059,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2091,7 +2087,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2121,7 +2117,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2193,7 +2189,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2226,7 +2221,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2360,7 +2354,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_add(rhs); let (c, d) = a.overflowing_add(carry as $SelfT); - (c, b || d) + (c, b | d) } /// Calculates `self` + `rhs` with a signed `rhs`. @@ -2451,7 +2445,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_sub(rhs); let (c, d) = a.overflowing_sub(borrow as $SelfT); - (c, b || d) + (c, b | d) } /// Calculates `self` - `rhs` with a signed `rhs` @@ -2545,7 +2539,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2576,7 +2570,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2604,7 +2598,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2635,7 +2629,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2838,8 +2832,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2872,7 +2866,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2900,7 +2894,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -3091,7 +3085,6 @@ macro_rules! uint_impl { // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_pow", since = "1.50.0"))] const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } @@ -3169,7 +3162,6 @@ macro_rules! uint_impl { #[inline] #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behavior")] - #[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 55deabbee8f..c4429b3cd7d 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -79,6 +79,7 @@ use crate::{convert, ops}; /// [`Break`]: ControlFlow::Break /// [`Continue`]: ControlFlow::Continue #[stable(feature = "control_flow_enum_type", since = "1.55.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ControlFlow")] // ControlFlow should not implement PartialOrd or Ord, per RFC 3058: // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index e9bb40d0fdd..c36d55fe2a8 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -405,18 +405,15 @@ unsafe impl<T: ?Sized> DerefPure for &mut T {} /// } /// ``` #[lang = "receiver"] -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] pub trait Receiver { /// The target type on which the method may be called. - #[cfg(not(bootstrap))] #[rustc_diagnostic_item = "receiver_target"] #[lang = "receiver_target"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] type Target: ?Sized; } -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] impl<P: ?Sized, T: ?Sized> Receiver for P where @@ -433,8 +430,7 @@ where /// facility based around the current "arbitrary self types" unstable feature. /// That new facility will use the replacement trait above called `Receiver` /// which is why this is now named `LegacyReceiver`. -#[cfg_attr(bootstrap, lang = "receiver")] -#[cfg_attr(not(bootstrap), lang = "legacy_receiver")] +#[lang = "legacy_receiver"] #[unstable(feature = "legacy_receiver_trait", issue = "none")] #[doc(hidden)] pub trait LegacyReceiver { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index cea1f84f3fd..40526f9583e 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -171,7 +171,6 @@ pub use self::deref::DerefPure; #[unstable(feature = "legacy_receiver_trait", issue = "none")] pub use self::deref::LegacyReceiver; #[unstable(feature = "arbitrary_self_types", issue = "44874")] -#[cfg(not(bootstrap))] pub use self::deref::Receiver; #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 29d1956af95..f4ac7af6396 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -563,7 +563,7 @@ use crate::pin::Pin; use crate::{cmp, convert, hint, mem, slice}; /// The `Option` type. See [the module level documentation](self) for more. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, Eq, Debug, Hash)] #[rustc_diagnostic_item = "Option"] #[lang = "Option"] @@ -738,7 +738,7 @@ impl<T> Option<T> { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> { // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { @@ -755,7 +755,7 @@ impl<T> Option<T> { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. @@ -802,7 +802,7 @@ impl<T> Option<T> { #[inline] #[must_use] #[stable(feature = "option_as_slice", since = "1.75.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_slice(&self) -> &[T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -857,7 +857,7 @@ impl<T> Option<T> { #[inline] #[must_use] #[stable(feature = "option_as_slice", since = "1.75.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 179aadf0c28..5fa340a6147 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -208,14 +208,13 @@ pub macro const_panic { #[rustc_allow_const_fn_unstable(const_eval_select)] #[inline(always)] // inline the wrapper #[track_caller] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))] const fn do_panic($($arg: $ty),*) -> ! { $crate::intrinsics::const_eval_select!( @capture { $($arg: $ty = $arg),* } -> !: #[noinline] if const #[track_caller] #[inline] { // Inline this, to prevent codegen $crate::panic!($const_msg) - } else #[track_caller] #[cfg_attr(bootstrap, inline)] { // Do not inline this, it makes perf worse + } else #[track_caller] { // Do not inline this, it makes perf worse $crate::panic!($runtime_msg) } ) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 230a9918dbf..9d53567a26f 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -165,7 +165,7 @@ impl<'a> PanicMessage<'a> { /// /// See [`fmt::Arguments::as_str`] for details. #[stable(feature = "panic_info_message", since = "1.81.0")] - #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index f603eb2971f..53e2b238bae 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -51,8 +51,7 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics #[rustc_do_not_const_check] // hooked by const-eval -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() @@ -86,8 +85,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, // which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { const_eval_select!( @@ -130,8 +128,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = "panic"] // used by lints and miri for panics pub const fn panic(expr: &'static str) -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -169,8 +166,7 @@ macro_rules! panic_const { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable + #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = stringify!($lang)] pub const fn $lang() -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -217,8 +213,7 @@ panic_const! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_nounwind(expr: &'static str) -> ! { panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); } @@ -234,8 +229,7 @@ pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { #[track_caller] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_explicit() -> ! { panic_display(&"explicit panic"); } @@ -252,8 +246,7 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! { #[inline] #[track_caller] #[rustc_diagnostic_item = "panic_str_2015"] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_str_2015(expr: &str) -> ! { panic_display(&expr); } @@ -263,8 +256,7 @@ pub const fn panic_str_2015(expr: &str) -> ! { #[rustc_do_not_const_check] // hooked by const-eval // enforce a &&str argument in const-check and hook this by const-eval #[rustc_const_panic_str] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_display<T: fmt::Display>(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } @@ -333,8 +325,7 @@ fn panic_in_cleanup() -> ! { /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] // needed by const-eval machine to replace calls to `panic_fmt` lang item -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if let Some(msg) = fmt.as_str() { // The panic_display function is hooked by const eval. diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index c14c49a0d92..f18a45083ff 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -373,9 +373,9 @@ //! exactly what we did with our `AddrTracker` example above. Without doing this, you *must not* //! rely on pinning-related guarantees to apply to your type! //! -//! If need to truly pin a value of a foreign or built-in type that implements [`Unpin`], you'll -//! need to create your own wrapper type around the [`Unpin`] type you want to pin and then -//! opts-out of [`Unpin`] using [`PhantomPinned`]. +//! If you really need to pin a value of a foreign or built-in type that implements [`Unpin`], +//! you'll need to create your own wrapper type around the [`Unpin`] type you want to pin and then +//! opt-out of [`Unpin`] using [`PhantomPinned`]. //! //! Exposing access to the inner field which you want to remain pinned must then be carefully //! considered as well! Remember, exposing a method that gives access to a @@ -1186,7 +1186,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> { /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); /// ``` #[inline(always)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn new(pointer: Ptr) -> Pin<Ptr> { // SAFETY: the value pointed to is `Unpin`, and so has no requirements @@ -1215,7 +1215,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> { /// ``` #[inline(always)] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const fn into_inner(pin: Pin<Ptr>) -> Ptr { pin.__pointer @@ -1352,7 +1352,7 @@ impl<Ptr: Deref> Pin<Ptr> { /// [`pin` module docs]: self #[lang = "new_unchecked"] #[inline(always)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> { Pin { __pointer: pointer } @@ -1423,7 +1423,7 @@ impl<Ptr: DerefMut> Pin<Ptr> { /// move in the future, and this method does not enable the pointee to move. "Malicious" /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. - #[stable(feature = "pin_deref_mut", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pin_deref_mut", since = "1.84.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] pub fn as_deref_mut(self: Pin<&mut Pin<Ptr>>) -> Pin<&mut Ptr::Target> { @@ -1505,7 +1505,7 @@ impl<Ptr: Deref> Pin<Ptr> { /// instead. #[inline(always)] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr { pin.__pointer @@ -1561,7 +1561,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// ["pinning projections"]: self#projections-and-structural-pinning #[inline(always)] #[must_use] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { self.__pointer @@ -1572,7 +1572,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { Pin { __pointer: self.__pointer } @@ -1590,7 +1590,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn get_mut(self) -> &'a mut T where T: Unpin, @@ -1611,7 +1611,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { self.__pointer } @@ -1654,7 +1654,7 @@ impl<T: ?Sized> Pin<&'static T> { /// This is safe because `T` is borrowed immutably for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn static_ref(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). @@ -1668,7 +1668,7 @@ impl<T: ?Sized> Pin<&'static mut T> { /// This is safe because `T` is borrowed for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 2538d60a8ee..74a1d40f4e7 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -41,7 +41,6 @@ impl Alignment { /// This provides the same numerical value as [`mem::align_of`], /// but in an `Alignment` instead of a `usize`. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn of<T>() -> Self { // SAFETY: rustc ensures that type alignment is always a power of two. @@ -53,7 +52,6 @@ impl Alignment { /// /// Note that `0` is not a power of two, nor a valid alignment. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn new(align: usize) -> Option<Self> { if align.is_power_of_two() { @@ -73,7 +71,6 @@ impl Alignment { /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. /// It must *not* be zero. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { assert_unsafe_precondition!( @@ -89,7 +86,6 @@ impl Alignment { /// Returns the alignment as a [`usize`]. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_usize(self) -> usize { self.0 as usize @@ -97,7 +93,6 @@ impl Alignment { /// Returns the alignment as a <code>[NonZero]<[usize]></code>. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_nonzero(self) -> NonZero<usize> { // SAFETY: All the discriminants are non-zero. @@ -118,7 +113,6 @@ impl Alignment { /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn log2(self) -> u32 { self.as_nonzero().trailing_zeros() @@ -148,7 +142,6 @@ impl Alignment { /// assert_ne!(one.mask(Alignment::of::<Align4>().mask()), one); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn mask(self) -> usize { // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0dbe819acb1..f100adecbbb 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -29,7 +29,7 @@ impl<T: ?Sized> *const T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] @@ -113,7 +113,6 @@ impl<T: ?Sized> *const T { /// println!("{:?}", unsafe { &*bad }); /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U @@ -159,7 +158,7 @@ impl<T: ?Sized> *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> usize { // A pointer-to-integer transmute currently has exactly the right semantics: it returns the // address without exposing the provenance. Note that this is *not* a stable guarantee about @@ -193,7 +192,7 @@ impl<T: ?Sized> *const T { /// [`with_exposed_provenance`]: with_exposed_provenance #[must_use] #[inline(always)] - #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "exposed_provenance", since = "1.84.0")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } @@ -211,7 +210,7 @@ impl<T: ?Sized> *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: usize) -> Self { // This should probably be an intrinsic to avoid doing any sort of arithmetic, but // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's @@ -230,7 +229,7 @@ impl<T: ?Sized> *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -282,7 +281,7 @@ impl<T: ?Sized> *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid @@ -347,7 +346,6 @@ impl<T: ?Sized> *const T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>> where T: Sized, @@ -1018,7 +1016,6 @@ impl<T: ?Sized> *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self @@ -1526,6 +1523,21 @@ impl<T> *const [T] { self as *const T } + /// Gets a raw pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array<const N: usize>(self) -> Option<*const [T; N]> { + if self.len() == N { + let me = self.as_ptr() as *const [T; N]; + Some(me) + } else { + None + } + } + /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// @@ -1594,7 +1606,6 @@ impl<T> *const [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> { if self.is_null() { None diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 5f20cb2ee72..ae9810e558a 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,6 @@ pub trait Thin = Pointee<Metadata = ()>; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata { ptr_metadata(ptr) @@ -106,7 +105,6 @@ pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts<T: ?Sized>( data_pointer: *const impl Thin, @@ -120,7 +118,6 @@ pub const fn from_raw_parts<T: ?Sized>( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts_mut<T: ?Sized>( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 805edddfe63..bc4c4e168a3 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -591,8 +591,8 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn without_provenance<T>(addr: usize) -> *const T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute @@ -613,8 +613,8 @@ pub const fn without_provenance<T>(addr: usize) -> *const T { /// some other means. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn dangling<T>() -> *const T { without_provenance(mem::align_of::<T>()) } @@ -634,8 +634,8 @@ pub const fn dangling<T>() -> *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn without_provenance_mut<T>(addr: usize) -> *mut T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute @@ -656,8 +656,8 @@ pub const fn without_provenance_mut<T>(addr: usize) -> *mut T { /// some other means. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn dangling_mut<T>() -> *mut T { without_provenance_mut(mem::align_of::<T>()) } @@ -695,7 +695,7 @@ pub const fn dangling_mut<T>() -> *mut T { /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exposed_provenance", since = "1.84.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn with_exposed_provenance<T>(addr: usize) -> *const T { @@ -735,7 +735,7 @@ pub fn with_exposed_provenance<T>(addr: usize) -> *const T { /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exposed_provenance", since = "1.84.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T { @@ -1009,6 +1009,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[rustc_diagnostic_item = "ptr_swap"] +#[rustc_const_stable_indirect] pub const unsafe fn swap<T>(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. @@ -1069,7 +1070,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) { /// ``` #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] -#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_const_unstable(feature = "const_swap_nonoverlapping", issue = "133668")] #[rustc_diagnostic_item = "ptr_swap_nonoverlapping"] pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { #[allow(unused)] @@ -1129,7 +1130,6 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { /// LLVM can vectorize this (at least it can for the power-of-two-sized types /// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] -#[rustc_const_unstable(feature = "const_swap", issue = "83163")] const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) { let x = x.cast::<MaybeUninit<T>>(); let y = y.cast::<MaybeUninit<T>>(); @@ -2111,7 +2111,6 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { /// when compiled with optimization: /// /// ``` -/// # #![feature(ptr_fn_addr_eq)] /// let f: fn(i32) -> i32 = |x| x; /// let g: fn(i32) -> i32 = |x| x + 0; // different closure, different body /// let h: fn(u32) -> u32 = |x| x + 0; // different signature too @@ -2136,7 +2135,6 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { /// # Examples /// /// ``` -/// #![feature(ptr_fn_addr_eq)] /// use std::ptr; /// /// fn a() { println!("a"); } @@ -2145,7 +2143,7 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { /// ``` /// /// [subtype]: https://doc.rust-lang.org/reference/subtyping.html -#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")] +#[stable(feature = "ptr_fn_addr_eq", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[must_use = "function pointer comparison produces a value"] pub fn fn_addr_eq<T: FnPtr, U: FnPtr>(f: T, g: U) -> bool { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f0204bd0f77..6d0361b8c63 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,7 +29,7 @@ impl<T: ?Sized> *mut T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { @@ -94,7 +94,6 @@ impl<T: ?Sized> *mut T { /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U @@ -146,7 +145,7 @@ impl<T: ?Sized> *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> usize { // A pointer-to-integer transmute currently has exactly the right semantics: it returns the // address without exposing the provenance. Note that this is *not* a stable guarantee about @@ -179,7 +178,7 @@ impl<T: ?Sized> *mut T { /// /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut #[inline(always)] - #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "exposed_provenance", since = "1.84.0")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } @@ -197,7 +196,7 @@ impl<T: ?Sized> *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: usize) -> Self { // This should probably be an intrinsic to avoid doing any sort of arithmetic, but // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's @@ -216,7 +215,7 @@ impl<T: ?Sized> *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -271,7 +270,7 @@ impl<T: ?Sized> *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -343,7 +342,6 @@ impl<T: ?Sized> *mut T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>> where T: Sized, @@ -619,7 +617,7 @@ impl<T: ?Sized> *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for @@ -677,7 +675,6 @@ impl<T: ?Sized> *mut T { /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>> where T: Sized, @@ -1097,7 +1094,6 @@ impl<T: ?Sized> *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self @@ -1760,6 +1756,21 @@ impl<T> *mut [T] { self.len() == 0 } + /// Gets a raw, mutable pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array<const N: usize>(self) -> Option<*mut [T; N]> { + if self.len() == N { + let me = self.as_mut_ptr() as *mut [T; N]; + Some(me) + } else { + None + } + } + /// Divides one mutable raw slice into two at an index. /// /// The first will contain all indices from `[0, mid)` (excluding @@ -1949,7 +1960,6 @@ impl<T> *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> { if self.is_null() { None @@ -2001,7 +2011,6 @@ impl<T> *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> { if self.is_null() { None diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index b69f8a4b9d3..d37b7eedfcb 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -278,7 +278,7 @@ impl<T: ?Sized> NonNull<T> { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> NonZero<usize> { // SAFETY: The pointer is guaranteed by the type to be non-null, // meaning that the address will be non-zero. @@ -293,7 +293,7 @@ impl<T: ?Sized> NonNull<T> { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: NonZero<usize>) -> Self { // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } @@ -307,7 +307,7 @@ impl<T: ?Sized> NonNull<T> { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(NonZero<usize>) -> NonZero<usize>) -> Self { self.with_addr(f(self.addr())) } @@ -629,7 +629,6 @@ impl<T: ?Sized> NonNull<T> { #[must_use = "returns a new pointer rather than modifying its argument"] #[stable(feature = "non_null_convenience", since = "1.80.0")] #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index a796820a7e4..ebdc918a729 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -92,6 +92,7 @@ impl<T: ?Sized> Unique<T> { /// Creates a new `Unique` if `ptr` is non-null. #[inline] + // rustc_const_unstable attribute can be removed when `const_nonnull_new` is stable #[rustc_const_unstable(feature = "ptr_internals", issue = "none")] pub const fn new(ptr: *mut T) -> Option<Self> { if let Some(pointer) = NonNull::new(ptr) { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b450123c5aa..9c7be618bc7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -520,7 +520,7 @@ use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// /// See the [module documentation](self) for details. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[rustc_diagnostic_item = "Result"] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 17ad4fd8f67..7cdb896586f 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -88,7 +88,7 @@ impl [u8] { /// /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. @@ -110,7 +110,7 @@ impl [u8] { /// /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 339adad1b17..98db7aaf533 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -16,7 +16,6 @@ const USIZE_BYTES: usize = mem::size_of::<usize>(); /// bytes where the borrow propagated all the way to the most significant /// bit." #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn contains_zero_byte(x: usize) -> bool { x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 } @@ -24,7 +23,6 @@ const fn contains_zero_byte(x: usize) -> bool { /// Returns the first index matching the byte `x` in `text`. #[inline] #[must_use] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> { // Fast path for small slices. if text.len() < 2 * USIZE_BYTES { @@ -35,7 +33,6 @@ pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> { } #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> { let mut i = 0; @@ -52,7 +49,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> { } #[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> { // The runtime version behaves the same as the compiletime version, it's // just more optimized. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b3defba5a98..191eaccff98 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -11,6 +11,7 @@ use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive}; +use crate::panic::const_panic; use crate::simd::{self, Simd}; use crate::ub_checks::assert_unsafe_precondition; use crate::{fmt, hint, ptr, range, slice}; @@ -735,7 +736,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_ptr(&self) -> *const T { @@ -766,7 +767,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { @@ -855,6 +856,42 @@ impl<T> [T] { start..end } + /// Gets a reference to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array<const N: usize>(&self) -> Option<&[T; N]> { + if self.len() == N { + let ptr = self.as_ptr() as *const [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &*ptr }; + Some(me) + } else { + None + } + } + + /// Gets a mutable reference to the slice's underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array<const N: usize>(&mut self) -> Option<&mut [T; N]> { + if self.len() == N { + let ptr = self.as_mut_ptr() as *mut [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &mut *ptr }; + Some(me) + } else { + None + } + } + /// Swaps two elements in the slice. /// /// If `a` equals to `b`, it's guaranteed that elements won't change value. @@ -921,7 +958,7 @@ impl<T> [T] { /// [`swap`]: slice::swap /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_swap_unchecked", issue = "88539")] - #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + #[rustc_const_unstable(feature = "slice_swap_unchecked", issue = "88539")] pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { assert_unsafe_precondition!( check_library_ub, @@ -1039,7 +1076,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `size` is 0. + /// Panics if `size` is zero. /// /// # Examples /// @@ -1095,7 +1132,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1130,7 +1167,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1172,7 +1209,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1211,7 +1248,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1288,7 +1325,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1334,7 +1371,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1372,7 +1409,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1448,7 +1485,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1489,7 +1526,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1533,7 +1570,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1568,7 +1605,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1604,7 +1641,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1639,7 +1676,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1682,7 +1719,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1722,7 +1759,7 @@ impl<T> [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -3665,8 +3702,9 @@ impl<T> [T] { /// [`split_at_mut`]: slice::split_at_mut #[doc(alias = "memcpy")] #[stable(feature = "copy_from_slice", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_copy_from_slice", issue = "131415")] #[track_caller] - pub fn copy_from_slice(&mut self, src: &[T]) + pub const fn copy_from_slice(&mut self, src: &[T]) where T: Copy, { @@ -3675,11 +3713,13 @@ impl<T> [T] { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] - fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { - panic!( - "source slice length ({}) does not match destination slice length ({})", - src_len, dst_len, - ); + const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { + const_panic!( + "copy_from_slice: source slice length does not match destination slice length", + "copy_from_slice: source slice length ({src_len}) does not match destination slice length ({dst_len})", + src_len: usize, + dst_len: usize, + ) } if self.len() != src.len() { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 4629b770cb4..8a473b398bb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -373,7 +373,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_ptr(&self) -> *const u8 { @@ -391,7 +391,7 @@ impl str { #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut u8 { @@ -2503,7 +2503,7 @@ impl str { /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. @@ -2531,7 +2531,7 @@ impl str { /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 7f2a5424787..487fffba881 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -469,7 +469,7 @@ impl AtomicBool { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -1264,7 +1264,7 @@ impl<T> AtomicPtr<T> { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -2263,7 +2263,7 @@ macro_rules! atomic_int { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 34673707f01..41e9c593ebd 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -319,7 +319,6 @@ impl<'a> ContextBuilder<'a> { /// Creates a ContextBuilder from a Waker. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; @@ -373,7 +372,6 @@ impl<'a> ContextBuilder<'a> { /// Builds the `Context`. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 3e6110c9c88..b289f6026ff 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -47,7 +47,6 @@ use crate::intrinsics::{self, const_eval_select}; /// order to call it. Since the precompiled standard library is built with full debuginfo and these /// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough /// debuginfo to have a measurable compile-time impact on debug builds. -#[cfg_attr(bootstrap, allow_internal_unstable(const_ub_checks))] // permit this to be called in stably-const fn #[macro_export] #[unstable(feature = "ub_checks", issue = "none")] macro_rules! assert_unsafe_precondition { @@ -89,7 +88,6 @@ pub use intrinsics::ub_checks as check_library_ub; /// /// The intention is to not do that when running in the interpreter, as that one has its own /// language UB checks which generally produce better errors. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn check_language_ub() -> bool { diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 7f4826402eb..4655d35e9c4 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,7 +1,6 @@ ///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, @@ -424,7 +423,6 @@ pub mod lowercase { (5, 187), (6, 78), (7, 132), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, @@ -549,7 +547,6 @@ pub mod uppercase { (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index f7825571cd7..e0b1c21e1ec 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,7 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_three_way_compare))] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] @@ -16,11 +13,10 @@ #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(clone_to_uninit)] -#![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_eval_select)] -#![feature(const_heap)] #![feature(const_nonnull_new)] +#![feature(const_swap)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] @@ -66,7 +62,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(noop_waker)] -#![feature(num_midpoint)] +#![feature(num_midpoint_signed)] #![feature(numfmt)] #![feature(pattern)] #![feature(pointer_is_aligned_to)] @@ -83,6 +79,7 @@ #![feature(step_trait)] #![feature(str_internals)] #![feature(strict_provenance_atomic_ptr)] +#![feature(strict_provenance_lints)] #![feature(test)] #![feature(trait_upcasting)] #![feature(trusted_len)] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 91f8c977d08..7e9773f2fb9 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -898,6 +898,25 @@ fn test_const_copy() { } #[test] +fn test_const_swap() { + const { + let mut ptr1 = &1; + let mut ptr2 = &666; + + // Swap ptr1 and ptr2, bytewise. `swap` does not take a count + // so the best we can do is use an array. + type T = [u8; mem::size_of::<&i32>()]; + unsafe { + ptr::swap(ptr::from_mut(&mut ptr1).cast::<T>(), ptr::from_mut(&mut ptr2).cast::<T>()); + } + + // Make sure they still work. + assert!(*ptr1 == 666); + assert!(*ptr2 == 1); + }; +} + +#[test] fn test_null_array_as_slice() { let arr: *mut [u8; 4] = null_mut(); let ptr: *mut [u8] = arr.as_mut_slice(); diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 6d1f9764efb..252f118fecf 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -23,7 +23,4 @@ libc = { version = "0.2", default-features = false } [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 925af6c0832..b2389078afd 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -5,7 +5,7 @@ //! documents linked from it. //! These are also good reads: //! * <https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html> -//! * <https://monoinfinito.wordpress.com/series/exception-handling-in-c/> +//! * <https://nicolasbrailo.github.io/blog/projects_texts/13exceptionsunderthehood.html> //! * <https://www.airs.com/blog/index.php?s=exception+frames> //! //! ## A brief summary diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 15770248b31..4aa47ce4e4f 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -22,7 +22,6 @@ // This library is copied into rust-analyzer to allow loading rustc compiled proc macros. // Please avoid unstable features where possible to minimize the amount of changes necessary // to make it compile with rust-analyzer on stable. -#![feature(rustc_allow_const_fn_unstable)] #![feature(staged_api)] #![feature(allow_internal_unstable)] #![feature(decl_macro)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c1ab70b714a..ca8b6af0565 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -34,7 +34,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.162", default-features = false, features = [ +libc = { version = "0.2.167", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } @@ -144,6 +144,4 @@ check-cfg = [ # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', ] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 24bbc2f32cf..109bc394634 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -204,6 +204,25 @@ use crate::ops::Index; /// println!("{viking:?} has {health} hp"); /// } /// ``` +/// +/// # Usage in `const` and `static` +/// +/// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed, +/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the +/// initializer of a `const` or `static` item, you will have to use a different hasher that does not +/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this +/// way is not resistant against HashDoS!** +/// +/// ```rust +/// use std::collections::HashMap; +/// use std::hash::{BuildHasherDefault, DefaultHasher}; +/// use std::sync::Mutex; +/// +/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> = +/// HashMap::with_hasher(BuildHasherDefault::new()); +/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> = +/// Mutex::new(HashMap::with_hasher(BuildHasherDefault::new())); +/// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")] #[stable(feature = "rust1", since = "1.0.0")] @@ -235,7 +254,7 @@ impl<K, V> HashMap<K, V, RandomState> { /// /// The hash map will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash map will not allocate. + /// `capacity`. If `capacity` is zero, the hash map will not allocate. /// /// # Examples /// @@ -277,7 +296,10 @@ impl<K, V, S> HashMap<K, V, S> { /// ``` #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")] + #[rustc_const_stable( + feature = "const_collections_with_hasher", + since = "CURRENT_RUSTC_VERSION" + )] pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> { HashMap { base: base::HashMap::with_hasher(hash_builder) } } @@ -287,7 +309,7 @@ impl<K, V, S> HashMap<K, V, S> { /// /// The hash map will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash map will not allocate. + /// `capacity`. If `capacity` is zero, the hash map will not allocate. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow HashMaps to be resistant to attacks that diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index f86bcdb4796..4c81aaff458 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -101,6 +101,25 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub}; /// [`HashMap`]: crate::collections::HashMap /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell +/// +/// # Usage in `const` and `static` +/// +/// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed, +/// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the +/// initializer of a `const` or `static` item, you will have to use a different hasher that does not +/// involve a random seed, as demonstrated in the following example. **A `HashSet` constructed this +/// way is not resistant against HashDoS!** +/// +/// ```rust +/// use std::collections::HashSet; +/// use std::hash::{BuildHasherDefault, DefaultHasher}; +/// use std::sync::Mutex; +/// +/// const EMPTY_SET: HashSet<String, BuildHasherDefault<DefaultHasher>> = +/// HashSet::with_hasher(BuildHasherDefault::new()); +/// static SET: Mutex<HashSet<String, BuildHasherDefault<DefaultHasher>>> = +/// Mutex::new(HashSet::with_hasher(BuildHasherDefault::new())); +/// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")] #[stable(feature = "rust1", since = "1.0.0")] pub struct HashSet<T, S = RandomState> { @@ -130,7 +149,7 @@ impl<T> HashSet<T, RandomState> { /// /// The hash set will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash set will not allocate. + /// `capacity`. If `capacity` is zero, the hash set will not allocate. /// /// # Examples /// @@ -369,7 +388,10 @@ impl<T, S> HashSet<T, S> { /// ``` #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")] + #[rustc_const_stable( + feature = "const_collections_with_hasher", + since = "CURRENT_RUSTC_VERSION" + )] pub const fn with_hasher(hasher: S) -> HashSet<T, S> { HashSet { base: base::HashSet::with_hasher(hasher) } } @@ -379,7 +401,7 @@ impl<T, S> HashSet<T, S> { /// /// The hash set will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash set will not allocate. + /// `capacity`. If `capacity` is zero, the hash set will not allocate. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow `HashSet`s to be resistant to attacks that diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 27f4daba44b..043747d0bc5 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -608,20 +608,16 @@ impl Error for JoinPathsError { /// /// # Windows /// -/// - Returns the value of the 'HOME' environment variable if it is set -/// (including to an empty string). -/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set -/// (including to an empty string). -/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path. +/// - Returns the value of the 'USERPROFILE' environment variable if it is set, and is not an empty string. +/// - Otherwise, [`GetUserProfileDirectory`][msdn] is used to return the path. This may change in the future. /// /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya /// -/// # Deprecation +/// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`. /// -/// This function is deprecated because the behavior on Windows is not correct. -/// The 'HOME' environment variable is not standard on Windows, and may not produce -/// desired results; for instance, under Cygwin or Mingw it will return `/home/you` -/// when it should return `C:\Users\you`. +/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable +/// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you` +/// instead of `C:\Users\you`. /// /// # Examples /// diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 328185d1f2b..fff140f1564 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1229,7 +1229,7 @@ impl From<&OsStr> for Box<OsStr> { } } -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Box<OsStr> { /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>. #[inline] @@ -1309,7 +1309,7 @@ impl From<&OsStr> for Arc<OsStr> { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Arc<OsStr> { /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>. #[inline] @@ -1339,7 +1339,7 @@ impl From<&OsStr> for Rc<OsStr> { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Rc<OsStr> { /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>. #[inline] diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 35b38ed783f..318c3508221 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1200,6 +1200,7 @@ pub trait IsTerminal: crate::sealed::Sealed { /// /// [changes]: io#platform-specific-behavior /// [`Stdin`]: crate::io::Stdin + #[doc(alias = "isatty")] #[stable(feature = "is_terminal", since = "1.70.0")] fn is_terminal(&self) -> bool; } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cf99a618e55..585946c1d50 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,7 +262,6 @@ #![allow(unused_features)] // // Features: -#![cfg_attr(not(bootstrap), feature(autodiff))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -274,13 +273,12 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(asm_experimental_arch)] +#![feature(autodiff)] #![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] @@ -292,7 +290,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] @@ -314,6 +311,7 @@ #![feature(rustdoc_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(thread_local)] #![feature(try_blocks)] #![feature(type_alias_impl_trait)] @@ -322,7 +320,6 @@ // Library features (core): // tidy-alphabetical-start #![feature(array_chunks)] -#![feature(build_hasher_default_const_new)] #![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] @@ -362,6 +359,7 @@ #![feature(strict_provenance_atomic_ptr)] #![feature(sync_unsafe_cell)] #![feature(ub_checks)] +#![feature(used_with_arg)] // tidy-alphabetical-end // // Library features (alloc): @@ -410,9 +408,7 @@ // // Only for const-ness: // tidy-alphabetical-start -#![feature(const_collections_with_hasher)] #![feature(io_const_error)] -#![feature(thread_local_internals)] // tidy-alphabetical-end // #![default_lib_allocator] @@ -622,7 +618,6 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// This module provides support for automatic differentiation. pub mod autodiff { diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs index 7a057ddb861..3b1bd974fa3 100644 --- a/library/std/src/os/darwin/mod.rs +++ b/library/std/src/os/darwin/mod.rs @@ -13,7 +13,7 @@ //! `aarch64-apple-darwin` target names, which are mostly named that way for //! legacy reasons. -#![stable(feature = "os_darwin", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "os_darwin", since = "1.84.0")] #![doc(cfg(target_vendor = "apple"))] pub mod fs; diff --git a/library/std/src/os/hurd/fs.rs b/library/std/src/os/hurd/fs.rs index 00ff1560f31..e3087fa8af1 100644 --- a/library/std/src/os/hurd/fs.rs +++ b/library/std/src/os/hurd/fs.rs @@ -298,7 +298,7 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for Metadata { fn st_dev(&self) -> u64 { - self.as_inner().as_inner().st_fsid as u64 + self.as_inner().as_inner().st_dev as u64 } fn st_ino(&self) -> u64 { self.as_inner().as_inner().st_ino as u64 diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index ba6481f052c..04a45fd035a 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -987,6 +987,11 @@ impl DirBuilderExt for fs::DirBuilder { /// Changing the group typically requires either being the owner and a member of the group, or /// having privileges. /// +/// Be aware that changing owner clears the `suid` and `sgid` permission bits in most cases +/// according to POSIX, usually even if the user is root. The sgid is not cleared when +/// the file is non-group-executable. See: <https://www.man7.org/linux/man-pages/man2/chown.2.html> +/// This call may also clear file capabilities, if there was any. +/// /// If called on a symbolic link, this will change the owner and group of the link target. To /// change the owner and group of the link itself, see [`lchown`]. /// diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index ac1f547c914..97f800dddaa 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -27,6 +27,22 @@ use crate::sys::backtrace; use crate::sys::stdio::panic_output; use crate::{fmt, intrinsics, process, thread}; +// This forces codegen of the function called by panic!() inside the std crate, rather than in +// downstream crates. Primarily this is useful for rustc's codegen tests, which rely on noticing +// complete removal of panic from generated IR. Since begin_panic is inline(never), it's only +// codegen'd once per crate-graph so this pushes that to std rather than our codegen test crates. +// +// (See https://github.com/rust-lang/rust/pull/123244 for more info on why). +// +// If this is causing problems we can also modify those codegen tests to use a crate type like +// cdylib which doesn't export "Rust" symbols to downstream linkage units. +#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] +#[doc(hidden)] +#[allow(dead_code)] +#[used(compiler)] +pub static EMPTY_PANIC: fn(&'static str) -> ! = + begin_panic::<&'static str> as fn(&'static str) -> !; + // Binary interface to the panic runtime that the standard library depends on. // // The standard library is tagged with `#![needs_panic_runtime]` (introduced in diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 33a3e4332f3..5b277a982ee 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1158,6 +1158,7 @@ impl FusedIterator for Ancestors<'_> {} /// Note that `PathBuf` does not always sanitize arguments, for example /// [`push`] allows paths built from strings which include separators: /// +/// ``` /// use std::path::PathBuf; /// /// let mut path = PathBuf::new(); @@ -1166,6 +1167,7 @@ impl FusedIterator for Ancestors<'_> {} /// path.push("windows"); /// path.push(r"..\otherdir"); /// path.push("system32"); +/// ``` /// /// The behavior of `PathBuf` may be changed to a panic on such inputs /// in the future. [`Extend::extend`] should be used to add multi-part paths. @@ -1762,7 +1764,7 @@ impl From<&Path> for Box<Path> { } } -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Box<Path> { /// Creates a boxed [`Path`] from a reference. /// @@ -2000,7 +2002,7 @@ impl From<&Path> for Arc<Path> { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Arc<Path> { /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer. #[inline] @@ -2030,7 +2032,7 @@ impl From<&Path> for Rc<Path> { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Rc<Path> { /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. #[inline] diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 2997e908fa1..ee36127cfdf 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -26,6 +26,7 @@ extern "C" { pub fn tgamma(n: f64) -> f64; pub fn tgammaf(n: f32) -> f32; pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + #[cfg(not(target_os = "aix"))] pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; pub fn acosf128(n: f128) -> f128; @@ -56,6 +57,13 @@ extern "C" { }} } +// On AIX, we don't have lgammaf_r only the f64 version, so we can +// use the f64 version lgamma_r +#[cfg(target_os = "aix")] +pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { + lgamma_r(n.into(), s) as f32 +} + // On 32-bit x86 MSVC these functions aren't defined, so we just define shims // which promote everything to f64, perform the calculation, and then demote // back to f32. While not precisely correct should be "correct enough" for now. diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 60a227afb84..2bf2e2ceb31 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -27,6 +27,14 @@ pub mod thread; #[path = "../unix/time.rs"] pub mod time; +#[path = "../unix/sync"] +pub mod sync { + mod condvar; + mod mutex; + pub use condvar::Condvar; + pub use mutex::Mutex; +} + use crate::io::ErrorKind; pub fn abort_internal() -> ! { diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 4fe18daa204..8eaa50d7f81 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -27,6 +27,7 @@ pub mod pipe; pub mod process; pub mod stack_overflow; pub mod stdio; +pub mod sync; pub mod thread; pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 789a40c13e6..b83772e34c1 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -427,11 +427,13 @@ pub fn current_exe() -> io::Result<PathBuf> { pub fn current_exe() -> io::Result<PathBuf> { unsafe { let mut sz: u32 = 0; + #[expect(deprecated)] libc::_NSGetExecutablePath(ptr::null_mut(), &mut sz); if sz == 0 { return Err(io::Error::last_os_error()); } let mut v: Vec<u8> = Vec::with_capacity(sz as usize); + #[expect(deprecated)] let err = libc::_NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); if err != 0 { return Err(io::Error::last_os_error()); diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index 13290fed762..342818ac911 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -393,7 +393,7 @@ impl Command { fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString { CString::new(s.as_bytes()).unwrap_or_else(|_e| { *saw_nul = true; - CString::new("<string-with-nul>").unwrap() + c"<string-with-nul>".to_owned() }) } diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs new file mode 100644 index 00000000000..73631053e9f --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -0,0 +1,172 @@ +use super::Mutex; +use crate::cell::UnsafeCell; +use crate::pin::Pin; +#[cfg(not(target_os = "nto"))] +use crate::sys::pal::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::pal::time::TIMESPEC_MAX_CAPPED; +use crate::sys::pal::time::Timespec; +use crate::time::Duration; + +pub struct Condvar { + inner: UnsafeCell<libc::pthread_cond_t>, +} + +impl Condvar { + pub fn new() -> Condvar { + Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) } + } + + #[inline] + fn raw(&self) -> *mut libc::pthread_cond_t { + self.inner.get() + } + + /// # Safety + /// `init` must have been called on this instance. + #[inline] + pub unsafe fn notify_one(self: Pin<&Self>) { + let r = unsafe { libc::pthread_cond_signal(self.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// `init` must have been called on this instance. + #[inline] + pub unsafe fn notify_all(self: Pin<&Self>) { + let r = unsafe { libc::pthread_cond_broadcast(self.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// * `init` must have been called on this instance. + /// * `mutex` must be locked by the current thread. + /// * This condition variable may only be used with the same mutex. + #[inline] + pub unsafe fn wait(self: Pin<&Self>, mutex: Pin<&Mutex>) { + let r = unsafe { libc::pthread_cond_wait(self.raw(), mutex.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// * `init` must have been called on this instance. + /// * `mutex` must be locked by the current thread. + /// * This condition variable may only be used with the same mutex. + pub unsafe fn wait_timeout(&self, mutex: Pin<&Mutex>, dur: Duration) -> bool { + let mutex = mutex.raw(); + + // OSX implementation of `pthread_cond_timedwait` is buggy + // with super long durations. When duration is greater than + // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` + // in macOS Sierra returns error 316. + // + // This program demonstrates the issue: + // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c + // + // To work around this issue, the timeout is clamped to 1000 years. + #[cfg(target_vendor = "apple")] + let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); + + let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur); + + #[cfg(not(target_os = "nto"))] + let timeout = timeout.and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); + + #[cfg(target_os = "nto")] + let timeout = timeout.and_then(|t| t.to_timespec_capped()).unwrap_or(TIMESPEC_MAX_CAPPED); + + let r = unsafe { libc::pthread_cond_timedwait(self.raw(), mutex, &timeout) }; + assert!(r == libc::ETIMEDOUT || r == 0); + r == 0 + } +} + +#[cfg(not(any( + target_os = "android", + target_vendor = "apple", + target_os = "espidf", + target_os = "horizon", + target_os = "l4re", + target_os = "redox", + target_os = "teeos", +)))] +impl Condvar { + pub const PRECISE_TIMEOUT: bool = true; + const CLOCK: libc::clockid_t = libc::CLOCK_MONOTONIC; + + /// # Safety + /// May only be called once per instance of `Self`. + pub unsafe fn init(self: Pin<&mut Self>) { + use crate::mem::MaybeUninit; + + struct AttrGuard<'a>(pub &'a mut MaybeUninit<libc::pthread_condattr_t>); + impl Drop for AttrGuard<'_> { + fn drop(&mut self) { + unsafe { + let result = libc::pthread_condattr_destroy(self.0.as_mut_ptr()); + assert_eq!(result, 0); + } + } + } + + unsafe { + let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit(); + let r = libc::pthread_condattr_init(attr.as_mut_ptr()); + assert_eq!(r, 0); + let attr = AttrGuard(&mut attr); + let r = libc::pthread_condattr_setclock(attr.0.as_mut_ptr(), Self::CLOCK); + assert_eq!(r, 0); + let r = libc::pthread_cond_init(self.raw(), attr.0.as_ptr()); + assert_eq!(r, 0); + } + } +} + +// `pthread_condattr_setclock` is unfortunately not supported on these platforms. +#[cfg(any( + target_os = "android", + target_vendor = "apple", + target_os = "espidf", + target_os = "horizon", + target_os = "l4re", + target_os = "redox", + target_os = "teeos", +))] +impl Condvar { + pub const PRECISE_TIMEOUT: bool = false; + const CLOCK: libc::clockid_t = libc::CLOCK_REALTIME; + + /// # Safety + /// May only be called once per instance of `Self`. + pub unsafe fn init(self: Pin<&mut Self>) { + if cfg!(any(target_os = "espidf", target_os = "horizon", target_os = "teeos")) { + // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet + // So on that platform, init() should always be called. + // + // Similar story for the 3DS (horizon) and for TEEOS. + let r = unsafe { libc::pthread_cond_init(self.raw(), crate::ptr::null()) }; + assert_eq!(r, 0); + } + } +} + +impl !Unpin for Condvar {} + +unsafe impl Sync for Condvar {} +unsafe impl Send for Condvar {} + +impl Drop for Condvar { + #[inline] + fn drop(&mut self) { + let r = unsafe { libc::pthread_cond_destroy(self.raw()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_cond_destroy() returns EINVAL if called on + // a condvar that was just initialized with + // libc::PTHREAD_COND_INITIALIZER. Once it is used or + // pthread_cond_init() is called, this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } + } +} diff --git a/library/std/src/sys/pal/unix/sync/mod.rs b/library/std/src/sys/pal/unix/sync/mod.rs new file mode 100644 index 00000000000..b430ff5d8ef --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/mod.rs @@ -0,0 +1,16 @@ +#![cfg(not(any( + target_os = "linux", + target_os = "android", + all(target_os = "emscripten", target_feature = "atomics"), + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "fuchsia", +)))] +#![forbid(unsafe_op_in_unsafe_fn)] + +mod condvar; +mod mutex; + +pub use condvar::Condvar; +pub use mutex::Mutex; diff --git a/library/std/src/sys/pal/unix/sync/mutex.rs b/library/std/src/sys/pal/unix/sync/mutex.rs new file mode 100644 index 00000000000..8ff6c3d3d15 --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/mutex.rs @@ -0,0 +1,135 @@ +use super::super::cvt_nz; +use crate::cell::UnsafeCell; +use crate::io::Error; +use crate::mem::MaybeUninit; +use crate::pin::Pin; + +pub struct Mutex { + inner: UnsafeCell<libc::pthread_mutex_t>, +} + +impl Mutex { + pub fn new() -> Mutex { + Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } + } + + pub(super) fn raw(&self) -> *mut libc::pthread_mutex_t { + self.inner.get() + } + + /// # Safety + /// May only be called once per instance of `Self`. + pub unsafe fn init(self: Pin<&mut Self>) { + // Issue #33770 + // + // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have + // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you + // try to re-lock it from the same thread when you already hold a lock + // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html). + // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL + // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that + // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same + // as setting it to `PTHREAD_MUTEX_NORMAL`, but not setting any mode will result in + // a Mutex where re-locking is UB. + // + // In practice, glibc takes advantage of this undefined behavior to + // implement hardware lock elision, which uses hardware transactional + // memory to avoid acquiring the lock. While a transaction is in + // progress, the lock appears to be unlocked. This isn't a problem for + // other threads since the transactional memory will abort if a conflict + // is detected, however no abort is generated when re-locking from the + // same thread. + // + // Since locking the same mutex twice will result in two aliasing &mut + // references, we instead create the mutex with type + // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to + // re-lock it from the same thread, thus avoiding undefined behavior. + unsafe { + let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); + cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); + let attr = AttrGuard(&mut attr); + cvt_nz(libc::pthread_mutexattr_settype( + attr.0.as_mut_ptr(), + libc::PTHREAD_MUTEX_NORMAL, + )) + .unwrap(); + cvt_nz(libc::pthread_mutex_init(self.raw(), attr.0.as_ptr())).unwrap(); + } + } + + /// # Safety + /// * If `init` was not called on this instance, reentrant locking causes + /// undefined behaviour. + /// * Destroying a locked mutex causes undefined behaviour. + pub unsafe fn lock(self: Pin<&Self>) { + #[cold] + #[inline(never)] + fn fail(r: i32) -> ! { + let error = Error::from_raw_os_error(r); + panic!("failed to lock mutex: {error}"); + } + + let r = unsafe { libc::pthread_mutex_lock(self.raw()) }; + // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect + // the lock call to never fail. Unfortunately however, some platforms + // (Solaris) do not conform to the standard, and instead always provide + // deadlock detection. How kind of them! Unfortunately that means that + // we need to check the error code here. To save us from UB on other + // less well-behaved platforms in the future, we do it even on "good" + // platforms like macOS. See #120147 for more context. + if r != 0 { + fail(r) + } + } + + /// # Safety + /// * If `init` was not called on this instance, reentrant locking causes + /// undefined behaviour. + /// * Destroying a locked mutex causes undefined behaviour. + pub unsafe fn try_lock(self: Pin<&Self>) -> bool { + unsafe { libc::pthread_mutex_trylock(self.raw()) == 0 } + } + + /// # Safety + /// The mutex must be locked by the current thread. + pub unsafe fn unlock(self: Pin<&Self>) { + let r = unsafe { libc::pthread_mutex_unlock(self.raw()) }; + debug_assert_eq!(r, 0); + } +} + +impl !Unpin for Mutex {} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +impl Drop for Mutex { + fn drop(&mut self) { + // SAFETY: + // If `lock` or `init` was called, the mutex must have been pinned, so + // it is still at the same location. Otherwise, `inner` must contain + // `PTHREAD_MUTEX_INITIALIZER`, which is valid at all locations. Thus, + // this call always destroys a valid mutex. + let r = unsafe { libc::pthread_mutex_destroy(self.raw()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a + // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. + // Once it is used (locked/unlocked) or pthread_mutex_init() is called, + // this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } + } +} + +struct AttrGuard<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>); + +impl Drop for AttrGuard<'_> { + fn drop(&mut self) { + unsafe { + let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr()); + assert_eq!(result, 0); + } + } +} diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index 4b83870fdea..f5e19f26bfe 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -2,7 +2,6 @@ use crate::ffi::CStr; use crate::num::NonZero; -use crate::sys::unsupported; use crate::time::Duration; use crate::{io, mem}; @@ -34,6 +33,8 @@ cfg_if::cfg_if! { #[allow(non_camel_case_types)] pub type pthread_t = *mut ffi::c_void; + pub const _SC_NPROCESSORS_ONLN: ffi::c_int = 84; + extern "C" { pub fn pthread_create( native: *mut pthread_t, @@ -121,7 +122,7 @@ impl Thread { } } else { pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> { - unsupported() + crate::sys::unsupported() } } } @@ -187,5 +188,14 @@ impl Thread { } pub fn available_parallelism() -> io::Result<NonZero<usize>> { - unsupported() + cfg_if::cfg_if! { + if #[cfg(target_feature = "atomics")] { + match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { + -1 => Err(io::Error::last_os_error()), + cpus => NonZero::new(cpus as usize).ok_or(io::Error::UNKNOWN_THREAD_COUNT), + } + } else { + crate::sys::unsupported() + } + } } diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 5242bc9da31..5231a34469a 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -377,8 +377,8 @@ fn home_dir_crt() -> Option<PathBuf> { } pub fn home_dir() -> Option<PathBuf> { - crate::env::var_os("HOME") - .or_else(|| crate::env::var_os("USERPROFILE")) + crate::env::var_os("USERPROFILE") + .filter(|s| !s.is_empty()) .map(PathBuf::from) .or_else(home_dir_crt) } diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index ad596ecff65..88a25caeff0 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -5,7 +5,7 @@ //! documents linked from it. //! These are also good reads: //! * <https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html> -//! * <https://monoinfinito.wordpress.com/series/exception-handling-in-c/> +//! * <https://nicolasbrailo.github.io/blog/projects_texts/13exceptionsunderthehood.html> //! * <https://www.airs.com/blog/index.php?s=exception+frames> //! //! ## A brief summary diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 2a67ed766aa..88ce39305e1 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -5,7 +5,6 @@ pub struct Condvar {} impl Condvar { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Condvar { Condvar {} } diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs index cee728e35cd..5bb7431eecf 100644 --- a/library/std/src/sys/sync/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -1,196 +1,88 @@ -use crate::cell::UnsafeCell; +#![forbid(unsafe_op_in_unsafe_fn)] + +use crate::pin::Pin; use crate::ptr; -use crate::sync::atomic::AtomicPtr; +use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::Relaxed; +use crate::sys::pal::sync as pal; use crate::sys::sync::{Mutex, OnceBox}; -#[cfg(not(target_os = "nto"))] -use crate::sys::time::TIMESPEC_MAX; -#[cfg(target_os = "nto")] -use crate::sys::time::TIMESPEC_MAX_CAPPED; -use crate::time::Duration; - -struct AllocatedCondvar(UnsafeCell<libc::pthread_cond_t>); +use crate::time::{Duration, Instant}; pub struct Condvar { - inner: OnceBox<AllocatedCondvar>, - mutex: AtomicPtr<libc::pthread_mutex_t>, -} - -unsafe impl Send for AllocatedCondvar {} -unsafe impl Sync for AllocatedCondvar {} - -impl AllocatedCondvar { - fn new() -> Box<Self> { - let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER))); - - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "l4re", - target_os = "android", - target_os = "redox", - target_vendor = "apple", - ))] { - // `pthread_condattr_setclock` is unfortunately not supported on these platforms. - } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "teeos"))] { - // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet - // So on that platform, init() should always be called - // Moreover, that platform does not have pthread_condattr_setclock support, - // hence that initialization should be skipped as well - // - // Similar story for the 3DS (horizon). - let r = unsafe { libc::pthread_cond_init(condvar.0.get(), crate::ptr::null()) }; - assert_eq!(r, 0); - } else { - use crate::mem::MaybeUninit; - let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit(); - let r = unsafe { libc::pthread_condattr_init(attr.as_mut_ptr()) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_cond_init(condvar.0.get(), attr.as_ptr()) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_condattr_destroy(attr.as_mut_ptr()) }; - assert_eq!(r, 0); - } - } - - condvar - } -} - -impl Drop for AllocatedCondvar { - #[inline] - fn drop(&mut self) { - let r = unsafe { libc::pthread_cond_destroy(self.0.get()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_cond_destroy() returns EINVAL if called on - // a condvar that was just initialized with - // libc::PTHREAD_COND_INITIALIZER. Once it is used or - // pthread_cond_init() is called, this behavior no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } + cvar: OnceBox<pal::Condvar>, + mutex: AtomicUsize, } impl Condvar { pub const fn new() -> Condvar { - Condvar { inner: OnceBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) } + Condvar { cvar: OnceBox::new(), mutex: AtomicUsize::new(0) } } - fn get(&self) -> *mut libc::pthread_cond_t { - self.inner.get_or_init(AllocatedCondvar::new).0.get() + #[inline] + fn get(&self) -> Pin<&pal::Condvar> { + self.cvar.get_or_init(|| { + let mut cvar = Box::pin(pal::Condvar::new()); + // SAFETY: we only call `init` once per `pal::Condvar`, namely here. + unsafe { cvar.as_mut().init() }; + cvar + }) } #[inline] - fn verify(&self, mutex: *mut libc::pthread_mutex_t) { - // Relaxed is okay here because we never read through `self.addr`, and only use it to + fn verify(&self, mutex: Pin<&pal::Mutex>) { + let addr = ptr::from_ref::<pal::Mutex>(&mutex).addr(); + // Relaxed is okay here because we never read through `self.mutex`, and only use it to // compare addresses. - match self.mutex.compare_exchange(ptr::null_mut(), mutex, Relaxed, Relaxed) { - Ok(_) => {} // Stored the address - Err(n) if n == mutex => {} // Lost a race to store the same address + match self.mutex.compare_exchange(0, addr, Relaxed, Relaxed) { + Ok(_) => {} // Stored the address + Err(n) if n == addr => {} // Lost a race to store the same address _ => panic!("attempted to use a condition variable with two mutexes"), } } #[inline] pub fn notify_one(&self) { - let r = unsafe { libc::pthread_cond_signal(self.get()) }; - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above. + unsafe { self.get().notify_one() } } #[inline] pub fn notify_all(&self) { - let r = unsafe { libc::pthread_cond_broadcast(self.get()) }; - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above. + unsafe { self.get().notify_all() } } #[inline] pub unsafe fn wait(&self, mutex: &Mutex) { - let mutex = mutex.get_assert_locked(); + // SAFETY: the caller guarantees that the lock is owned, thus the mutex + // must have been initialized already. + let mutex = unsafe { mutex.pal.get_unchecked() }; self.verify(mutex); - let r = libc::pthread_cond_wait(self.get(), mutex); - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + unsafe { self.get().wait(mutex) } } - // This implementation is used on systems that support pthread_condattr_setclock - // where we configure condition variable to use monotonic clock (instead of - // default system clock). This approach avoids all problems that result - // from changes made to the system time. - #[cfg(not(any( - target_os = "android", - target_os = "espidf", - target_os = "horizon", - target_vendor = "apple", - )))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - use crate::sys::time::Timespec; - - let mutex = mutex.get_assert_locked(); + // SAFETY: the caller guarantees that the lock is owned, thus the mutex + // must have been initialized already. + let mutex = unsafe { mutex.pal.get_unchecked() }; self.verify(mutex); - #[cfg(not(target_os = "nto"))] - let timeout = Timespec::now(libc::CLOCK_MONOTONIC) - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec()) - .unwrap_or(TIMESPEC_MAX); - - #[cfg(target_os = "nto")] - let timeout = Timespec::now(libc::CLOCK_MONOTONIC) - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec_capped()) - .unwrap_or(TIMESPEC_MAX_CAPPED); - - let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout); - assert!(r == libc::ETIMEDOUT || r == 0); - r == 0 - } - - // This implementation is modeled after libcxx's condition_variable - // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 - // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 - #[cfg(any( - target_os = "android", - target_os = "espidf", - target_os = "horizon", - target_vendor = "apple", - ))] - pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - use crate::sys::time::SystemTime; - use crate::time::Instant; - - let mutex = mutex.get_assert_locked(); - self.verify(mutex); - - // OSX implementation of `pthread_cond_timedwait` is buggy - // with super long durations. When duration is greater than - // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` - // in macOS Sierra returns error 316. - // - // This program demonstrates the issue: - // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c - // - // To work around this issue, and possible bugs of other OSes, timeout - // is clamped to 1000 years, which is allowable per the API of `wait_timeout` - // because of spurious wakeups. - let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); - - // pthread_cond_timedwait uses system time, but we want to report timeout - // based on stable time. - let now = Instant::now(); - - let timeout = SystemTime::now() - .t - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec()) - .unwrap_or(TIMESPEC_MAX); - - let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout); - debug_assert!(r == libc::ETIMEDOUT || r == 0); - - // ETIMEDOUT is not a totally reliable method of determining timeout due - // to clock shifts, so do the check ourselves - now.elapsed() < dur + if pal::Condvar::PRECISE_TIMEOUT { + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + unsafe { self.get().wait_timeout(mutex, dur) } + } else { + // Timeout reports are not reliable, so do the check ourselves. + let now = Instant::now(); + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + let woken = unsafe { self.get().wait_timeout(mutex, dur) }; + woken || now.elapsed() < dur + } } } diff --git a/library/std/src/sys/sync/condvar/sgx.rs b/library/std/src/sys/sync/condvar/sgx.rs index e60715e4b59..2bde9d0694e 100644 --- a/library/std/src/sys/sync/condvar/sgx.rs +++ b/library/std/src/sys/sync/condvar/sgx.rs @@ -13,17 +13,19 @@ impl Condvar { } fn get(&self) -> &SpinMutex<WaitVariable<()>> { - self.inner.get_or_init(|| Box::new(SpinMutex::new(WaitVariable::new(())))) + self.inner.get_or_init(|| Box::pin(SpinMutex::new(WaitVariable::new(())))).get_ref() } #[inline] pub fn notify_one(&self) { - let _ = WaitQueue::notify_one(self.get().lock()); + let guard = self.get().lock(); + let _ = WaitQueue::notify_one(guard); } #[inline] pub fn notify_all(&self) { - let _ = WaitQueue::notify_all(self.get().lock()); + let guard = self.get().lock(); + let _ = WaitQueue::notify_all(guard); } pub unsafe fn wait(&self, mutex: &Mutex) { diff --git a/library/std/src/sys/sync/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs index 7b243575e01..57c78f454c5 100644 --- a/library/std/src/sys/sync/mutex/no_threads.rs +++ b/library/std/src/sys/sync/mutex/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false) } } diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index abd58122523..75b4b9c6dad 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -1,163 +1,66 @@ -use crate::cell::UnsafeCell; -use crate::io::Error; -use crate::mem::{MaybeUninit, forget}; -use crate::sys::cvt_nz; -use crate::sys::sync::OnceBox; +#![forbid(unsafe_op_in_unsafe_fn)] -struct AllocatedMutex(UnsafeCell<libc::pthread_mutex_t>); +use crate::mem::forget; +use crate::pin::Pin; +use crate::sys::pal::sync as pal; +use crate::sys::sync::OnceBox; pub struct Mutex { - inner: OnceBox<AllocatedMutex>, -} - -unsafe impl Send for AllocatedMutex {} -unsafe impl Sync for AllocatedMutex {} - -impl AllocatedMutex { - fn new() -> Box<Self> { - let mutex = Box::new(AllocatedMutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))); - - // Issue #33770 - // - // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have - // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you - // try to re-lock it from the same thread when you already hold a lock - // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html). - // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL - // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that - // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same - // as setting it to `PTHREAD_MUTEX_NORMAL`, but not setting any mode will result in - // a Mutex where re-locking is UB. - // - // In practice, glibc takes advantage of this undefined behavior to - // implement hardware lock elision, which uses hardware transactional - // memory to avoid acquiring the lock. While a transaction is in - // progress, the lock appears to be unlocked. This isn't a problem for - // other threads since the transactional memory will abort if a conflict - // is detected, however no abort is generated when re-locking from the - // same thread. - // - // Since locking the same mutex twice will result in two aliasing &mut - // references, we instead create the mutex with type - // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to - // re-lock it from the same thread, thus avoiding undefined behavior. - unsafe { - let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); - cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); - let attr = PthreadMutexAttr(&mut attr); - cvt_nz(libc::pthread_mutexattr_settype( - attr.0.as_mut_ptr(), - libc::PTHREAD_MUTEX_NORMAL, - )) - .unwrap(); - cvt_nz(libc::pthread_mutex_init(mutex.0.get(), attr.0.as_ptr())).unwrap(); - } - - mutex - } -} - -impl Drop for AllocatedMutex { - #[inline] - fn drop(&mut self) { - let r = unsafe { libc::pthread_mutex_destroy(self.0.get()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. - // Once it is used (locked/unlocked) or pthread_mutex_init() is called, - // this behavior no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } + pub pal: OnceBox<pal::Mutex>, } impl Mutex { #[inline] pub const fn new() -> Mutex { - Mutex { inner: OnceBox::new() } + Mutex { pal: OnceBox::new() } } - /// Gets access to the pthread mutex under the assumption that the mutex is - /// locked. - /// - /// This allows skipping the initialization check, as the mutex can only be - /// locked if it is already initialized, and allows relaxing the ordering - /// on the pointer load, since the allocation cannot have been modified - /// since the `lock` and the lock must have occurred on the current thread. - /// - /// # Safety - /// Causes undefined behavior if the mutex is not locked. #[inline] - pub(crate) unsafe fn get_assert_locked(&self) -> *mut libc::pthread_mutex_t { - unsafe { self.inner.get_unchecked().0.get() } - } - - #[inline] - fn get(&self) -> *mut libc::pthread_mutex_t { - // If initialization fails, the mutex is destroyed. This is always sound, - // however, as the mutex cannot have been locked yet. - self.inner.get_or_init(AllocatedMutex::new).0.get() + fn get(&self) -> Pin<&pal::Mutex> { + // If the initialization race is lost, the new mutex is destroyed. + // This is sound however, as it cannot have been locked. + self.pal.get_or_init(|| { + let mut pal = Box::pin(pal::Mutex::new()); + // SAFETY: we only call `init` once per `pal::Mutex`, namely here. + unsafe { pal.as_mut().init() }; + pal + }) } #[inline] pub fn lock(&self) { - #[cold] - #[inline(never)] - fn fail(r: i32) -> ! { - let error = Error::from_raw_os_error(r); - panic!("failed to lock mutex: {error}"); - } - - let r = unsafe { libc::pthread_mutex_lock(self.get()) }; - // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect - // the lock call to never fail. Unfortunately however, some platforms - // (Solaris) do not conform to the standard, and instead always provide - // deadlock detection. How kind of them! Unfortunately that means that - // we need to check the error code here. To save us from UB on other - // less well-behaved platforms in the future, we do it even on "good" - // platforms like macOS. See #120147 for more context. - if r != 0 { - fail(r) - } + // SAFETY: we call `init` above, therefore reentrant locking is safe. + // In `drop` we ensure that the mutex is not destroyed while locked. + unsafe { self.get().lock() } } #[inline] pub unsafe fn unlock(&self) { - let r = libc::pthread_mutex_unlock(self.get_assert_locked()); - debug_assert_eq!(r, 0); + // SAFETY: the mutex can only be locked if it is already initialized + // and we observed this initialization since we observed the locking. + unsafe { self.pal.get_unchecked().unlock() } } #[inline] pub fn try_lock(&self) -> bool { - unsafe { libc::pthread_mutex_trylock(self.get()) == 0 } + // SAFETY: we call `init` above, therefore reentrant locking is safe. + // In `drop` we ensure that the mutex is not destroyed while locked. + unsafe { self.get().try_lock() } } } impl Drop for Mutex { fn drop(&mut self) { - let Some(mutex) = self.inner.take() else { return }; + let Some(pal) = self.pal.take() else { return }; // We're not allowed to pthread_mutex_destroy a locked mutex, // so check first if it's unlocked. - if unsafe { libc::pthread_mutex_trylock(mutex.0.get()) == 0 } { - unsafe { libc::pthread_mutex_unlock(mutex.0.get()) }; - drop(mutex); + if unsafe { pal.as_ref().try_lock() } { + unsafe { pal.as_ref().unlock() }; + drop(pal) } else { // The mutex is locked. This happens if a MutexGuard is leaked. // In this case, we just leak the Mutex too. - forget(mutex); - } - } -} - -pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>); - -impl Drop for PthreadMutexAttr<'_> { - fn drop(&mut self) { - unsafe { - let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr()); - debug_assert_eq!(result, 0); + forget(pal) } } } diff --git a/library/std/src/sys/sync/mutex/sgx.rs b/library/std/src/sys/sync/mutex/sgx.rs index 8529e857970..3eb981bc65a 100644 --- a/library/std/src/sys/sync/mutex/sgx.rs +++ b/library/std/src/sys/sync/mutex/sgx.rs @@ -13,7 +13,7 @@ impl Mutex { } fn get(&self) -> &SpinMutex<WaitVariable<bool>> { - self.inner.get_or_init(|| Box::new(SpinMutex::new(WaitVariable::new(false)))) + self.inner.get_or_init(|| Box::pin(SpinMutex::new(WaitVariable::new(false)))).get_ref() } #[inline] @@ -33,7 +33,7 @@ impl Mutex { pub unsafe fn unlock(&self) { // SAFETY: the mutex was locked by the current thread, so it has been // initialized already. - let guard = unsafe { self.inner.get_unchecked().lock() }; + let guard = unsafe { self.inner.get_unchecked().get_ref().lock() }; if let Err(mut guard) = WaitQueue::notify_one(guard) { // No other waiters, unlock *guard.lock_var_mut() = false; diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index fb1b496510a..88a1d50361e 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -35,7 +35,6 @@ unsafe impl Sync for Once {} impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state: Cell::new(State::Incomplete) } } diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 87837915b39..5beff4ce683 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -116,7 +116,6 @@ fn to_state(current: StateAndQueue) -> usize { impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) } } diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs index 4105af50329..6953b91999a 100644 --- a/library/std/src/sys/sync/once_box.rs +++ b/library/std/src/sys/sync/once_box.rs @@ -6,6 +6,7 @@ #![allow(dead_code)] // Only used on some platforms. use crate::mem::replace; +use crate::pin::Pin; use crate::ptr::null_mut; use crate::sync::atomic::AtomicPtr; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; @@ -27,46 +28,46 @@ impl<T> OnceBox<T> { /// pointer load in this function can be performed with relaxed ordering, /// potentially allowing the optimizer to turn code like this: /// ```rust, ignore - /// once_box.get_or_init(|| Box::new(42)); + /// once_box.get_or_init(|| Box::pin(42)); /// unsafe { once_box.get_unchecked() } /// ``` /// into /// ```rust, ignore - /// once_box.get_or_init(|| Box::new(42)) + /// once_box.get_or_init(|| Box::pin(42)) /// ``` /// /// # Safety /// This causes undefined behavior if the assumption above is violated. #[inline] - pub unsafe fn get_unchecked(&self) -> &T { - unsafe { &*self.ptr.load(Relaxed) } + pub unsafe fn get_unchecked(&self) -> Pin<&T> { + unsafe { Pin::new_unchecked(&*self.ptr.load(Relaxed)) } } #[inline] - pub fn get_or_init(&self, f: impl FnOnce() -> Box<T>) -> &T { + pub fn get_or_init(&self, f: impl FnOnce() -> Pin<Box<T>>) -> Pin<&T> { let ptr = self.ptr.load(Acquire); match unsafe { ptr.as_ref() } { - Some(val) => val, + Some(val) => unsafe { Pin::new_unchecked(val) }, None => self.initialize(f), } } #[inline] - pub fn take(&mut self) -> Option<Box<T>> { + pub fn take(&mut self) -> Option<Pin<Box<T>>> { let ptr = replace(self.ptr.get_mut(), null_mut()); - if !ptr.is_null() { Some(unsafe { Box::from_raw(ptr) }) } else { None } + if !ptr.is_null() { Some(unsafe { Pin::new_unchecked(Box::from_raw(ptr)) }) } else { None } } #[cold] - fn initialize(&self, f: impl FnOnce() -> Box<T>) -> &T { - let new_ptr = Box::into_raw(f()); + fn initialize(&self, f: impl FnOnce() -> Pin<Box<T>>) -> Pin<&T> { + let new_ptr = Box::into_raw(unsafe { Pin::into_inner_unchecked(f()) }); match self.ptr.compare_exchange(null_mut(), new_ptr, Release, Acquire) { - Ok(_) => unsafe { &*new_ptr }, + Ok(_) => unsafe { Pin::new_unchecked(&*new_ptr) }, Err(ptr) => { // Lost the race to another thread. // Drop the value we created, and use the one from the other thread instead. drop(unsafe { Box::from_raw(new_ptr) }); - unsafe { &*ptr } + unsafe { Pin::new_unchecked(&*ptr) } } } } diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index c11e59f719e..573d0d602db 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } diff --git a/library/std/src/sys/sync/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs index 76df73b2a8e..19cabd7dd75 100644 --- a/library/std/src/sys/sync/thread_parking/pthread.rs +++ b/library/std/src/sys/sync/thread_parking/pthread.rs @@ -1,93 +1,19 @@ //! Thread parking without `futex` using the `pthread` synchronization primitives. -use crate::cell::UnsafeCell; -use crate::marker::PhantomPinned; use crate::pin::Pin; use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -#[cfg(not(target_os = "nto"))] -use crate::sys::time::TIMESPEC_MAX; -#[cfg(target_os = "nto")] -use crate::sys::time::TIMESPEC_MAX_CAPPED; +use crate::sys::pal::sync::{Condvar, Mutex}; use crate::time::Duration; const EMPTY: usize = 0; const PARKED: usize = 1; const NOTIFIED: usize = 2; -unsafe fn lock(lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_mutex_lock(lock); - debug_assert_eq!(r, 0); -} - -unsafe fn unlock(lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_mutex_unlock(lock); - debug_assert_eq!(r, 0); -} - -unsafe fn notify_one(cond: *mut libc::pthread_cond_t) { - let r = libc::pthread_cond_signal(cond); - debug_assert_eq!(r, 0); -} - -unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_cond_wait(cond, lock); - debug_assert_eq!(r, 0); -} - -unsafe fn wait_timeout( - cond: *mut libc::pthread_cond_t, - lock: *mut libc::pthread_mutex_t, - dur: Duration, -) { - // Use the system clock on systems that do not support pthread_condattr_setclock. - // This unfortunately results in problems when the system time changes. - #[cfg(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple"))] - let (now, dur) = { - use crate::cmp::min; - use crate::sys::time::SystemTime; - - // OSX implementation of `pthread_cond_timedwait` is buggy - // with super long durations. When duration is greater than - // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` - // in macOS Sierra return error 316. - // - // This program demonstrates the issue: - // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c - // - // To work around this issue, and possible bugs of other OSes, timeout - // is clamped to 1000 years, which is allowable per the API of `park_timeout` - // because of spurious wakeups. - let dur = min(dur, Duration::from_secs(1000 * 365 * 86400)); - let now = SystemTime::now().t; - (now, dur) - }; - // Use the monotonic clock on other systems. - #[cfg(not(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple")))] - let (now, dur) = { - use crate::sys::time::Timespec; - - (Timespec::now(libc::CLOCK_MONOTONIC), dur) - }; - - #[cfg(not(target_os = "nto"))] - let timeout = - now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); - #[cfg(target_os = "nto")] - let timeout = now - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec_capped()) - .unwrap_or(TIMESPEC_MAX_CAPPED); - let r = libc::pthread_cond_timedwait(cond, lock, &timeout); - debug_assert!(r == libc::ETIMEDOUT || r == 0); -} - pub struct Parker { state: AtomicUsize, - lock: UnsafeCell<libc::pthread_mutex_t>, - cvar: UnsafeCell<libc::pthread_cond_t>, - // The `pthread` primitives require a stable address, so make this struct `!Unpin`. - _pinned: PhantomPinned, + lock: Mutex, + cvar: Condvar, } impl Parker { @@ -96,38 +22,21 @@ impl Parker { /// # Safety /// The constructed parker must never be moved. pub unsafe fn new_in_place(parker: *mut Parker) { - // Use the default mutex implementation to allow for simpler initialization. - // This could lead to undefined behavior when deadlocking. This is avoided - // by not deadlocking. Note in particular the unlocking operation before any - // panic, as code after the panic could try to park again. - (&raw mut (*parker).state).write(AtomicUsize::new(EMPTY)); - (&raw mut (*parker).lock).write(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER)); + parker.write(Parker { + state: AtomicUsize::new(EMPTY), + lock: Mutex::new(), + cvar: Condvar::new(), + }); - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "l4re", - target_os = "android", - target_os = "redox", - target_os = "vita", - target_vendor = "apple", - ))] { - (&raw mut (*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER)); - } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { - let r = libc::pthread_cond_init((&raw mut (*parker).cvar).cast(), crate::ptr::null()); - assert_eq!(r, 0); - } else { - use crate::mem::MaybeUninit; - let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit(); - let r = libc::pthread_condattr_init(attr.as_mut_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC); - assert_eq!(r, 0); - let r = libc::pthread_cond_init((&raw mut (*parker).cvar).cast(), attr.as_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_destroy(attr.as_mut_ptr()); - assert_eq!(r, 0); - } - } + Pin::new_unchecked(&mut (*parker).cvar).init(); + } + + fn lock(self: Pin<&Self>) -> Pin<&Mutex> { + unsafe { self.map_unchecked(|p| &p.lock) } + } + + fn cvar(self: Pin<&Self>) -> Pin<&Condvar> { + unsafe { self.map_unchecked(|p| &p.cvar) } } // This implementation doesn't require `unsafe`, but other implementations @@ -142,7 +51,7 @@ impl Parker { } // Otherwise we need to coordinate going to sleep - lock(self.lock.get()); + self.lock().lock(); match self.state.compare_exchange(EMPTY, PARKED, Relaxed, Relaxed) { Ok(_) => {} Err(NOTIFIED) => { @@ -154,20 +63,20 @@ impl Parker { // read from the write it made to `state`. let old = self.state.swap(EMPTY, Acquire); - unlock(self.lock.get()); + self.lock().unlock(); assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park state") } } loop { - wait(self.cvar.get(), self.lock.get()); + self.cvar().wait(self.lock()); match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) { Ok(_) => break, // got a notification @@ -175,7 +84,7 @@ impl Parker { } } - unlock(self.lock.get()); + self.lock().unlock(); } // This implementation doesn't require `unsafe`, but other implementations @@ -189,19 +98,19 @@ impl Parker { return; } - lock(self.lock.get()); + self.lock().lock(); match self.state.compare_exchange(EMPTY, PARKED, Relaxed, Relaxed) { Ok(_) => {} Err(NOTIFIED) => { // We must read again here, see `park`. let old = self.state.swap(EMPTY, Acquire); - unlock(self.lock.get()); + self.lock().unlock(); assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park_timeout state") } } @@ -210,13 +119,13 @@ impl Parker { // from a notification we just want to unconditionally set the state back to // empty, either consuming a notification or un-flagging ourselves as // parked. - wait_timeout(self.cvar.get(), self.lock.get(), dur); + self.cvar().wait_timeout(self.lock(), dur); match self.state.swap(EMPTY, Acquire) { - NOTIFIED => unlock(self.lock.get()), // got a notification, hurray! - PARKED => unlock(self.lock.get()), // no notification, alas + NOTIFIED => self.lock().unlock(), // got a notification, hurray! + PARKED => self.lock().unlock(), // no notification, alas n => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park_timeout state: {n}") } } @@ -248,21 +157,9 @@ impl Parker { // parked thread wakes it doesn't get woken only to have to wait for us // to release `lock`. unsafe { - lock(self.lock.get()); - unlock(self.lock.get()); - notify_one(self.cvar.get()); + self.lock().lock(); + self.lock().unlock(); + self.cvar().notify_one(); } } } - -impl Drop for Parker { - fn drop(&mut self) { - unsafe { - libc::pthread_cond_destroy(self.cvar.get_mut()); - libc::pthread_mutex_destroy(self.lock.get_mut()); - } - } -} - -unsafe impl Sync for Parker {} -unsafe impl Send for Parker {} diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs index 97df8997b80..e1bc08eabb3 100644 --- a/library/std/src/sys/thread_local/key/racy.rs +++ b/library/std/src/sys/thread_local/key/racy.rs @@ -30,7 +30,6 @@ const KEY_SENTVAL: usize = 0; const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl LazyKey { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> LazyKey { LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 58f291ffdb9..00d2e30bd60 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -60,7 +60,6 @@ struct Value<T: 'static> { } impl<T: 'static> Storage<T> { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new() -> Storage<T> { Storage { key: LazyKey::new(Some(destroy_value::<T>)), marker: PhantomData } } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index bc5f701e346..56cf438bd9b 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -237,7 +237,6 @@ impl<T: 'static> LocalKey<T> { reason = "recently added to create a key", issue = "none" )] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> { LocalKey { inner } } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 2ff44fcd4c6..cfbf6548a38 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1021,11 +1021,11 @@ impl Drop for PanicGuard { /// /// # Memory Ordering /// -/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory /// operations performed before a call to `unpark` are made visible to the thread that /// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and `park` synchronizes-with -/// _all_ prior `unpark` operations. +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. /// /// In atomic ordering terms, `unpark` performs a `Release` operation and `park` /// performs the corresponding `Acquire` operation. Calls to `unpark` for the same diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 4e472b4ce99..44fe84c989f 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -122,19 +122,19 @@ fn env_home_dir() { assert!(home_dir().is_some()); - set_var("HOME", "/home/MountainView"); + set_var("HOME", "/home/PaloAlto"); + assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used"); + + set_var("USERPROFILE", "/home/MountainView"); assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); remove_var("HOME"); - set_var("USERPROFILE", "/home/MountainView"); assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - set_var("HOME", "/home/MountainView"); - set_var("USERPROFILE", "/home/PaloAlto"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + set_var("USERPROFILE", ""); + assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored"); - remove_var("HOME"); remove_var("USERPROFILE"); if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 569a1b3299e..96ddae16f0a 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -37,7 +37,4 @@ system-llvm-libunwind = [] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d7ae0299dd6..762f4e653e9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1029,7 +1029,8 @@ class RustBuild(object): raise Exception("no cargo executable found at `{}`".format( self.cargo())) args = [self.cargo(), "build", "--manifest-path", - os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] + os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), + "-Zroot-dir="+self.rust_root] args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 92c8f5dc452..a1f38b9ac14 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -108,11 +108,13 @@ ci-msvc: ci-msvc-py ci-msvc-ps1 ## MingW native builders -# test both x and bootstrap entrypoints +# Set of tests that should represent half of the time of the test suite. +# Used to split tests across multiple CI runners. +# Test both x and bootstrap entrypoints. ci-mingw-x: - $(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy + $(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src ci-mingw-bootstrap: - $(Q)$(BOOTSTRAP) test --stage 2 --skip tidy + $(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest ci-mingw: ci-mingw-x ci-mingw-bootstrap .PHONY: dist diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 409a644b9be..ee813de1c9e 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -99,7 +99,7 @@ fn main() { // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not. // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime. // Instead, look for this comment, which is almost certainly not in any custom hook. - if fs::read_to_string(pre_commit).map_or(false, |contents| { + if fs::read_to_string(pre_commit).is_ok_and(|contents| { contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570") }) { println!( diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index d857de96cce..61cc9eeed55 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -203,10 +203,8 @@ fn rm_rf(path: &Path) { do_op(path, "remove dir", |p| match fs::remove_dir(p) { // Check for dir not empty on Windows - // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized, - // match on `e.kind()` instead. #[cfg(windows)] - Err(e) if e.raw_os_error() == Some(145) => Ok(()), + Err(e) if e.kind() == ErrorKind::DirectoryNotEmpty => Ok(()), r => r, }); } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 8e088682f92..0cacd6e4f37 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -330,7 +330,7 @@ fn copy_third_party_objects( if target == "x86_64-fortanix-unknown-sgx" || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree - && (target.contains("linux") || target.contains("fuchsia")) + && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix")) { let libunwind_path = copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target)); @@ -1655,7 +1655,7 @@ impl Step for Sysroot { let mut add_filtered_files = |suffix, contents| { for path in contents { let path = Path::new(&path); - if path.parent().map_or(false, |parent| parent.ends_with(suffix)) { + if path.parent().is_some_and(|parent| parent.ends_with(suffix)) { filtered_files.push(path.file_name().unwrap().to_owned()); } } diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 5ca4321d855..29a96f77672 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -56,10 +56,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { let stamp_file = build.out.join("rustfmt.stamp"); - let mut cmd = command(match build.initial_rustfmt() { - Some(p) => p, - None => return None, - }); + let mut cmd = command(build.initial_rustfmt()?); cmd.arg("--version"); let output = cmd.allow_failure().run_capture(build); @@ -279,7 +276,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { Box::new(move |entry| { let cwd = std::env::current_dir(); let entry = t!(entry); - if entry.file_type().map_or(false, |t| t.is_file()) { + if entry.file_type().is_some_and(|t| t.is_file()) { formatted_paths_ref.lock().unwrap().push({ // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter // relative path. diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 704fa46ab1e..3a8f9e48c0d 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -572,6 +572,7 @@ Select which editor you would like to set up [default: None]: "; "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d", "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", + "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", ], EditorKind::Emacs => vec![ "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index dd967bca867..161157acffe 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -263,12 +263,16 @@ pub struct Cargo { host: TargetSelection, } +impl Cargo { + const CRATE_PATH: &str = "src/tools/cargo"; +} + impl Step for Cargo { type Output = (); const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/cargo") + run.path(Self::CRATE_PATH) } fn make_run(run: RunConfig<'_>) { @@ -286,7 +290,7 @@ impl Step for Cargo { Mode::ToolRustc, self.host, Kind::Test, - "src/tools/cargo", + Self::CRATE_PATH, SourceType::Submodule, &[], ); @@ -301,6 +305,10 @@ impl Step for Cargo { // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); cargo.env("PATH", path_for_cargo(builder, compiler)); + // Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is + // relative to. Cargo no longer sets this env var, so we have to do that. This has to be the + // same value as `-Zroot-dir`. + cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string()); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( @@ -1064,7 +1072,7 @@ impl Step for Tidy { if builder.config.channel == "dev" || builder.config.channel == "nightly" { builder.info("fmt check"); if builder.initial_rustfmt().is_none() { - let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap(); + let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); eprintln!( "\ ERROR: no `rustfmt` binary found in {PATH} @@ -2748,6 +2756,10 @@ impl Step for Crate { // `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that // instead. But crucially we only do that for the library, not the test builds. cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1"); + // std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder + // does not set this directly, but relies on the rustc wrapper to set it, and we are not using + // the wrapper -- hence we have to set it ourselves. + cargo.rustflag("-Zforce-unstable-if-unmarked"); cargo } else { // Also prepare a sysroot for the target. diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 0688a1d6892..77f6edaabb2 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -703,6 +703,9 @@ impl Builder<'_> { cargo.arg("-j").arg(self.jobs().to_string()); + // Make cargo emit diagnostics relative to the rustc src dir. + cargo.arg(format!("-Zroot-dir={}", self.src.display())); + // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name let mut metadata = if compiler.stage == 0 { @@ -1030,6 +1033,15 @@ impl Builder<'_> { if mode == Mode::Rustc { rustflags.arg("-Wrustc::internal"); + // cfg(bootstrap) - remove this check when lint is in bootstrap compiler + if stage != 0 { + // Lint is allow by default so downstream tools don't get a lit + // they can do nothing about + // We shouldn't be preinterning symbols used by tests + if cmd_kind != Kind::Test { + rustflags.arg("-Drustc::symbol_intern_string_literal"); + } + } // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all // of the individual lints are satisfied. rustflags.arg("-Wkeyword_idents_2024"); diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index e6902bb8cee..026c26479d3 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -258,11 +258,11 @@ impl PathSet { // internal use only fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool { - if let Some(p_kind) = &p.kind { - p.path.ends_with(needle) && *p_kind == module - } else { - p.path.ends_with(needle) - } + let check_path = || { + // This order is important for retro-compatibility, as `starts_with` was introduced later. + p.path.ends_with(needle) || p.path.starts_with(needle) + }; + if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() } } /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the @@ -765,6 +765,54 @@ impl Kind { } } +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +struct Libdir { + compiler: Compiler, + target: TargetSelection, +} + +impl Step for Libdir { + type Output = PathBuf; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.never() + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler); + let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib"); + + if !builder.config.dry_run() { + // Avoid deleting the `rustlib/` directory we just copied (in `impl Step for + // Sysroot`). + if !builder.download_rustc() { + let sysroot_target_libdir = sysroot.join(self.target).join("lib"); + builder.verbose(|| { + eprintln!( + "Removing sysroot {} to avoid caching bugs", + sysroot_target_libdir.display() + ) + }); + let _ = fs::remove_dir_all(&sysroot_target_libdir); + t!(fs::create_dir_all(&sysroot_target_libdir)); + } + + if self.compiler.stage == 0 { + // The stage 0 compiler for the build triple is always pre-built. Ensure that + // `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use + // it when run. + dist::maybe_install_llvm_target( + builder, + self.compiler.host, + &builder.sysroot(self.compiler), + ); + } + } + + sysroot + } +} + impl<'a> Builder<'a> { fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> { macro_rules! describe { @@ -1165,56 +1213,13 @@ impl<'a> Builder<'a> { /// Returns the bindir for a compiler's sysroot. pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { - self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin") + self.ensure(Libdir { compiler, target }).join(target).join("bin") } /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { - #[derive(Debug, Clone, Hash, PartialEq, Eq)] - struct Libdir { - compiler: Compiler, - target: TargetSelection, - } - impl Step for Libdir { - type Output = PathBuf; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - let lib = builder.sysroot_libdir_relative(self.compiler); - let sysroot = builder - .sysroot(self.compiler) - .join(lib) - .join("rustlib") - .join(self.target) - .join("lib"); - // Avoid deleting the rustlib/ directory we just copied - // (in `impl Step for Sysroot`). - if !builder.download_rustc() { - builder.verbose(|| { - println!("Removing sysroot {} to avoid caching bugs", sysroot.display()) - }); - let _ = fs::remove_dir_all(&sysroot); - t!(fs::create_dir_all(&sysroot)); - } - - if self.compiler.stage == 0 { - // The stage 0 compiler for the build triple is always pre-built. - // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run. - dist::maybe_install_llvm_target( - builder, - self.compiler.host, - &builder.sysroot(self.compiler), - ); - } - - sysroot - } - } - self.ensure(Libdir { compiler, target }) + self.ensure(Libdir { compiler, target }).join(target).join("lib") } pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { @@ -1262,7 +1267,7 @@ impl<'a> Builder<'a> { pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { match self.config.libdir_relative() { Some(relative_libdir) if compiler.stage >= 1 => relative_libdir, - _ if compiler.stage == 0 => &self.build.initial_libdir, + _ if compiler.stage == 0 => &self.build.initial_relative_libdir, _ => Path::new("lib"), } } @@ -1523,15 +1528,19 @@ impl<'a> Builder<'a> { pub(crate) fn maybe_open_in_browser<S: Step>(&self, path: impl AsRef<Path>) { if self.was_invoked_explicitly::<S>(Kind::Doc) { self.open_in_browser(path); + } else { + self.info(&format!("Doc path: {}", path.as_ref().display())); } } pub(crate) fn open_in_browser(&self, path: impl AsRef<Path>) { + let path = path.as_ref(); + if self.config.dry_run() || !self.config.cmd.open() { + self.info(&format!("Doc path: {}", path.display())); return; } - let path = path.as_ref(); self.info(&format!("Opening doc {}", path.display())); if let Err(err) = opener::open(path) { self.info(&format!("{err}\n")); diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index a1c8bff0db9..b2ffbd9c70f 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -738,3 +738,49 @@ mod dist { ]); } } + +mod sysroot_target_dirs { + use super::{ + Build, Builder, Compiler, TEST_TRIPLE_1, TEST_TRIPLE_2, TargetSelection, configure, + }; + + #[test] + fn test_sysroot_target_libdir() { + let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); + let builder = Builder::new(&build); + let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1); + let compiler = Compiler { stage: 1, host: target_triple_1 }; + let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2); + let actual = builder.sysroot_target_libdir(compiler, target_triple_2); + + assert_eq!( + builder + .sysroot(compiler) + .join(builder.sysroot_libdir_relative(compiler)) + .join("rustlib") + .join(TEST_TRIPLE_2) + .join("lib"), + actual + ); + } + + #[test] + fn test_sysroot_target_bindir() { + let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); + let builder = Builder::new(&build); + let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1); + let compiler = Compiler { stage: 1, host: target_triple_1 }; + let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2); + let actual = builder.sysroot_target_bindir(compiler, target_triple_2); + + assert_eq!( + builder + .sysroot(compiler) + .join(builder.sysroot_libdir_relative(compiler)) + .join("rustlib") + .join(TEST_TRIPLE_2) + .join("bin"), + actual + ); + } +} diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9b2d49e7620..b06147055f2 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -379,6 +379,7 @@ pub struct Config { pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, pub initial_cargo_clippy: Option<PathBuf>, + pub initial_sysroot: PathBuf, #[cfg(not(test))] initial_rustfmt: RefCell<RustfmtState>, @@ -1563,8 +1564,6 @@ impl Config { ); } - config.initial_cargo_clippy = cargo_clippy; - config.initial_rustc = if let Some(rustc) = rustc { if !flags.skip_stage0_validation { config.check_stage0_version(&rustc, "rustc"); @@ -1580,6 +1579,10 @@ impl Config { .join(exe("rustc", config.build)) }; + config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into(); + + config.initial_cargo_clippy = cargo_clippy; + config.initial_cargo = if let Some(cargo) = cargo { if !flags.skip_stage0_validation { config.check_stage0_version(&cargo, "cargo"); @@ -1587,12 +1590,7 @@ impl Config { cargo } else { config.download_beta_toolchain(); - config - .out - .join(config.build) - .join("stage0") - .join("bin") - .join(exe("cargo", config.build)) + config.initial_sysroot.join("bin").join(exe("cargo", config.build)) }; // NOTE: it's important this comes *after* we set `initial_rustc` just above. @@ -1665,7 +1663,7 @@ impl Config { } config.llvm_assertions = - toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false)); + toml.llvm.as_ref().is_some_and(|llvm| llvm.assertions.unwrap_or(false)); // Store off these values as options because if they're not provided // we'll infer default values for them later @@ -2507,6 +2505,7 @@ impl Config { // Check the config compatibility // FIXME: this doesn't cover `--set` flags yet. let res = check_incompatible_options_for_ci_rustc( + self.build, current_config_toml, ci_config_toml, ); @@ -3088,17 +3087,18 @@ pub(crate) fn check_incompatible_options_for_ci_llvm( /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options. /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing. fn check_incompatible_options_for_ci_rustc( + host: TargetSelection, current_config_toml: TomlConfig, ci_config_toml: TomlConfig, ) -> Result<(), String> { macro_rules! err { - ($current:expr, $expected:expr) => { + ($current:expr, $expected:expr, $config_section:expr) => { if let Some(current) = &$current { if Some(current) != $expected.as_ref() { return Err(format!( - "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \ + "ERROR: Setting `{}` is incompatible with `rust.download-rustc`. \ Current value: {:?}, Expected value(s): {}{:?}", - stringify!($expected).replace("_", "-"), + format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")), $current, if $expected.is_some() { "None/" } else { "" }, $expected, @@ -3109,13 +3109,13 @@ fn check_incompatible_options_for_ci_rustc( } macro_rules! warn { - ($current:expr, $expected:expr) => { + ($current:expr, $expected:expr, $config_section:expr) => { if let Some(current) = &$current { if Some(current) != $expected.as_ref() { println!( - "WARNING: `rust.{}` has no effect with `rust.download-rustc`. \ + "WARNING: `{}` has no effect with `rust.download-rustc`. \ Current value: {:?}, Expected value(s): {}{:?}", - stringify!($expected).replace("_", "-"), + format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")), $current, if $expected.is_some() { "None/" } else { "" }, $expected, @@ -3125,6 +3125,31 @@ fn check_incompatible_options_for_ci_rustc( }; } + let current_profiler = current_config_toml.build.as_ref().and_then(|b| b.profiler); + let profiler = ci_config_toml.build.as_ref().and_then(|b| b.profiler); + err!(current_profiler, profiler, "build"); + + let current_optimized_compiler_builtins = + current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins); + let optimized_compiler_builtins = + ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins); + err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build"); + + // We always build the in-tree compiler on cross targets, so we only care + // about the host target here. + let host_str = host.to_string(); + if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) { + if current_cfg.profiler.is_some() { + let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str)); + let ci_cfg = ci_target_toml.ok_or(format!( + "Target specific config for '{host_str}' is not present for CI-rustc" + ))?; + + let profiler = &ci_cfg.profiler; + err!(current_cfg.profiler, profiler, "build"); + } + } + let (Some(current_rust_config), Some(ci_rust_config)) = (current_config_toml.rust, ci_config_toml.rust) else { @@ -3198,24 +3223,24 @@ fn check_incompatible_options_for_ci_rustc( // If the option belongs to the first category, we call `err` macro for a hard error; // otherwise, we just print a warning with `warn` macro. - err!(current_rust_config.optimize, optimize); - err!(current_rust_config.randomize_layout, randomize_layout); - err!(current_rust_config.debug_logging, debug_logging); - err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc); - err!(current_rust_config.rpath, rpath); - err!(current_rust_config.strip, strip); - err!(current_rust_config.lld_mode, lld_mode); - err!(current_rust_config.llvm_tools, llvm_tools); - err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker); - err!(current_rust_config.jemalloc, jemalloc); - err!(current_rust_config.default_linker, default_linker); - err!(current_rust_config.stack_protector, stack_protector); - err!(current_rust_config.lto, lto); - err!(current_rust_config.std_features, std_features); - - warn!(current_rust_config.channel, channel); - warn!(current_rust_config.description, description); - warn!(current_rust_config.incremental, incremental); + err!(current_rust_config.optimize, optimize, "rust"); + err!(current_rust_config.randomize_layout, randomize_layout, "rust"); + err!(current_rust_config.debug_logging, debug_logging, "rust"); + err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust"); + err!(current_rust_config.rpath, rpath, "rust"); + err!(current_rust_config.strip, strip, "rust"); + err!(current_rust_config.lld_mode, lld_mode, "rust"); + err!(current_rust_config.llvm_tools, llvm_tools, "rust"); + err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust"); + err!(current_rust_config.jemalloc, jemalloc, "rust"); + err!(current_rust_config.default_linker, default_linker, "rust"); + err!(current_rust_config.stack_protector, stack_protector, "rust"); + err!(current_rust_config.lto, lto, "rust"); + err!(current_rust_config.std_features, std_features, "rust"); + + warn!(current_rust_config.channel, channel, "rust"); + warn!(current_rust_config.description, description, "rust"); + warn!(current_rust_config.incremental, incremental, "rust"); Ok(()) } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index db1f5b08338..db35e6907e6 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -427,9 +427,8 @@ impl Config { let version = &self.stage0_metadata.compiler.version; let host = self.build; - let bin_root = self.out.join(host).join("stage0"); - let clippy_stamp = bin_root.join(".clippy-stamp"); - let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host)); + let clippy_stamp = self.initial_sysroot.join(".clippy-stamp"); + let cargo_clippy = self.initial_sysroot.join("bin").join(exe("cargo-clippy", host)); if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) { return cargo_clippy; } @@ -830,7 +829,7 @@ download-rustc = false fn path_is_dylib(path: &Path) -> bool { // The .so is not necessarily the extension, it might be libLLVM.so.18.1 - path.to_str().map_or(false, |path| path.contains(".so")) + path.to_str().is_some_and(|path| path.contains(".so")) } /// Checks whether the CI rustc is available for the given target triple. diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index fabb4f2b13b..dcf68cbeeda 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -135,19 +135,15 @@ pub fn check(build: &mut Build) { // We need cmake, but only if we're actually building LLVM or sanitizers. let building_llvm = !build.config.llvm_from_ci - && build - .hosts - .iter() - .map(|host| { - build.config.llvm_enabled(*host) - && build - .config - .target_config - .get(host) - .map(|config| config.llvm_config.is_none()) - .unwrap_or(true) - }) - .any(|build_llvm_ourselves| build_llvm_ourselves); + && build.hosts.iter().any(|host| { + build.config.llvm_enabled(*host) + && build + .config + .target_config + .get(host) + .map(|config| config.llvm_config.is_none()) + .unwrap_or(true) + }); let need_cmake = building_llvm || build.config.any_sanitizers_to_build(); if need_cmake && cmd_finder.maybe_have("cmake").is_none() { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index c384fd6bf43..0ecf61ffcd9 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -158,7 +158,7 @@ pub struct Build { initial_rustc: PathBuf, initial_cargo: PathBuf, initial_lld: PathBuf, - initial_libdir: PathBuf, + initial_relative_libdir: PathBuf, initial_sysroot: PathBuf, // Runtime state filled in later on @@ -312,46 +312,19 @@ impl Build { let in_tree_llvm_info = config.in_tree_llvm_info.clone(); let in_tree_gcc_info = config.in_tree_gcc_info.clone(); - let initial_target_libdir_str = if config.dry_run() { - "/dummy/lib/path/to/lib/".to_string() - } else { - output( - Command::new(&config.initial_rustc) - .arg("--target") - .arg(config.build.rustc_target_arg()) - .arg("--print") - .arg("target-libdir"), - ) - }; + let initial_target_libdir_str = + config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib"); + let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap(); let initial_lld = initial_target_dir.join("bin").join("rust-lld"); - let initial_sysroot = if config.dry_run() { - "/dummy".to_string() - } else { - output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot")) - } - .trim() - .to_string(); - - // FIXME(Zalathar): Determining this path occasionally fails locally for - // unknown reasons, so we print some extra context to help track down why. - let find_initial_libdir = || { - let initial_libdir = - initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?; - Some(initial_libdir.to_path_buf()) - }; - let Some(initial_libdir) = find_initial_libdir() else { - panic!( - "couldn't determine `initial_libdir`: -- config.initial_rustc: {rustc:?} -- initial_target_libdir_str: {initial_target_libdir_str:?} -- initial_target_dir: {initial_target_dir:?} -- initial_sysroot: {initial_sysroot:?} -", - rustc = config.initial_rustc, - ); - }; + let initial_relative_libdir = initial_target_dir + .ancestors() + .nth(2) + .unwrap() + .strip_prefix(&config.initial_sysroot) + .expect("Couldn’t determine initial relative libdir.") + .to_path_buf(); let version = std::fs::read_to_string(src.join("src").join("version")) .expect("failed to read src/version"); @@ -380,11 +353,11 @@ impl Build { } let mut build = Build { + initial_lld, + initial_relative_libdir, initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), - initial_lld, - initial_libdir, - initial_sysroot: initial_sysroot.into(), + initial_sysroot: config.initial_sysroot.clone(), local_rebuild: config.local_rebuild, fail_fast: config.cmd.fail_fast(), doc_tests: config.cmd.doc_tests(), diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 079213e8c3d..923cc2dfc28 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -55,7 +55,7 @@ pub fn exe(name: &str, target: TargetSelection) -> String { /// Returns `true` if the file name given looks like a dynamic library. pub fn is_dylib(path: &Path) -> bool { - path.extension().and_then(|ext| ext.to_str()).map_or(false, |ext| { + path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| { ext == "dylib" || ext == "so" || ext == "dll" || (ext == "a" && is_aix_shared_archive(path)) }) } diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile index 222fa8a7355..aade9588268 100644 --- a/src/ci/docker/host-x86_64/arm-android/Dockerfile +++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive COPY scripts/android-base-apt-get.sh /scripts/ @@ -11,7 +11,8 @@ RUN . /scripts/android-ndk.sh && \ RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ - libgl1-mesa-glx \ + libgl1 \ + libglx-mesa0 \ libpulse0 \ libstdc++6:i386 \ openjdk-8-jre-headless \ diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile index 54649e0d22b..95fed6ee767 100644 --- a/src/ci/docker/host-x86_64/dist-android/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh diff --git a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile index 6dff3095b46..bbbf0b3adf2 100644 --- a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh index 22e2e243e43..d0252e356fd 100644 --- a/src/ci/docker/scripts/android-base-apt-get.sh +++ b/src/ci/docker/scripts/android-base-apt-get.sh @@ -10,7 +10,7 @@ apt-get install -y --no-install-recommends \ g++ \ git \ libssl-dev \ - libncurses5 \ + libncurses-dev \ make \ ninja-build \ pkg-config \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2f59892acf6..2ea37c168dd 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -338,6 +338,7 @@ auto: --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin + --set rust.codegen-units=1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 @@ -439,14 +440,24 @@ auto: NO_DOWNLOAD_CI_LLVM: 1 <<: *job-windows-8c - - image: x86_64-mingw + # x86_64-mingw is split into two jobs to run tests in parallel. + - image: x86_64-mingw-1 env: - SCRIPT: make ci-mingw + SCRIPT: make ci-mingw-x RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - <<: *job-windows-8c + <<: *job-windows + + - image: x86_64-mingw-2 + env: + SCRIPT: make ci-mingw-bootstrap + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + <<: *job-windows - image: dist-x86_64-msvc env: diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 1e6a008a5de..9fce68947f4 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -53,7 +53,8 @@ function isLinux { } function isKnownToBeMingwBuild { - isGitHubActions && [[ "${CI_JOB_NAME}" == *mingw ]] + # CI_JOB_NAME must end with "mingw" and optionally `-N` to be considered a MinGW build. + isGitHubActions && [[ "${CI_JOB_NAME}" =~ mingw(-[0-9]+)?$ ]] } function isCiBranch { diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md index e7e3fd01c4d..3c3e35a51b8 100644 --- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -16,7 +16,7 @@ BE8 architecture is the default big-endian architecture for Arm since [Armv6](ht The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard Arm configuration). ## Target definition -The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required. +The target definition can be seen [here](https://github.com/rust-lang/rust/blob/master/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required. ## Building the target Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md index 60e06c404c0..6f09ce42dbb 100644 --- a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md @@ -64,6 +64,22 @@ There are no special requirements for testing and running the target. For testing cross builds on the host, please refer to the "Cross-compilation toolchains and C code" section below. +If you want to do native testing but do not have your own s390x +machine, there are several options how to get access to one: + +* The [IBM LinuxONE Community Cloud][cloud-community] provides a + self-service portal where you can create s390x virtual machine + instances. These are intended for temporary use (limited to 120 days). + +* The [IBM LinuxONE Open Source Cloud][cloud-opensource] provides + permanent access to s390x machines. This requires approval by IBM, + which will normally be granted if you're planning to use the machine + to work on an open-source project that is relevant to the IBM Z + ecosystem - the Rust compiler would certainly qualify. + +[cloud-community]: https://linuxone.cloud.marist.edu/ +[cloud-opensource]: https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/ + ## Cross-compilation toolchains and C code Rust code built using the target is compatible with C code compiled with diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index e9524c0b78d..db8426492ee 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -47,6 +47,10 @@ It can be enabled using: #![deny(rustdoc::missing_doc_code_examples)] ``` +It is not emitted for items that cannot be instantiated/called such as fields, variants, modules, +associated trait/impl items, impl blocks, statics and constants. +It is also not emitted for foreign items, aliases, extern crates and imports. + ## Extensions to the `#[doc]` attribute These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md new file mode 100644 index 00000000000..bea667dcf44 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md @@ -0,0 +1,7 @@ +# `debug-info-type-line-numbers` + +--- + +This option causes additional type and line information to be emitted in debug +info to provide richer information to debuggers. This is currently off by +default as it causes some compilation scenarios to be noticeably slower. diff --git a/src/doc/unstable-book/src/compiler-flags/randomize-layout.md b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md new file mode 100644 index 00000000000..84c6712bc23 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md @@ -0,0 +1,23 @@ +# `randomize-layout` + +The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764). + +------------------------ + +The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal +optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified +default representation. This also affects type sizes and padding. +Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized. + +It can be used to find unsafe code that accidentally relies on unspecified behavior. + +Randomization is not guaranteed to use a different permutation for each compilation session. +`-Zlayout-seed=<u64>` can be used to supply additional entropy. + +Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently +result in the same layout due to limitations of the current implementation. Randomization may become +more aggressive over time as our coverage of the available degrees of freedoms improves. +Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds +on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts. + +Randomization may also become less aggressive in the future if additional guarantees get added to the default layout. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 01de12bb90e..c2f4170d7d2 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -30,10 +30,11 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg64` | None\* | `l` | | Hexagon | `reg` | `r[0-28]` | `r` | +| Hexagon | `preg` | `p[0-3]` | Only clobbers | | PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | | PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | | PowerPC | `freg` | `f[0-31]` | `f` | -| PowerPC | `vreg` | `v[0-31]` | Only clobbers | +| PowerPC | `vreg` | `v[0-31]` | `v` | | PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | | PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | @@ -70,10 +71,12 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| Hexagon | `preg` | N/A | Only clobbers | | PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | -| PowerPC | `vreg` | N/A | Only clobbers | +| PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | +| PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` | | PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | @@ -179,6 +182,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | None | | PowerPC | `freg` | None | `0` | None | +| PowerPC | `vreg` | None | `0` | None | | SPARC | `reg` | None | `%o0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | diff --git a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md b/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md deleted file mode 100644 index b20c30ec8f1..00000000000 --- a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md +++ /dev/null @@ -1,10 +0,0 @@ -# `extended_varargs_abi_support` - -The tracking issue for this feature is: [#100189] - -[#100189]: https://github.com/rust-lang/rust/issues/100189 - ------------------------- - -This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling -conventions on functions with varargs. diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index d1b186fd316..b104356d44c 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -34,5 +34,8 @@ "rust-analyzer.rustc.source": "./Cargo.toml", "rust-analyzer.cargo.extraEnv": { "RUSTC_BOOTSTRAP": "1" + }, + "rust-analyzer.server.extraEnv": { + "RUSTUP_TOOLCHAIN": "nightly" } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 3fe567b1c39..185898c31b7 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_hir as hir; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::bug; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Region, Ty}; use rustc_span::def_id::DefId; use rustc_span::symbol::{Symbol, kw}; @@ -182,7 +183,7 @@ fn clean_param_env<'tcx>( .is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id())) }) .map(|pred| { - tcx.fold_regions(pred, |r, _| match *r { + fold_regions(tcx, pred, |r, _| match *r { // FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that // we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds // of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests. diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 9255242611a..0dfb8a52eba 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -391,7 +391,7 @@ fn write_with_opt_paren<T: fmt::Display>( Ok(()) } -impl<'a> fmt::Display for Display<'a> { +impl fmt::Display for Display<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.0 { Cfg::Not(ref child) => match **child { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5ddd6188c2d..d81c47886d2 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -367,7 +367,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).into_iter() { + for &did in tcx.inherent_impls(did).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); @@ -382,7 +382,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_).into_iter() { + for &did in tcx.incoherent_impls(type_).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 97a2c331012..34141c47cf3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -290,6 +290,7 @@ pub(crate) fn clean_const<'tcx>( ConstantKind::Path { path: qpath_to_string(qpath).into() } } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, + hir::ConstArgKind::Infer(..) => ConstantKind::Infer, } } @@ -1803,30 +1804,27 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()), - TyKind::Array(ty, ref length) => { - let length = match length { - hir::ArrayLen::Infer(..) => "_".to_string(), - hir::ArrayLen::Body(const_arg) => { - // NOTE(min_const_generics): We can't use `const_eval_poly` for constants - // as we currently do not supply the parent generics to anonymous constants - // but do allow `ConstKind::Param`. - // - // `const_eval_poly` tries to first substitute generic parameters which - // results in an ICE while manually constructing the constant and using `eval` - // does nothing for `ConstKind::Param`. + TyKind::Array(ty, ref const_arg) => { + // NOTE(min_const_generics): We can't use `const_eval_poly` for constants + // as we currently do not supply the parent generics to anonymous constants + // but do allow `ConstKind::Param`. + // + // `const_eval_poly` tries to first substitute generic parameters which + // results in an ICE while manually constructing the constant and using `eval` + // does nothing for `ConstKind::Param`. + let length = match const_arg.kind { + hir::ConstArgKind::Infer(..) => "_".to_string(), + hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); + let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); + print_const(cx, ct) + } + hir::ConstArgKind::Path(..) => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); - let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = - const_arg.kind - { - let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); - cx.tcx.normalize_erasing_regions(typing_env, ct) - } else { - ct - }; print_const(cx, ct) } }; - Array(Box::new(clean_ty(ty, cx)), length.into()) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), @@ -2509,16 +2507,14 @@ fn clean_generic_args<'tcx>( let args = generic_args .args .iter() - .filter_map(|arg| { - Some(match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { - GenericArg::Lifetime(clean_lifetime(lt, cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { + GenericArg::Lifetime(clean_lifetime(lt, cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), + hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) .collect::<Vec<_>>() .into(); @@ -2651,7 +2647,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) { }); args.tokens = TokenStream::new(tokens); } - ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {} + ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {} } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a10a6a92bf5..715bf68374a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -264,17 +264,19 @@ impl ExternalCrate { // rendering by delegating everything to a hash map. let as_primitive = |res: Res<!>| { let Res::Def(DefKind::Mod, def_id) = res else { return None }; - tcx.get_attrs(def_id, sym::rustc_doc_primitive).find_map(|attr| { - let attr_value = attr.value_str().expect("syntax should already be validated"); - let Some(prim) = PrimitiveType::from_symbol(attr_value) else { - span_bug!( - attr.span, - "primitive `{attr_value}` is not a member of `PrimitiveType`" - ); - }; + tcx.get_attrs(def_id, sym::rustc_doc_primitive) + .map(|attr| { + let attr_value = attr.value_str().expect("syntax should already be validated"); + let Some(prim) = PrimitiveType::from_symbol(attr_value) else { + span_bug!( + attr.span, + "primitive `{attr_value}` is not a member of `PrimitiveType`" + ); + }; - Some((def_id, prim)) - }) + (def_id, prim) + }) + .next() }; if root.is_local() { @@ -339,7 +341,7 @@ pub(crate) struct ItemInner { impl std::ops::Deref for Item { type Target = ItemInner; fn deref(&self) -> &ItemInner { - &*self.inner + &self.inner } } @@ -412,7 +414,7 @@ impl Item { pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> { let kind = match &self.kind { - ItemKind::StrippedItem(k) => &*k, + ItemKind::StrippedItem(k) => k, _ => &self.kind, }; match kind { @@ -1870,7 +1872,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } @@ -1878,7 +1880,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } @@ -2397,6 +2399,8 @@ pub(crate) enum ConstantKind { Extern { def_id: DefId }, /// `const FOO: u32 = ...;` Local { def_id: DefId, body: BodyId }, + /// An inferred constant as in `[10u8; _]`. + Infer, } impl Constant { @@ -2422,6 +2426,7 @@ impl ConstantKind { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) } + ConstantKind::Infer { .. } => "_".to_string(), } } @@ -2429,7 +2434,8 @@ impl ConstantKind { match *self { ConstantKind::TyConst { .. } | ConstantKind::Path { .. } - | ConstantKind::Anonymous { .. } => None, + | ConstantKind::Anonymous { .. } + | ConstantKind::Infer => None, ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { print_evaluated_const(tcx, def_id, true, true) } @@ -2440,7 +2446,8 @@ impl ConstantKind { match *self { ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } - | ConstantKind::Path { .. } => false, + | ConstantKind::Path { .. } + | ConstantKind::Infer => false, ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { is_literal_expr(tcx, body.hir_id) } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 5071ed1c47f..34c91e33db7 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -178,7 +178,7 @@ impl fmt::Debug for Options { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { struct FmtExterns<'a>(&'a Externs); - impl<'a> fmt::Debug for FmtExterns<'a> { + impl fmt::Debug for FmtExterns<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.0.iter()).finish() } @@ -508,7 +508,7 @@ impl Options { }; let parts_out_dir = - match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() { + match matches.opt_str("parts-out-dir").map(PathToParts::from_flag).transpose() { Ok(parts_out_dir) => parts_out_dir, Err(e) => dcx.fatal(e), }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 25e576e9e63..da1316a19cc 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -700,7 +700,7 @@ impl IndividualTestOptions { fn new(options: &RustdocOptions, test_id: &Option<String>, test_path: PathBuf) -> Self { let outdir = if let Some(ref path) = options.persist_doctests { let mut path = path.clone(); - path.push(&test_id.as_deref().unwrap_or("<doctest>")); + path.push(test_id.as_deref().unwrap_or("<doctest>")); if let Err(err) = std::fs::create_dir_all(&path) { eprintln!("Couldn't create directory for doctest executables: {err}"); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 27d0be133fe..dc68f48f635 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -88,7 +88,7 @@ impl<'tcx> HirCollector<'tcx> { } } -impl<'tcx> HirCollector<'tcx> { +impl HirCollector<'_> { fn visit_testable<F: FnOnce(&mut Self)>( &mut self, name: String, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index ff0d537b19f..e387eb010be 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -203,7 +203,7 @@ impl Cache { } } -impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { +impl DocFolder for CacheBuilder<'_, '_> { fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> { if item.item_id.is_local() { debug!( diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index edd7d56b179..582ef7d2c48 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,5 @@ +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_middle::ty::TyCtxt; -use tracing::debug; use crate::clean; use crate::config::RenderOptions; @@ -17,6 +17,18 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { /// /// This is true for html, and false for json. See #80664 const RUN_ON_MODULE: bool; + /// This associated type is the type where the current module information is stored. + /// + /// For each module, we go through their items by calling for each item: + /// + /// 1. save_module_data + /// 2. item + /// 3. set_back_info + /// + /// However,the `item` method might update information in `self` (for example if the child is + /// a module). To prevent it to impact the other children of the current module, we need to + /// reset the information between each call to `item` by using `set_back_info`. + type ModuleData; /// Sets up any state required for the renderer. When this is called the cache has already been /// populated. @@ -27,8 +39,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; - /// Make a new renderer to render a child of the item currently being rendered. - fn make_child_renderer(&self) -> Self; + /// This method is called right before call [`Self::item`]. This method returns a type + /// containing information that needs to be reset after the [`Self::item`] method has been + /// called with the [`Self::set_back_info`] method. + /// + /// In short it goes like this: + /// + /// ```ignore (not valid code) + /// let reset_data = type.save_module_data(); + /// type.item(item)?; + /// type.set_back_info(reset_data); + /// ``` + fn save_module_data(&mut self) -> Self::ModuleData; + /// Used to reset current module's information. + fn set_back_info(&mut self, info: Self::ModuleData); /// Renders a single non-module item. This means no recursive sub-item rendering is required. fn item(&mut self, item: clean::Item) -> Result<(), Error>; @@ -47,6 +71,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { fn cache(&self) -> &Cache; } +fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>( + cx: &mut T, + item: clean::Item, + prof: &SelfProfilerRef, +) -> Result<(), Error> { + if item.is_mod() && T::RUN_ON_MODULE { + // modules are special because they add a namespace. We also need to + // recurse into the items of the module as well. + let _timer = + prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); + + cx.mod_item_in(&item)?; + let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = + item.inner.kind + else { + unreachable!() + }; + for it in module.items { + let info = cx.save_module_data(); + run_format_inner(cx, it, prof)?; + cx.set_back_info(info); + } + + cx.mod_item_out()?; + // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special + // cases. Use an explicit match instead. + } else if let Some(item_name) = item.name + && !item.is_extern_crate() + { + prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?; + } + Ok(()) +} + /// Main method for rendering a crate. pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( krate: clean::Crate, @@ -66,36 +124,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( } // Render the crate documentation - let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; - - while let Some((mut cx, item)) = work.pop() { - if item.is_mod() && T::RUN_ON_MODULE { - // modules are special because they add a namespace. We also need to - // recurse into the items of the module as well. - let _timer = - prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); - - cx.mod_item_in(&item)?; - let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = - item.inner.kind - else { - unreachable!() - }; - for it in module.items { - debug!("Adding {:?} to worklist", it.name); - work.push((cx.make_child_renderer(), it)); - } - - cx.mod_item_out()?; - // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special - // cases. Use an explicit match instead. - } else if let Some(item_name) = item.name - && !item.is_extern_crate() - { - prof.generic_activity_with_arg("render_item", item_name.as_str()) - .run(|| cx.item(item))?; - } - } + run_format_inner(&mut format_renderer, krate.module, prof)?; + prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr()) .run(|| format_renderer.after_krate()) } diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 31a2701f06a..48771571f8f 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -11,7 +11,7 @@ use unicode_segmentation::UnicodeSegmentation; /// string when passed to a format string. pub(crate) struct Escape<'a>(pub &'a str); -impl<'a> fmt::Display for Escape<'a> { +impl fmt::Display for Escape<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -49,7 +49,7 @@ impl<'a> fmt::Display for Escape<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyText<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyText<'a> { +impl fmt::Display for EscapeBodyText<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -86,7 +86,7 @@ impl<'a> fmt::Display for EscapeBodyText<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { +impl fmt::Display for EscapeBodyTextWithWbr<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let EscapeBodyTextWithWbr(text) = *self; if text.len() < 8 { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 46bc2915d0a..0a563b1df26 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,6 +9,7 @@ use std::borrow::Cow; use std::cell::Cell; +use std::cmp::Ordering; use std::fmt::{self, Display, Write}; use std::iter::{self, once}; @@ -785,16 +786,20 @@ pub(crate) fn href_relative_parts<'fqp>( ); } } - // e.g. linking to std::sync::atomic from std::sync - if relative_to_fqp.len() < fqp.len() { - Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) - // e.g. linking to std::sync from std::sync::atomic - } else if fqp.len() < relative_to_fqp.len() { - let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); - Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) - // linking to the same module - } else { - Box::new(iter::empty()) + match relative_to_fqp.len().cmp(&fqp.len()) { + Ordering::Less => { + // e.g. linking to std::sync::atomic from std::sync + Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) + } + Ordering::Greater => { + // e.g. linking to std::sync from std::sync::atomic + let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); + Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) + } + Ordering::Equal => { + // linking to the same module + Box::new(iter::empty()) + } } } @@ -1384,7 +1389,7 @@ impl clean::Impl { write!(f, ">")?; } } else { - fmt_type(&type_, f, use_absolute, cx)?; + fmt_type(type_, f, use_absolute, cx)?; } Ok(()) } @@ -1531,14 +1536,14 @@ impl clean::FnDecl { (None, Some(last_i)) if i != last_i => write!(f, ", ")?, (None, Some(_)) => (), (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?, - (Some(_), Some(_)) => write!(f, ",\n")?, + (Some(_), Some(_)) => writeln!(f, ",")?, } } if self.c_variadic { match line_wrapping_indent { None => write!(f, ", ...")?, - Some(n) => write!(f, "{}...\n", Indent(n + 4))?, + Some(n) => writeln!(f, "{}...", Indent(n + 4))?, }; } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index b2fc1a47f78..48a537ad5e7 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -144,7 +144,7 @@ struct TokenHandler<'a, 'tcx, F: Write> { href_context: Option<HrefContext<'a, 'tcx>>, } -impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { +impl<F: Write> TokenHandler<'_, '_, F> { fn handle_exit_span(&mut self) { // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is // being used in `write_pending_elems`. @@ -207,7 +207,7 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { } } -impl<'a, 'tcx, F: Write> Drop for TokenHandler<'a, 'tcx, F> { +impl<F: Write> Drop for TokenHandler<'_, '_, F> { /// When leaving, we need to flush all pending data to not have missing content. fn drop(&mut self) { if self.pending_exit_span.is_some() { @@ -1017,7 +1017,7 @@ fn string_without_closing_tag<T: Display>( .ok() .map(|(url, _, _)| url), LinkFromSrc::Doc(def_id) => { - format::href_with_root_path(*def_id, context, Some(&href_context.root_path)) + format::href_with_root_path(*def_id, context, Some(href_context.root_path)) .ok() .map(|(doc_link, _, _)| doc_link) } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 31ccfeb3873..b4bc0b80d6c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -33,7 +33,7 @@ pub(crate) struct Page<'a> { pub(crate) rust_logo: bool, } -impl<'a> Page<'a> { +impl Page<'_> { pub(crate) fn get_static_root_path(&self) -> String { match self.static_root_path { Some(s) => s.to_string(), diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs index 8562e103dc1..fdb1ddc1f53 100644 --- a/src/librustdoc/html/length_limit.rs +++ b/src/librustdoc/html/length_limit.rs @@ -77,7 +77,7 @@ impl HtmlWithLimit { /// This function will panic if called with a non-alphabetic `tag_name`. pub(super) fn open_tag(&mut self, tag_name: &'static str) { assert!( - tag_name.chars().all(|c| ('a'..='z').contains(&c)), + tag_name.chars().all(|c: char| c.is_ascii_lowercase()), "tag_name contained non-alphabetic chars: {tag_name:?}", ); self.queued_tags.push(tag_name); @@ -85,16 +85,15 @@ impl HtmlWithLimit { /// Close the most recently opened HTML tag. pub(super) fn close_tag(&mut self) { - match self.unclosed_tags.pop() { + if let Some(tag_name) = self.unclosed_tags.pop() { // Close the most recently opened tag. - Some(tag_name) => write!(self.buf, "</{tag_name}>").unwrap(), - // There are valid cases where `close_tag()` is called without - // there being any tags to close. For example, this occurs when - // a tag is opened after the length limit is exceeded; - // `flush_queue()` will never be called, and thus, the tag will - // not end up being added to `unclosed_tags`. - None => {} + write!(self.buf, "</{tag_name}>").unwrap() } + // There are valid cases where `close_tag()` is called without + // there being any tags to close. For example, this occurs when + // a tag is opened after the length limit is exceeded; + // `flush_queue()` will never be called, and thus, the tag will + // not end up being added to `unclosed_tags`. } /// Write all queued tags and add them to the `unclosed_tags` list. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 1d42ec8eec7..5e3d06a4ae7 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,7 +32,6 @@ use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; use std::str::{self, CharIndices}; -use std::sync::OnceLock; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, @@ -499,7 +498,7 @@ struct HeadingLinks<'a, 'b, 'ids, I> { heading_offset: HeadingOffset, } -impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { +impl<'b, 'ids, I> HeadingLinks<'_, 'b, 'ids, I> { fn new( iter: I, toc: Option<&'b mut TocBuilder>, @@ -510,9 +509,7 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { } } -impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator - for HeadingLinks<'a, 'b, 'ids, I> -{ +impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for HeadingLinks<'a, '_, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option<Self::Item> { @@ -908,7 +905,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } fn parse_string(&mut self, start: usize) -> Option<Indices> { - while let Some((pos, c)) = self.inner.next() { + for (pos, c) in self.inner.by_ref() { if c == '"' { return Some(Indices { start: start + 1, end: pos }); } @@ -1032,7 +1029,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { /// Returns `false` if an error was emitted. fn skip_paren_block(&mut self) -> bool { - while let Some((_, c)) = self.inner.next() { + for (_, c) in self.inner.by_ref() { if c == ')' { return true; } @@ -1074,9 +1071,8 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return Some(LangStringToken::LangToken(&self.data[start..pos])); } return self.next(); - } else if pos == start && is_leading_char(c) { - continue; - } else if pos != start && is_bareword_char(c) { + } else if (pos == start && is_leading_char(c)) || (pos != start && is_bareword_char(c)) + { continue; } else { self.emit_error(format!("unexpected character `{c}`")); @@ -1088,7 +1084,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } } -impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { +impl<'a> Iterator for TagIterator<'a, '_> { type Item = LangStringToken<'a>; fn next(&mut self) -> Option<Self::Item> { @@ -1324,7 +1320,7 @@ impl Markdown<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1358,7 +1354,7 @@ impl MarkdownWithToc<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1428,7 +1424,7 @@ impl MarkdownSummaryLine<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1475,7 +1471,7 @@ fn markdown_summary_with_limit( let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1556,7 +1552,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1751,7 +1747,7 @@ pub(crate) fn markdown_links<'md, R>( }; let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); - let mut event_iter = Parser::new_with_broken_link_callback( + let event_iter = Parser::new_with_broken_link_callback( md, main_body_opts(), Some(&mut broken_link_callback), @@ -1759,7 +1755,7 @@ pub(crate) fn markdown_links<'md, R>( .into_offset_iter(); let mut links = Vec::new(); - while let Some((event, span)) = event_iter.next() { + for (event, span) in event_iter { match event { Event::Start(Tag::Link { link_type, dest_url, .. }) if may_be_doc_link(link_type) => { let range = match link_type { @@ -1821,7 +1817,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust let lang_string = if syntax.is_empty() { Default::default() } else { - LangString::parse(&*syntax, ErrorCodes::Yes, false, Some(extra_info)) + LangString::parse(syntax, ErrorCodes::Yes, false, Some(extra_info)) }; if !lang_string.rust { continue; @@ -1885,75 +1881,82 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust #[derive(Clone, Default, Debug)] pub struct IdMap { - map: FxHashMap<Cow<'static, str>, usize>, + map: FxHashMap<String, usize>, existing_footnotes: usize, } -// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly. -static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new(); - -fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { - let mut map = FxHashMap::default(); - // This is the list of IDs used in JavaScript. - map.insert("help".into(), 1); - map.insert("settings".into(), 1); - map.insert("not-displayed".into(), 1); - map.insert("alternative-display".into(), 1); - map.insert("search".into(), 1); - map.insert("crate-search".into(), 1); - map.insert("crate-search-div".into(), 1); - // This is the list of IDs used in HTML generated in Rust (including the ones - // used in tera template files). - map.insert("themeStyle".into(), 1); - map.insert("settings-menu".into(), 1); - map.insert("help-button".into(), 1); - map.insert("sidebar-button".into(), 1); - map.insert("main-content".into(), 1); - map.insert("toggle-all-docs".into(), 1); - map.insert("all-types".into(), 1); - map.insert("default-settings".into(), 1); - map.insert("sidebar-vars".into(), 1); - map.insert("copy-path".into(), 1); - map.insert("rustdoc-toc".into(), 1); - map.insert("rustdoc-modnav".into(), 1); - // This is the list of IDs used by rustdoc sections (but still generated by - // rustdoc). - map.insert("fields".into(), 1); - map.insert("variants".into(), 1); - map.insert("implementors-list".into(), 1); - map.insert("synthetic-implementors-list".into(), 1); - map.insert("foreign-impls".into(), 1); - map.insert("implementations".into(), 1); - map.insert("trait-implementations".into(), 1); - map.insert("synthetic-implementations".into(), 1); - map.insert("blanket-implementations".into(), 1); - map.insert("required-associated-types".into(), 1); - map.insert("provided-associated-types".into(), 1); - map.insert("provided-associated-consts".into(), 1); - map.insert("required-associated-consts".into(), 1); - map.insert("required-methods".into(), 1); - map.insert("provided-methods".into(), 1); - map.insert("dyn-compatibility".into(), 1); - map.insert("implementors".into(), 1); - map.insert("synthetic-implementors".into(), 1); - map.insert("implementations-list".into(), 1); - map.insert("trait-implementations-list".into(), 1); - map.insert("synthetic-implementations-list".into(), 1); - map.insert("blanket-implementations-list".into(), 1); - map.insert("deref-methods".into(), 1); - map.insert("layout".into(), 1); - map.insert("aliased-type".into(), 1); - map +fn is_default_id(id: &str) -> bool { + matches!( + id, + // This is the list of IDs used in JavaScript. + "help" + | "settings" + | "not-displayed" + | "alternative-display" + | "search" + | "crate-search" + | "crate-search-div" + // This is the list of IDs used in HTML generated in Rust (including the ones + // used in tera template files). + | "themeStyle" + | "settings-menu" + | "help-button" + | "sidebar-button" + | "main-content" + | "toggle-all-docs" + | "all-types" + | "default-settings" + | "sidebar-vars" + | "copy-path" + | "rustdoc-toc" + | "rustdoc-modnav" + // This is the list of IDs used by rustdoc sections (but still generated by + // rustdoc). + | "fields" + | "variants" + | "implementors-list" + | "synthetic-implementors-list" + | "foreign-impls" + | "implementations" + | "trait-implementations" + | "synthetic-implementations" + | "blanket-implementations" + | "required-associated-types" + | "provided-associated-types" + | "provided-associated-consts" + | "required-associated-consts" + | "required-methods" + | "provided-methods" + | "dyn-compatibility" + | "implementors" + | "synthetic-implementors" + | "implementations-list" + | "trait-implementations-list" + | "synthetic-implementations-list" + | "blanket-implementations-list" + | "deref-methods" + | "layout" + | "aliased-type" + ) } impl IdMap { pub fn new() -> Self { - IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 } + IdMap { map: FxHashMap::default(), existing_footnotes: 0 } } pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String { let id = match self.map.get_mut(candidate.as_ref()) { - None => candidate.to_string(), + None => { + let candidate = candidate.to_string(); + if is_default_id(&candidate) { + let id = format!("{}-{}", candidate, 1); + self.map.insert(candidate.into(), 2); + id + } else { + candidate + } + } Some(a) => { let id = format!("{}-{}", candidate.as_ref(), *a); *a += 1; @@ -1973,4 +1976,9 @@ impl IdMap { closure(self, &mut existing_footnotes); self.existing_footnotes = existing_footnotes; } + + pub(crate) fn clear(&mut self) { + self.map.clear(); + self.existing_footnotes = 0; + } } diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index fcb8a174a95..ebf55b38373 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -64,7 +64,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> { } } -impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b, I> { +impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option<Self::Item> { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5f255c18ec6..40468aef4db 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::io; use std::path::{Path, PathBuf}; -use std::rc::Rc; use std::sync::mpsc::{Receiver, channel}; use rinja::Template; @@ -49,36 +48,49 @@ pub(crate) struct Context<'tcx> { /// The current destination folder of where HTML artifacts should be placed. /// This changes as the context descends into the module hierarchy. pub(crate) dst: PathBuf, - /// A flag, which when `true`, will render pages which redirect to the - /// real location of an item. This is used to allow external links to - /// publicly reused items to redirect to the right location. - pub(super) render_redirect_pages: bool, /// Tracks section IDs for `Deref` targets so they match in both the main /// body and the sidebar. - pub(super) deref_id_map: DefIdMap<String>, + pub(super) deref_id_map: RefCell<DefIdMap<String>>, /// The map used to ensure all generated 'id=' attributes are unique. - pub(super) id_map: IdMap, + pub(super) id_map: RefCell<IdMap>, /// Shared mutable state. /// /// Issue for improving the situation: [#82381][] /// /// [#82381]: https://github.com/rust-lang/rust/issues/82381 - pub(crate) shared: Rc<SharedContext<'tcx>>, + pub(crate) shared: SharedContext<'tcx>, + /// Collection of all types with notable traits referenced in the current module. + pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>, + /// Contains information that needs to be saved and reset after rendering an item which is + /// not a module. + pub(crate) info: ContextInfo, +} + +/// This struct contains the information that needs to be reset between each +/// [`FormatRenderer::item`] call. +/// +/// When we enter a new module, we set these values for the whole module but they might be updated +/// in each child item (especially if it's a module). So to prevent these changes to impact other +/// items rendering in the same module, we need to reset them to the module's set values. +#[derive(Clone, Copy)] +pub(crate) struct ContextInfo { + /// A flag, which when `true`, will render pages which redirect to the + /// real location of an item. This is used to allow external links to + /// publicly reused items to redirect to the right location. + pub(super) render_redirect_pages: bool, /// This flag indicates whether source links should be generated or not. If /// the source files are present in the html rendering, then this will be /// `true`. pub(crate) include_sources: bool, - /// Collection of all types with notable traits referenced in the current module. - pub(crate) types_with_notable_traits: FxIndexSet<clean::Type>, /// Field used during rendering, to know if we're inside an inlined item. pub(crate) is_inside_inlined_module: bool, } -// `Context` is cloned a lot, so we don't want the size to grow unexpectedly. -#[cfg(all(not(windows), target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 192); -#[cfg(all(windows, target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 200); +impl ContextInfo { + fn new(include_sources: bool) -> Self { + Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false } + } +} /// Shared mutable state used in [`Context`] and elsewhere. pub(crate) struct SharedContext<'tcx> { @@ -163,8 +175,8 @@ impl<'tcx> Context<'tcx> { self.shared.tcx.sess } - pub(super) fn derive_id<S: AsRef<str> + ToString>(&mut self, id: S) -> String { - self.id_map.derive(id) + pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String { + self.id_map.borrow_mut().derive(id) } /// String representation of how to get back to the root path of the 'doc/' @@ -174,14 +186,16 @@ impl<'tcx> Context<'tcx> { } fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String { - let mut render_redirect_pages = self.render_redirect_pages; + let mut render_redirect_pages = self.info.render_redirect_pages; // If the item is stripped but inlined, links won't point to the item so no need to generate // a file for it. if it.is_stripped() && let Some(def_id) = it.def_id() && def_id.is_local() { - if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) { + if self.info.is_inside_inlined_module + || self.shared.cache.inlined_items.contains(&def_id) + { // For now we're forced to generate a redirect page for stripped items until // `record_extern_fqn` correctly points to external items. render_redirect_pages = true; @@ -200,7 +214,7 @@ impl<'tcx> Context<'tcx> { }; title.push_str(" - Rust"); let tyname = it.type_(); - let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache())); + let desc = plain_text_summary(&it.doc_value(), &it.link_names(self.cache())); let desc = if !desc.is_empty() { desc } else if it.is_crate() { @@ -221,24 +235,23 @@ impl<'tcx> Context<'tcx> { }; if !render_redirect_pages { - let clone_shared = Rc::clone(&self.shared); + let mut page_buffer = Buffer::html(); + print_item(self, it, &mut page_buffer); let page = layout::Page { css_class: tyname_s, root_path: &self.root_path(), - static_root_path: clone_shared.static_root_path.as_deref(), + static_root_path: self.shared.static_root_path.as_deref(), title: &title, description: &desc, - resource_suffix: &clone_shared.resource_suffix, + resource_suffix: &self.shared.resource_suffix, rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo), }; - let mut page_buffer = Buffer::html(); - print_item(self, it, &mut page_buffer); layout::render( - &clone_shared.layout, + &self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), move |buf: &mut Buffer| buf.push_buffer(page_buffer), - &clone_shared.style_files, + &self.shared.style_files, ) } else { if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) { @@ -441,6 +454,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } const RUN_ON_MODULE: bool = true; + type ModuleData = ContextInfo; fn init( krate: clean::Crate, @@ -562,13 +576,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let mut cx = Context { current: Vec::new(), dst, - render_redirect_pages: false, - id_map, + id_map: RefCell::new(id_map), deref_id_map: Default::default(), - shared: Rc::new(scx), - include_sources, - types_with_notable_traits: FxIndexSet::default(), - is_inside_inlined_module: false, + shared: scx, + types_with_notable_traits: RefCell::new(FxIndexSet::default()), + info: ContextInfo::new(include_sources), }; if emit_crate { @@ -582,18 +594,15 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { Ok((cx, krate)) } - fn make_child_renderer(&self) -> Self { - Self { - current: self.current.clone(), - dst: self.dst.clone(), - render_redirect_pages: self.render_redirect_pages, - deref_id_map: Default::default(), - id_map: IdMap::new(), - shared: Rc::clone(&self.shared), - include_sources: self.include_sources, - types_with_notable_traits: FxIndexSet::default(), - is_inside_inlined_module: self.is_inside_inlined_module, - } + fn save_module_data(&mut self) -> Self::ModuleData { + self.deref_id_map.borrow_mut().clear(); + self.id_map.borrow_mut().clear(); + self.types_with_notable_traits.borrow_mut().clear(); + self.info + } + + fn set_back_info(&mut self, info: Self::ModuleData) { + self.info = info; } fn after_krate(&mut self) -> Result<(), Error> { @@ -607,7 +616,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if !root_path.ends_with('/') { root_path.push('/'); } - let shared = Rc::clone(&self.shared); + let shared = &self.shared; let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod sys", @@ -739,7 +748,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { &shared.layout, &page, "", - scrape_examples_help(&*shared), + scrape_examples_help(&shared), &shared.style_files, ); shared.fs.write(scrape_examples_help_file, v)?; @@ -754,11 +763,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { shared.fs.write(redirect_map_path, paths)?; } - // No need for it anymore. - drop(shared); - // Flush pending errors. - Rc::get_mut(&mut self.shared).unwrap().fs.close(); + self.shared.fs.close(); let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count(); if nb_errors > 0 { Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), "")) @@ -775,11 +781,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // External crates will provide links to these structures, so // these modules are recursed into, but not rendered normally // (a flag on the context). - if !self.render_redirect_pages { - self.render_redirect_pages = item.is_stripped(); + if !self.info.render_redirect_pages { + self.info.render_redirect_pages = item.is_stripped(); } let item_name = item.name.unwrap(); - self.dst.push(&*item_name.as_str()); + self.dst.push(item_name.as_str()); self.current.push(item_name); info!("Recursing into {}", self.dst.display()); @@ -793,26 +799,26 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.shared.fs.write(joint_dst, buf)?; } } - if !self.is_inside_inlined_module { + if !self.info.is_inside_inlined_module { if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) { - self.is_inside_inlined_module = true; + self.info.is_inside_inlined_module = true; } } else if !self.cache().document_hidden && item.is_doc_hidden() { // We're not inside an inlined module anymore since this one cannot be re-exported. - self.is_inside_inlined_module = false; + self.info.is_inside_inlined_module = false; } // Render sidebar-items.js used throughout this module. - if !self.render_redirect_pages { + if !self.info.render_redirect_pages { let (clean::StrippedItem(box clean::ModuleItem(ref module)) | clean::ModuleItem(ref module)) = item.kind else { unreachable!() }; let items = self.build_sidebar_items(module); - let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); + let js_dst = self.dst.join(format!("sidebar-items{}.js", self.shared.resource_suffix)); let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap()); self.shared.fs.write(js_dst, v)?; } @@ -836,8 +842,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // External crates will provide links to these structures, so // these modules are recursed into, but not rendered normally // (a flag on the context). - if !self.render_redirect_pages { - self.render_redirect_pages = item.is_stripped(); + if !self.info.render_redirect_pages { + self.info.render_redirect_pages = item.is_stripped(); } let buf = self.render_item(&item, false); @@ -850,7 +856,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let joint_dst = self.dst.join(file_name); self.shared.fs.write(joint_dst, buf)?; - if !self.render_redirect_pages { + if !self.info.render_redirect_pages { self.shared.all.borrow_mut().append(full_path(self, &item), &item_type); } // If the item is a macro, redirect from the old macro URL (with !) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f11356b44d8..f4367257572 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -41,7 +41,6 @@ use std::collections::VecDeque; use std::fmt::{self, Write}; use std::iter::Peekable; use std::path::PathBuf; -use std::rc::Rc; use std::{fs, str}; use rinja::Template; @@ -151,13 +150,13 @@ impl RenderType { string.push('{'); write_optional_id(self.id, string); string.push('{'); - for generic in &self.generics.as_deref().unwrap_or_default()[..] { + for generic in self.generics.as_deref().unwrap_or_default() { generic.write_to_string(string); } string.push('}'); if self.bindings.is_some() { string.push('{'); - for binding in &self.bindings.as_deref().unwrap_or_default()[..] { + for binding in self.bindings.as_deref().unwrap_or_default() { string.push('{'); binding.0.write_to_string(string); string.push('{'); @@ -504,7 +503,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { } fn document<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, item: &'a clean::Item, parent: Option<&'a clean::Item>, heading_offset: HeadingOffset, @@ -525,7 +524,7 @@ fn document<'a, 'cx: 'a>( /// Render md_text as markdown. fn render_markdown<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, md_text: &'a str, links: Vec<RenderedLink>, heading_offset: HeadingOffset, @@ -537,7 +536,7 @@ fn render_markdown<'a, 'cx: 'a>( Markdown { content: md_text, links: &links, - ids: &mut cx.id_map, + ids: &mut cx.id_map.borrow_mut(), error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -552,7 +551,7 @@ fn render_markdown<'a, 'cx: 'a>( /// docs are longer, a "Read more" link is appended to the end. fn document_short<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, link: AssocItemLink<'a>, parent: &'a clean::Item, show_def_docs: bool, @@ -585,7 +584,7 @@ fn document_short<'a, 'cx: 'a>( fn document_full_collapsible<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { document_full_inner(item, cx, true, heading_offset) @@ -593,7 +592,7 @@ fn document_full_collapsible<'a, 'cx: 'a>( fn document_full<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { document_full_inner(item, cx, false, heading_offset) @@ -601,7 +600,7 @@ fn document_full<'a, 'cx: 'a>( fn document_full_inner<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, is_collapsible: bool, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { @@ -644,7 +643,7 @@ struct ItemInfo { /// * Deprecated /// * Required features (through the `doc_cfg` feature) fn document_item_info( - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, parent: Option<&clean::Item>, ) -> ItemInfo { @@ -690,7 +689,7 @@ enum ShortItemInfo { /// the item's documentation. fn short_item_info( item: &clean::Item, - cx: &mut Context<'_>, + cx: &Context<'_>, parent: Option<&clean::Item>, ) -> Vec<ShortItemInfo> { let mut extra_info = vec![]; @@ -715,7 +714,8 @@ fn short_item_info( if let Some(note) = note { let note = note.as_str(); - let html = MarkdownItemInfo(note, &mut cx.id_map); + let mut id_map = cx.id_map.borrow_mut(); + let html = MarkdownItemInfo(note, &mut id_map); message.push_str(": "); message.push_str(&html.into_string()); } @@ -749,18 +749,17 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). pub(crate) fn render_impls( - cx: &mut Context<'_>, + cx: &Context<'_>, mut w: impl Write, impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, ) { - let tcx = cx.tcx(); let mut rendered_impls = impls .iter() .map(|i| { let did = i.trait_did().unwrap(); - let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); + let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx()); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); let mut buffer = Buffer::new(); render_impl( @@ -906,7 +905,7 @@ fn assoc_method( d: &clean::FnDecl, link: AssocItemLink<'_>, parent: ItemType, - cx: &mut Context<'_>, + cx: &Context<'_>, render_mode: RenderMode, ) { let tcx = cx.tcx(); @@ -1071,7 +1070,7 @@ fn render_assoc_item( item: &clean::Item, link: AssocItemLink<'_>, parent: ItemType, - cx: &mut Context<'_>, + cx: &Context<'_>, render_mode: RenderMode, ) { match &item.kind { @@ -1191,7 +1190,7 @@ fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) { pub(crate) fn render_all_impls( mut w: impl Write, - cx: &mut Context<'_>, + cx: &Context<'_>, containing_item: &clean::Item, concrete: &[&Impl], synthetic: &[&Impl], @@ -1225,7 +1224,7 @@ pub(crate) fn render_all_impls( } fn render_assoc_items<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, containing_item: &'a clean::Item, it: DefId, what: AssocItemRender<'a>, @@ -1240,15 +1239,14 @@ fn render_assoc_items<'a, 'cx: 'a>( fn render_assoc_items_inner( mut w: &mut dyn fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, derefs: &mut DefIdSet, ) { info!("Documenting associated items of {:?}", containing_item.name); - let shared = Rc::clone(&cx.shared); - let cache = &shared.cache; + let cache = &cx.shared.cache; let Some(v) = cache.impls.get(&it) else { return }; let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { @@ -1276,7 +1274,7 @@ fn render_assoc_items_inner( ); tmp_buf.write_str("</summary>"); if let Some(def_id) = type_.def_id(cx.cache()) { - cx.deref_id_map.insert(def_id, id); + cx.deref_id_map.borrow_mut().insert(def_id, id); } (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#) } @@ -1340,7 +1338,7 @@ fn render_assoc_items_inner( fn render_deref_methods( mut w: impl Write, - cx: &mut Context<'_>, + cx: &Context<'_>, impl_: &Impl, container_item: &clean::Item, deref_mut: bool, @@ -1407,7 +1405,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> { +pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<String> { let mut has_notable_trait = false; if ty.is_unit() { @@ -1450,7 +1448,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O } if has_notable_trait { - cx.types_with_notable_traits.insert(ty.clone()); + cx.types_with_notable_traits.borrow_mut().insert(ty.clone()); Some(format!( " <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>", ty = Escape(&format!("{:#}", ty.print(cx))), @@ -1554,7 +1552,7 @@ struct ImplRenderingParameters { fn render_impl( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, i: &Impl, parent: &clean::Item, link: AssocItemLink<'_>, @@ -1563,8 +1561,7 @@ fn render_impl( aliases: &[String], rendering_params: ImplRenderingParameters, ) { - let shared = Rc::clone(&cx.shared); - let cache = &shared.cache; + let cache = &cx.shared.cache; let traits = &cache.traits; let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = <Vec<&str>>::with_capacity(2); @@ -1577,7 +1574,7 @@ fn render_impl( fn doc_impl_item( boring: &mut Buffer, interesting: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, parent: &clean::Item, link: AssocItemLink<'_>, @@ -1867,7 +1864,7 @@ fn render_impl( fn render_default_items( boring: &mut Buffer, interesting: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, t: &clean::Trait, i: &clean::Impl, parent: &clean::Item, @@ -1907,6 +1904,7 @@ fn render_impl( } } + let trait_is_none = trait_.is_none(); // If we've implemented a trait, then also emit documentation for all // default items which weren't overridden in the implementation block. // We don't emit documentation for default items if they appear in the @@ -1952,7 +1950,7 @@ fn render_impl( } if let Some(ref dox) = i.impl_item.opt_doc_value() { - if trait_.is_none() && impl_.items.is_empty() { + if trait_is_none && impl_.items.is_empty() { w.write_str( "<div class=\"item-info\">\ <div class=\"stab empty-impl\">This impl block contains no items.</div>\ @@ -1963,9 +1961,9 @@ fn render_impl( w, "<div class=\"docblock\">{}</div>", Markdown { - content: &*dox, + content: dox, links: &i.impl_item.links(cx), - ids: &mut cx.id_map, + ids: &mut cx.id_map.borrow_mut(), error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -2025,7 +2023,7 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render pub(crate) fn render_impl_summary( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, i: &Impl, parent: &clean::Item, show_def_docs: bool, @@ -2093,9 +2091,7 @@ pub(crate) fn small_url_encode(s: String) -> String { // and https://url.spec.whatwg.org/#urlencoded-parsing // and https://url.spec.whatwg.org/#url-code-points fn dont_escape(c: u8) -> bool { - (b'a' <= c && c <= b'z') - || (b'A' <= c && c <= b'Z') - || (b'0' <= c && c <= b'9') + c.is_ascii_alphanumeric() || c == b'-' || c == b'_' || c == b'.' @@ -2150,7 +2146,7 @@ pub(crate) fn small_url_encode(s: String) -> String { } } -fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String { +fn get_id_for_impl(tcx: TyCtxt<'_>, impl_id: ItemId) -> String { use rustc_middle::ty::print::with_forced_trimmed_paths; let (type_, trait_) = match impl_id { ItemId::Auto { trait_, for_ } => { @@ -2188,7 +2184,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String /// implementations that are on concrete or partially generic types, only keeping implementations /// of the form `impl<T> Trait for &T`. pub(crate) fn get_filtered_impls_for_reference<'a>( - shared: &'a Rc<SharedContext<'_>>, + shared: &'a SharedContext<'_>, it: &clean::Item, ) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) { let def_id = it.item_id.expect_def_id(); @@ -2381,7 +2377,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> { let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { - out.push(join_with_double_colon(&path)); + out.push(join_with_double_colon(path)); } }; @@ -2425,14 +2421,14 @@ const MAX_FULL_EXAMPLES: usize = 5; const NUM_VISIBLE_LINES: usize = 10; /// Generates the HTML for example call locations generated via the --scrape-examples flag. -fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) { +fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean::Item) { let tcx = cx.tcx(); let def_id = item.item_id.expect_def_id(); let key = tcx.def_path_hash(def_id); let Some(call_locations) = cx.shared.call_locations.get(&key) else { return }; // Generate a unique ID so users can link to this section for a given method - let id = cx.id_map.derive("scraped-examples"); + let id = cx.derive_id("scraped-examples"); write!( &mut w, "<div class=\"docblock scraped-example-list\">\ @@ -2462,8 +2458,8 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c }; // Generate the HTML for a single example, being the title and code block - let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { - let contents = match fs::read_to_string(&path) { + let write_example = |w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { + let contents = match fs::read_to_string(path) { Ok(contents) => contents, Err(err) => { let span = item.span(tcx).map_or(DUMMY_SP, |span| span.inner()); @@ -2532,7 +2528,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c decoration_info.insert("highlight", byte_ranges); sources::print_src( - &mut w, + w, contents_subset, file_span, cx, @@ -2581,7 +2577,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c // An example may fail to write if its source can't be read for some reason, so this method // continues iterating until a write succeeds let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| { - while let Some(example) = it.next() { + for example in it.by_ref() { if write_example(&mut *w, example) { break; } diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs index 7abe40eef3b..d1dddfebc83 100644 --- a/src/librustdoc/html/render/ordered_json.rs +++ b/src/librustdoc/html/render/ordered_json.rs @@ -23,7 +23,7 @@ impl OrderedJson { pub(crate) fn array_sorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self { let items = items .into_iter() - .sorted_unstable_by(|a, b| a.borrow().cmp(&b.borrow())) + .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow())) .format_with(",", |item, f| f(item.borrow())); Self(format!("[{}]", items)) } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d247e90d298..4c8d704e65b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,7 +1,5 @@ -use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::fmt; -use std::rc::Rc; use itertools::Itertools; use rinja::Template; @@ -61,7 +59,7 @@ macro_rules! item_template { ( $(#[$meta:meta])* struct $name:ident<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, $($field_name:ident: $field_ty:ty),*, }, @@ -70,14 +68,14 @@ macro_rules! item_template { #[derive(Template)] $(#[$meta])* struct $name<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, $($field_name: $field_ty),* } impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { - (&self.it, self.cx.borrow_mut()) + fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>) { + (&self.it, &self.cx) } } @@ -95,8 +93,8 @@ macro_rules! item_template_methods { (document $($rest:tt)*) => { fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, mut cx) = self.item_and_mut_cx(); - let v = document(*cx, item, None, HeadingOffset::H2); + let (item, cx) = self.item_and_cx(); + let v = document(cx, item, None, HeadingOffset::H2); write!(f, "{v}") }) } @@ -105,9 +103,9 @@ macro_rules! item_template_methods { (document_type_layout $($rest:tt)*) => { fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, cx) = self.item_and_mut_cx(); + let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); - let v = document_type_layout(*cx, def_id); + let v = document_type_layout(cx, def_id); write!(f, "{v}") }) } @@ -116,8 +114,8 @@ macro_rules! item_template_methods { (render_attributes_in_pre $($rest:tt)*) => { fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, cx) = self.item_and_mut_cx(); - let v = render_attributes_in_pre(item, "", &cx); + let (item, cx) = self.item_and_cx(); + let v = render_attributes_in_pre(item, "", cx); write!(f, "{v}") }) } @@ -126,9 +124,9 @@ macro_rules! item_template_methods { (render_assoc_items $($rest:tt)*) => { fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, mut cx) = self.item_and_mut_cx(); + let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); - let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All); + let v = render_assoc_items(cx, item, def_id, AssocItemRender::All); write!(f, "{v}") }) } @@ -175,7 +173,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>( len_before != buffer.len() } -pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) { +pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); let typ = match item.kind { clean::ModuleItem(_) => { @@ -223,7 +221,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. let src_href = - if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; + if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; let path_components = if item.is_primitive() || item.is_keyword() { vec![] @@ -277,13 +275,14 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf } // Render notable-traits.js used for all methods in this module. - if !cx.types_with_notable_traits.is_empty() { + let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut(); + if !types_with_notable_traits.is_empty() { write!( buf, r#"<script type="text/json" id="notable-traits-data">{}</script>"#, - notable_traits_json(cx.types_with_notable_traits.iter(), cx) + notable_traits_json(types_with_notable_traits.iter(), cx) ); - cx.types_with_notable_traits.clear(); + types_with_notable_traits.clear(); } } @@ -308,10 +307,10 @@ fn toggle_close(mut w: impl fmt::Write) { } trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); + fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>); } -fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { +fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) { write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); let mut not_stripped_items = @@ -594,7 +593,7 @@ fn extra_info_tags<'a, 'tcx: 'a>( }) } -fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) { +fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { let tcx = cx.tcx(); let header = it.fn_header(tcx).expect("printing a function which isn't a function"); debug!( @@ -649,7 +648,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); } -fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) { +fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { let tcx = cx.tcx(); let bounds = bounds(&t.bounds, false, cx); let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>(); @@ -751,7 +750,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_methods.is_empty() { - write!(w, " // Required method{}\n", pluralize(required_methods.len())); + writeln!(w, " // Required method{}", pluralize(required_methods.len())); } for (pos, m) in required_methods.iter().enumerate() { render_assoc_item( @@ -773,7 +772,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !provided_methods.is_empty() { - write!(w, " // Provided method{}\n", pluralize(provided_methods.len())); + writeln!(w, " // Provided method{}", pluralize(provided_methods.len())); } for (pos, m) in provided_methods.iter().enumerate() { render_assoc_item( @@ -801,7 +800,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Trait documentation write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) { + fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.unwrap(); info!("Documenting {name} on {ty_name:?}", ty_name = t.name); let item_type = m.type_(); @@ -929,8 +928,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // If there are methods directly on this trait object, render them here. write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); - let cloned_shared = Rc::clone(&cx.shared); - let cache = &cloned_shared.cache; let mut extern_crates = FxIndexSet::default(); if !t.is_dyn_compatible(cx.tcx()) { @@ -940,7 +937,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: "Dyn Compatibility", "dyn-compatibility", None, - &format!( + format!( "<div class=\"dyn-compatibility-info\"><p>This trait is <b>not</b> \ <a href=\"{base}/reference/items/traits.html#object-safety\">dyn compatible</a>.</p>\ <p><i>In older versions of Rust, dyn compatibility was called \"object safety\", \ @@ -950,12 +947,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: ); } - if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { + if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default(); for implementor in implementors { - if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) + if let Some(did) = + implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache) && !did.is_local() { extern_crates.insert(did.krate); @@ -1036,7 +1034,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: it, w, &implementor_dups, - &collect_paths_for_type(implementor.inner_impl().for_.clone(), cache), + &collect_paths_for_type( + implementor.inner_impl().for_.clone(), + &cx.shared.cache, + ), ); } w.write_str("</div>"); @@ -1139,8 +1140,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: .chain(std::iter::once("trait.impl")) .collect(); if let Some(did) = it.item_id.as_def_id() - && let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } - && let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) + && let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) } + && let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern) { js_src_path.extend(fqp[..fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap())); @@ -1164,7 +1165,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn item_trait_alias( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias, ) { @@ -1190,7 +1191,7 @@ fn item_trait_alias( .unwrap(); } -fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { +fn item_type_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { wrap_item(w, |w| { write!( w, @@ -1225,14 +1226,14 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c w, cx, Some(&t.generics), - &variants, + variants, variants_count, has_stripped_entries, *is_non_exhaustive, enum_def_id, ) }); - item_variants(w, cx, it, &variants, enum_def_id); + item_variants(w, cx, it, variants, enum_def_id); } clean::TypeAliasInnerType::Union { fields } => { wrap_item(w, |w| { @@ -1355,8 +1356,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c // // [JSONP]: https://en.wikipedia.org/wiki/JSONP // [^115718]: https://github.com/rust-lang/rust/issues/115718 - let cloned_shared = Rc::clone(&cx.shared); - let cache = &cloned_shared.cache; + let cache = &cx.shared.cache; if let Some(target_did) = t.type_.def_id(cache) && let get_extern = { || cache.external_paths.get(&target_did) } && let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) && @@ -1380,11 +1380,11 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c } } -fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { +fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { item_template!( #[template(path = "item_union.html")] struct ItemUnion<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, s: &'a clean::Union, }, @@ -1394,8 +1394,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let cx = self.cx.borrow_mut(); - let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); + let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx); write!(f, "{v}") }) } @@ -1405,15 +1404,13 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: field: &'a clean::Item, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + let v = document(self.cx, field, Some(self.it), HeadingOffset::H3); write!(f, "{v}") }) } fn stability_field(&self, field: &clean::Item) -> Option<String> { - let cx = self.cx.borrow(); - field.stability_class(cx.tcx()) + field.stability_class(self.cx.tcx()) } fn print_ty<'b>( @@ -1421,8 +1418,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: ty: &'a clean::Type, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let cx = self.cx.borrow(); - let v = ty.print(*cx); + let v = ty.print(&self.cx); write!(f, "{v}") }) } @@ -1441,7 +1437,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: } } - ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap(); + ItemUnion { cx, it, s }.render_into(w).unwrap(); } fn print_tuple_struct_fields<'a, 'cx: 'a>( @@ -1471,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( }) } -fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { +fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { let count_variants = e.variants().count(); wrap_item(w, |w| { render_attributes_in_code(w, it, cx); @@ -1532,7 +1528,7 @@ fn should_show_enum_discriminant( fn display_c_like_variant( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, variant: &clean::Variant, index: VariantIdx, @@ -1557,7 +1553,7 @@ fn display_c_like_variant( fn render_enum_fields( mut w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, g: Option<&clean::Generics>, variants: &IndexVec<VariantIdx, clean::Item>, count_variants: usize, @@ -1621,7 +1617,7 @@ fn render_enum_fields( fn item_variants( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, variants: &IndexVec<VariantIdx, clean::Item>, enum_def_id: DefId, @@ -1743,7 +1739,7 @@ fn item_variants( write!(w, "</div>"); } -fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { +fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) { wrap_item(w, |w| { // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`. if !t.macro_rules { @@ -1756,7 +1752,7 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn item_proc_macro( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro, ) { @@ -1790,7 +1786,7 @@ fn item_proc_macro( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); } -fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) { +fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) { let def_id = it.item_id.expect_def_id(); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { @@ -1798,8 +1794,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. - let shared = Rc::clone(&cx.shared); - let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it); render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl); } @@ -1807,7 +1802,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite fn item_constant( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, generics: &clean::Generics, ty: &clean::Type, @@ -1824,7 +1819,7 @@ fn item_constant( name = it.name.unwrap(), generics = generics.print(cx), typ = ty.print(cx), - where_clause = print_where_clause(&generics, cx, 0, Ending::NoNewline), + where_clause = print_where_clause(generics, cx, 0, Ending::NoNewline), ); // FIXME: The code below now prints @@ -1862,7 +1857,7 @@ fn item_constant( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } -fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { +fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) { wrap_item(w, |w| { render_attributes_in_code(w, it, cx); render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); @@ -1879,7 +1874,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean fn item_fields( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, fields: &[clean::Item], ctor_kind: Option<CtorKind>, @@ -1920,7 +1915,7 @@ fn item_fields( fn item_static( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, s: &clean::Static, safety: Option<hir::Safety>, @@ -1944,7 +1939,7 @@ fn item_static( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); } -fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) { +fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) { wrap_item(w, |buffer| { buffer.write_str("extern {\n").unwrap(); render_attributes_in_code(buffer, it, cx); @@ -1962,7 +1957,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean:: .unwrap(); } -fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { +fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } @@ -2134,7 +2129,7 @@ impl Ord for ImplString { } fn render_implementor( - cx: &mut Context<'_>, + cx: &Context<'_>, implementor: &Impl, trait_: &clean::Item, w: &mut Buffer, @@ -2194,7 +2189,7 @@ fn render_union<'a, 'cx: 'a>( f.write_str(" ")?; } - write!(f, "{{\n")?; + writeln!(f, "{{")?; let count_fields = fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -2204,9 +2199,9 @@ fn render_union<'a, 'cx: 'a>( for field in fields { if let clean::StructFieldItem(ref ty) = field.kind { - write!( + writeln!( f, - " {}{}: {},\n", + " {}{}: {},", visibility_print_with_space(field, cx), field.name.unwrap(), ty.print(cx) @@ -2215,7 +2210,7 @@ fn render_union<'a, 'cx: 'a>( } if it.has_stripped_entries().unwrap() { - write!(f, " <span class=\"comment\">/* private fields */</span>\n")?; + writeln!(f, " <span class=\"comment\">/* private fields */</span>")?; } if toggle { toggle_close(&mut f); @@ -2355,7 +2350,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a { +fn document_non_exhaustive(item: &clean::Item) -> impl fmt::Display + '_ { display_fn(|f| { if item.is_non_exhaustive() { write!( diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f91fdfa1fb5..cfb62c3ca16 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -55,10 +55,10 @@ pub(crate) struct SerializedSearchIndex { const DESC_INDEX_SHARD_LEN: usize = 128 * 1024; /// Builds the search index from the collected metadata -pub(crate) fn build_index<'tcx>( +pub(crate) fn build_index( krate: &clean::Crate, cache: &mut Cache, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, ) -> SerializedSearchIndex { // Maps from ID to position in the `crate_paths` array. let mut itemid_to_pathid = FxHashMap::default(); @@ -126,7 +126,7 @@ pub(crate) fn build_index<'tcx>( let mut lastpathid = 0isize; // First, on function signatures - let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new()); + let mut search_index = std::mem::take(&mut cache.search_index); for item in search_index.iter_mut() { fn insert_into_map<F: std::hash::Hash + Eq>( map: &mut FxHashMap<F, isize>, @@ -194,7 +194,7 @@ pub(crate) fn build_index<'tcx>( { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need // to store the name once (and the path is re-used for everything @@ -298,7 +298,7 @@ pub(crate) fn build_index<'tcx>( true }); } - let Some(id) = ty.id.clone() else { + let Some(id) = ty.id else { assert!(ty.generics.is_some()); return; }; @@ -372,7 +372,7 @@ pub(crate) fn build_index<'tcx>( if let Some(&(ref fqp, short)) = paths.get(&defid) { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) .filter(|exact_fqp| { exact_fqp.last() == Some(&item.name) && *exact_fqp != fqp }); @@ -397,7 +397,7 @@ pub(crate) fn build_index<'tcx>( // Their parent carries the exact fqp instead. let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)); + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)); item.exact_path = exact_fqp.and_then(|fqp| { // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need @@ -426,7 +426,7 @@ pub(crate) fn build_index<'tcx>( } // Omit the parent path if it is same to that of the prior item. - if lastpath == &item.path { + if lastpath == item.path { item.path.clear(); } else { lastpath = &item.path; @@ -512,7 +512,7 @@ pub(crate) fn build_index<'tcx>( } } - impl<'a> Serialize for CrateData<'a> { + impl Serialize for CrateData<'_> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, @@ -640,7 +640,7 @@ pub(crate) fn build_index<'tcx>( let mut last_name = None; for (index, item) in self.items.iter().enumerate() { let n = item.ty as u8; - let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); + let c = char::from(n + b'A'); assert!(c <= 'z', "item types must fit within ASCII printables"); types.push(c); @@ -741,22 +741,22 @@ pub(crate) fn build_index<'tcx>( let mut len: usize = 0; let mut item_index: u32 = 0; for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { - if desc == "" { + if desc.is_empty() { empty_desc.push(item_index); item_index += 1; continue; } if set.len() >= DESC_INDEX_SHARD_LEN { - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); len = 0; } else if len != 0 { set.push('\n'); } - set.push_str(&desc); + set.push_str(desc); len += 1; item_index += 1; } - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); (empty_desc, result) }; @@ -792,9 +792,9 @@ pub(crate) fn build_index<'tcx>( SerializedSearchIndex { index, desc } } -pub(crate) fn get_function_type_for_search<'tcx>( +pub(crate) fn get_function_type_for_search( item: &clean::Item, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_generics: Option<&(clean::Type, clean::Generics)>, parent: Option<DefId>, cache: &Cache, @@ -861,7 +861,7 @@ fn get_index_type_id( match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { - bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id())) + bounds.first().map(|b| RenderTypeId::DefId(b.trait_.def_id())) } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)), @@ -953,7 +953,7 @@ fn simplify_fn_type<'a, 'tcx>( WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, _ => false, }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); + let bounds = where_pred.get_bounds().unwrap_or(&[]); for bound in bounds.iter() { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; @@ -1043,7 +1043,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1058,7 +1058,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1074,7 +1074,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1117,7 +1117,7 @@ fn simplify_fn_type<'a, 'tcx>( ); let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; res.push(RenderType { - id: get_index_type_id(&arg, rgen), + id: get_index_type_id(arg, rgen), bindings: Some(ty_bindings), generics: Some(ty_generics), }); @@ -1134,7 +1134,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &type_, + type_, tcx, recurse + 1, &mut ty_generics, @@ -1249,7 +1249,7 @@ fn simplify_fn_type<'a, 'tcx>( } } } - let id = get_index_type_id(&arg, rgen); + let id = get_index_type_id(arg, rgen); if id.is_some() || !ty_generics.is_empty() { res.push(RenderType { id, @@ -1261,11 +1261,11 @@ fn simplify_fn_type<'a, 'tcx>( } } -fn simplify_fn_constraint<'a, 'tcx>( +fn simplify_fn_constraint<'a>( self_: Option<&'a Type>, generics: &Generics, constraint: &'a clean::AssocItemConstraint, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, recurse: usize, res: &mut Vec<(RenderTypeId, Vec<RenderType>)>, rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>, @@ -1347,9 +1347,9 @@ fn simplify_fn_constraint<'a, 'tcx>( /// /// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return /// `[u32, Display, Option]`. -fn get_fn_inputs_and_outputs<'tcx>( +fn get_fn_inputs_and_outputs( func: &Function, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>, cache: &Cache, ) -> (Vec<RenderType>, Vec<RenderType>, Vec<Symbol>, Vec<Vec<RenderType>>) { diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index 8d715814faa..8816ea65059 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -25,7 +25,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { break; } shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } // now write the rest while shift < 32 { @@ -33,7 +33,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); string.push(hex); shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } } @@ -64,7 +64,7 @@ impl Container { Container::Array(array) => { array.push(value); if array.len() >= 4096 { - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Bits(Box::new([0; 1024])); for value in array { self.push(value); @@ -123,7 +123,7 @@ impl Container { if 2 + 4 * r >= 2 * array.len() + 2 { return false; } - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Run(Vec::new()); for value in array { self.push(value); @@ -145,7 +145,7 @@ pub(crate) fn write_bitmap_to_bytes( let mut keys = Vec::<u16>::new(); let mut containers = Vec::<Container>::new(); let mut key: u16; - let mut domain_iter = domain.into_iter().copied().peekable(); + let mut domain_iter = domain.iter().copied().peekable(); let mut has_run = false; while let Some(entry) = domain_iter.next() { key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); @@ -236,7 +236,7 @@ pub(crate) fn write_bitmap_to_bytes( pub(crate) fn bitmap_to_string(domain: &[u32]) -> String { let mut buf = Vec::new(); let mut strbuf = String::new(); - write_bitmap_to_bytes(&domain, &mut buf).unwrap(); + write_bitmap_to_bytes(domain, &mut buf).unwrap(); BASE64_STANDARD.encode_string(&buf, &mut strbuf); strbuf } diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6df9486e658..e99e2f04b2c 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -1,10 +1,9 @@ use std::borrow::Cow; -use std::rc::Rc; use rinja::Template; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::CtorKind; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def_id::{DefIdMap, DefIdSet}; use rustc_middle::ty::{self, TyCtxt}; use tracing::debug; @@ -44,7 +43,7 @@ pub(super) struct Sidebar<'a> { pub(super) path: String, } -impl<'a> Sidebar<'a> { +impl Sidebar<'_> { /// Only create a `<section>` if there are any blocks /// which should actually be rendered. pub fn should_render_blocks(&self) -> bool { @@ -119,17 +118,18 @@ pub(crate) mod filters { pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let mut ids = IdMap::new(); let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect(); + let deref_id_map = cx.deref_id_map.borrow(); match it.kind { - clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks), - clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks), - clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks), - clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks), - clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks), - clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks), + clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks, &deref_id_map), + clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks, &deref_id_map), + clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks, &deref_id_map), + clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks, &deref_id_map), + clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks, &deref_id_map), + clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks, &deref_id_map), clean::ModuleItem(ref m) => { blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it))) } - clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks), + clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks, &deref_id_map), _ => {} } // The sidebar is designed to display sibling functions, modules and @@ -245,6 +245,7 @@ fn sidebar_struct<'a>( it: &'a clean::Item, s: &'a clean::Struct, items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { let fields = get_struct_fields_name(&s.fields); let field_name = match s.ctor_kind { @@ -255,7 +256,7 @@ fn sidebar_struct<'a>( if let Some(name) = field_name { items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields)); } - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } fn sidebar_trait<'a>( @@ -263,6 +264,7 @@ fn sidebar_trait<'a>( it: &'a clean::Item, t: &'a clean::Trait, blocks: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { fn filter_items<'a>( items: &'a [clean::Item], @@ -313,7 +315,7 @@ fn sidebar_trait<'a>( .into_iter() .map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)), ); - sidebar_assoc_items(cx, it, blocks); + sidebar_assoc_items(cx, it, blocks, deref_id_map); if !t.is_dyn_compatible(cx.tcx()) { blocks.push(LinkBlock::forced( @@ -331,13 +333,17 @@ fn sidebar_trait<'a>( } } -fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>) { +fn sidebar_primitive<'a>( + cx: &'a Context<'_>, + it: &'a clean::Item, + items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, +) { if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } else { - let shared = Rc::clone(&cx.shared); let (concrete, synthetic, blanket_impl) = - super::get_filtered_impls_for_reference(&shared, it); + super::get_filtered_impls_for_reference(&cx.shared, it); sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items); } @@ -348,6 +354,7 @@ fn sidebar_type_alias<'a>( it: &'a clean::Item, t: &'a clean::TypeAlias, items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { if let Some(inner_type) = &t.inner_type { items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type")); @@ -370,7 +377,7 @@ fn sidebar_type_alias<'a>( } } } - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } fn sidebar_union<'a>( @@ -378,10 +385,11 @@ fn sidebar_union<'a>( it: &'a clean::Item, u: &'a clean::Union, items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { let fields = get_struct_fields_name(&u.fields); items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields)); - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } /// Adds trait implementations into the blocks of links @@ -389,6 +397,7 @@ fn sidebar_assoc_items<'a>( cx: &'a Context<'_>, it: &'a clean::Item, links: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { let did = it.item_id.expect_def_id(); let cache = cx.cache(); @@ -433,7 +442,15 @@ fn sidebar_assoc_items<'a>( { let mut derefs = DefIdSet::default(); derefs.insert(did); - sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links); + sidebar_deref_methods( + cx, + &mut blocks, + impl_, + v, + &mut derefs, + &mut used_links, + deref_id_map, + ); } let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = @@ -462,6 +479,7 @@ fn sidebar_deref_methods<'a>( v: &[Impl], derefs: &mut DefIdSet, used_links: &mut FxHashSet<String>, + deref_id_map: &'a DefIdMap<String>, ) { let c = cx.cache(); @@ -501,7 +519,7 @@ fn sidebar_deref_methods<'a>( if !ret.is_empty() { let id = if let Some(target_def_id) = real_target.def_id(c) { Cow::Borrowed( - cx.deref_id_map + deref_id_map .get(&target_def_id) .expect("Deref section without derived id") .as_str(), @@ -531,7 +549,15 @@ fn sidebar_deref_methods<'a>( .unwrap_or(false) }) { - sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links); + sidebar_deref_methods( + cx, + out, + target_deref_impl, + target_impls, + derefs, + used_links, + deref_id_map, + ); } } } @@ -541,6 +567,7 @@ fn sidebar_enum<'a>( it: &'a clean::Item, e: &'a clean::Enum, items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { let mut variants = e .variants() @@ -550,7 +577,7 @@ fn sidebar_enum<'a>( variants.sort_unstable(); items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants)); - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } pub(crate) fn sidebar_module_like( @@ -564,9 +591,9 @@ pub(crate) fn sidebar_module_like( .filter(|sec| item_sections_in_use.contains(sec)) .map(|sec| Link::new(ids.derive(sec.id()), sec.name())) .collect(); - let header = if let Some(first_section) = item_sections.get(0) { + let header = if let Some(first_section) = item_sections.first() { Link::new( - first_section.href.to_owned(), + first_section.href.clone(), if module_like.is_crate() { "Crate Items" } else { "Module Items" }, ) } else { @@ -607,8 +634,9 @@ fn sidebar_foreign_type<'a>( cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>, + deref_id_map: &'a DefIdMap<String>, ) { - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } /// Renders the trait implementations for this type diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs index 28f7766d7c7..dc894840f92 100644 --- a/src/librustdoc/html/render/sorted_template.rs +++ b/src/librustdoc/html/render/sorted_template.rs @@ -84,7 +84,7 @@ impl<F: FileFormat> FromStr for SortedTemplate<F> { let offset = offset .strip_suffix(F::COMMENT_END) .ok_or(Error("last line expected to end with a comment"))?; - let offset: Offset = serde_json::from_str(&offset).map_err(|_| { + let offset: Offset = serde_json::from_str(offset).map_err(|_| { Error("could not find insertion location descriptor object on last line") })?; let (before, mut s) = diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index d4cca562d6c..81d79a6be96 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -63,7 +63,7 @@ struct SpanMapVisitor<'tcx> { pub(crate) matches: FxHashMap<Span, LinkFromSrc>, } -impl<'tcx> SpanMapVisitor<'tcx> { +impl SpanMapVisitor<'_> { /// This function is where we handle `hir::Path` elements and add them into the "span map". fn handle_path(&mut self, path: &rustc_hir::Path<'_>) { match path.res { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index c82f7e9aaf9..ce10e5ecc24 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -43,7 +43,6 @@ use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::Impl; -use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::format::Buffer; use crate::html::layout; @@ -62,14 +61,13 @@ pub(crate) fn write_shared( tcx: TyCtxt<'_>, ) -> Result<(), Error> { // NOTE(EtomicBomb): I don't think we need sync here because no read-after-write? - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); + cx.shared.fs.set_sync_only(true); let lock_file = cx.dst.join(".lock"); // Write shared runs within a flock; disable thread dispatching of IO temporarily. let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - let SerializedSearchIndex { index, desc } = - build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - write_search_desc(cx, &krate, &desc)?; // does not need to be merged + let SerializedSearchIndex { index, desc } = build_index(krate, &mut cx.shared.cache, tcx); + write_search_desc(cx, krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand @@ -80,7 +78,7 @@ pub(crate) fn write_shared( src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, - crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, + crates_index: CratesIndexPart::get(crate_name, &external_crates)?, trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; @@ -104,7 +102,7 @@ pub(crate) fn write_shared( &cx.shared.style_files, cx.shared.layout.css_file_extension.as_deref(), &cx.shared.resource_suffix, - cx.include_sources, + cx.info.include_sources, )?; match &opt.index_page { Some(index_page) if opt.enable_index_page => { @@ -112,7 +110,7 @@ pub(crate) fn write_shared( md_opts.output = cx.dst.clone(); md_opts.external_html = cx.shared.layout.external_html.clone(); try_err!( - crate::markdown::render_and_write(&index_page, md_opts, cx.shared.edition()), + crate::markdown::render_and_write(index_page, md_opts, cx.shared.edition()), &index_page ); } @@ -128,7 +126,7 @@ pub(crate) fn write_shared( } } - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); + cx.shared.fs.set_sync_only(false); Ok(()) } @@ -158,13 +156,13 @@ fn write_rendered_cross_crate_info( let m = &opt.should_merge; if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { if include_sources { - write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, &crates, m)?; + write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, crates, m)?; } - write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, &crates, m)?; - write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, &crates, m)?; + write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, crates, m)?; + write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, crates, m)?; } - write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, &crates, m)?; - write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, &crates, m)?; + write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, crates, m)?; + write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, crates, m)?; Ok(()) } @@ -234,7 +232,7 @@ fn write_search_desc( &cx.shared.resource_suffix, ); let path = path.join(filename); - let part = OrderedJson::serialize(&part).unwrap(); + let part = OrderedJson::serialize(part).unwrap(); let part = format!("searchState.loadedDescShard({encoded_crate_name}, {i}, {part})"); create_parents(&path)?; try_err!(fs::write(&path, part), &path); @@ -261,7 +259,7 @@ impl CrateInfo { .iter() .map(|parts_path| { let path = &parts_path.0; - let parts = try_err!(fs::read(&path), &path); + let parts = try_err!(fs::read(path), &path); let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path); Ok::<_, Error>(parts) }) @@ -439,7 +437,7 @@ impl CratesIndexPart { const DELIMITER: &str = "\u{FFFC}"; // users are being naughty if they have this let content = format!("<h1>List of all crates</h1><ul class=\"all-items\">{DELIMITER}</ul>"); - let template = layout::render(layout, &page, "", content, &style_files); + let template = layout::render(layout, &page, "", content, style_files); match SortedTemplate::from_template(&template, DELIMITER) { Ok(template) => template, Err(e) => panic!( @@ -534,7 +532,7 @@ impl Hierarchy { } fn add_path(self: &Rc<Self>, path: &Path) { - let mut h = Rc::clone(&self); + let mut h = Rc::clone(self); let mut elems = path .components() .filter_map(|s| match s { @@ -597,16 +595,14 @@ impl TypeAliasPart { krate: &Crate, crate_name_json: &OrderedJson, ) -> Result<PartsAndLocations<Self>, Error> { - let cache = &Rc::clone(&cx.shared).cache; let mut path_parts = PartsAndLocations::default(); let mut type_impl_collector = TypeImplCollector { aliased_types: IndexMap::default(), visited_aliases: FxHashSet::default(), - cache, cx, }; - DocVisitor::visit_crate(&mut type_impl_collector, &krate); + DocVisitor::visit_crate(&mut type_impl_collector, krate); let cx = type_impl_collector.cx; let aliased_types = type_impl_collector.aliased_types; for aliased_type in aliased_types.values() { @@ -623,16 +619,16 @@ impl TypeAliasPart { // render_impl will filter out "impossible-to-call" methods // to make that functionality work here, it needs to be called with // each type alias, and if it gives a different result, split the impl - for &(type_alias_fqp, ref type_alias_item) in type_aliases { + for &(type_alias_fqp, type_alias_item) in type_aliases { let mut buf = Buffer::html(); - cx.id_map = Default::default(); - cx.deref_id_map = Default::default(); + cx.id_map.borrow_mut().clear(); + cx.deref_id_map.borrow_mut().clear(); let target_did = impl_ .inner_impl() .trait_ .as_ref() .map(|trait_| trait_.def_id()) - .or_else(|| impl_.inner_impl().for_.def_id(cache)); + .or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache)); let provided_methods; let assoc_link = if let Some(target_did) = target_did { provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx()); @@ -643,8 +639,8 @@ impl TypeAliasPart { super::render_impl( &mut buf, cx, - *impl_, - &type_alias_item, + impl_, + type_alias_item, assoc_link, RenderMode::Normal, None, @@ -680,7 +676,7 @@ impl TypeAliasPart { path.push(component.as_str()); } let aliased_item_type = aliased_type.target_type; - path.push(&format!( + path.push(format!( "{aliased_item_type}.{}.js", aliased_type.target_fqp[aliased_type.target_fqp.len() - 1] )); @@ -720,7 +716,7 @@ impl TraitAliasPart { } fn get( - cx: &mut Context<'_>, + cx: &Context<'_>, crate_name_json: &OrderedJson, ) -> Result<PartsAndLocations<Self>, Error> { let cache = &cx.shared.cache; @@ -781,7 +777,7 @@ impl TraitAliasPart { for component in &remote_path[..remote_path.len() - 1] { path.push(component.as_str()); } - path.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); + path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let part = OrderedJson::array_sorted( implementors @@ -828,8 +824,7 @@ struct TypeImplCollector<'cx, 'cache, 'item> { /// Map from DefId-of-aliased-type to its data. aliased_types: IndexMap<DefId, AliasedType<'cache, 'item>>, visited_aliases: FxHashSet<DefId>, - cache: &'cache Cache, - cx: &'cache mut Context<'cx>, + cx: &'cache Context<'cx>, } /// Data for an aliased type. @@ -865,10 +860,10 @@ struct AliasedTypeImpl<'cache, 'item> { type_aliases: Vec<(&'cache [Symbol], &'item Item)>, } -impl<'cx, 'cache, 'item> DocVisitor<'item> for TypeImplCollector<'cx, 'cache, 'item> { +impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { fn visit_item(&mut self, it: &'item Item) { self.visit_item_recur(it); - let cache = self.cache; + let cache = &self.cx.shared.cache; let ItemKind::TypeAliasItem(ref t) = it.kind else { return }; let Some(self_did) = it.item_id.as_def_id() else { return }; if !self.visited_aliases.insert(self_did) { @@ -963,15 +958,13 @@ fn get_path_parts<T: CciPart>( crates_info: &[CrateInfo], ) -> FxIndexMap<PathBuf, Vec<String>> { let mut templates: FxIndexMap<PathBuf, Vec<String>> = FxIndexMap::default(); - crates_info - .iter() - .map(|crate_info| T::from_crate_info(crate_info).parts.iter()) - .flatten() - .for_each(|(path, part)| { - let path = dst.join(&path); + crates_info.iter().flat_map(|crate_info| T::from_crate_info(crate_info).parts.iter()).for_each( + |(path, part)| { + let path = dst.join(path); let part = part.to_string(); templates.entry(path).or_default().push(part); - }); + }, + ); templates } @@ -994,10 +987,10 @@ where if !should_merge.read_rendered_cci { return Ok(make_blank()); } - match fs::read_to_string(&path) { + match fs::read_to_string(path) { Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), - Err(e) => Err(Error::new(e, &path)), + Err(e) => Err(Error::new(e, path)), } } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f4a0ef01c25..c37506e3588 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::ffi::OsStr; use std::ops::RangeInclusive; use std::path::{Component, Path, PathBuf}; -use std::rc::Rc; use std::{fmt, fs}; use rinja::Template; @@ -35,8 +34,8 @@ pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), E Ok(()) } -pub(crate) fn collect_local_sources<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn collect_local_sources( + tcx: TyCtxt<'_>, src_root: &Path, krate: &clean::Crate, ) -> FxIndexMap<PathBuf, String> { @@ -80,7 +79,7 @@ impl LocalSourcesCollector<'_, '_> { let href = RefCell::new(PathBuf::new()); clean_path( - &self.src_root, + self.src_root, &p, |component| { href.borrow_mut().push(component); @@ -124,7 +123,7 @@ struct SourceCollector<'a, 'tcx> { impl DocVisitor<'_> for SourceCollector<'_, '_> { fn visit_item(&mut self, item: &clean::Item) { - if !self.cx.include_sources { + if !self.cx.info.include_sources { return; } @@ -146,7 +145,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> { // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.cx.include_sources = match self.emit_source(&filename, file_span) { + self.cx.info.include_sources = match self.emit_source(&filename, file_span) { Ok(()) => true, Err(e) => { self.cx.shared.tcx.dcx().span_err( @@ -197,7 +196,7 @@ impl SourceCollector<'_, '_> { // Remove the utf-8 BOM if any let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents); - let shared = Rc::clone(&self.cx.shared); + let shared = &self.cx.shared; // Create the intermediate directories let cur = RefCell::new(PathBuf::new()); let root_path = RefCell::new(PathBuf::new()); @@ -250,12 +249,11 @@ impl SourceCollector<'_, '_> { &page, "", |buf: &mut _| { - let cx = &mut self.cx; print_src( buf, contents, file_span, - cx, + self.cx, &root_path, highlight::DecorationInfo::default(), SourceContext::Standalone { file_path }, diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66a8a198928..90aa5904daf 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -36,6 +36,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ --button-border-radius: 2px; --toolbar-button-border-radius: 6px; --code-block-border-radius: 6px; + --impl-items-indent: 0.3em; + --docblock-indent: 24px; } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -909,7 +911,7 @@ both the code example and the line numbers, so we need to remove the radius in t .docblock h6 { font-size: 0.875rem; } .docblock { - margin-left: 24px; + margin-left: var(--docblock-indent); position: relative; } @@ -982,7 +984,11 @@ div.where { .item-info { display: block; - margin-left: 24px; + margin-left: var(--docblock-indent); +} +.impl-items > .item-info { + /* Margin of docblocks + margin of impl block items. */ + margin-left: calc(var(--docblock-indent) + var(--impl-items-indent)); } .item-info code { @@ -2166,6 +2172,15 @@ details.toggle > summary:not(.hideme)::before { left: -24px; } +/* We indent items of an impl block to have a visual marker that these items are part + of this impl block. */ +.impl-items > *:not(.item-info), +/* We also indent the first top doc comment the same to still keep an indent on the + doc block while aligning it with the impl block items. */ +.implementors-toggle > .docblock { + margin-left: var(--impl-items-indent); +} + details.big-toggle > summary:not(.hideme)::before { left: -34px; top: 9px; @@ -2255,6 +2270,10 @@ If you update this line, then you also need to update the line with the same war in src-script.js and main.js */ @media (max-width: 700px) { + :root { + --impl-items-indent: 0.7em; + } + /* When linking to an item with an `id` (for instance, by clicking a link in the sidebar, or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured by the topbar. Anything with an `id` gets scroll-margin-top equal to .mobile-topbar's size. @@ -2454,19 +2473,20 @@ in src-script.js and main.js padding-top: 0; } - /* Position of the "[-]" element. */ - details.toggle:not(.top-doc) > summary, .impl-items > section { + details.implementors-toggle:not(.top-doc) > summary { margin-left: 10px; } - .impl-items > details.toggle > summary:not(.hideme)::before, - #main-content > details.toggle:not(.top-doc) > summary::before, - #main-content > div > details.toggle > summary::before { - left: -11px; + + .impl-items > details.toggle > summary:not(.hideme)::before { + left: -20px; } /* Align summary-nested and unnested item-info gizmos. */ + summary > .item-info { + margin-left: 10px; + } .impl-items > .item-info { - margin-left: 34px; + margin-left: calc(var(--impl-items-indent) + 10px); } .src nav.sub { @@ -2500,24 +2520,24 @@ in src-script.js and main.js } @media print { + :root { + --docblock-indent: 0; + } + nav.sidebar, nav.sub, .out-of-band, a.src, #copy-path, details.toggle[open] > summary::before, details.toggle > summary::before, details.toggle.top-doc > summary { display: none; } - .docblock { - margin-left: 0; - } - main { padding: 10px; } } @media (max-width: 464px) { - .docblock { - margin-left: 12px; + :root { + --docblock-indent: 12px; } .docblock code { diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index a4dc8cd1ed9..6457ac731cb 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -57,7 +57,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { pub(crate) fn static_filename(filename: &str, sha256: &str) -> PathBuf { let filename = filename.rsplit('/').next().unwrap(); - suffix_path(filename, &sha256) + suffix_path(filename, sha256) } macro_rules! static_files { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 1c8303d4c20..bb967b7f163 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum { MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)), ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)), - StaticItem(s) => ItemEnum::Static(s.into_json(renderer)), - ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)), + StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)), + ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)), ForeignTypeItem => ItemEnum::ExternType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)), // FIXME(generic_const_items): Add support for generic free consts @@ -831,17 +831,20 @@ impl FromClean<Box<clean::TypeAlias>> for TypeAlias { } } -impl FromClean<clean::Static> for Static { - fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self { - let tcx = renderer.tcx; - Static { - type_: (*stat.type_).into_json(renderer), - is_mutable: stat.mutability == ast::Mutability::Mut, - expr: stat - .expr - .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) - .unwrap_or_default(), - } +fn convert_static( + stat: clean::Static, + safety: rustc_hir::Safety, + renderer: &JsonRenderer<'_>, +) -> Static { + let tcx = renderer.tcx; + Static { + type_: (*stat.type_).into_json(renderer), + is_mutable: stat.mutability == ast::Mutability::Mut, + is_unsafe: safety == rustc_hir::Safety::Unsafe, + expr: stat + .expr + .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) + .unwrap_or_default(), } } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index df97c5ea263..9efcf6b4983 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -73,7 +73,7 @@ impl<'tcx> JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - self.id_from_item(&item) + self.id_from_item(item) }) .collect() }) @@ -104,7 +104,7 @@ impl<'tcx> JsonRenderer<'tcx> { if item.item_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); - Some(self.id_from_item(&item)) + Some(self.id_from_item(item)) } else { None } @@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { } const RUN_ON_MODULE: bool = false; + type ModuleData = (); fn init( krate: clean::Crate, @@ -161,8 +162,12 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { )) } - fn make_child_renderer(&self) -> Self { - self.clone() + fn save_module_data(&mut self) -> Self::ModuleData { + unreachable!("RUN_ON_MODULE = false should never call save_module_data") + } + + fn set_back_info(&mut self, _info: Self::ModuleData) { + unreachable!("RUN_ON_MODULE = false should never call set_back_info") } /// Inserts an item into the index. This should be used rather than directly calling insert on @@ -223,7 +228,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::Macro(_) | types::ItemEnum::ProcMacro(_) => false, }; - let removed = self.index.borrow_mut().insert(new_item.id.clone(), new_item.clone()); + let removed = self.index.borrow_mut().insert(new_item.id, new_item.clone()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // to make sure the items are unique. The main place this happens is when an item, is @@ -289,7 +294,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { format_version: types::FORMAT_VERSION, }; if let Some(ref out_dir) = self.out_dir { - try_err!(create_dir_all(&out_dir), out_dir); + try_err!(create_dir_all(out_dir), out_dir); let mut p = out_dir.clone(); p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 436d36d899e..8bc543f7e72 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -68,7 +68,7 @@ extern crate test; // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs // about jemalloc. #[cfg(feature = "jemalloc")] -extern crate jemalloc_sys; +extern crate tikv_jemalloc_sys as jemalloc_sys; use std::env::{self, VarError}; use std::io::{self, IsTerminal}; diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 2afb9e549d9..dcc27cd62e3 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -222,7 +222,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| { }); pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) { - lint_store.register_lints(&**RUSTDOC_LINTS); + lint_store.register_lints(&RUSTDOC_LINTS); lint_store.register_group( true, "rustdoc::all", diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 9f9a093da8a..135aa799060 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -118,7 +118,7 @@ fn limit_filename_len(filename: String) -> String { } } -impl<'a, 'b> CoverageCalculator<'a, 'b> { +impl CoverageCalculator<'_, '_> { fn to_json(&self) -> String { serde_json::to_string( &self @@ -188,7 +188,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { } } -impl<'a, 'b> DocVisitor<'_> for CoverageCalculator<'a, 'b> { +impl DocVisitor<'_> for CoverageCalculator<'_, '_> { fn visit_item(&mut self, i: &clean::Item) { if !i.item_id.is_local() { // non-local items are skipped because they can be out of the users control, diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 484bdb5627c..c288a3cf2a4 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -34,7 +34,7 @@ pub(crate) fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) - krate } -impl<'a, 'tcx> DocVisitor<'_> for DocTestVisibilityLinter<'a, 'tcx> { +impl DocVisitor<'_> for DocTestVisibilityLinter<'_, '_> { fn visit_item(&mut self, item: &Item) { look_for_tests(self.cx, &item.doc_value(), item); @@ -60,8 +60,6 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - item.kind, clean::StructFieldItem(_) | clean::VariantItem(_) - | clean::AssocConstItem(..) - | clean::AssocTypeItem(..) | clean::TypeAliasItem(_) | clean::StaticItem(_) | clean::ConstantItem(..) @@ -69,6 +67,15 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::ImportItem(_) | clean::PrimitiveItem(_) | clean::KeywordItem + | clean::ModuleItem(_) + | clean::TraitAliasItem(_) + | clean::ForeignFunctionItem(..) + | clean::ForeignStaticItem(..) + | clean::ForeignTypeItem + | clean::AssocConstItem(..) + | clean::AssocTypeItem(..) + | clean::TyAssocConstItem(..) + | clean::TyAssocTypeItem(..) // check for trait impl | clean::ImplItem(box clean::Impl { trait_: Some(_), .. }) ) @@ -106,7 +113,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) } -pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { +pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { // If non-local, no need to check anything. return; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 140fda70918..c9d1ceb0a91 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -53,12 +53,12 @@ pub(crate) fn collect_intra_doc_links<'a, 'tcx>( (krate, collector) } -fn filter_assoc_items_by_name_and_namespace<'a>( - tcx: TyCtxt<'a>, +fn filter_assoc_items_by_name_and_namespace( + tcx: TyCtxt<'_>, assoc_items_of: DefId, ident: Ident, ns: Namespace, -) -> impl Iterator<Item = &'a ty::AssocItem> + 'a { +) -> impl Iterator<Item = &ty::AssocItem> + '_ { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) @@ -232,7 +232,7 @@ impl UrlFragment { s.push_str(kind); s.push_str(tcx.item_name(def_id).as_str()); } - UrlFragment::UserWritten(raw) => s.push_str(&raw), + UrlFragment::UserWritten(raw) => s.push_str(raw), } } } @@ -307,7 +307,7 @@ pub(crate) struct AmbiguousLinks { resolved: Vec<(Res, Option<UrlFragment>)>, } -impl<'a, 'tcx> LinkCollector<'a, 'tcx> { +impl<'tcx> LinkCollector<'_, 'tcx> { /// Given a full link, parse it as an [enum struct variant]. /// /// In particular, this will return an error whenever there aren't three @@ -339,7 +339,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // If there's no third component, we saw `[a::b]` before and it failed to resolve. // So there's no partial res. let path = split.next().ok_or_else(no_res)?; - let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?; + let ty_res = self.resolve_path(path, TypeNS, item_id, module_id).ok_or_else(no_res)?; match ty_res { Res::Def(DefKind::Enum, did) => match tcx.type_of(did).instantiate_identity().kind() { @@ -628,7 +628,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .map(|item| (root_res, item.def_id)) .collect::<Vec<_>>() }) - .unwrap_or(Vec::new()) + .unwrap_or_default() } } Res::Def(DefKind::TyAlias, did) => { @@ -693,7 +693,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .into_iter() + .iter() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, @@ -878,7 +878,7 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<Vec<(Res, T)>, ResolutionFailu } } -impl<'a, 'tcx> DocVisitor<'_> for LinkCollector<'a, 'tcx> { +impl DocVisitor<'_> for LinkCollector<'_, '_> { fn visit_item(&mut self, item: &Item) { self.resolve_links(item); self.visit_item_recur(item) @@ -1152,7 +1152,7 @@ impl LinkCollector<'_, '_> { } cache.paths.get(&did).is_some() - || cache.external_paths.get(&did).is_some() + || cache.external_paths.contains_key(&did) || !did.is_local() } @@ -1271,7 +1271,7 @@ impl LinkCollector<'_, '_> { } res.def_id(self.cx.tcx).map(|page_id| ItemLink { - link: Box::<str>::from(&*diag_info.ori_link), + link: Box::<str>::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1293,7 +1293,7 @@ impl LinkCollector<'_, '_> { let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id)); Some(ItemLink { - link: Box::<str>::from(&*diag_info.ori_link), + link: Box::<str>::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1387,7 +1387,7 @@ impl LinkCollector<'_, '_> { ) .unwrap_or_else(|| item.attr_span(self.cx.tcx)); rustc_session::parse::feature_err( - &self.cx.tcx.sess, + self.cx.tcx.sess, sym::intra_doc_pointers, span, "linking to associated items of raw pointers is experimental", @@ -1414,7 +1414,7 @@ impl LinkCollector<'_, '_> { // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether. // However I'm not sure how to check that across crates. - if let Some(candidate) = candidates.get(0) + if let Some(candidate) = candidates.first() && candidate.0 == Res::Primitive(PrimitiveType::RawPointer) && key.path_str.contains("::") // We only want to check this if this is an associated item. @@ -1493,7 +1493,7 @@ impl LinkCollector<'_, '_> { } } resolution_failure(self, diag, path_str, disambiguator, smallvec![err]); - return vec![]; + vec![] } } } @@ -1509,15 +1509,12 @@ impl LinkCollector<'_, '_> { type_ns: candidate(TypeNS), value_ns: candidate(ValueNS).and_then(|v_res| { for (res, _) in v_res.iter() { - match res { - // Constructors are picked up in the type namespace. - Res::Def(DefKind::Ctor(..), _) => { - return Err(ResolutionFailure::WrongNamespace { - res: *res, - expected_ns: TypeNS, - }); - } - _ => {} + // Constructors are picked up in the type namespace. + if let Res::Def(DefKind::Ctor(..), _) = res { + return Err(ResolutionFailure::WrongNamespace { + res: *res, + expected_ns: TypeNS, + }); } } Ok(v_res) @@ -1536,7 +1533,7 @@ impl LinkCollector<'_, '_> { disambiguator, candidates.into_iter().filter_map(|res| res.err()).collect(), ); - return vec![]; + vec![] } else if len == 1 { candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>() } else { @@ -1850,7 +1847,7 @@ fn report_diagnostic( (sp, MarkdownLinkRange::Destination(md_range)) } MarkdownLinkRange::WholeLink(md_range) => ( - source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs.doc_strings), + source_span_for_markdown_range(tcx, dox, md_range, &item.attrs.doc_strings), link_range.clone(), ), }; @@ -1985,8 +1982,7 @@ fn resolution_failure( .tcx .resolutions(()) .all_macro_rules - .get(&Symbol::intern(path_str)) - .is_some() + .contains_key(&Symbol::intern(path_str)) { diag.note(format!( "`macro_rules` named `{path_str}` exists in this crate, \ diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index f3589080322..87f85c57315 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -229,7 +229,7 @@ struct SyntheticImplCollector<'a, 'tcx> { impls: Vec<Item>, } -impl<'a, 'tcx> DocVisitor<'_> for SyntheticImplCollector<'a, 'tcx> { +impl DocVisitor<'_> for SyntheticImplCollector<'_, '_> { fn visit_item(&mut self, i: &Item) { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? @@ -256,7 +256,7 @@ impl<'cache> ItemAndAliasCollector<'cache> { } } -impl<'cache> DocVisitor<'_> for ItemAndAliasCollector<'cache> { +impl DocVisitor<'_> for ItemAndAliasCollector<'_> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); @@ -276,7 +276,7 @@ struct BadImplStripper<'a> { cache: &'a Cache, } -impl<'a> BadImplStripper<'a> { +impl BadImplStripper<'_> { fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool { if let Generic(_) = ty { // keep impls made on generics diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index 35b62370abb..1ecb53e61ac 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -25,7 +25,7 @@ pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate { krate } -impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { +impl DocVisitor<'_> for Linter<'_, '_> { fn visit_item(&mut self, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else { // If non-local, no need to check anything. @@ -34,7 +34,7 @@ impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { let dox = item.doc_value(); if !dox.is_empty() { let may_have_link = dox.contains(&[':', '['][..]); - let may_have_block_comment_or_html = dox.contains(&['<', '>']); + let may_have_block_comment_or_html = dox.contains(['<', '>']); // ~~~rust // // This is a real, supported commonmark syntax for block code // ~~~ diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 1397eadb288..77d7cf5772d 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -18,7 +18,7 @@ use crate::html::markdown::main_body_opts; pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range<usize>| { - let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) + let sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings) .unwrap_or_else(|| item.attr_span(cx.tcx)); cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { lint.primary_message(msg) @@ -34,14 +34,14 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & }); }; - let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter(); while let Some((event, range)) = p.next() { match event { Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - while let Some((event, _)) = p.next() { + for (event, _) in p.by_ref() { match event { Event::End(end) if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index e0dc5b4c513..20d65d8cd9f 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -150,7 +150,7 @@ impl Translate for BufferEmitter { } fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 223174838ad..3fb154dc515 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -15,7 +15,7 @@ use crate::html::markdown::main_body_opts; pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; let report_diag = |msg: String, range: &Range<usize>, is_open_tag: bool| { - let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) { + let sp = match source_span_for_markdown_range(tcx, dox, range, &item.attrs.doc_strings) { Some(sp) => sp, None => item.attr_span(tcx), }; @@ -30,7 +30,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let mut generics_end = range.end; if let Some(Some(mut generics_start)) = (is_open_tag && dox[..generics_end].ends_with('>')) - .then(|| extract_path_backwards(&dox, range.start)) + .then(|| extract_path_backwards(dox, range.start)) { while generics_start != 0 && generics_end < dox.len() @@ -39,19 +39,19 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & { generics_end += 1; generics_start -= 1; - if let Some(new_start) = extract_path_backwards(&dox, generics_start) { + if let Some(new_start) = extract_path_backwards(dox, generics_start) { generics_start = new_start; } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } let generics_sp = match source_span_for_markdown_range( tcx, - &dox, + dox, &(generics_start..generics_end), &item.attrs.doc_strings, ) { @@ -125,7 +125,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } }; - let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let p = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); for (event, range) in p { @@ -233,7 +233,7 @@ fn extract_path_forward(text: &str, start_pos: usize) -> Option<usize> { break; } } - while let Some(c) = chars.next() { + for c in chars { if is_id_continue(c) { current_pos += c.len_utf8(); } else { diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index f3599688454..6bc4374c06b 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -35,12 +35,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { } } -fn check_redundant_explicit_link_for_did<'md>( +fn check_redundant_explicit_link_for_did( cx: &DocContext<'_>, item: &Item, did: DefId, hir_id: HirId, - doc: &'md str, + doc: &str, ) { let Some(local_item_id) = did.as_local() else { return; @@ -71,7 +71,7 @@ fn check_redundant_explicit_link_for_did<'md>( return; }; - check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); + check_redundant_explicit_link(cx, item, hir_id, doc, resolutions); } fn check_redundant_explicit_link<'md>( @@ -90,60 +90,52 @@ fn check_redundant_explicit_link<'md>( .into_offset_iter(); while let Some((event, link_range)) = offset_iter.next() { - match event { - Event::Start(Tag::Link { link_type, dest_url, .. }) => { - let link_data = collect_link_data(&mut offset_iter); - - if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { - if &link_data.display_link.replace('`', "") != resolvable_link { - // Skips if display link does not match to actual - // resolvable link, usually happens if display link - // has several segments, e.g. - // [this is just an `Option`](Option) - continue; - } + if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event { + let link_data = collect_link_data(&mut offset_iter); + + if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { + if &link_data.display_link.replace('`', "") != resolvable_link { + // Skips if display link does not match to actual + // resolvable link, usually happens if display link + // has several segments, e.g. + // [this is just an `Option`](Option) + continue; } + } - let explicit_link = dest_url.to_string(); - let display_link = link_data.resolvable_link.clone()?; - - if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) - { - match link_type { - LinkType::Inline | LinkType::ReferenceUnknown => { - check_inline_or_reference_unknown_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - dest_url.to_string(), - link_data, - if link_type == LinkType::Inline { - (b'(', b')') - } else { - (b'[', b']') - }, - ); - } - LinkType::Reference => { - check_reference_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - &dest_url, - link_data, - ); - } - _ => {} + let explicit_link = dest_url.to_string(); + let display_link = link_data.resolvable_link.clone()?; + + if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) { + match link_type { + LinkType::Inline | LinkType::ReferenceUnknown => { + check_inline_or_reference_unknown_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + dest_url.to_string(), + link_data, + if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') }, + ); + } + LinkType::Reference => { + check_reference_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + &dest_url, + link_data, + ); } + _ => {} } } - _ => {} } } @@ -169,18 +161,18 @@ fn check_inline_or_reference_unknown_redundancy( if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range, open, close), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; @@ -210,27 +202,27 @@ fn check_reference_redundancy( let (resolvable_link, resolvable_link_range) = (&link_data.resolvable_link?, &link_data.resolvable_link_range?); let (dest_res, display_res) = - (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + (find_resolution(resolutions, dest)?, find_resolution(resolutions, resolvable_link)?); if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range.clone(), b'[', b']'), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; let def_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_reference_def_range(doc, dest, link_range), &item.attrs.doc_strings, )?; @@ -263,7 +255,7 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>( let mut display_link = String::new(); let mut is_resolvable = true; - while let Some((event, range)) = offset_iter.next() { + for (event, range) in offset_iter.by_ref() { match event { Event::Text(code) => { let code = code.to_string(); diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index d79f682a580..88f4c3ac1cd 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -22,7 +22,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & .find(|link| *link.original_text == *broken_link.reference) .map(|link| ((*link.href).into(), (*link.new_text).into())) }; - let parser = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let parser = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); let mut element_stack = Vec::new(); @@ -44,7 +44,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // use the span of the entire attribute as a fallback. let span = source_span_for_markdown_range( tcx, - &dox, + dox, &(backtick_index..backtick_index + 1), &item.attrs.doc_strings, ) @@ -61,12 +61,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // "foo` `bar`" -> "`foo` `bar`" if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -80,11 +80,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // Don't `clamp_end` here, because the suggestion is guaranteed to be inside // an inline code node and we intentionally "break" the inline code here. let suggest_index = guess; - if can_suggest_backtick(&dox, suggest_index) { + if can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -98,15 +98,15 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & if !element.prev_code_guess.is_confident() { // "`foo` bar`" -> "`foo` `bar`" if let Some(guess) = - guess_start_of_code(&dox, element.element_range.start..backtick_index) + guess_start_of_code(dox, element.element_range.start..backtick_index) && let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -120,16 +120,16 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // if we already suggested opening backtick. For example: // "foo`." -> "`foo`." or "foo`s" -> "`foo`s". if let Some(guess) = - guess_end_of_code(&dox, backtick_index + 1..element.element_range.end) + guess_end_of_code(dox, backtick_index + 1..element.element_range.end) && let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) && (!help_emitted || suggest_index - backtick_index > 2) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -148,7 +148,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & suggest_insertion( cx, item, - &dox, + dox, lint, backtick_index, '\\', @@ -177,13 +177,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let is_confident = text_inside.starts_with(char::is_whitespace) || text_inside.ends_with(char::is_whitespace); - if let Some(guess) = guess_end_of_code(&dox, range_inside) { + if let Some(guess) = guess_end_of_code(dox, range_inside) { // Find earlier end of code. element.prev_code_guess = PrevCodeGuess::End { guess, is_confident }; } else { // Find alternate start of code. let range_before = element.element_range.start..event_range.start; - if let Some(guess) = guess_start_of_code(&dox, range_before) { + if let Some(guess) = guess_start_of_code(dox, range_before) { element.prev_code_guess = PrevCodeGuess::Start { guess, is_confident }; } } @@ -421,7 +421,7 @@ fn suggest_insertion( if let Some(span) = source_span_for_markdown_range( cx.tcx, - &dox, + dox, &(insert_index..insert_index), &item.attrs.doc_strings, ) { diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs index f8368a866c8..a3c3134f4c2 100644 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ b/src/librustdoc/passes/lint/unportable_markdown.rs @@ -49,8 +49,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarkn::Options::ENABLE_TASKLISTS | cmarkn::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_new = cmarkn::Parser::new_ext(&dox, main_body_opts_new()).into_offset_iter(); - while let Some((event, span)) = parser_new.next() { + let parser_new = cmarkn::Parser::new_ext(dox, main_body_opts_new()).into_offset_iter(); + for (event, span) in parser_new { if let cmarkn::Event::Start(cmarkn::Tag::BlockQuote(_)) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.insert(span.start); @@ -71,8 +71,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarko::Options::ENABLE_TASKLISTS | cmarko::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_old = cmarko::Parser::new_ext(&dox, main_body_opts_old()).into_offset_iter(); - while let Some((event, span)) = parser_old.next() { + let parser_old = cmarko::Parser::new_ext(dox, main_body_opts_old()).into_offset_iter(); + for (event, span) in parser_old { if let cmarko::Event::Start(cmarko::Tag::BlockQuote) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.remove(&span.start); @@ -88,13 +88,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & for start in spaceless_block_quotes { let (span, precise) = - source_span_for_markdown_range(tcx, &dox, &(start..start + 1), &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &(start..start + 1), &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, span, |lint| { lint.primary_message("unportable markdown"); - lint.help(format!("confusing block quote with no space after the `>` marker")); + lint.help("confusing block quote with no space after the `>` marker".to_string()); if precise { lint.span_suggestion( span.shrink_to_hi(), @@ -113,7 +113,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } for (_caret, span) in missing_footnote_references { let (ref_span, precise) = - source_span_for_markdown_range(tcx, &dox, &span, &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 350be37f553..572c9bf7552 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -27,7 +27,7 @@ struct CfgPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { +impl CfgPropagator<'_, '_> { // Some items need to merge their attributes with their parents' otherwise a few of them // (mostly `cfg` ones) will be missing. fn merge_with_parent_attributes(&mut self, item: &mut Item) { @@ -65,7 +65,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> { +impl DocFolder for CfgPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option<Item> { let old_parent_cfg = self.parent_cfg.clone(); diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index a28487cc79e..a81b130a218 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -30,7 +30,7 @@ struct StabilityPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> { +impl DocFolder for StabilityPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option<Item> { let parent_stability = self.parent_stability; diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index a078eec048e..fa7737bc143 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -21,7 +21,7 @@ struct AliasedNonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { +impl DocFolder for AliasedNonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option<Item> { Some(match i.kind { clean::TypeAliasItem(..) => { @@ -39,7 +39,7 @@ struct NonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for NonLocalStripper<'tcx> { +impl DocFolder for NonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option<Item> { // If not local, we want to respect the original visibility of // the field and not the one given by the user for the currrent crate. @@ -50,7 +50,7 @@ impl<'tcx> DocFolder for NonLocalStripper<'tcx> { { if i.is_doc_hidden() // Default to *not* stripping items with inherited visibility. - || i.visibility(self.tcx).map_or(false, |viz| viz != Visibility::Public) + || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public) { return Some(strip_item(i)); } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 4ef5f7f20a9..a71bb62e56c 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -57,7 +57,7 @@ struct Stripper<'a, 'tcx> { last_reexport: Option<LocalDefId>, } -impl<'a, 'tcx> Stripper<'a, 'tcx> { +impl Stripper<'_, '_> { fn set_last_reexport_then_fold_item(&mut self, i: Item) -> Item { let prev_from_reexport = self.last_reexport; if i.inline_stmt_id.is_some() { @@ -86,7 +86,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option<Item> { let has_doc_hidden = i.is_doc_hidden(); let is_impl_or_exported_macro = match i.kind { diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 98b3446c26d..60909754b33 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -37,7 +37,7 @@ fn is_item_reachable( } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option<Item> { match i.kind { clean::StrippedItem(..) => { @@ -171,7 +171,7 @@ pub(crate) struct ImplStripper<'a, 'tcx> { pub(crate) document_hidden: bool, } -impl<'a> ImplStripper<'a, '_> { +impl ImplStripper<'_, '_> { #[inline] fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool { if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) { @@ -193,7 +193,7 @@ impl<'a> ImplStripper<'a, '_> { } } -impl<'a> DocFolder for ImplStripper<'a, '_> { +impl DocFolder for ImplStripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option<Item> { if let clean::ImplItem(ref imp) = i.kind { // Impl blocks can be skipped if they are: empty; not a trait impl; and have no @@ -259,7 +259,7 @@ pub(crate) struct ImportStripper<'tcx> { pub(crate) document_hidden: bool, } -impl<'tcx> ImportStripper<'tcx> { +impl ImportStripper<'_> { fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool { if self.is_json_output { // FIXME: This should be handled the same way as for HTML output. @@ -270,11 +270,11 @@ impl<'tcx> ImportStripper<'tcx> { } } -impl<'tcx> DocFolder for ImportStripper<'tcx> { +impl DocFolder for ImportStripper<'_> { fn fold_item(&mut self, i: Item) -> Option<Item> { match &i.kind { clean::ImportItem(imp) - if !self.document_hidden && self.import_should_be_hidden(&i, &imp) => + if !self.document_hidden && self.import_should_be_hidden(&i, imp) => { None } diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 2c00bb7e132..a49fb06bde3 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -54,7 +54,7 @@ fn skip_comment(iter: &mut Peekable<Chars<'_>>) { /// Skips a line comment (`//`). fn skip_line_comment(iter: &mut Peekable<Chars<'_>>) { - while let Some(c) = iter.next() { + for c in iter.by_ref() { if c == '\n' { break; } diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index bfa285c57fa..c2e8ffd7665 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -55,7 +55,7 @@ pub(crate) trait DocVisitor<'a>: Sized { /// Don't override! fn visit_item_recur(&mut self, item: &'a Item) { match &item.kind { - StrippedItem(i) => self.visit_inner_recur(&*i), + StrippedItem(i) => self.visit_inner_recur(i), _ => self.visit_inner_recur(&item.kind), } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 31c33fbf497..11f06f7d917 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir().item(i); @@ -476,7 +476,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Macro(ref macro_def, _) => { + hir::ItemKind::Macro(macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, // above, since they need to be documented at the module top level. Accordingly, // we only want to handle macros if one of three conditions holds: @@ -496,7 +496,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Mod(ref m) => { + hir::ItemKind::Mod(m) => { self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); } hir::ItemKind::Fn(..) @@ -560,7 +560,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // We need to implement this visitor so it'll go everywhere and retrieve items we're interested in // such as impl blocks in const blocks. -impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index f553a78d766..84b33e3d860 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 36; +pub const FORMAT_VERSION: u32 = 37; /// The root of the emitted JSON blob. /// @@ -1238,6 +1238,22 @@ pub struct Static { /// /// It's not guaranteed that it'll match the actual source code for the initial value. pub expr: String, + + /// Is the static `unsafe`? + /// + /// This is only true if it's in an `extern` block, and not explicity marked + /// as `safe`. + /// + /// ```rust + /// unsafe extern { + /// static A: i32; // unsafe + /// safe static B: i32; // safe + /// } + /// + /// static C: i32 = 0; // safe + /// static mut D: i32 = 0; // safe + /// ``` + pub is_unsafe: bool, } /// A primitive type declaration. Declarations of this kind can only come from the core library. diff --git a/src/stage0 b/src/stage0 index 57a01edb6fd..23ee3304b42 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,456 +14,456 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-10-16 +compiler_date=2024-11-27 compiler_version=beta -rustfmt_date=2024-10-16 +rustfmt_date=2024-11-27 rustfmt_version=nightly -dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.gz=24719797bf50fb494c61cf4711d6bb238ea9e789a1b10d957abb23f9849a06cd -dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.xz=5eed456f0034e2b31ed4f6089163dd5e86ecb04630371e408aca741c32d845c5 -dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f337d992f4a730d39ae571d602f15d2c66ed0b6abf1b2c63112b570e855ac409 -dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d22b4f26ba8b82e32114311c1f0386d0126eecffa2accab8ca9ecd6a7aa38400 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=047735b5c90fca9f26e5eca2a1d24dcac6fdddfddcb89c9d1e2f6d0af0199946 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c70bce1fa2a6e98577683d94473ca7046e8add65b85792e9887fee4edb8bdcb7 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4c75417b640557b35172ea384fa34a3e8da1960efdf4a40cf8d1fdbdd50ee997 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.xz=f7f5e67b831af5fdb28266fadd7cfd9f092c066f7e7322b058d6fb2bc7f6ff77 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=5d94f4e51767b02ddcdafdcaba3404a3133d308fe98c7bf5145a41bde8146319 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=49166b4eb2e18e009ebde1e4c133adcacc3d5257fbd63b07418642d5c841957a -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=9e51ecc782cf9738adafd70c055ed793ab895c9616619c525cb52d7412cdf884 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=d60502f25273c2552997de281727b0f5914a2a97f32310f921ea714c5a1080d7 -dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=5796a33eda8d7b47c8982d3a2e425728cf681043151a291fea107b3aca9ff1a7 -dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=71fb2132822aa284cae878a76f9996092316942f84dc5a674fb8be17eb391cb0 -dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.gz=d089cdb87961d00e7dc51c767993342a2fa704756a94c421be7f195dfa6c5293 -dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.xz=42865105f308f7e0cf9af250b54086eaa20da8ef13e9cbf82380340a9db4ce90 -dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.gz=5753e00d74de3ceb1af0dc533496d7db6295d673eb05aea779734a519b5f789f -dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.xz=dff93d0c39e8653f01248f0db05123018c63c92a1d3861935b12ad1818b00864 -dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.gz=4e2e06e503be7d15211dad18911ce951491d2596cef466ae8282af840184427c -dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.xz=77d0d69f3e0c2b32bd1ccb73f12b5b770a1a720e7928859d454f42e611f77d67 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=5faa3516ecfe77f8fb21ba80e78c21a1b039f5fffae508cceffd04c8c329f152 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8f086e53b3abffd7c947f5b0784f9977ed4559e654805bc3877ada99072d38e4 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=2147f76d151c513aaef63cb2365bb2c9a8d0eb21a6b1c7c2ff535dab0882c46a -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=db2c17f1f3e0af9ad56982e1396a031df07939aa04c73795f541b16161fc3bdf -dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e5d3fabc7902695ccf85171dd16cfe772a480dce203004da0853170450e57b1c -dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=db2f03a41470e60a0070b4d96590ae049c23d2c0f8c07a5778023a4ecf3e52eb -dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=49610d2df0b6ece6b2afc583db707eed0a6a12ef99a8ba0a82f9acb7c1e15fca -dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=801a92eebf0c068c88a48129b054c4ecea143f38468ff5d53e28fd00a0fad6de -dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=db8a9c4bc9313627d5ad2ed2ebe91b6129958254a32862aec67edee10cdf9bca -dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fb2f2f2acb7516d98a6abf17e84e8b36beb7179c69776d69465f1c981466321d -dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=87effe21c4b4333769fa7b4b0fc4bd43edaabc1c8ba33e75480cb4da0d59dae9 -dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=71701db843d0974b4fc09afb65e3872faaaf66bfda258c9627576efe8f998f96 -dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.gz=6485ed4c99deffdde4eee34e46b8be2eeb65a3f8f4b4eb032a4ccd9c6f4e29e7 -dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.xz=e8ee8b61386d490c8e59e0c2ccb30fb7758ea0ff0b1448d5f946d9fc58496a11 -dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.gz=23e36a4892e948a6dc231d15913562f1f95f798a62a38315a6b19244aaf78385 -dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.xz=2db43b3b599eab832a13c784d3a1bc60c3222f5bfce8e112688e1478837b8c25 -dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.gz=099c529cc84219ae3ed9a33dbc5265c46a01c8cffb8989e66e367078bc981eec -dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.xz=efef4dd4a40d4f96d151293031783688c84b088a5f2cdde84d931bd44aee923a -dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28633202a502121e9369e93a8cc66bcb52b2cc959d7598f9bbb8e4c840381baa -dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.xz=c7b879d2e7d7c21eafc7b8e9f18f009d2d38f91a2eafa51d25d38e3b51e17ef3 -dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.gz=69bdb56ac4f47fa614fa9e8be5218a492d31a423454c192ed5850f49357687e5 -dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.xz=36c995c1dd55ab4501f250a77f27cce34330daa2a3e74129ce389aa23b4e3a05 -dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.gz=84bb641a5576ef0e93c7b5bae7417eae344f32271a0ebc31bb987d15316815a3 -dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.xz=a7311a345dddc9f8cf1eab6b3e82658fadb485bd755a115d4d6ffdfb42a5625e -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=9def7618829111d1014e21fb0bc10abc26459e59ce61fdac5fb3b63583f472c6 -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=97d124a65a7d7e5610901521b565ff031313685cc37a1caf89de58d952065c3c -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.gz=101a440c383011cb4621825481582a81bfbad0ac03439542bd8d05ccb5aaf2c4 -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.xz=4148b4311ce8e1cc5dae86d5f27e207496b85e5c23a53c7bc5b05ba18918f717 -dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.gz=25c5c35f2acd37a7c72eb8dc546cb6e9f62b3e76e1569d188bbe2aa9b31ea3e1 -dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.xz=9b84ce176d4015ed8f6946ef2d42f2f601cf419d1a6477f44bd6b7c7d27c95fc -dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.gz=ebdf49b8d4fab00c7fb4d396c54caf5cb234389b7353856734b960f908c3cff9 -dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.xz=4d0d5fbc235d8cc78e9997302c45916008e203ba7f02edcd061290fb9639ee8f -dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.gz=6693f5a06df0ea5929df18b633ad6373d098db4454d0e1d35e4c19b6dd7fa4ed -dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.xz=351a1a2a13316161edcf97238d868cf4b1b5216bdf28ca0aff5a1dba2a1258f4 -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=f0e13e1700a1cbc1489c0a5728ce6c0f5ba1432a75ca2c0c0573b9fcf130ae9b -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=825550e3a2afbe15130dcf7b702ea62b3b90f8a1e0b850cd6e9a5b5dd180e72d -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.gz=f77a6c24301c5c7165de3bf51b5b6d45e7d37a82d00446d1abbe5a5c591ca616 -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.xz=5a9507e0c06b252196203b01319355e4d246eddead60993262bd680b6a1d2315 -dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.gz=eca36ae4253e5f1b51c065631a650135b71797b452a7fbf6dfa17c49a01f71d9 -dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.xz=1da17cca8397bedda8b5403ddcc9f7686d7ad207daa7389a6cf80f922bac8140 -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a4eea434371a7d95b473410a42d8409995119c85954f94a75b8b0a69aa3095b -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=cea3d7d9568d2ed86ab11d28f5a02cf36210971b798c4d61e133357c24108f6f -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=355fa0988a68a1a331a2794a573cd065e6fbbe8b312e187dfff59f4f4245cc5f -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=c93347602b0133e0da072243ba9419c95179f9f548b6284612967d7b80a42144 -dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c4305667ed2a77764c729fe236491b239cea7c2605039c2bc28a926d21f343cc -dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=02b6b621a1b3b91e25482400680cd38be806d7de541cf364d0ed181a92fdcbf5 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=830e1b90ea156eee05b0c5fab514d82558e2473eb5f6bddfeafa51e7417315c2 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c5910437177f607439a6b18bd05b93c3965f915a0d372fb540deecf044b21880 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=7a0f343b5fa50168a3edd0770dee148c82e43e7b2b82e2149ca22badeade3218 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=dc4d7b3cb830451044726e72b848e529e92ec0330e610f06b07f8ed37415c3cd -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8a9e341e6f208d5036e4c774f68b75802c64c53c4a9381ffd5a62e9b3c486cdd -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd24b56cc9891d9a1246e62eb33f6de8385acb265ca875af79f2593ff4bd323d -dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.gz=51a58a9f663de787ca58da8e4ed705a1099bfeca945eaab3bbce01edd45aff4b -dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.xz=47fcf0fcdabaddde929e4828c1de1db3986af1d32a752c057ec69aee9c8f6162 -dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=207281137a1b6ec8c1df21c581c23a6db7bfdd11c550749203bbe24b9ae80019 -dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=217625e68479d09d8e63f931983e030ea9f0829cdd559ba88bf657e711c96aa6 -dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.gz=4c5fa8fc4e18723c4522a1e93e9e343e35f02e74fc82e6fc44951bf7e1849371 -dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.xz=f4440f97ebab6a79d50683169994cef569a427cb1811b85ee196432d4e2d0b38 -dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.gz=ab7dfa2b8aff6bb7514798d11970e4c09c8a4844d7408e295c547f1a87c23ea0 -dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.xz=fb9ce70893a8c89bc3e66dd6ded2e0c4813c96bd0781b6c3b420a278c53ba4cd -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4650f832189a221337fc172c2ffa113ff209774949ae12e7ef159117a02e984e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=f6bb5528b914311802fdb9816260e8a57531fedc5f68bef2dc6ba83d59d5ce4c -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2fff203abd959498321680582bb969de89c9de4718b38e06cc91a789d7fd415e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=df5cadfd5895ee1552bbcfebc40b34826481932bdde309ecb2c13f55541ca2c0 -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e29900d97e62c7568395191e1230fa6f98f971c1593303810f05d4db5c68592e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=4455ff5a1de11281aca0df4f3f6d33d245314ce4276bda9d161bf850eda24ad6 -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=26fcafd19aee4fcba45875d0f35aeceed7cb0a0fa070e6a2447b3d9b86170c8a -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=cc43780fa58e7fa1d23a3b5e2695dfd3f4ac3c02398756516c395f4546e2042d -dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a67a25cdaa3fabdd2b619434e3b98f05acc13f25cc7ebf8f936e7f3d1761e272 -dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=e8ee762127e02a73614e636b77d34d927f34e967cadd79158ca6ea27687c679a -dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.gz=7343489518ad6d354f9bfcbbc884d1c0e4fc88c4650cc68d9b9b84ee12b750b2 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.xz=eef35d9c016fdb67b9825104558ca0fc1aec3af8a738636a0f24797ad270b8e6 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.gz=ed36702bbf1d45c263b8b52a06f2b4a9783c6ec78db28e00d317acd09a549977 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.xz=e4fbf4007af9858e1bebffef6bdb4c66f419b035c8fb385dc70d46ce2e312e2e -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=1eebca6a4ed9b04a1cd3fc57f8f75bda14cc03c8909385586c8a084e46aa96fd -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=0bf68ccaa22a4782f23a34b8a52ca250b183e265f12bffde7cda9ddac515040c -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6f7b932bb0176fefbcc1de700a36da7c60dac609ec91e6bf351e4c42ea6fb119 -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a0d9397caf812fa479da6b389b653fcff451f8d54fa0545e5c908e73391b6dee -dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.gz=5be2ca5bd0340fa2e7ffe435081d1848ab883e46a9c0f07eee69f7dd9d08e0f6 -dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.xz=ed563b78d4201ce29ba79cf6ebf5a3b7d8020611309e39b8790c59edcdd05b29 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=53f7928406a1a14dfc6774fb2704bfa9c68091b135b750c5e46e3610e00e8c72 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d71cf98a8b6dfa2cc1682819d1bc5bbfe0eae819f63bb91d64e4f52bbee4158f -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f65eccc2a47e34d96faa94954c738813d9b5acae351936b07df6ee2ee8592296 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4f44230338a6b6bc17a8a2a80125ba18a9dedb6f9347c6e93b7f7b88c87e4468 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=80eae216bc5c3f77817d244f0d81cc13704894c1c7bde30c89b4f58b6049767f -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=b8036aee8615786593f83c3e7808eac2a59ad44ae9f5959b9719fd475b3197b0 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=95ca16bf6931261a62f4a3637495c02450d34fd0a0ee8abe350881b9aa0bc773 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=df92b9f5ec3ea09c2cc48e4c91d41ecb1fa82db87180458b1e051bbceeb4efc2 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=26a4426464874411bf51cf0148569c9a110681632d228dc9c9d57fbe24292e93 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=70ee4948185aec3b556c963ba030abbb6424e09190e31afb11d063bc2ba21664 -dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.gz=50c5b3d721cb5d83ab5f277c24eecbdbde32bdbc208bc0597830329fd19bf786 -dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.xz=9add40fc1a971f135796a8020e3ecbc6ccfa657714cee2535866f2af38fcde97 -dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.gz=d9e4695576a9f34e67804a636de6164fa7d381ac2193095cd2daa74fe148b748 -dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.xz=6592a61388b53c3d3040245b8634715026f1e2a020a118edaf43f98839537aa3 -dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.gz=da24db2c8642e8273ef7d0e74fd32a1045ec99f5201b35d0116ba1818ab330d3 -dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.xz=75574d203e5e15973ce1e6e12a43d6b26825844382ef76b05c4dd568912fd16b -dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.gz=2e4bab4042bac836ac40e07c36c6057273d6bffaf97b1b22a64cd0876d48895d -dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.xz=f335988ba2ae2853c4c8928562fa6ed81a2bbd2bd5d09dbcebd7e64cbc7d458e -dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e96921c51d49ae28871286147d589bb59eec596826d1e0eeddd928f57ed4499f -dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.xz=c17d7cbbc6bb30899a1a94f74f380bb54878b927ebe58b31592f7adb64d7b5fb -dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.gz=f9030f5b2ae0411349f1f4fabd00efa3e1117ca5dc5ba60fe87f33f94e51787b -dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.xz=d45b9c7c6f8de53f99b550a6d673bf8ff29e507c60ef63271d7d5ac73c765e07 -dist/2024-10-16/rust-std-beta-i686-linux-android.tar.gz=2a6b9c893d2d8bbdb5900c4105fe54a988101c7d69f504e4d2983ba7aaadbbd4 -dist/2024-10-16/rust-std-beta-i686-linux-android.tar.xz=94c884a0cd03fe092bdfb6fe718fd335921a82c9c2887e0e68a13fe6a183a877 -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.gz=2d4a8b299987ab046536db276f3c4ea97413be5915189b9af085e4a4ba7b28ab -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.xz=eb60bf4d73fa45fe61730427287585939ff1a14efa8910877546818167b343cc -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=ec0f11f5cce47e6ad288393dafaa69b27fc5207194e886f0a00b4e6c3a006164 -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=10a5c127538bc9b951c62692ca4d626cd669919d5bb2236ef6112da28db028a5 -dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.gz=7c9afcae592f5494ffd2baa95947b4fa5483c795e516852b463170e4797984cc -dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.xz=ad9381999c1846c188d7264992c79faf413d675fdd70f22f25afcf84ed6e3b22 -dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.gz=9b4ea3de244aaf14b6759807444bb983ec5732b119faad1c9437eb2c02d407ed -dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.xz=88f975eff5146af6ae548e2d7be8d402ca3d6f470b6760b75e27dedcac9f70fb -dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.gz=8a8a255695d36a86ab32abe9f37f9f6f3e9b75eee75953486d82f186d8342180 -dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.xz=00a55b220767f3b692286bea728208bf665ea9a54869f82b31805b40ff56f763 -dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.gz=96e838064bfdace0fcd5596c50714585a221a5116e2825aba448cc1f188d0edf -dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.xz=78c5be28afda04d536a634a049c175b38d46309eb4b02126ba2cda3102b92d45 -dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.gz=41a11092091b1f3b508f606978c0ac026e94614fe4b2207522b4f5f3d6c3262b -dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.xz=a2250a5bb179549426ead55edaf3eba7626ee57a5e2c578057c3166348a47523 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=782998317c6c9cca107e84538ee166a37490b287efb437e5da9bf799178084b1 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=75b15b6d6db6f801a74419aa294b9537aa6e92b4d9d4c482e66aa6e319accee5 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=003a9949067435194f6a9bc6ea742876d5894ade67b5831c111826aa8ba5c2d5 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=5f1a4b6acfc1c82049c13ee2553ac20df016062feb368a54e44aead601105987 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.gz=f5e851d27f7017832de64c134727b7cd045495ed93fece21101c1e32b4c4c5e2 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.xz=289a56a0ee6087fbebed28a8d2110961c08889724d1a776a41094d5589cd112d -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=86cc3aa69dd4b18fc8435b6f6c1c73a24dc0b031cd79f942f6bc20a11f093f67 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e29c510424862fbd96cf61e89b6f9d64cef3c0274dea125f4af2c2a84816f5d -dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=7506febb3ffaf1e763084d06a8dc9da096155c6a609a5c4c26feb993688f45f4 -dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=9c7e50509abfe5f0faa41eb526effa915e0799f59e5404e5a667c5f674a1ed18 -dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=6070daa8b4fc8bfb6c392767ac669a80067520c0fa85c923cb435c03a5ba6b9b -dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=32e4064ed11bc521f26e222897ca651704e41bd42df214eb618b6fffcb909b56 -dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=51a092e812baf52f5eb7100e433fc1d5ac7cd984f8062b7d960711b9b88f1431 -dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=444bcbf145d1aff19d8e2474191ee4ff0be738c7c3b1ded12e1a9bb35d700c2f -dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9a4968669cb034ebdd0623f57f86a674df513abf6c01cbffce0d104447f0aacf -dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=11e478ed0cf115eaed256e9f0f64ab9f879ea0fb26b2f520a6388d3efe705422 -dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0476e97436699b50ce459b3c38b55425b81864162639997bc14bce33fd7ea429 -dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f76163c6963a7f1e29cc6a348b68e3c0659b739383273029eefac4d292280a3f -dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f922ff15e927c047bed29d64534218d392bb584e12abdba09d9d9243613de3b4 -dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0131845949fe27479123189bca11f2ff13aa14e0349c0901407cf65723271fad -dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a7898b83bf49203172e6191cc720b6b184aca6cdbe44386278fab0e6c8ca4bca -dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d5a4a03dfa52f732af211ae3ed3220fd76c5a2a6babada0bf94de3817e71cca9 -dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=c074043d065a85860d2f99b657035b87a1ee7fdcea53c557035a8da6fbba96ad -dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9a02c6c4c5cf7c57942a89da30869d7bbe2b0f5bf7374b7dec868bb5f84e00f6 -dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=1c016db6ffad0ecc552025777b2d2df5a54d6ec3a215eb2b4af0f1ccc6e45f14 -dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=399d56e3525aeb354a0c9250f070a43a7426e185960db6d8b57484f47ad11a4d -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=64f01a83583f4d025c95b3b2c09b86c4bae123c72a66a6a0995994d4226d34fa -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=794cb971242dedc2926a6b56badeffd1b4aa4f1753a22a1228eda8f336c2a5c5 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=1eaa20562af0921066ae04c8e1d9191ecfc4f9816a721ad2797c47b58a343084 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=423b35248c797ea494e6462b4a9c16e49649f0105b06b16c6137799a82f0a401 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=38a31b095b74cb4b678ecd797ed768f4f9f967a201b79f21b059ef8a39fbd4f9 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d7a53419a2f604102bda0d0b8ee9aba790082ccb0d63c31ff28be15f37ee87d6 -dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0cbccec64f57ca0951fe678299cf17a7aec8bb2a8d71aa7fea1a26cd720b38ca -dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=aed7bcbb60aa5444ed8a8e1ccc7b74cc978b7e1646eb618a1899ebe61adf2c34 -dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0cd68dad85a5cc084d8a0cddc275cd5e932e50cea18d3d622d03ecca068008e4 -dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=0873ae093594ae2d93f19003ded34d1d6d4884757e0a5a790d4766be4bd7622a -dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=ae70c9e9edd7d83776cdd0013e081d3b16dadb2a2504037b245acc82f104112f -dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=810c1346632064535769e8fb15ac207de45f06700e8cc9875b3971c44725a3df -dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.gz=0538ccf4739439c52d6c7d99b573e7d8163a834a6163720829816d291e067217 -dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.xz=8064bfdddb99ba6ff202ab92e3492bd2191ea11387b930a35fcde5ac7e341c29 -dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.gz=a988938091594f39015783e78a334d72d41f5a3646a3da09fe7a7a0db7ec2662 -dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.xz=0dbf287df801225c52d4dcbfd7afdfd5c1bb8410d9342885c092a4982a0d038b -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.gz=d5b46640810193ee163ef6cf3bb8d506b6844104c3d00c033d436d79ee790dcf -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.xz=f4e7ee83d5392e2496b9d3fc1e42b45d73be3b67e723a2e62f931c11a61480af -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.gz=0fa0ba0ca7c4e73f8b9ff2800919484cad7d902cc5e704e5aa3adb742cf6a6a0 -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.xz=ce3f3f3bc51cf79449df550b8c3fbcac588444b3234f379b93076034be6a40e7 -dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b2aee46d16f38cf43cdd3f3fab78df181bab6438cb012c2caa56fa097ad1402 -dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.xz=3ee398b8497b7920f5d3cb18be2334ce440ec61b11e80c3ffb9eb1d898be45cc -dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=26a67116e52dc1fcf179dd226fc28e3e21f2d2b482330d254b5882502573ee6b -dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d051ae1bc98060db4a2ca7fa3c3dfc6c3107632631edac41d553e4b192ccc2d3 -dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=dc34a8335b1a9dc077e38b4e4a8222d84340de604a6af547fa17bb142cd0c4da -dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=2d5c375d09bcaad6f983d4c4e0762532feb1d3706beacbf3a8d2e4fd75bf0c71 -dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=30c73a59d9138a542337fbb2be848a152172be272a25a1ad9a28f37510e35e94 -dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=467775974be97da92015790d49cb4f89d967ed1fd7846456b4b30e20f9585501 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=06db2989a00b1913822cec211225b0d37143dfe1e62d394c18c04954f7396ac0 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=65de9bf3cfc8ac6910953b2d3b2e9de532220f692519875e7da50a6493500fe5 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=26a6aec0f92b238c4d75c9eda3ecbb8bf0f1628ea5bdf52941e7b5ca398ec03a -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=7a4b72ba1d507f418b30d7a110eb5e9025872e2398f0aa68abbef150f4c49ef1 -dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cf04dc8f1df723dbca4fa3a1155dc3bced6b3c96588bf41f6bcc196b74ae19cf -dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fd17a62d10d27c13818cc3dbe1c62aa85d9c7123b88310d12cc40939010ec97 -dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.gz=64ddae5e3e08ede16960f50595c4205de9962e0f5b8de9de5df1e9a8946bf66a -dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.xz=0d6449807c02e1ef817fa2d378e77d9becd3a1560192bc9fdfad84cdee5cc8b3 -dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.gz=c4ba753891162f604effac480ded4c536f294e39768f41d7b4fea1ab28c71be3 -dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.xz=46a6f680f19ee2ddeb41e7aa13bb91a893ae27ae89ec41c36094f6e4db4a3e0d -dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.gz=3f89ca539044a79abd2b25f12d08ae954a7fcdcdf0288239c57d241b225776f9 -dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.xz=18a922eb41f5c907bfb624d18ca882dfd569f6775105dcdc29e7c7eb49187859 -dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.gz=6dec5910a96e7a8e0713c109c993df44094e03fc8ac90b1a99f72dfdf84798f7 -dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.xz=00e21ba70b0ee2760dcd51bf68f6be74c5cf38fc301476f406bf1f1d21ae7503 -dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.gz=c0b620ffb0debcd0f20155b1be250627450f14b4f62b32d9d9e4ee4c4e57cca7 -dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.xz=4d14c5de2f92b67c99e6fd2342d4ee968805d9eb68d4f9d1f549bb27e866f3b0 -dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.gz=b3ffba3cdef26174462e65847414458eba1c6aea63a78f6087497a04b427295b -dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.xz=1923ee9008ca30677642d1e66463555ba6fcee88dc0ed947e0ece7e4ce4efdd4 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.gz=e8f1cd196c5e3b10a58f640cc8bdf3d015e1b23d49724112aaa7e4019cf01107 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.xz=5fec3b22adc67fc6e4ef2cb873d446cb1520cfcee2ef4248e3dcc2816ada683e -dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=852e5067d47ac896c18e424cedcb984b0b4724b7fcd05e550151de2781603737 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=2333f02b870c6e7b673f5e8e166bf9166c3f6d1586daafa4eeb626d8de5b305e -dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=5c2bfde266aefa83ef9e65448900f4aa73e1d91de3719ada2512230a69090e2c -dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=218f4a4861812e38992bf261e390e95fbe67402f89827e6ac1b68fa42c705166 -dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.gz=5cd9859a22f77dffae58fb6573a8f5e23dc75bf030f54c152714777e5a01eef3 -dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.xz=be754bee393794ac427718b687f5e4aaf61aa1544795ed0da0b9d20e77e45803 -dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.gz=556f48c0ee8276bc847f3519dc0dfb72bd11cf27add709815da47f5cbb48716d -dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.xz=aa185610d66b606913d1102f62b62c5bbf9c5baf2e091d14d37c30b1526fb583 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=1a7dd15c91fb1597593b27dc0b72bc0b1a6e758935efae3c9db714cd624d7639 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=be18c0a1f2d0a1852c81ac1619a01d04d0c8c22472655710f643d86cb559508d -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e18f210cfe890af8285da5f99cc476770daa78cddb7f8213f7f26f66111e17ef -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=b207877400dbfad09b6a3c2917516b63faa159f922ad03911736634ff46898d1 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6f277d2e2e9a9057e2a2c8045c3949ab36ee8ed58b64829b10470e0c6b111671 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=51a102726ddf492dbc530437047fcb4d5e542dc4ace0e64da21c7ec79ebc001c -dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eeb6a46dd78fe3b477454c256ba8486b906e7a7ed044e686bd4f8c868265bd90 -dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.xz=67e103b9742ebf2798fe8e2647a6755a1d253301fea13a5193ced5bc394b9a0c -dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b42fcd18458cff0ffa0902a0797e9b42cdf9475f5e84279972e4010608a14ba3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=878e3950e0aefbd5c5c155f1ba2a4e8abebab10e3e77311403fc2c475e6da9df -dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.gz=d72be5ca5fde3ac33da483058b8132707c93647652245864c988158e6dd70ca1 -dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.xz=270959bb47366b7276717b677c5303ba0d579c9fd1f98fcf3774ce033caf0015 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=33370d376f3ecd80ddb5f614eef222c601e2df5dd18ae98ec034922790f56218 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=061a262fe98e6e1b41df6f9f60367259d44215f528938574098ede8698985c94 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=70328a15c8e29be07f248bb073336f06eba613c377ea4e98a1e0a4abe5e2eb6e -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=ac389ebe5ca69cb382fd104161c9068bd8aa4d28960d578f2d925faafffb61da -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=22d350bc0718b999d88e715cba73ef1860e1b1b8efac026f46d9050952d739b3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=0761b9cb94210ee40fd0dbde38cd049a9e727a73da4ebc2cf10e5db92e6860de -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=35f975847adac17d19abba5385b951ce2015dd8b62ce4b0a716ac612808cc9d7 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=5a9679805c1bdfa835aee94ed0d3ed4d2b4d0b6a8e2ec4471fcbcefd331cb200 -dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.gz=e4269be360d9823bccf6f7d71e4f51feeb8e955c7851d5bb6527055d709b68b7 -dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.xz=58880cc63fb93bbbb78fa4268eb69b37464b429de2f007abf05f5fd7c53aec8a -dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.gz=42c77c14c433f43a092bef5ea0cfa60aea747301a9499c66bdd81d7998a74143 -dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.xz=0cdfb3cf58d8f6db3bd65f4848aec8a431ffb4e1a5f79e56ceafe09849a96ac3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.gz=35ba471138c115ac3e1ac3560fe8590038cb6002d22a45dd92f09a868270d223 -dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.xz=f250b60b52e2f84864406a0ef7e2f8896e1373f4f14f555a47a2019fd370f553 -dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.gz=7332cbab92c48611604eb13ac025b845fd0dc0bfe838a4edb02f8266a5245aeb -dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.xz=7cbef4955ee702d845116c59742194b1019d67f564145cf809ecec67245ca8af -dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.gz=59321dd2f962c7b14514fdf1ec96907c16735a03a799479055f40f17883b8b6e -dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.xz=336c7dff9f3a1d9de819a32f62eb518dd94d45ee591afb01d329127a2146c3fb -dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.gz=00c53e3a327909882282a32850c82e4aa18508a5e355532951d380e985b75c79 -dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.xz=39d09b49740b0512a84fd5351d473c5802de30721f621cf99ccd0178d8eebd60 -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=dcb522627c49811d2e6eb133725e301089a4942da1347721ea28f2cdd670685a -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b9ce402bb130d35e482ee360f8f142726ff51bac3954aeed14800eef0bd96f6d -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.gz=670c0b78cd5c985e6bacb2bb2cc3a5a2478c2623992c4cc35d0d4c624e1b4b16 -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8a936c0c457a1d5c659611e7a69fe9934313d9ceea04c0a0eb393e28544ce7b1 -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=10150caa2130a73443942f1dde7c849172b57b7b9e07e8939cd6c126c701d7d7 -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4dc0ffb898e66661a1b9844b965a0b0ca115bd6d9bb25fd5c5df022fdbeb56bf -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6db24d0a3eb7de6e3d40dceccf6a92ed86e170e0c4dd2ebc9702652655ad664b -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=c5699a6a4ad49c34a77c94a4982b1a0ea7f6dea84d2771c24fdc05dfe9d4cdb4 -dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=f5621b39e7608e8461b559f3c3e57969e7eadce82798b395ba41e6302b2e0283 -dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=d7f62c0ac375f56d9ebbd0edbfaee4684d7d47ed8ad38bf7d25fb75a5770bdb1 -dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.gz=b895fa9240c3a6c089cde6b08a21408b5a6f38818c4a9cf25394b17e9610da96 -dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.xz=e26de92566339b932cdf4a4ee90464f1f3863d89534c03a3c9f9a632a278993d -dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.gz=ba64512c0732f5821ac4d1eb7fb53c0f340847c0cbc7dd5f88f67e03bc3f58ee -dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.xz=cf9872ad8ce5621faf517c2796620f24c1a99bccff7f328b7e7650e89e604b22 -dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.gz=23496080baad6b976f8680b7f6c856461a410a4dce5c66a41cfa220d9479cd95 -dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.xz=9799594bddbe1e04e1d625a6ead04efdd4749d4f0773585d21ba2be6636f0bee -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=5a1b95969f002c25717751337951aed39e6f6256ee58acce150d5ffaf0046300 -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=36bab05ec8b39c7e230ed78f64b2680ea21fa9f7997c980c22edde61c0799b5a -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=19bfbd70b98c0bbbf29a0a796572d1661b8902132087173ca0e6aaadb4d51d09 -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=629e42e188447a392bfc7cef5fe04c31380ee30523dc0bc33b0f3c02bd2fd82c -dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=5d8b1daa253ebe0750e6f073b8367b053de09b4f209327d4114bfa60b2bb5602 -dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=545d7ad3b7b0b5d2ec0b4bb70b7e31dd823048d6087d6c3fa2139f307ea35fbb -dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2111cbc7586a1e58dc7e6e54a63157f9606f5586c7bb72ffa15f1a94284d4c97 -dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=0d6702d3ec5a6aa9dfb06d565e4e16b27cd3d445871bf2344c876d7ffe2f8a32 -dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0f750831b518b452a2ac17c9bab3a02f30f58bba6ffcd962eed06012102c7b31 -dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6d476e16109e9bc5dd055c537a9382ce154d2837a32bc2c165a1aec76ba1ba43 -dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=850bbca95670afa1262b5d46bb02f0bb367c83f851bc2a9817f8bf2eda9bd2ef -dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f42b3b5cb506886bcfc92c0a7f3dd3d0668bdda0f2db657b98becb4c0e99bfd1 -dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f3a8541b3e6c12f350fcfbf43a8efb2a8bb48a62e055d9dc522d568b94476f43 -dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.xz=12c5411791c715562c99dd211095c9924142053d510e17e6ec50b7b8b927eda1 -dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.gz=95885bfcf5fc1de80d0f9b5415dd261136d5577b7d61716c184a6c6379acca21 -dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.xz=881c9d88bf2a848f5b5cd61d18068e2dda3542a65e93ab373e3a047cc30369d2 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.gz=c04ca1768c5925d5c7e19d5f232adbda355469974b19a2a130a6967db94b56c3 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc02593e98f5393ce2032fb605ec2bc053a1a19311a5a80d27c3a552ec8b968b -dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8ffb930c33ad454806f2f61a10949a3fa5b92b9313454927dbd76928955ed7f2 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.xz=ef0bbe8512b3dc9bdc9f3a47abf2834bcde1fd7f59e319f7c7040b7100ba1f8a -dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.gz=eb21f7739dbd7c120dc9552360e8aa6e1e0eee14d80ea16e3dcecb9e94efe7c0 -dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.xz=9e287f3d0c7e402dbc121cd737fd2360dfcd97fa886770aae93c07474494bb77 -dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.gz=1cb86b6953ec99e95d92d61ead263021d16921cfe6152b6331efb838c46be85c -dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.xz=c356e671ca97dcb4d945567e33f06911d5269fdebc19fe83a9313f574d446576 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=7613e679837e2769b9e8df5b8785fdb7e51665379e64547bae9d6015eb8e45c0 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=39ae7207f84ee3da16ee11271070e8b82d2991cde29771d5154bb2957d9beccc -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4dfaa69f4377bb724eb7d1990aea7ac219a960b690601769f8e06b72f59f86b4 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.xz=4cf72f3f0048e8cfb2b05566cbc1d76e9730cf1f71f9d0f3a71bd9379f30b08c -dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.gz=e1d3ff748dcf1777bc2d999ec82f0b8a67295f91a9cb07a9c1123cd5424928c3 -dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.xz=7e21e89e218118d536d489d16e77e667df7ba7c809135ba179e7097a2243df5d -dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.gz=244ed83cac923e00647cdd3aab9d0479cf420991e9e06eee5ffd8acc9e5a199e -dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.xz=6dd93a671fca0efb2d3b8cc461aba66483624327a382fd714a526832034c8438 -dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.gz=56710fa9c7d46fb881903e08e407c258e3ffc75ce3de0226dcdc3709dc59180e -dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.xz=6ee782709786c310fb1e887cc576e7e61b0a4b120f6a46c7dea1e2f2bf7dad1d -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=06f0ee2195349921d1ae791fa1628fceaa7adb377968fa09dbe17aa77c762a47 -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=6e792e91db8b54e0cfb9eaed8187b5202ac5d5735ed0f73080a6a73bf15ce683 -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bde52962b121472cd1b755c506b9362ff88ec582cb3fe9d307948c51f4d96f1c -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.xz=70a06d5b8175d078bd246adf45f3058d362f0b128f1dc11d3797840b28692bf5 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ab8b54d8436dbc6af279a048d2b75eea9eabfa369f23c51fc1c47388f642a755 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a2715009144defc9aea3ff0d6a15485d8feedd37b333658470d479600fe87ffd -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a1863b47208051a231f9571bdac3628d8afdfca7eac3b1cb7a04a843c176ae80 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=a5926e8e3e2867a8fa87db77dc26bd18734f84a4a685374dda07d50d21068f62 -dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f70eabd386aac93c676485bd42845e62b34c034b8710bf0db24a440c03b15bce -dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cfde41ebe7398d0858bf507b9322c5f4959becd5a3a4624027b4bf3321730a29 -dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.gz=3d988126d6a0ed9133b73b8aea3b16d6355db8ad83254a7499f7dc3b414d62f8 -dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.xz=6efe88aab2daa0c7df17bbb449c2b815e085ca7e859b17bb578978d18ca2ea04 -dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.gz=2c2eb32ebe3ec89a985c07ce87cc1dbc627f5f8588aeac72fd381c6e19034095 -dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.xz=fe2d2ae70e0ce102794450d4259b706d3bda2c5b05bd21a863b2ecd8ed54274b -dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.gz=0d633381b174f04523f13cc574e79af5041a231aa61b0befc406c7e3ccb0ebf3 -dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.xz=029558aecdd4862dc74ce9726a462f1d34a7e2a6eda5bf791995dfd6933096e7 -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=2bdaa7f730f30db62ed0661f135227c54249786a78a8022428ead03766c9e29b -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=2a4f5982eac9cb5e8372d35c13a7832d532a31e5c38d13b0643d16832e1e341e -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a9a1fc5b74e19a567c45ce1789c7bfd50b28774bca8320886108e4a18a1d7765 -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9e957652f80b2de14c5a8f5faaa5662d0ebd26e18b2bc5d248587d72413e483b -dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a9fa9caea0f784ed096b3ff204a8261126102e05456c52d544c7036f9ee30c41 -dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0e3d3472e3e73b02aca8797ecaa2471e472d361b0c44126e4bfc2d25a8fad96c -dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=211c52eed69942aed1e6b1fb4799232ea4fd3f898a44a4bb6343336e89dfec74 -dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=8c07b34223e465e17094b7e20efdbf8ec6ef5aa042485d3cfbc6ef58dbca0be9 -dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fc3cc6e81ef118eada3c01fc3535dfc622b92377d8e735f80d7661b4b847fb -dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e885c534589fac79046bb31b92aefe7674dee13c8df1a456e91ca63e9d92c6d5 -dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=fcfbf29d105ade4a6d7537dc44d01c6de2de70d066afd8ac3af58bf3bcb6f7d0 -dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a5425df8cd724fd992de26434090e157e9d148d063161bfb43789d6b4234ad02 -dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ab96fc1c538a9a526124bc2cf3e97edd655f29f8d6d310b3b5f017cfbe6311e3 -dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.xz=096de4e9f80f40a294dfd1ba32e9de038c3449b2760189a5c9e46cf8e36dc0d6 -dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.gz=5614651ef2acd5ce1d43cc2504d353e471d9c8c425c16e3649f81e1cef44b86f -dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.xz=26e39442af2251c52bcd275c7ae25a88211ec2f582bbe7a29724f816768c9781 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b2626513cbcd9b1456dce8543c2b11458eb052434f9ca84a6e926a77e5be2362 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.xz=87403c11e1b92bbbc2651183b2b480c41d9c7e0fa6f08551702c6ab308fbbf5e -dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.gz=929029e67d34bc813061c524490b8f0030d31097fc1fd439acd4d8c3545589a1 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1584df60f086c6af01f06023236f612bf59be9d5b991bd09ed66f4c505737533 -dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.gz=d5ee8cfefbf164d33529f1a777437f49216e93173a2ac04b605e74fea89fc6a3 -dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.xz=9469aead14fc03ebe984e51bbee0db6d1cd8e877b67ca361c44939e2464a95fe -dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.gz=79bd918b2a391cbeb885b7075b1e0534054c81784c332a2aa8539d0e1cd15f69 -dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.xz=16b808026a4fdfaa85a4ac01b01b4fc79c4824a651bd4e412e4ee9b0011eca4c -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=62224af7a1831140fc3f06e7e918191e9443751549ec5c96afdcb3ffb5b18e06 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=78bab115fa696fc95d911655575032fc9af324c8b6df136044f11681239e5c41 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1a76ea2b1596acd396585d78d01be5d3b795641d7b20f84379cd2c344e7536e9 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.xz=63ac980b41b0a3b744d94727af6ee1679b8bc4c50db4ef68402d0253b1852ffb -dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.gz=eba61354aecfea64815a68b569122e029501d85876d37f5ea4119f36f932e146 -dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.xz=37f9395e78a2bf2977b38929b9511e9668f26e23705d025609f028b282aeaee2 -dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.gz=05cc308cd0c35063b43a45dab3e84001e2d580b10431c74899a86cd8971e5b36 -dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.xz=aede50889786bc1e902162b9347cf59ee67b15e902b0ed78d7187d3c24a7c4a0 -dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=1c25ee283dbc720b471d435ed952e6d794ecacafd4c889a2ad8d43725cba8ded -dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=67602978481a53b0b4681523d94bf79ad731a369cc088c3b0adf8e7d54b1fbce -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ed7c9c38071f9d1e632104ff1d9a9407efec99d74eabd127db795c56e84b9d73 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=65ee60bfefa1334cece9f5da72789d90b4b5918e7afea2b47aa4d1450d9a1237 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=e92d5ddf80c94bdc34697bec4d7a1b1ea677e5fc6c68c41059a7829e53e95505 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2f1737178817318d1543deabd865aa83a1f395a36cc83e3717157b4dad827f22 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=a4be0eb92a011ed940db67973d5fb62c4b5d3fdd52a08981223c5fa5278826b5 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=a47b2dab4f20f53e6c29fbce06383144a67ece61a63f33c3fb86beaabfe4bce5 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7bfef0a8b7cb4a905ad145311c320a8ccb2048e806ef68688a1423009770b35a -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=d944161b92bdd74f3ba533b94b67a3a361a01b82fa5c156710608f00c46913ec -dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=46a46ad32e2829550e301a84212f057faf21bf67ff6862f77f11cb0e13f80453 -dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d917336a949ad5a5f0fcfe1ef261d87d4dcbde22b467258543c50715a9041d64 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=38a9cd401774ff1d832e536ed0aca9a3f0d5593814bd6db9ba4f8341a5545fd3 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=fa2194663d11d517bbd67c157fc40cf67149246c391e9b8adf0a46c2eb96c860 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c5271c244d8055401d3d3a97873064b93915dbcc52108cb9b61381af1ebe99ad -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=56c6a0cedf3ec4667d65a209477cfe0d395e534654b49e28efbd3836e8a0dae7 -dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c4325b80bfc63dc58c4632ede188efdc94aa4cad49abfa4e57d81faad673a35c -dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=35b4fba91cad3bf9e627d59baf1f1864e30d002b05696c61498e73fd0e0f299f -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=b2f856cc81be2c6f2c4250ec88cbab0a51c3d59e73fefd66cae9b1a91a32b0bb -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=1b1a40377a8a13b74f62f5bb382cb8056930c543b97261d32613c53826c758da -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=98b1f0fc4f45eae47a6cae7e7d4d9734979d8f860c7c96da281fa1d9ed3ca39f -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=bae7dbd1342d5aa89c335f1dcdac0d93f5cd8198ce9f869ef4c32dba8bc6c0d7 -dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=cb5dc166002aba8a95f7e10d2d9e93a66d51483540c7e733b528bfccdbc74d9f -dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=c070a48d0aad7ce42cfe5eba9477a0f54a9e04c9ec5c770e91bd2db55d0d764a -dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=424c0d9a047ac228cfed286d0a2936b857e1c575ddebd931ca634e0501c125da -dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=b067b3d095a5b53191ff148d0e89baed0b53c2099142d885961220548b904c52 -dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=01acab58a327ee34d100e67a4a40a9efb66a64d478d6bcaaf94ce35874296c42 -dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c1a715f7502ef54a236d4ebe15488ec4c1c5cc5b1c50eea416a5b9c57de66f53 -dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=cb014573a52f2d6776e47f3f728ae1e8b05feac2274c5916b1545675e658fc15 -dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=5abf6bf36bcb57c0492e9bb4953ef78a61acf347d20ab788b4b31da44ae3bd39 -dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=0bee2c4ea3f8ba07c189f7e2e0df1b2627b7bb638823fde2839d46a353e0480a -dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=df352612d69dff13b59da185581a48062e54ee07161b1fe205b92d0687a4e896 -dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b7b44f5fb37fac58a83c2220a68c251513fcca96c51a71b189152a78cf095cf9 -dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.xz=f5876f1d8181880e4ecb71eaa2477b0431dd0bbb45e6a4da8f20bc31426cb43d -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=cae33e30d7b2e5589a6fe681345f6edbf406aa803d0d521ea182a575ee32dca2 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=21324d7c6949bd12c841db8904d9485dd709f8c324e7aea31f2a9eb2a32844c0 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=cfccffb90721492cc79212ba49dd88361c6d38eab24ca4fbfd8110c2eefea001 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=05c528e683c40467ed3911ec5f852914e117fd71e8a0826f17d91295d4f1b047 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=97cd5e773bfebd3e1d78dc3d486a75b969e30f1dd0311d07c337440d275d0443 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=19989c6e9ce4d67e068d449b92dfedd8e07bd1a287cee0410f43aa43432346f9 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c3d8ed4650b4f7902a8643bfee849926892aea2e664400b858f61000966042cd -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=6b0dce2bb77036d154d15ffb2495480ed8c8cc441dc8979b4fd767af80e0736d -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=de7b427a783d588a778a2301a1bf8e4fec076ede2006e275f45d82a87e965feb -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=43fdb72c7e74c86eedbb01631ec357c2cf469512c0c591d15f35f747bcfbbd30 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3fccaaf7106f47302eb3c489dd722a91727e25351278a17f81d06fbb4cd4041d -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=988d6c342a4561790d1024455be643e17525ae07e02fe5238fc61d00c91d3cd6 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=71c10377a84b3bd612a83cd2822bc6c0eb4a540c681114d63be368da84ef3766 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1e6a3c7080334663ef6fe246eae3482a05446b83c8a0c659084ca8186b9cab01 -dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.gz=e68c96b5d6fc204944cd1bfd80e2c6a8332dedede98a968e170fa657e012ec1f -dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.xz=9f7138fecf991a17483e0359c7a5a0b4292cffeafdd4b52b7c1021cbf993ec5c -dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0f31c36e6b6b765e9814dd193861e2ae2a176160f22aaff6211a6da3efbc1fd0 -dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ab4cbc70a6002bdba2955fbbdd99f03d3e54d14d32bd2f7250be6a323f39dfd9 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=e088594f42b88494401df68cc60b8d94a4c1199e3549aa6dffd513b0c5f7508a -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a204d11814dfb6a3283ed84abf8b88492283eb6cfbec018a0f249d496e2db5f1 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=802ae62e1023c460739670a12b8a331637cec02aec14769bf0bbdbad44217555 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9ab24e33a80a442a540720377855710c2b33617531daa625dff537d1251bb9b4 -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=08a139d7e1ad8559d3add81416581984d24eb997f5d03f2ea85a76eac62df57e -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=dc9dface28b81a1b241a6ad034cd910221866cff7188d94929bd80e3d2dc1598 -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=ecfb3225d805cb7faeb185e43471b35decc735c1330bcb45d54cbb93fac0db4f -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=60437f2b7cd51cebff36687bc904c7493ef834e39033c08e35883b3de03ed15f -dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=aab495b49ad218fbaf6f36e0dc82ae76dd867ca77411568f15039e494154d890 -dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=51648f6d14e8684c3f258ede3e97371c1530be584b5bc47a92b7bce84d70b397 -dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.gz=6bf818c20105a30461336053b40b9b298388b341766536137a3fd6039e7885ad -dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.xz=60346687b8359a3df7bc4d7beb5532be716bb699fe8aec76664b5b5b4d7cacfc -dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.gz=48b542959792f1cb4c316ee417fec68ccab0ee76a68accbe667fc56ca9d5a367 -dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.xz=b83ebe192f8e2d82fdb0765952e69e4234f11fd6a0a4a69d089b2df42a3c637f -dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.gz=03b36beaf28462424b3b70e6a944d24a22a551c4fd9c245cfd5eef464047ec30 -dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e00e81bfca624087f97ae2ff675adf08a72519240e31cfaf0f4da238d7be8050 -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f71e27157be06043624ebb769cffc92593d4db6d2a9edabec6815d0f9be64b9f -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=5bd77608b891be20b38739d2b1cd4319feeb13f92214e550a01c599349fd6ce2 -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=0cda1b3a287843431991468cf8dea7a34221d42153e9421ed89a8f58d048e01b -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=57f3a4d73a40ffe0dad530334f2e584c1279ce3b81458023f034bf8c35dc6641 -dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=5d7c5164b12ad921f1d8461d0edeb17566bf4d5861d6b0f18f66ac1a91b7306d -dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=8ba849b777182977ad9b87c002bff49ff9ad2007932abab98509e96274b9c7d9 -dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=03c12e5d01a6f0b66dfd728610fc0df2f3bef8d5cf418a4d5a385b11f35ecd81 -dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=db0b2d5a9a12c9c8aa0d5d3a320ef8f815ea2ac84718e1bbe94514e7480db6b5 -dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2e3a85da6e7a74b079a5bbbbcd433e0271b89b873aec22c19537669bd908a98c -dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2b19af7ec21a9e442975b073455e4b3a2711832f6f4a521335034f47dd7725e3 -dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=c293489afe56e4ab984bab7c0ea8db292464b1b0a83b3efac3d38079f71303b2 -dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fad8d9fce164461c81c5fca56c3557e76635f70ad755cfdb1a448faf161a6b02 -dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1a4d7fb7e5d74649270e79fcdd5b7686bf3db6985d3a781ebb1f069404639884 -dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb1ca19ca8a99b68a1665937c2bfde2a275ff2746cd8b50e097202352a0f7cba -dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.gz=32d6c59ee1bb8d1449393b37ae9399d24ecbfcaa6dc5831ad2bdfb3a586c8ab9 -dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.xz=5a9237c1b359da2c6aac0d6c9202f527d5982310477c414c3c03c6eee50feaf3 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9b03ad10b3e5de01a813fd9be676135de072de0d3fe6db63e82ff881b9d81c51 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=1e7b91da95fa7fba74c4f8937fc9e02b592c4a66260aab1a4feca24e136501e3 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=59efe9285d460cf8080d3aaed31742cc7ae5dffebb9bdd3410be22a061fa8dc0 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e64edab835454e2024081b9c447798075cc2df3703a8b627d9661c32233c8540 -dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c1ceabe8ad4f89b401a72a6a02843a5f31267cb9762d1a8c30dbcb51c1967488 -dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.xz=456708749343846153490593eebc55d78ae347d0a1096d0fdbea19c99aa24d9e -dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.gz=e01be583da5371501755ca0f6d44cd2abef40543d7d97448933e27ba0de78c8e -dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.xz=42dca4d9e7d76109a3c963b5783554d6ce0171001d744f3fa6b5001bc6ad66a1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4464cc28f6a15d5a2a1de098f28224848d0b91779bb70ace3106f3a6208d25dd -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=5f9b9cf42730255c27bef5187241736693b5e39de9fde935da25c9f33deb4325 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d6c2b41d4fff28d12b254d3cdab480ac4a81054e50794b6cfb7ed30065cad5a1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1acfe2f78ff7aa747e5b307b40ff5a8be5e8076897b78b2fb5828d1bb1d74cf1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.gz=9d5bfab5bfb9e6d627a5acd1f54fb164538e84c449aa3ea15841636257ec7ab4 -dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dddd1663a821d99ea19864435e1c7daed6bcb4fd914e6b79c94d644836bc8d1a \ No newline at end of file +dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.gz=58e2ba5f6a388a5bc9ecfa1c7ec4ba3efd9662e1875ea5fba484c75c5f930227 +dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.xz=95f3ed14a6e3093cdee83f80227c7966783fffcc0ff0be6ef095df0dc744b9f8 +dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz=687b58e25baa685be9357048cc1e0c469c25dc6530db55e0179234615ff4d289 +dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz=694e2405efb25c53575599ad6573d8c4646a168e5d4bde922ef5e7d43f3e530c +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=4b42d00e701f90c1fff9a692f1bc1da957fcadbd1813c3066dc1f1990bceadcc +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=4f83a8cced878c03aea2d6cec7e1d588c2b6590850664f28f3b49a3be3a8b827 +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz=bae97ca3778fbaa40f6db4da4f6da0b2bb870e9880165fc3126363f55a1fb23a +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3e617e866a8c03fef243dede8c086d085a6564aeeb5570bada62db5a16e95f2a +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=96d2f23814db8286de9ffce7bab033aa4dc656f83aa39418c8f877a5befbb100 +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0433a866c4d8a434990746216232759345d3ef556b0b92358b231fc1e727962e +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=6a776c6eb2b7b4992eed6a127d11b8845695cdc5d23938ced2267f88f8d97033 +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=2649e0f522755dcd511a6459258c3c3a24808fc49d3513f3d9098b17bd0f2c79 +dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=02a65e970ee930b46c2d10e1eb3d2e6f2420e08bbef039f10a8311baf57f274f +dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=3843610c7ecf98948a5f78a364c223d520a084bc8c49ec0c3c8ec48bad6c0bf8 +dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.gz=75288ca1e65157b8902195ec2fff31015017c90d3b8f51890f2f851529b200cb +dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.xz=5c694e50b41cd6f2c7b59b891eda3e728a1a2c56617b96c9da001b35885637b4 +dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.gz=6d1a66c090322ccf272a425c779f9165398e6bd9e0c7e5d0a5f262086d43ed88 +dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.xz=e826fe8be287f8969d11f620da9d01ea0d913eba145fb79ae86bc78674f1b919 +dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.gz=31e0d9a1ff97d92c391cc913fd865a0c8afd614279654350d469bdf881a1b1a3 +dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.xz=3b11a6be4863cb6ad420b66558b7745431834d1fac5dbda899a384dc30b526cf +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=59d96cd092a56d12ea796b65225479803edadbdcb483effdfa36e191f73483f1 +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=0714a469cbd7d96118e9260f80fedf34b21234776904e9c8ec5b71c9493dd36a +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=25113ca9719a036ae581f68df4dda74f1446b49ababe7bb194510fbd1b296e7a +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=25bd910ea722fe2d4a1e66089352c92f97759ec7212af2b9a04431b469ed8e12 +dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=7a83c9f63d88849c4d691ad1d7fbe7ab5924b5a7d76378ddff5024269be95310 +dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=fbbb11b4c986186d94b0e00ebc70400d0071efc2ba3b802abdd877d86b8cacdd +dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=6223dff24490e3e8506dfbe2b12620155d7c05fce92191cb01f3b28e269bf1be +dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=6fb1edea73bcb76d9cb6061d1aba15ee4655a212c1bf96328a225c7c05df3462 +dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=0b7bc9ec0c40a6203fb62eb71fb6eeab43a4f64a2f7d0d51a1e0d041a216adb1 +dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=d77a49acbf26b8c9a2a5f79fdc640feb1c81b9fa38f442b81f69127f49c7cde7 +dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=bdf45a37fad10df4822690ea73840b38ee3e1048878982e625efbad3b2054f28 +dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=ad6a2f03b2e27711e1ec4eb75502782c4bc0200cfaca2b5246e0bd5b86bf29ad +dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz=b0cc3024a717d33775dbea63e83f317f8826e564ceb4ecb7a6cf23676f66ccdc +dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz=9d5b44a82803d5de5355ffced6ec1dcb9860950910bba6dc54878ad4da7ff444 +dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.gz=c7174c35b530453182f5f0b15c6684c030a2ff2770f4cc1a4a4ba75695e53b99 +dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.xz=c68c26159a3fb4d4380fb25488aa78223989893d7786b8ec947d82ce0cc905bc +dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz=c97caf7877097d78fe2191e715e3a45d827d28c27b4dabf0747f8ca522ee43f5 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz=b7794ecabc42698cb77c1c90d66676a8b1b3632108ab95954ee496ee7d6e5708 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28068a6e050abe21933920dba3ead2261f7d0c09687d5a86a5db51cca6e72ea9 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz=3860d7ec8564019c79551727a3a54c66453a7d654fbb89b8feeae75d9021fa77 +dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.gz=6c2a918f8d40ba01e648565c98ea120d32562dd93820e8f2e33abb2aef08e1da +dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.xz=5d1edcc6c4be49849c3c2d1c3c173d4a127db3cfb615093e5ee396e0d0c77366 +dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.gz=a64c30d82dca58d09bfa38e72bbe1457b48b101157193a3ee33dd85922bbfe9d +dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.xz=87d14b146386fe1f9e24fedc25e1bf9682913bbd7537047b0baef0d74cad5473 +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=3f186913535ac59446e249f4d3e35e3d93a3f8207b31ee31b3f70af8344856bc +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=0c17a60ebac74a9cdfc2ec69fd71a21e370ff178f4c83be6020642b55b6d78ab +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz=327973698dd0ffe9b2d56b3b5929f82ec552f2002b4113fc9a738e27b0005ac0 +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz=d7e2f768922ae36a9eb302667398ee308c13f829c03235682529fce90253813d +dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.gz=13f327974170a0423ea6e7241cd3a454ab8c39b657a707c08f2e306a7a657b45 +dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.xz=5c75388802c0ddcfa51336883f4039b6f7963e0efbe47c209bb455c12951990b +dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.gz=84c4c02fdecc669c5d26c49120fdece5899133c098f5ef791ea19aba33936dea +dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.xz=7ea047840073e6ad3123a61ca799bc56c951edbb71cb8495ecbc2029759a0190 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.gz=dfb8207b4b3bc13a9704fd1d212d92a22a0e7a57293f24f28bcaa846ad4c08b6 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.xz=96940a84d95b4cfdde84a501758c9dd83f5d6cb5afce9142917d5cb3dd75c040 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=4ed66daf59e9a8b61d66caef4b2248be72049282518d7526be771301bee2b905 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=013d59e32097917b269c45a837bff380a41c4f6401b0c145264cca5a1bbd91c3 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz=270a0322dd3c2342745faa8797f4f64da8c0028b322385d209ff65cf04965a47 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz=9d54f7f51c99f17ba9cfe7cbe005ddbfe598f8af6df1dfccc9ef37029cc08b41 +dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.gz=9ae4c1d6044b2c3586791f127108e308e0a381e8e14ecc20b3830ae5258a03c2 +dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.xz=689225ea098a88a88e8e2269ef53f964405a6c31b3ee2bda0fef98da4ed9178e +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=f1d9c996cbe468ca93b15c76b84c544930d7452f1eff2968a298c885203f14cb +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f3f8c088d74c81b2457ddff57008cb908cc86e16d0fac60d10969e45210d88d6 +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=fb4e5d66911a47bd63429686885cd5c7f0a6310b25622f36bb43a754300526be +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ab6c7d346bfd72f06fbbc198743bda35fcb7fd1e131c05c54935b6ceff282f17 +dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=32b2e0d5161f7d8354d846c91e5cb25530e78351dfcff4ebf0a6fba669e2c483 +dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=656fc4a8af570b28b3f83cd59d4e5226f15d11b5d8c26b58ca2c1b2a4e18c4df +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=13c98efcde78c1e187f728509f2950a0a407ba32e730877cb9ca4cbb4ba01469 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=6372891715046375fd0a04e80c95bf79080db2d136e187b02ea96647e9281407 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=db156e0d5db6f04621e625e92323a04091c049a8b5e2b4f7e0fb2e50b81ab2ec +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=b610214bb59b8f58be96b84b0f13e5f50473e21039f6e827fa16c446d0e9ccba +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=99f96b0bda31bf21853c96b3618408587f275f46ea9bd7d1fc741e58343a5625 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=dfa1f209f546b457aa6ef742a645f00f55c70fde86522c737f7a560494170157 +dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.gz=4735b29991a2337a7e2016c5a827635e17ac149372efafc0442a86b0dc0759fb +dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.xz=fead0635c572aa4f5e5564e497f1b7e892217ebe52fea54aedacbefb32f6343d +dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=bbb9b6fedb874a61d99d22b4cdb2d20d8b9e6c69924922312692aa526851b960 +dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=9e0d48236676dc9947565daf0c2605316c5b4abc06bdb1c343559c46b9c4e304 +dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.gz=e230ffa3d46dbe5330416cdf8b7235b8dc2cf119ef8990b422eeebd017ebd17f +dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.xz=38a5560575740f92cb8664d204924cf7a2972e0f2f396852d8a22befd2cdd848 +dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.gz=0b0a9f95d10484207c52fcd8ab1bd56903b53f18ce46fe263d5b7bb085044246 +dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.xz=91f7655ab2bce397a0821edc0f523dbf2bac0af39a50ead106eb1de637ec5c44 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=e8210f03bc18661954f147dedd0b4af721d005866c0c4fea1e91594cd6c9bc2b +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=56a623817e6a600e802727d59d4cd653e84cb628695e39ecb23ae99065113115 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=310a408bde58335d8011af480d4f8c38745865772d71631596cef1a79f9f4fc2 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=fd6766ea9e828adc2e43ff1654a459785eed05ad00c7f6804c742ff8ae8f6b8a +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e663e30526d85d89f41456a3d5bcd411397cb69e7cb9508aa1472b015963fd18 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0361504ada464a7d21e7ac66fdf9e1e820695f3a8ca4854695e78a748c5c7a18 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=c375be97e626900d809390c61bf6f2d689c9fca8e58c85e4e02b694bed4c5ce0 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=c33e3b4f9098860f75fcc9a8f86c7e7173692ad4c19cbb2c0de068961f87c192 +dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=3f50d9afd9df4db85958e4575429dd4c80b6702a8d91c3f1d9327345aaadefe0 +dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=0016d3a6ec8351ee9fac2eeae358a0854a3c2b360822bb3ba670255e8f27f57e +dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.gz=f23117b972ccd21c0a6f4db4b544401045c9f157595a297fb56d7e864cf190fe +dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.xz=ab9be4bb25b1575af276cbec7fb1a1f8c683741b0f137bca7b4b61ab13575645 +dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.gz=673561456e26bc992cb6a888c34c0b6b13e1bd0d3e0764360a785a6c3369f0d0 +dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.xz=29c6f01c636bcd901b88e92c60874c454369efd41f690d74b1fa2adf3450166a +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=c214d4439676a19c057324dc736d63aa0328ac74c0eb9ced8d782d8bc89757ae +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=4baf85ac632750c35d007bcae8f23720208c5197f4a1d49b0a85b2b0e137f603 +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=a7e81c0e80f2508c81ba9d8e658dabeb19af2de6f7365f6e377d39e99d8449e7 +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3f37f746aaa03107573a3a2b201c15bf86777ec405dc03640e7d3f24f718f67f +dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.gz=fe7c7ecb8a8e612caf0e7ecf04d18ccaed31d8b93911ded6b3cba0c78fcbbddc +dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.xz=d571b714821de4b7d2accad221b5e043e7f9aead8dbc06586f4f7ff3f3f3e38e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=663396f0e4c45bfc041b1a502b64627620f499ca6343664633761c3fb1c2229e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4d8c47d74958e3b1058ab721e9c6635774afad0252f251b0c9fe4f0895d0c81e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=3cba82809bc1204b6e8f62877c5e9f9a08f111da7d439032cc30d55be0e88fd7 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=d525a4dde496e72fd18c6f2a525756d652ced436007f513267e9201d8b1c0a40 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=ec0311a0722f205b117160817b2137e9a73f0f4e540930d61c831ceba1265f0d +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=c63c4a28225dfca26baab129f06d8537fae5710083046f203a2fb73c50b48671 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=52eae1bdf37366bf406cff95e5e7979d0651979ae5ad4c036e8badddc8ec8b82 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=542791fb5cd80fe5515ab0812c9fd8671f083151d4262fc76d26f7723ba961e1 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=91697f75c762bdb51f19348953768a45bc37c389c2e904a56f4f092604ed2d1c +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=a79a7a5974b365f70598c413da3db8262d14414e3b4d48dde45f529bca4c6ef8 +dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.gz=6eec497ec2aaf6c5beb8e6dfbeaf32190b6f7206aebffb7499b5fdd7e5e7643a +dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.xz=234924a6746fed2efa112b0b805d0ca56252b6cde82e6422774871e9c009fed6 +dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.gz=1b0cd107412fae22266267bd8eccd2b39a36afa8936da3888d0bd0d2f4cfdb1c +dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.xz=0d0d1ee48f9032df88ea7b3f73f06300686f4d5b9fc16f1d4554caf8356cfd74 +dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.gz=72f0549de44925bd08286e092261164dac47826124123e3fe707411a3dfa756c +dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.xz=eb45acd55dd70be3670de83c8cbef5b6ef05827b3f97b7c71679a19c88f8f3e6 +dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.gz=edd8dadbba618f2a786dfcc68e4a5c7f2b7cf1528d1c16ca6ddbc52622df95c6 +dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.xz=ae59c5d77b31aeac30c22104abc0abda6b7f725419e9f86db6cae634ededf262 +dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz=8996c94269e4c60270d253ea75bddb9482facc441ee2314a387888924bea1d92 +dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz=f6b59e3d6e7f0e458c048ad4aad9a2da23f3b54aeac20a905d2e00379da1bd6a +dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.gz=85f22b148be72691214dee620eac582405dc3b8937d2ef7c480c9070b963af3a +dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.xz=4b48538541dd20fad8569cb3f0994d5ce6aceaacdd8b319d00b0234cefc5c267 +dist/2024-11-27/rust-std-beta-i686-linux-android.tar.gz=6e5ce19fc4cd8cf4dbaca8b31f4032b08ee413ce20f354186e4945efd4e8b6af +dist/2024-11-27/rust-std-beta-i686-linux-android.tar.xz=5e78b98abdf2b7348381863052c109beec025a5f68285ce72e6f6e9245c22ce3 +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.gz=50057f990d1127e7d693b1c5b9539b19262a478130bed51dbc2837d61d2db6da +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.xz=ea524b276e42a1cb918625df12b8d3397ada5ecd43bb9ad5c676747e1f916c8b +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=c7c9093e277187590b86ea02fcd940071c8bce93a894396d73953276ec58eb1d +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a67879ff0dcc591d30a155fd972149953eaac3b139bec9aca3a383dc277ddbc6 +dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.gz=a086c8272f9c7c0db3d5de37b027478dfc22fc577c613254a821700c645df3c9 +dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.xz=8ac4b938e0b643e47d6d0ba6e5283887fcc73cb1a825fc065c35879b085d9c28 +dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.gz=3614b95b54ca24c598e3ed6e14aaa86f7048c2a5be2b3e9f97d9ca00f3d890ce +dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.xz=6d36127f5c113b01300fa0d54062bc1137b51d2514346c8d84bafb9f2c56a972 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz=a6d33a96eeb667f3f4649ea6ccdd6212a183bce85f095ff7db5036c3a50d35a6 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz=bab1dada484d61bb96e2834da5fc6ed5d4d788e6636849e9802f9fb6bff45d55 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.gz=0ac331a1c9e384430a5f316809bffdf01bae3ae9cc1f807f07142ffde7388602 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.xz=136341bbf4c820dfc98e96cee41fa0e9fcbc7d81d2772407efaf1d4be6d10f7f +dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.gz=32f06ca3b2752a8687e2f282a59823671fcec672bffc0775a9fb27da50b6bb11 +dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.xz=b2f376089b39a34f3308833ce9bf65200f9665e5c55bbda3e5b7e9c5096b7e67 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=a2ca950893c93be71c7db707230b98674a29c013546e27d95bdf8c3c6eebf9a7 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c70b58f4583578347e9f0fa20d17bd5fc51d88717095e05d73091209f2a363be +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ed284c40b6253c022e39718dc2af2e4100ca7e805d35d86aca04937586f26ece +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=3efcabf46e0d02505ebf0926c6c14e0c70838f9b510f2328ccd98dd0fa977794 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.gz=9b9f8418fdf64fef652f15b28a1a1f2f8c63c18da8b323994f10f921010721ab +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.xz=fdc673e4b250424c6dafc18a165ffb592aecd7b897e483af8ca54aa145a0e6a9 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=802d22c1c364a58402f9313c6ba2f58b79f3cf3163842a608b78680fa2b3d476 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=dc4932d91d8a2887d309dbd6317d6c41afd083043f44742138ca7c97f60b931c +dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=636b19ca036fc7ddcf358062c98f6bcf31e8c2cd035cbb9dc0a6b96c81217f7c +dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=31f80fc50be95bf665d21fe52b714532ff34ebfcdc0c975bb68f7d2f2cebd0e0 +dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=f2c83275df652bc5b387525e77a1aa30bac31fb301b304ddd7e6bf402e140c34 +dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=41358bdb20fe3a97a95fd7b656b1ed03d5b8012354d8cfad2437bc9ef6c7aeb6 +dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=49b8f286b4abb3b34bd38c92ea3e15efbd1f623d5efa7bcff10711b595363579 +dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=283f065701c77fa47a2d5413d20fa40989fbbcc75bc938889de6c4f9b6b9e53e +dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=d0ee5ba5dd6f94dc6ca981be0d55f2e3f51c2af25877131a7a74e0ab9848dc3d +dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=79c78bb31022ec8e7a3fad9823c5d22ac553d389104844110473d1877d8c8302 +dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b953686e3034f2b51033a2630328c8eb5f59fdf8ef4e26189bddb8efb4c482cf +dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=fb25ac2e68594d379f915f0555b3ded2b1a7b5a67144e12eb62949f540b0d957 +dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=fbf5a16a57de3a7e846389aebe18bc7871f43e67eff39fc9b4744b5a445b2639 +dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=55a92aa5770924a21b706724c15f58d66ef2ca5b630f7025f6ba1416152ef350 +dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=b880b7209ea604761ad2a46832925d32fc547737b879645fd3cf99ec235e7b39 +dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=c48cc6a6fda06fab014c0b8fef49006dd32fb71f8e981ba44a0c25d47fbfe034 +dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=7d133b6c8d0e8b8ec8b65a74ed8d64a22e2fa5e4f6d4a1e36f9e0ebb8826f40e +dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=1c507e003c38115bfffe8701df1ff7aed6ad16ef5ac4b383f84bd2d6aa0216bd +dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=111a909b3d1a04b328ca1c1f247ee4eaaa84349eeaa8df77f7901bbc0efc94c1 +dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d29f92ed071c60259feaa8005eb5392da549f8e2069fecb1b77e112f89cf1bbc +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=241b1ec9ef6a89277944c9d8021f521284dc28822c5f80513b6cd94d2bdd1d64 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=9f5b02be846fa2084becc5616f024094d47beca102442ac7a0e3588e0f12ee7e +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=7272eae1625415c0f57bf541dd62c14e02b9946ca1de04615827a1f5218c2181 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=d4bcd0068d3c9e7351565fec57ca68d36c9ddbfe59249a6bd2c56930ebad2257 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=758ccc47004398add2e3cfef52e4839e14dc4d132a215658e576e590401a28ca +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=6902fee1027b0136f8dc5179e69e24ed9e34366e9409129b9ba223043ddadea1 +dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3024570f3e382a57fce0e832c52d080a83d42206d8412b724361bd1f0087ec4d +dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=20eaa72b6fa32b9884b43030a0bee554bafa9de3f3b51c5768ba0ff47ec492c1 +dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=a3eae70be3fa5b0a56cc88cc6433cdb7c42b3b974caf0d879d21a5219f4f826e +dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1da88d1882d4dd1f15ca97e016f392a01b56951882ae75929023e83fa557d796 +dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=387cc8ccaeed6f9c6a8c9d21004e45ac97a9739643a63448eb893e13ed4df22d +dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=1b9afe3631fb7847b2a8a8f483fc00ca203ccc18ae298339801dab1c7b06b3b3 +dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.gz=f9a4d2115d6fce06e0da7a9f579b197d383034c218573e145b3c7dae0aad21d4 +dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.xz=c352bc631e538d4e68eaaccdfb9dca1c9dc8ff0ef4a75d8ee91016aada39d717 +dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.gz=d97851ca9193d98192a55aeaf695973ac706e6ba3e198643c200cf410817b424 +dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.xz=89a6524a3743e5a769a583b4a6bf8a76ef5b45c67b7e39da7ae24b687bed4943 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.gz=6fe614db166618a8f2ccb5807e02884daa8bd8dfded2164f88d79fc688047020 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.xz=91c5e4f4575ab004119797988679077e5057881ad9a7f6790b673dd062a8b7ee +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d0e05467fb1562ed7d6687a50b7fafa14ba0c2aad328f0e7c19eaca1ee366475 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz=0473372df5fece49e58efcd3b2a702bb93e47ec149b38fd5244ad667804e7c63 +dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.gz=e6b6130a1a571325cc1bda8ddba6b2672104c2feeed5c93c6022bfcc8ba4b247 +dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.xz=d4c739c42104e04aba55b96a3ad434e11b013ba44649dd3a648cfbb15de83eb9 +dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=e427d5d6a53abfb53b436df96457d58eedc648198fce6b1d976b50de18cbc31a +dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=11142018c11849c21adaa7096abf50d0c923f3b8f07d67eb96d6860d428e9b27 +dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=46596d8f2271dd5a6f0f84387ac19d0e81976adfc6050b6aab6cc554102fe469 +dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=f3d0c9db1c50a018540278433fed2e0ae4bc798aa0dac87cf0f55ad1808618a1 +dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c46fc4bf174fc54f5565fa04e80efff4e853642e3e5f0bf5b696a2bd6e7ae817 +dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=706c10ef22cc16b3d4cab8fc09d8783384313b9f774229470b8ae1dd292850b2 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=b9cec80ed374f7b5f22f1446e3f2e0dacfaa0e2d4d6c631ad66cc42a23e156f7 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=41c67ee95e72a3d10bdf739c4841bd937c4e0b19c33451724c1f603b4bd2a318 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=5ad8603f98cff0d5d015c72f3a55730d75d59680a867c067928bf4586c00d805 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=61a75701f7e000f86f318a04dc6746f029fb933e0ea94944d76c7eefca1f24b2 +dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz=89bfbfea23974ed75a53ff134386992e9c257d3e51a55eb49847aec9c5ba6b13 +dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz=e34d1586bc6767b4b244f98754badda706645fdec7168ddc0a409b9f95f2b18d +dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.gz=8a88bb923e138d0015c8f46bc1c3d5f2f5f75f40dddfca72a49eed42c080d1db +dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.xz=79a980f2b999c3e3b04d7e327bd2b548007039b45da705847c6da2bfec3ffc04 +dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.gz=454e2c4b46b4684e591c6e4c0f1ce8e3c44623a29d561be3a481ae008072dbd5 +dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.xz=4dcf652ab51fe03c4691de46365218dc483cf1f7c2f5a552a38509685a0ca873 +dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.gz=c2c34d9b3998633cfa145dc2a5568a99d1fe26b91c5be55a08870a1d27db4af7 +dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.xz=4d5b25e4b5fb71d879f15f320f7513eec1ad078d3ca6f525ebf56b9620bdb5ad +dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.gz=e1385a340d3d9a4003cc456156bfbb1435a5255b2bdae3a40b6d7339768bdc81 +dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.xz=245e7914174d213ddbb550b09fff200f419bcd632de98548a470013891666410 +dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.gz=d5d924ea001f914bf87df8765b013db6e838a930a4865e95f8d35bfaa86bc81e +dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.xz=bb98d0d55f38f2308bf99d4e5f11842683452571075eefa5b4e1f18f2bd553bf +dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.gz=edd5e7ea230a13be750dd74c5f7a7dee20db8683f7978aeb352307a0ce110b9d +dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.xz=c6cec9a501d9873e3c7abdefd5b9418f7250c8cb915be8b816cb48dedf1f201e +dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.gz=e970c2a4ebfb69219dc66e4c7541cf22c52da5f94983c7c914df1f93beda3d31 +dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.xz=594ae9bf5f1501322d986dc91249a48a61c22371513b872fd63e134097ac55ca +dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=d57bf579b4629417dbe1c02506db4a4ba4428871a2684141d21303e6c99551f5 +dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=714db83e7563a5f286fb37bc629b64834a9ed981bb9a05931122072f95e39bf8 +dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=feafcba9c46ba3e5fa0bd9b5bedc05ef3423c9962dc4d25a7b2367e3e1caa679 +dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=78fbc8f45df64dca21da7223b5d081111922f2268fcc4f1f83595d159d310bce +dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.gz=74fb57da7f2907afbaa2a7a73847273ef81e2d6902a326f1ae87767677a864d3 +dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.xz=3216eb73d9c9effcd2a2de7f63d78055c3d7e50fb8141e2910a45a36ce744ffb +dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.gz=3df431c8941ac28906c3a6568d3debe478d9349d868ea8bd3ad79e65792c20e8 +dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.xz=548c2a6104148bf0da21bf5e009b80522fd15539077a62021a64f16282815a5e +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=235228431d67feb4c8e6aad44e20bf68574f335e8f948808b597ae98d827171d +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=5a2d4ed70aed26f902cf45e1dcabc5f25884cf6e9aaff775405ba9c1f0a5cacd +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=818131158e8be6af4b762750f7927c4a799346c94059a6073230da79b4408720 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fc08b39833e2c9319dcb55cef5c6d1f0110aea794c9a6f163ca39749a22a94b9 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6164c3ade38c03113193301b815c52df0ee84a4ca1c8ef21e1a56d386e28df00 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=0846126e6c4cf2b5184979b6025fbb7bddb5c22905bc7ba31fff69f6b1459280 +dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz=ae308e29be13a176b26c142347a81facf8c11ef1a28e67d5898f4f2a0d3344ca +dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz=e80bcba8b011a4dd3f7b2a2cea69b5a95ae2cde9b2d9078ac8fdd492ac162139 +dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b25f0d605b7f4a2a93adb746e32f59bfc26af569a4169e9fb203cb33751d1575 +dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=010f35236062a651b1b54d7c928068efca8dc486856b84b04e98f4f97583bf32 +dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.gz=db3d258c2caea73b469feb9c11fbd3bcc29d22c3969c406321d11f05c24974ed +dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.xz=a952b0c2bbed9085525c041c957f00b6b1020e031149dba70c09a1a0d40db3ad +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=817d3d3a931eba2255bd5721435cba7604fe37a72c18a179c1fd5f06dc3b97a1 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=170a54aa50f161576d4b0d103f2ab6dcbbb81ee57a5a47f7fbd181128f6c17ff +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=ea991dce55415ed7462abbeb1ac1c70795cb628b0460e14230e8cecd41117fca +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=a8f620c3a641f8f4c29d88e4cc54d7637aeb18cf8eaed8571ce558835f742601 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=875e2e3309b1deccc1a4476e4847a2849df32e0e2a394e4ddf3b4abd1feca534 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=23f21ac664b3341771109ac69d094518a512391b86219ffec50725dc68a08504 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=680f5b2c63f58643bd34f9921e2c1699a549410ab06bfd04ce991907e8fd7d8f +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd10f6f3ce39489b6e3f3f638573e850c36518e3b2e8ffad0c50c3143e3a8124 +dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz=fd31ba490f0bfc53530e34e6e5ab35a52eebee616efc8ed18d473065ea885230 +dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz=daffc01050f5cf0b5ece91717d7a4c42cd4a148c4c11f641b494d9c375df5177 +dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.gz=376d571641a9f1f75fadf951da91bb73ba94a5495d7d33389f5f914ccbec57bb +dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.xz=ffd9e826537dc94c6d8e767ef5a61d1fcf0385b8ccbe508ff9177de0fe772939 +dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.gz=447e434b5e40f7882d7adb6d0346629e0e3e92d0f339c7781e5a437898a84b4a +dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.xz=bc21caabcb492ca648e19a8f3b9dc1a1bf7792135a202831deb554ec3ea11077 +dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.gz=40ca7d9ebcf6610c26f2921c0560729e708f5661bf6167266e9d8cb3987ad0b3 +dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.xz=06966d5901f5d9accadb47c4d1e561f3f95bd050f3f8e78f30000389f39e9b6c +dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.gz=e1a24f081ddd93b483c0f1c196bae676163db50fef0a994bc47c2a7c98c9dfa7 +dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.xz=d51a5f0669906eceeee4e09b079828e2ebf3404aaedf1fb20745339205270ee0 +dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz=e135a5f0f83432b58d9e093c6d560b021a133707e39e1ded90a28a9967105e0f +dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz=1fbe65015cb8c7ab0b863ffc6f7aa72d3bf52f7830957ede8915c61a22e5b993 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=9d4e830e9ba582302865fcefe31883cef4a471e77d46e70838e549ca11a0fbce +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=233f6347a36e806dcf27ecad4906c90bb3353051f440a819989efcf091cb78b8 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz=6cd719a7255a0eb1f11592b9a92d0aa4986363f624ee0d6077fcc253acab66a8 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz=b874ca8285ad1936adc70a9323cf80f06322b1e6d5925f54b58500129830f0ca +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=ec7200319224ccabe814cb051e51d147f1ae8c763413002fd03c9263a02c2320 +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=86e96c80a91862e59123272c80f1cfabdca56bfddcd66af4a5e840af7421c4e1 +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=3f7cfdcb28fe8c3f0dde58c24a0c424652b40d00a24fc50891351fa5bff5c15e +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2d5a184b0103ac943ec4f6756fbc7126773e739e0d120acea7b3244c7cd19b1b +dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=9a77540943f28584d90b4bcae4e234cc9d833eb732f65d7fbd680a0f4e915da4 +dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=7696a065951b7d7179b30ff2fd16a05675b6bd4250f293666b98ec05299113a5 +dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.gz=eaff75076ad71a4291af5465dedf0fb0998dc171e35ab8f707ac63b43e89c38a +dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.xz=205d3d19726a1a87a1533d94f77b73ed9de8181906acb48088dca22835aa7a83 +dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.gz=58da319889533ff7be5c9142c2abdd1ade79de10eb83d7ef82ebd93b75607f8b +dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.xz=5ae699d0f6b9e210a988af5b8f2f0c4d62fb1695ed6fa55718fdf05298039b9c +dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.gz=362f6338ea929ceb632307031e049dee1b3ed998f5cf160654c327c5e0e7ed39 +dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.xz=88f14ca7b5c8af006f3c54749b61747485f7e93fde4c65b5969e73503d12c5c2 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=9ee8f29e3e715cd7c85e679fd01ca724a27503a50edb0e6f8912f289630bc7a5 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=4c643f0d18ba101c2b248e1df32ec3ddba82efc0d5f9b47945d484fd3d462794 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=f70952c63e2eebd05acc326cfa667595535fc36db34bc0262fda4ba100ff2145 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=0546a908cc12884801c35b461f98db01e87a7f92d276ca6cb6b89eb76c596e2c +dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=3534e839b34603e4e2b32fb8ecc76163ea3b9cd9907c1a22fde4165860d1fb56 +dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=b402a2e73debd81dc5cbc866f00c2ca82f676e2f923193674969af0ab34ad311 +dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=fa69011557fdde5af1f78f33f9ba75a1d6f4488b9d8edd2958582593dba347fe +dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=679be0bf62c7371b92f1824c8718662672ac3ef2d79e8af5c752fe34effbe333 +dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=ecc2ba0da5c1057136eb105ec0727e55396e414d75efe0c2b96bef0477961574 +dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=a89ad44842df861c69c6633ba79bf4ecefc38419d5669b6f22a265dd7be836f2 +dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=051437ff7d177bdeb7a5a0eb947d27b8cf352c8e809b9311a1cc21b785a5a8b5 +dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=1a4f50972104a95c404e778279a4acd42176cae45f58d316d601e7f38dc7bbc0 +dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz=bbe9812fe890b900e71aa4714dabd2f3e67bdc610fe0bbd5aea645ee807dd0ff +dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eebac7e8555f44ea9094750b61bd11d758197a72d4d436e1713e4bca42fa8080 +dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.gz=6773b94f012a3d3589e2bca28f35dd23208fb245f107e4a17b8b3e7f893c038a +dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.xz=d3a20dbd60545b0162dc06499317e342bea077cff369e053eb89e85e2b640188 +dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz=39e16c97c0b22533dfa674d6e8f5bf5df256e2b426d02dca5ed33e246f18d05b +dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz=ffd939f901c64a17c3f24fc69744cd2af1c176a45d8e5fa8209067ada403db7d +dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8addc12e74a983f3166b89d1d53ce87c92f38c7c3a62ec7c66580aa424d20516 +dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz=8e5622917395ff50e53b237e7322f1faf2b64f0446c41ccaa0096e57a3e7de69 +dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.gz=2734d099aa1ada79346213aec8cc7ebe40312df1dfb40a32d09ccd3b6622e025 +dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.xz=642edcaf16dd74c0935d28ce9b37cf1c5ecb9c03bec30f6ff0e7476760ae7ca2 +dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.gz=4f28de38005de48db7126dcb698b748063341de41dc71175605301837a3f7336 +dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.xz=ce18692f99780ec09d01816277ee4e71785bdfbd7abb4375ba8d87c1b6905ffa +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f1d692c3a1c280f34de167ef26af3c13a6d0a3b5ae4fb86b0a9f2178c3287a94 +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=21f477af2b49ec8809bf8bc7b4c4919c7d2ac57782b829f5a0d9ef1967c5d71a +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4bed61be221c1347b1649f54222b27e2a3577b84816ce1099c9f0f461c6e9e5a +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz=33f463209d50ca6b04a8953c87d2177a84d1729d635de9a7c9b1a711ccb5d751 +dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.gz=ce46b5b2d767cc0d790d8fd21052ecfb787dffb4218a238a339fe5f1afd26d6f +dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.xz=0afd0489cb4231edc5bc1ef24a43c3f1918f681f08c1207d184fefdb46416509 +dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.gz=6e5f1a85dad2b899567369aceac0102943ab807dad7e218c273b7b4d6393dba7 +dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.xz=f784ac4a6ab180675396adf8256ac2bf2d1e823bef106d1c6c59911a8360692c +dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.gz=22f1e9299a24aebaf9a32471ddc6cdbf856b455d059ca077170aecf5989f8772 +dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.xz=7f3fd047ed5aa85ea6ca2b0d6103f7530d7d070c93b0f212c9d1a6491f160cbc +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=f383ecb5cd654268f00be1f577572993c38e7386a1e1d18b864338e87c7b2b42 +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=b2043facf587f98a8f10a92ae129b7f608297709f4ac61d683b7c813cc65e41e +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.gz=6678d45195bd2a7b27ed2d4bad3790e6b63e376da71d112b9333760ea375c40f +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.xz=f6c77e80c9ea4e312fc2715a9f66ea9a2e6344e3f04ab96cc572e4c0e8c915db +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=be8c0dfde3f09bf476d6600b530aa498b01415015665429bebed8814c7568b73 +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=4315f7623dcf0a278cccb6c8b397a29f83f70ecb9b03588f61e383e5ebaa697d +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=c31ff694c68f28e0f462133e783a5d732cf9c539737fc8dbbfd01a53e9a456c3 +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=2553ae5596b8273d8a61ec66d2e20d0c9733c9f791ca5c56217c60884f0ccf9a +dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=1842cf2c26ab474df47e74720c56997e270b37609f840ac50ab0b05064cb38fb +dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=e882b1cc2814e3c97c33991fa0a80de62556ce8f4f88307f6338a90be32b045b +dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.gz=7c6e08b841f21e3b8953e51a6a9fd9df0c719e8defd7b1ab0660d8920fe72185 +dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.xz=137aec194877446fec994a233427db419bb4f2910151c456c3ec80d9329628e7 +dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.gz=52ba38277ac3f80d124fdc8dd1709b8c1115cecfc53fae4731da8615a63f78cb +dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.xz=548d3eb599334ab98791b8ba27decff8b0de98dfcffadc994ad38aad6255cff5 +dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.gz=448071394d5e647e8da8f64cfbf85e8305d85ff9357dd24737523c95eb339ab3 +dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.xz=e25daa6264cf5e0a7cbcfd827e27a8e276c29c88c86cc15977c1a1650d0303f9 +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=9f080cc937e7209ad83fdb8bf4b2cd7b080af83dbd9061229f154785e273bfec +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7d537f66195c581ff51ce8f53c4687a762daf225c7f0ce76393953ab04b804e1 +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=2bd38261a9ef33ad687b3edcd33f283c32a493a80b56dbefc822c1116edb1f2f +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=7e63dff1d8abe517aefeb4b1976932d23a9a7ed5e4db2398d8ba2659301f639c +dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1495b2a49cfce014da72beb691e6c477d189ef34080acb1761b588d11b75d27a +dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=75da94f1ade2ef48674b77ded595c69ee715f62f9d9dd96e72039e27807b7314 +dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=2d6b826fb4d3d9b61ecd3aaffdd1334f766dd5a5fb0d8279e0de26d381c5cbdc +dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=f5ceaca2651d6002f232f71809458ad912bb5f00030790e907ff7b0e12c9e0c1 +dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=1a62f307197c6fd08fbeabef89f58842cfd59c6d62f530850592fe55852d61f7 +dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=4c65fd6a5d74527391fbc7c242a2313e5290209f5a15763d74eeaa6cba0a0ed0 +dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=8ab9f735a98de1949e65d51c3050b29ceba3ddc28167ba0180353253dc726392 +dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=0367eb23a9349ebd829d59fe0a2638557c8e57205e48f66a701b238461385bf2 +dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ffe9100ec6b81b081d5f9d840bdf01c658790d7e6bc0674e5ebb6b28f79c2f7f +dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b19b1b28bb7ddf8cf977f102acb623f65d5117c44ab8b62cf197f2d3d33c15de +dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.gz=d986de5c01bde3469693dea7cb4248155ee9791550aa179d601066d27e45afb1 +dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.xz=8000e46ccc2598fdb770c69c68aeb18d94db9b2847d0509f7a9c51ef28714ba7 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.gz=c701581f28d885889ae5c845a7b34beebb04a4631c2740e9333b69390cfaf499 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.xz=fc285792e6f626e133edede613a9a9a90ee12191765e2f0beac642a3b3c9ca12 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.gz=91afdb71bdd54e5c04fc7c933dac06d5e769627e886e20eb712524e852a01966 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.xz=2ef7018c7319e3a299c5eddf36748d9d293ae43eaf54662d9855fd211eb4658c +dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.gz=02234d4c47478112e01d51bc7dd48cd467293e1eeba55bd383d08bc7376c471d +dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.xz=a3e6a0c7f31278866d97816c5ed434b1987e0bc5a89b24283e836402803c1388 +dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.gz=b238ab536ac963929884da4dc9bab43679e6fa9aba4251c73ab7e5cbe5d8eeb9 +dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.xz=797ea7a7643a8302e45347f21c4dc6bdee617c2a9d9ccef74ed525c7d2e9dd91 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=d630a6b25a08af85d3d426e73d3231e018e0ab7176a5934572786147fbbf3823 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d0259a0112f452ee49b8c9bebd760ab8945e5bc3a0d57b1cdc2b8e24accd35c7 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.gz=5febe478e5040f0f74a14c23e78eed21b080900d875d6b447354945c07677a6f +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.xz=552c35bbe76a83439e66cf9ccd522d97e43a8fe4f6aadbabd1f02c4b2c1814dd +dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.gz=ff6db2d7b84e1b01c81e494de15ccd07f60fef6dc60fa46d47e128ebaba4022c +dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.xz=b27f89b175bee3769dab1c2d0c54f17ff3efba2038f3b600f4077435c7fd21d3 +dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5b5015483d0a98e9dc715c3cc8c23598c02fc14ea6e5878790ae68f2f1c8ef46 +dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ce5706f0397a1b2fd9e17dbf34ccfbc3e8c87cc81c92b54b81fd33accc2b7c06 +dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=3f5077c8743b5c4f233da7d0aa0aa13fc488ef0fa9da24b002bfa413d52dc845 +dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=087eb30f24ba7d8ee42e28bce2a6cd75e5fb7ef5dca8a738ef23fac82ad59566 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=28a716ef9c5318543559ab4c0c2d062b0deeab1ecec80d5d83ad5effb574f209 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=99cf9ec4b7bea4281f64a613784350a8ac34e9b0387fed7eb26d6f8c21c83735 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a23c3de89603bd4d1035a267e6ee456c6de12efa4029d76ded3edf7c69285a15 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=462dfd28b631b5a6d8277920cfa8037d8583cbf6a2e5c9159c492161013e820a +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=44af5b13726cab40865580df8bc05182a2359eae64e41a92f84790ef55ca6bdb +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=0a7c0b207e745d01194d96f0fbe2402273d630d4f1aa05001a5f5371c9585a2c +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=66e2fc688b8f746d15c0dce042f2a94e06c5b652d5e0b6534d9e992eec186784 +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=15a2e087f7b482fa8c027fe6e6fbaf846d784c8e917fed375048a297d5e13c45 +dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=71788ea2544f8349ec548a2f150dca2afe80a49deb91c00c46484a5e3039742d +dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d9fa7b780b9d8b93549abf0a3f0e6f31cc8e1e991ddf682adf3b616fe2a1f0c8 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=30924bad51ffa62f762d4c000f86ea3457b590f6397d65755c711ff7f77ac129 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=14fff13942e6a65927776c49013249b2e75aa3a630667ecf49c9ba721e47bcb4 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=02d82688bdf3bd3c261a4a6d4acfb07835e29ce262cdc3165ba849a6a8490bcc +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2a19b55bb609542ec49dea87e3b67532e5d18df8be43d0ad775bb34f4f9f96a0 +dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d07ca0ddfb0dd89a9cc935b2b9662379bcc9503cb28a28d68c5165f787a7d762 +dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=de8106801b1e49dfd8a4fffbfc2a4f949218eaa011ca2085953ebf2a5ea9b141 +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=309024f86e80a4568721b5bb61aa936e027accc251fa97acd5043b513b325576 +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=55bf234aa2ec7fd4c6a7179f779d790e7f62969967519bacfeae84db5cd29abe +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=4bf9571182e7ef40e76c7e5905fab8ac35269ace390f5007480b4951f80cfa3b +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=2a2cde80fcbf68768ba7a99cb059a0cdc9313ad0c934383dde9598d6147ef756 +dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=b747fb16b15cff3f9368ce1a1f5cad0d2930bde5a609547a3afa2679d7ab8a1a +dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=b861f8361ee806d83f38afbbbf312e0e5e4d8851e7048444c409de1a83484446 +dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=ebe56700ad0948e4dcd9930730f7df8e01a5eefca1d1157fe12160d782e2a5c0 +dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=5081c9b8677314464d8a3a50220809def18badb2269d2cd8b7106f3547b0e25a +dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2ed9094b538b6450371311b742f2d309a1f40b2b4c84deb9867059336b76d1b0 +dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d9d52d9b9f4da7a457d05dd4645885d092f170bd2f751a49b4ab3b88395a5248 +dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=a2e51d381645c6bf18502ca72fe9f10ffd309281dae87ec16c5627f232f77e50 +dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c526efc054c33a08626b882eebadf887a9aaf8fd60a4adf6a146659a7c1ec8d7 +dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=04e5b7c97b57ff7d967abb4f98374f0833108c04f6edf482b8b3fefbde340956 +dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=1829afdebce1c3fe249f81958de68c765db18b431927e54fc42be37ea4ab8226 +dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz=d6cf138d02e50168f8ee4a89abb2a4a39e19458d060d7b46cf227bba1fd4c0d8 +dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e8185262c82c064c4bb9ae6f1d3072819410de9cfca943b77605012a546c254e +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=64d78f9f05a978b95b9e22a63bbb31dcf98152df5638f498a361a96d9d2b0c04 +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c07041ab84364ace58a357c18b5c4dca037852e1159edabb02f4579ac6853b4a +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=7ef0122ccd3a0c77c917bd75e93358eb95d7e87d78a165c724e3f0cd90f8209c +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=d0d0566a0a50e1e9e7f4251cf207bde82d96c27016f0a0acc364754561ab4881 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=e4854528c31316894339bfa97b07ec607e8956877c285778e555885ce9c8a068 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d79c9b352ed7b2f132f06dcdf360527502b2153beb09cca968a5ced521edcd39 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=df76cbeae0a61506a29db22e8743d16fcd97ef2da216ea15bf4d6cd709814017 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=103cbb30bbe92da6666d84fab53dd7fe8105c2ebe62eeab5f6609488e62a481b +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=5f3c61663a319d6162240192f387e10ab87e2a972062198082158a243b667d7f +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=221b45c3928b1c45fedbeea987ad80750d3f55fbc564cf3ccf910a68447ad725 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=18eb24fd665ce1cc4ce66b37b19c22397bff9369963b127137780870c179228d +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=bcd09587a21ea10953a14521e9e0ba7b5100e8e15b6a10cc4e7bd359200d5279 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=db712c5e1d21231770e12dc95f6bcbe2f1d04b9cde61bc7adf8b529b41773adf +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=43303e426752dcd15964416822cdce0e5f3012366a9b77f3d68e6011c7bacd0f +dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.gz=95d543a835b11cb5ccbf0578df1ce4e1846e4915622d23a36cc6e18e44e17f29 +dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.xz=db9e0c51c35c81c2ec8be0838f3231f7374917215792ffee159e3d7ffed855d8 +dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=bf9b83d6418bf97caf2df70a8e8298cd8fecb7b950cdaaa2cecbec243ed57c74 +dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=bb520da5b522fffb5a20eed4390990c2ab9d22eb4f77196535a84ae7a434c9f5 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=4072d9ca2d617d09d394139c0b8608bb8b2b8b2b4fa450f13c41975a16a791c7 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3d75a8a534e86bb55b63f5b5b2df66ae47862cb7f3ecd1591a829435031d7279 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=3cf05e90bc1f95e92cca4769f74055245234037009cf464df3062238c88bc2b6 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=245ebb7886cfba64d667630ca8bd672520cfece0ccec3b916e3de0f26aeada52 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=dadff4abd2f169f9aa1910d4ea247b7d1f767fca74238ad31485b73399ab6dda +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=ff97e1201e9a305673e8a9b740b7696cc4cb5e86bfaa3e137cd8e3e28cffd7a6 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0c411e0824140323f51600d387d52bd01f601f5539d6457815e950224a6d29a4 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=dc5731a70c393f69555433d522cde8a52893bfb88beec519c1bbb03b2a0e060c +dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=01ef2f07f1222fbf3e0cfc5b957c287fb886fd0bd08cbf18f90dc37fb0b63541 +dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d45042b3ea0c0ce6befea7bfdd731e890dbd1f47d1992fe8718a1363f9f18779 +dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.gz=5437da4c0b73d203789829512d856a66c1697d95afb1ffeaa6347ad0f7c04672 +dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.xz=a7cb4cb627d75de1ade9211d8ea489ada9ac76ed38909751861ef0cb729dcbcd +dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.gz=fd6ee6fc171459092e5e8a012d9cfb7491313e021d1c38965605836b5b101b0a +dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.xz=314c7cd558a3654db85d75b3ed71da7cfec3614e4a5f2c449dbc6663b64c7e3d +dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.gz=7a1118011b11befb7df2df57e4450c7611bb3503b3b3cfece9c9c7d4a304391d +dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.xz=2cb95208e77546bcce56d8d5646c3fb5e49ed711894926cb50903ba10431a36e +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=4a76c4493e5ba19aaf14947a6c2e28ebfc7f2da530f1441a9fdfa328e15ea4cf +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=9b361904c691e17fbf44d80c7f7789511db1d8f251d65ba9cf6fda7f06fd495f +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=e89dc76ab061ae23081aee1619fcbf4a94e3acefef6b9b149231f3e1c22f9ec1 +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=11266d557e6d1d9155e6f04f65e4815cfbfd9f8e1aaa47221030e3ff11b22f78 +dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=30f2eae1b8694607a04c836f750b4b7c204e1e14e52ec37885b9a821c2c9646e +dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=495316e70b26140c66b074e9d7f714ab949f422c2635cab784a5e133538e4bb9 +dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=ca560c4fe28051573d54f512652ac9740a2d1111aeb8e36b004a6ff9c325925c +dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=1191f15bb6da98b01b43f0e9d7f51c5c45d38e3c5be2b4ae5f7c0c8fd25e9a90 +dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5f85829aaab919fa4b2fa5ac843b87358e8da4797adbb6eeaed5be02666ce964 +dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=7c671d366fec561f0b568bfb4b6a08a6071303077a60f76da1307453e51ebc36 +dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=300307ab6cf88afc4312edaa510769e901598492deec4834176c6fc9f3eef6cb +dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=6fcf91c8679f4963f7d510cc8afbc24a1070b25ea6d20d5d31ad78ea659da194 +dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=ab905f6f3119648c83a2f37ebe1a55b7899a5ac6d10070e4dbbfb89762a369af +dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=13688b6857c8b10f7fb497f07c969d406cb6b76869957b5138f4b20fcc5d7c5a +dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.gz=e6bb782014e34fafdc5dcf3aeb407eb636d822d346c5a8c6227cc45bc645561a +dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.xz=6016ae620deddc42d1d6b6134b0164dab45a204089754b73db41ec837aa88a84 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ed3a381858612e25cacfd89c08496e9d06378d593ccedea4217ad4fa1ab326d4 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=4819bb9c25aa743de7ab7e93b10b30336a87f1f75e5122d578df2c83fbc59850 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=404aac87c77871c80f83cd7c59390af9af704ee468f40eba68d224d23e2c84e9 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=0e1e0d2454ad24fe1da2cce2dce425bc1167bbca68832da2476c7996c00ba612 +dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.gz=946d5bcc3ac0b83fd0b53b60290a6361b179f16ba2aa6a2467789ad520278792 +dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f3bd1a053399ec89dccaa7456da41d54a8e91deb5c628e4c502fdcf34c5fe780 +dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.gz=c353588a38705b7ae050d4b9868b6c4d3527295edbfb25c115b22cda4912be1f +dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.xz=a71d8b2b42f6cd522da237f99492ed59cd34ea8c86fc1e73c8854c8234e1c980 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=5116b949572fd6c7b11a079d9453b15a4c48562bce22b26d82b7050da772789b +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=3635df40363273d44c6f8182f5f6a3a099ed55897bb764cab2565363cd31c1f4 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=5233af0b907fb7b176d2b5fee07c486e92dcbbbab1d54a60d814a827befaa984 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c908cad6d28657f1fdcbe9d84ecb86f247c75134803dd5273ca24c6c68a58f37 +dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c799165c319218a2fb4cdc0ac8db87fc9e2992a8e402d984ea27938a5ad1c5af +dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.xz=ec12763fa5d4cc150f663361cd245c30835e05e3b1928898b1b7300de559468c \ No newline at end of file diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index dd3124ee9a3..61efaa3bf3e 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,56 @@ document. ## Unreleased / Beta / In Rust Nightly -[0f8eabd6...master](https://github.com/rust-lang/rust-clippy/compare/0f8eabd6...master) +[aa0d5513...master](https://github.com/rust-lang/rust-clippy/compare/aa0d5513...master) + +## Rust 1.83 + +Current stable, released 2024-11-28 + +[View all 64 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-08-25T09%3A59%3A01Z..2024-10-03T13%3A42%3A56Z+base%3Amaster) + +### Important Change + +* Removed the implicit `cargo-clippy` feature set by Clippy as announced here: + <https://blog.rust-lang.org/2024/02/28/Clippy-deprecating-feature-cargo-clippy.html> + [#13246](https://github.com/rust-lang/rust-clippy/pull/13246) + +### New Lints + +* Added [`unused_trait_names`] to `restriction` + [#13322](https://github.com/rust-lang/rust-clippy/pull/13322) +* Added [`unnecessary_first_then_check`] to `complexity` + [#13421](https://github.com/rust-lang/rust-clippy/pull/13421) +* Added [`non_zero_suggestions`] to `restriction` + [#13167](https://github.com/rust-lang/rust-clippy/pull/13167) +* Added [`manual_is_power_of_two`] to `pedantic` + [#13327](https://github.com/rust-lang/rust-clippy/pull/13327) +* Added [`manual_div_ceil`] to `complexity` + [#12987](https://github.com/rust-lang/rust-clippy/pull/12987) +* Added [`zombie_processes`] to `suspicious` + [#11476](https://github.com/rust-lang/rust-clippy/pull/11476) +* Added [`used_underscore_items`] to `pedantic` + [#13294](https://github.com/rust-lang/rust-clippy/pull/13294) + +### Moves and Deprecations + +* Moved [`ref_option`] to `pedantic` (From `nursery`) + [#13469](https://github.com/rust-lang/rust-clippy/pull/13469) +* Moved [`manual_c_str_literals`] to `complexity` (From `pedantic`, now warn-by-default) + [#13263](https://github.com/rust-lang/rust-clippy/pull/13263) +* Moved [`empty_line_after_doc_comments`] to `suspicious` (From `nursery`, now warn-by-default) + [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) +* Moved [`empty_line_after_outer_attr`] to `suspicious` (From `nursery`, now warn-by-default) + [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) + +### Enhancements + +* [`missing_panics_doc`]: No longer lints in const environments + [#13382](https://github.com/rust-lang/rust-clippy/pull/13382) ## Rust 1.82 -Current stable, released 2024-10-17 +Released 2024-10-17 [View all 108 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-07-11T20%3A12%3A07Z..2024-08-24T20%3A55%3A35Z+base%3Amaster) @@ -5441,6 +5486,7 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 50a2afbfc07..77cb0006ff8 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy" -version = "0.1.84" +# begin autogenerated version +version = "0.1.85" +# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -27,7 +29,7 @@ rustc_tools_util = "0.4.0" tempfile = { version = "3.3", optional = true } termize = "0.1" color-print = "0.3.4" -anstream = "0.6.0" +anstream = "0.6.18" [dev-dependencies] cargo_metadata = "0.18.1" diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md index be13fcbe260..19328fdd3cd 100644 --- a/src/tools/clippy/book/src/SUMMARY.md +++ b/src/tools/clippy/book/src/SUMMARY.md @@ -7,6 +7,7 @@ - [Configuration](configuration.md) - [Lint Configuration](lint_configuration.md) - [Clippy's Lints](lints.md) +- [Attributes for Crate Authors](attribs.md) - [Continuous Integration](continuous_integration/README.md) - [GitHub Actions](continuous_integration/github_actions.md) - [GitLab CI](continuous_integration/gitlab.md) diff --git a/src/tools/clippy/book/src/attribs.md b/src/tools/clippy/book/src/attribs.md new file mode 100644 index 00000000000..cf99497bc0f --- /dev/null +++ b/src/tools/clippy/book/src/attribs.md @@ -0,0 +1,53 @@ +# Attributes for Crate Authors + +In some cases it is possible to extend Clippy coverage to 3rd party libraries. +To do this, Clippy provides attributes that can be applied to items in the 3rd party crate. + +## `#[clippy::format_args]` + +_Available since Clippy v1.84_ + +This attribute can be added to a macro that supports `format!`, `println!`, or similar syntax. +It tells Clippy that the macro is a formatting macro, and that the arguments to the macro +should be linted as if they were arguments to `format!`. Any lint that would apply to a +`format!` call will also apply to the macro call. The macro may have additional arguments +before the format string, and these will be ignored. + +### Example + +```rust +/// A macro that prints a message if a condition is true. +#[macro_export] +#[clippy::format_args] +macro_rules! print_if { + ($condition:expr, $($args:tt)+) => {{ + if $condition { + println!($($args)+) + } + }}; +} +``` + +## `#[clippy::has_significant_drop]` + +_Available since Clippy v1.60_ + +The `clippy::has_significant_drop` attribute can be added to types whose Drop impls have an important side effect, +such as unlocking a mutex, making it important for users to be able to accurately understand their lifetimes. +When a temporary is returned in a function call in a match scrutinee, its lifetime lasts until the end of the match +block, which may be surprising. + +### Example + +```rust +#[clippy::has_significant_drop] +struct CounterWrapper<'a> { + counter: &'a Counter, +} + +impl<'a> Drop for CounterWrapper<'a> { + fn drop(&mut self) { + self.counter.i.fetch_sub(1, Ordering::Relaxed); + } +} +``` diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index 963e02e5c16..c07568697d0 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -438,7 +438,7 @@ need to ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are required, just use the one with a lower MSRV. -First, add an MSRV alias for the required feature in [`clippy_config::msrvs`]. +First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`]. This can be accessed later as `msrvs::STR_STRIP_PREFIX`, for example. ```rust @@ -517,7 +517,7 @@ define_Conf! { } ``` -[`clippy_config::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html +[`clippy_utils::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html Afterwards update the documentation for the book as described in [Adding configuration to a lint](#adding-configuration-to-a-lint). diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 670b5cbef82..275d125096e 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -895,7 +895,7 @@ The order of associated items in traits. ## `trivial-copy-size-limit` The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by -reference. By default there is no limit +reference. **Default Value:** `target_pointer_width * 2` diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index d21df202dca..3f18a0bc7d2 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,11 +1,15 @@ [package] name = "clippy_config" -version = "0.1.84" +# begin autogenerated version +version = "0.1.85" +# end autogenerated version edition = "2021" +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clippy_utils = { path = "../clippy_utils" } itertools = "0.12" serde = { version = "1.0", features = ["derive"] } toml = "0.7.3" diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 600d5b6e2c8..41b56b45d9a 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -1,10 +1,10 @@ use crate::ClippyConfiguration; -use crate::msrvs::Msrv; use crate::types::{ DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, }; +use clippy_utils::msrvs::Msrv; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; @@ -181,7 +181,7 @@ macro_rules! define_Conf { )*) => { /// Clippy lint configuration pub struct Conf { - $($(#[doc = $doc])+ pub $name: $ty,)* + $($(#[cfg_attr(doc, doc = $doc)])+ pub $name: $ty,)* } mod defaults { @@ -678,7 +678,7 @@ define_Conf! { #[lints(arbitrary_source_item_ordering)] trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(), /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by - /// reference. By default there is no limit + /// reference. #[default_text = "target_pointer_width * 2"] #[lints(trivially_copy_pass_by_ref)] trivial_copy_size_limit: Option<u64> = None, diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index 1c3f32c2514..5d6e8b87516 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -13,18 +13,14 @@ rustc::untranslatable_diagnostic )] -extern crate rustc_ast; -extern crate rustc_attr; -#[allow(unused_extern_crates)] -extern crate rustc_driver; extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; -extern crate smallvec; mod conf; mod metadata; -pub mod msrvs; pub mod types; pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation}; diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs index fe576424148..c949db9109d 100644 --- a/src/tools/clippy/clippy_config/src/types.rs +++ b/src/tools/clippy/clippy_config/src/types.rs @@ -1,3 +1,6 @@ +use clippy_utils::def_path_def_ids; +use rustc_hir::def_id::DefIdMap; +use rustc_middle::ty::TyCtxt; use serde::de::{self, Deserializer, Visitor}; use serde::{Deserialize, Serialize, ser}; use std::collections::HashMap; @@ -31,6 +34,18 @@ impl DisallowedPath { } } +/// Creates a map of disallowed items to the reason they were disallowed. +pub fn create_disallowed_map( + tcx: TyCtxt<'_>, + disallowed: &'static [DisallowedPath], +) -> DefIdMap<(&'static str, Option<&'static str>)> { + disallowed + .iter() + .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x.reason())) + .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason)))) + .collect() +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] pub enum MatchLintBehaviour { AllTypes, diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index 952a8711fb4..d3a103eaf4c 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] aho-corasick = "1.0" +chrono = { version = "0.4.38", default-features = false, features = ["clock"] } clap = { version = "4.4", features = ["derive"] } indoc = "1.0" itertools = "0.12" diff --git a/src/tools/clippy/clippy_dev/src/dogfood.rs b/src/tools/clippy/clippy_dev/src/dogfood.rs index a0d57f5ab48..75a4cbd2f92 100644 --- a/src/tools/clippy/clippy_dev/src/dogfood.rs +++ b/src/tools/clippy/clippy_dev/src/dogfood.rs @@ -1,4 +1,4 @@ -use crate::{clippy_project_root, exit_if_err}; +use crate::utils::{clippy_project_root, exit_if_err}; use std::process::Command; /// # Panics diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs index 8c61c35533c..c6673859282 100644 --- a/src/tools/clippy/clippy_dev/src/fmt.rs +++ b/src/tools/clippy/clippy_dev/src/fmt.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::clippy_project_root; use itertools::Itertools; use rustc_lexer::{TokenKind, tokenize}; use shell_escape::escape; diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index ad385d5fbd2..9280369c23b 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -14,69 +14,13 @@ extern crate rustc_driver; extern crate rustc_lexer; -use std::io; -use std::path::PathBuf; -use std::process::{self, ExitStatus}; - pub mod dogfood; pub mod fmt; pub mod lint; pub mod new_lint; +pub mod release; pub mod serve; pub mod setup; +pub mod sync; pub mod update_lints; - -#[cfg(not(windows))] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; -#[cfg(windows)] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; - -/// Returns the path to the `cargo-clippy` binary -/// -/// # Panics -/// -/// Panics if the path of current executable could not be retrieved. -#[must_use] -pub fn cargo_clippy_path() -> PathBuf { - let mut path = std::env::current_exe().expect("failed to get current executable name"); - path.set_file_name(CARGO_CLIPPY_EXE); - path -} - -/// Returns the path to the Clippy project directory -/// -/// # Panics -/// -/// Panics if the current directory could not be retrieved, there was an error reading any of the -/// Cargo.toml files or ancestor directory is the clippy root directory -#[must_use] -pub fn clippy_project_root() -> PathBuf { - let current_dir = std::env::current_dir().unwrap(); - for path in current_dir.ancestors() { - let result = std::fs::read_to_string(path.join("Cargo.toml")); - if let Err(err) = &result { - if err.kind() == io::ErrorKind::NotFound { - continue; - } - } - - let content = result.unwrap(); - if content.contains("[package]\nname = \"clippy\"") { - return path.to_path_buf(); - } - } - panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); -} - -/// # Panics -/// Panics if given command result was failed. -pub fn exit_if_err(status: io::Result<ExitStatus>) { - match status.expect("failed to run command").code() { - Some(0) => {}, - Some(n) => process::exit(n), - None => { - eprintln!("Killed by signal"); - process::exit(1); - }, - } -} +pub mod utils; diff --git a/src/tools/clippy/clippy_dev/src/lint.rs b/src/tools/clippy/clippy_dev/src/lint.rs index f308f5dfdfd..125195397e6 100644 --- a/src/tools/clippy/clippy_dev/src/lint.rs +++ b/src/tools/clippy/clippy_dev/src/lint.rs @@ -1,4 +1,4 @@ -use crate::{cargo_clippy_path, exit_if_err}; +use crate::utils::{cargo_clippy_path, exit_if_err}; use std::process::{self, Command}; use std::{env, fs}; diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index fc15913354c..56ed60256f1 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Args, Parser, Subcommand}; -use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; +use clippy_dev::{dogfood, fmt, lint, new_lint, release, serve, setup, sync, update_lints, utils}; use std::convert::Infallible; fn main() { @@ -23,9 +23,9 @@ fn main() { if print_only { update_lints::print_lints(); } else if check { - update_lints::update(update_lints::UpdateMode::Check); + update_lints::update(utils::UpdateMode::Check); } else { - update_lints::update(update_lints::UpdateMode::Change); + update_lints::update(utils::UpdateMode::Change); } }, DevCommand::NewLint { @@ -35,7 +35,7 @@ fn main() { r#type, msrv, } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) { - Ok(()) => update_lints::update(update_lints::UpdateMode::Change), + Ok(()) => update_lints::update(utils::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {e}"), }, DevCommand::Setup(SetupCommand { subcommand }) => match subcommand { @@ -75,6 +75,12 @@ fn main() { uplift, } => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift), DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, &reason), + DevCommand::Sync(SyncCommand { subcommand }) => match subcommand { + SyncSubcommand::UpdateNightly => sync::update_nightly(), + }, + DevCommand::Release(ReleaseCommand { subcommand }) => match subcommand { + ReleaseSubcommand::BumpVersion => release::bump_version(), + }, } } @@ -225,6 +231,10 @@ enum DevCommand { /// The reason for deprecation reason: String, }, + /// Sync between the rust repo and the Clippy repo + Sync(SyncCommand), + /// Manage Clippy releases + Release(ReleaseCommand), } #[derive(Args)] @@ -291,3 +301,29 @@ enum RemoveSubcommand { /// Remove the tasks added with 'cargo dev setup vscode-tasks' VscodeTasks, } + +#[derive(Args)] +struct SyncCommand { + #[command(subcommand)] + subcommand: SyncSubcommand, +} + +#[derive(Subcommand)] +enum SyncSubcommand { + #[command(name = "update_nightly")] + /// Update nightly version in rust-toolchain and `clippy_utils` + UpdateNightly, +} + +#[derive(Args)] +struct ReleaseCommand { + #[command(subcommand)] + subcommand: ReleaseSubcommand, +} + +#[derive(Subcommand)] +enum ReleaseSubcommand { + #[command(name = "bump_version")] + /// Bump the version in the Cargo.toml files + BumpVersion, +} diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index e15ba339717..24d1a53266a 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::{clippy_project_root, clippy_version}; use indoc::{formatdoc, writedoc}; use std::fmt; use std::fmt::Write as _; @@ -186,23 +186,8 @@ fn to_camel_case(name: &str) -> String { } pub(crate) fn get_stabilization_version() -> String { - fn parse_manifest(contents: &str) -> Option<String> { - let version = contents - .lines() - .filter_map(|l| l.split_once('=')) - .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?; - let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else { - return None; - }; - let (minor, patch) = version.split_once('.')?; - Some(format!( - "{}.{}.0", - minor.parse::<u32>().ok()?, - patch.parse::<u32>().ok()? - )) - } - let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`"); - parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") + let (minor, patch) = clippy_version(); + format!("{minor}.{patch}.0") } fn get_test_file_contents(lint_name: &str, msrv: bool) -> String { @@ -273,7 +258,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { result.push_str(&if enable_msrv { formatdoc!( r" - use clippy_config::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, Msrv}}; use clippy_config::Conf; {pass_import} use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; @@ -399,7 +384,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let _: fmt::Result = writedoc!( lint_file_contents, r#" - use clippy_config::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, Msrv}}; use rustc_lint::{{{context_import}, LintContext}}; use super::{name_upper}; diff --git a/src/tools/clippy/clippy_dev/src/release.rs b/src/tools/clippy/clippy_dev/src/release.rs new file mode 100644 index 00000000000..ac755168701 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/release.rs @@ -0,0 +1,27 @@ +use std::fmt::Write; +use std::path::Path; + +use crate::utils::{UpdateMode, clippy_version, replace_region_in_file}; + +const CARGO_TOML_FILES: [&str; 4] = [ + "clippy_config/Cargo.toml", + "clippy_lints/Cargo.toml", + "clippy_utils/Cargo.toml", + "Cargo.toml", +]; + +pub fn bump_version() { + let (minor, mut patch) = clippy_version(); + patch += 1; + for file in &CARGO_TOML_FILES { + replace_region_in_file( + UpdateMode::Change, + Path::new(file), + "# begin autogenerated version\n", + "# end autogenerated version", + |res| { + writeln!(res, "version = \"0.{minor}.{patch}\"").unwrap(); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_dev/src/sync.rs b/src/tools/clippy/clippy_dev/src/sync.rs new file mode 100644 index 00000000000..3522d182e90 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/sync.rs @@ -0,0 +1,33 @@ +use std::fmt::Write; +use std::path::Path; + +use chrono::offset::Utc; + +use crate::utils::{UpdateMode, replace_region_in_file}; + +pub fn update_nightly() { + // Update rust-toolchain nightly version + let date = Utc::now().format("%Y-%m-%d").to_string(); + replace_region_in_file( + UpdateMode::Change, + Path::new("rust-toolchain"), + "# begin autogenerated nightly\n", + "# end autogenerated nightly", + |res| { + writeln!(res, "channel = \"nightly-{date}\"").unwrap(); + }, + ); + + // Update clippy_utils nightly version + replace_region_in_file( + UpdateMode::Change, + Path::new("clippy_utils/README.md"), + "<!-- begin autogenerated nightly -->\n", + "<!-- end autogenerated nightly -->", + |res| { + writeln!(res, "```").unwrap(); + writeln!(res, "nightly-{date}").unwrap(); + writeln!(res, "```").unwrap(); + }, + ); +} diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 795456ad3c5..612d1c0ae13 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::{UpdateMode, clippy_project_root, exit_with_failure, replace_region_in_file}; use aho_corasick::AhoCorasickBuilder; use itertools::Itertools; use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape}; @@ -17,12 +17,6 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; -#[derive(Clone, Copy, PartialEq, Eq)] -pub enum UpdateMode { - Check, - Change, -} - /// Runs the `update_lints` command. /// /// This updates various generated values from the lint source code. @@ -511,14 +505,6 @@ fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) } } -fn exit_with_failure() { - println!( - "Not all lints defined properly. \ - Please run `cargo dev update_lints` to make sure all lints are defined properly." - ); - std::process::exit(1); -} - /// Lint data parsed from the Clippy source code. #[derive(Clone, PartialEq, Eq, Debug)] struct Lint { @@ -851,61 +837,6 @@ fn remove_line_splices(s: &str) -> String { }); res } - -/// Replaces a region in a file delimited by two lines matching regexes. -/// -/// `path` is the relative path to the file on which you want to perform the replacement. -/// -/// See `replace_region_in_text` for documentation of the other options. -/// -/// # Panics -/// -/// Panics if the path could not read or then written -fn replace_region_in_file( - update_mode: UpdateMode, - path: &Path, - start: &str, - end: &str, - write_replacement: impl FnMut(&mut String), -) { - let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display())); - let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { - Ok(x) => x, - Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()), - }; - - match update_mode { - UpdateMode::Check if contents != new_contents => exit_with_failure(), - UpdateMode::Check => (), - UpdateMode::Change => { - if let Err(e) = fs::write(path, new_contents.as_bytes()) { - panic!("Cannot write to `{}`: {e}", path.display()); - } - }, - } -} - -/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters -/// were found, or the missing delimiter if not. -fn replace_region_in_text<'a>( - text: &str, - start: &'a str, - end: &'a str, - mut write_replacement: impl FnMut(&mut String), -) -> Result<String, &'a str> { - let (text_start, rest) = text.split_once(start).ok_or(start)?; - let (_, text_end) = rest.split_once(end).ok_or(end)?; - - let mut res = String::with_capacity(text.len() + 4096); - res.push_str(text_start); - res.push_str(start); - write_replacement(&mut res); - res.push_str(end); - res.push_str(text_end); - - Ok(res) -} - fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { match OpenOptions::new().create_new(true).write(true).open(new_name) { Ok(file) => drop(file), diff --git a/src/tools/clippy/clippy_dev/src/utils.rs b/src/tools/clippy/clippy_dev/src/utils.rs new file mode 100644 index 00000000000..b87fcca13b1 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/utils.rs @@ -0,0 +1,142 @@ +use std::path::{Path, PathBuf}; +use std::process::{self, ExitStatus}; +use std::{fs, io}; + +#[cfg(not(windows))] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; +#[cfg(windows)] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; + +/// Returns the path to the `cargo-clippy` binary +/// +/// # Panics +/// +/// Panics if the path of current executable could not be retrieved. +#[must_use] +pub fn cargo_clippy_path() -> PathBuf { + let mut path = std::env::current_exe().expect("failed to get current executable name"); + path.set_file_name(CARGO_CLIPPY_EXE); + path +} + +/// Returns the path to the Clippy project directory +/// +/// # Panics +/// +/// Panics if the current directory could not be retrieved, there was an error reading any of the +/// Cargo.toml files or ancestor directory is the clippy root directory +#[must_use] +pub fn clippy_project_root() -> PathBuf { + let current_dir = std::env::current_dir().unwrap(); + for path in current_dir.ancestors() { + let result = fs::read_to_string(path.join("Cargo.toml")); + if let Err(err) = &result { + if err.kind() == io::ErrorKind::NotFound { + continue; + } + } + + let content = result.unwrap(); + if content.contains("[package]\nname = \"clippy\"") { + return path.to_path_buf(); + } + } + panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); +} + +/// # Panics +/// Panics if given command result was failed. +pub fn exit_if_err(status: io::Result<ExitStatus>) { + match status.expect("failed to run command").code() { + Some(0) => {}, + Some(n) => process::exit(n), + None => { + eprintln!("Killed by signal"); + process::exit(1); + }, + } +} + +pub(crate) fn clippy_version() -> (u32, u32) { + fn parse_manifest(contents: &str) -> Option<(u32, u32)> { + let version = contents + .lines() + .filter_map(|l| l.split_once('=')) + .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?; + let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else { + return None; + }; + let (minor, patch) = version.split_once('.')?; + Some((minor.parse().ok()?, patch.parse().ok()?)) + } + let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`"); + parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum UpdateMode { + Check, + Change, +} + +pub(crate) fn exit_with_failure() { + println!( + "Not all lints defined properly. \ + Please run `cargo dev update_lints` to make sure all lints are defined properly." + ); + process::exit(1); +} + +/// Replaces a region in a file delimited by two lines matching regexes. +/// +/// `path` is the relative path to the file on which you want to perform the replacement. +/// +/// See `replace_region_in_text` for documentation of the other options. +/// +/// # Panics +/// +/// Panics if the path could not read or then written +pub(crate) fn replace_region_in_file( + update_mode: UpdateMode, + path: &Path, + start: &str, + end: &str, + write_replacement: impl FnMut(&mut String), +) { + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display())); + let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { + Ok(x) => x, + Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()), + }; + + match update_mode { + UpdateMode::Check if contents != new_contents => exit_with_failure(), + UpdateMode::Check => (), + UpdateMode::Change => { + if let Err(e) = fs::write(path, new_contents.as_bytes()) { + panic!("Cannot write to `{}`: {e}", path.display()); + } + }, + } +} + +/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters +/// were found, or the missing delimiter if not. +pub(crate) fn replace_region_in_text<'a>( + text: &str, + start: &'a str, + end: &'a str, + mut write_replacement: impl FnMut(&mut String), +) -> Result<String, &'a str> { + let (text_start, rest) = text.split_once(start).ok_or(start)?; + let (_, text_end) = rest.split_once(end).ok_or(end)?; + + let mut res = String::with_capacity(text.len() + 4096); + res.push_str(text_start); + res.push_str(start); + write_replacement(&mut res); + res.push_str(end); + res.push_str(text_end); + + Ok(res) +} diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 63ea6faf60d..c1f8e82f698 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy_lints" -version = "0.1.84" +# begin autogenerated version +version = "0.1.85" +# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs index 370f0c482fd..2af5178920d 100644 --- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs +++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{trim_span, walk_span_to_context}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 4f8f091a095..ebd35fd2b27 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -91,7 +91,7 @@ impl ApproxConstant { let s = s.as_str(); if s.parse::<f64>().is_ok() { for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| self.msrv.meets(msrv)) { + if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(msrv)) { span_lint_and_help( cx, APPROX_CONSTANT, diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 00626a37ef8..c8dd77d9578 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local}; use rustc_errors::Applicability; @@ -100,13 +100,13 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. - && path_to_local(lhs).map_or(true, |lhs| local_is_initialized(cx, lhs)) + && path_to_local(lhs).is_none_or(|lhs| local_is_initialized(cx, lhs)) && let Some(resolved_impl) = cx.tcx.impl_of_method(resolved_fn.def_id()) // Derived forms don't implement `clone_from`/`clone_into`. // See https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 && !cx.tcx.is_builtin_derived(resolved_impl) // Don't suggest calling a function we're implementing. - && resolved_impl.as_local().map_or(true, |block_id| { + && resolved_impl.as_local().is_none_or(|block_id| { cx.tcx.hir().parent_owner_iter(e.hir_id).all(|(id, _)| id.def_id != block_id) }) && let resolved_assoc_items = cx.tcx.associated_items(resolved_impl) diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs index abf924f7542..3a462018e3e 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -1,6 +1,6 @@ use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg}; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::EarlyContext; diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index c29c9f08cf7..a9766597d50 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -13,7 +13,7 @@ mod useless_attribute; mod utils; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, Item, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs index fadd5272880..97cffeb098e 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -9,7 +9,7 @@ use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args { + if let AttrArgs::Eq { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 6948cf560a5..2eb0566bf9a 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -1,6 +1,7 @@ use clippy_config::Conf; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{create_disallowed_map, match_def_path, paths}; +use clippy_utils::{match_def_path, paths}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 896bd5fd03d..6eef0d42a55 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_ast::ast::LitKind; diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index f2551a05b1a..8892a9e6b6b 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { && !addrof_target.span.from_expansion() && let ref_ty = cx.typeck_results().expr_ty(deref_target) && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind() - && get_parent_expr(cx, e).map_or(true, |parent| { + && get_parent_expr(cx, e).is_none_or(|parent| { match parent.kind { // `*&*foo` should lint `deref_addrof` instead. ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id), diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs index 6714c053913..80514cb52e6 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs @@ -43,7 +43,7 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel } fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: Option<&T>) -> bool { - value.map_or(true, |s| s.as_ref().is_empty()) + value.is_none_or(|s| s.as_ref().is_empty()) } fn is_empty_vec(value: &[String]) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs index b7b63250864..ae433773193 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index 84a44b14dde..4ad39d9160d 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_const_context; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 40a1a9d1ce8..48e9f1d690e 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -134,7 +134,7 @@ pub(super) fn check( }; let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); - let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),)); + let cast_from_ptr_size = def.repr().int.is_none_or(|ty| matches!(ty, IntegerType::Pointer(_),)); let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) { (_, false) if from_nbits > to_nbits => "", (false, true) if from_nbits > 64 => "", diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index 285f0357112..030c2d322db 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index 1d89f6c75e1..c3bc5c0c9f2 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index 3acd4eca420..8b884399f92 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -24,8 +24,8 @@ mod utils; mod zero_ptr; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::is_hir_ty_cfg_dependant; +use clippy_utils::msrvs::{self, Msrv}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index 46d67e615c7..a138ade54aa 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs index 7518dd2435a..945c05ee943 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::std_or_core; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index f76e399517c..364f5c7dc7a 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 3ecd36d3711..89808d38b9f 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -212,7 +212,7 @@ fn lint_if_same_then_else(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[& .array_windows::<2>() .enumerate() .fold(true, |all_eq, (i, &[lhs, rhs])| { - if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).map_or(true, |e| !contains_let(e)) { + if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).is_none_or(|e| !contains_let(e)) { span_lint_and_note( cx, IF_SAME_THEN_ELSE, @@ -470,7 +470,7 @@ fn scan_block_for_eq<'tcx>( b.stmts // the bounds check will catch the underflow .get(b.stmts.len().wrapping_sub(offset + 1)) - .map_or(true, |s| hash != hash_stmt(cx, s)) + .is_none_or(|s| hash != hash_stmt(cx, s)) }) }) .map_or(block.stmts.len() - start_end_eq, |(i, _)| i); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index dff60f76b74..c4a0c8f1865 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -135,6 +135,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, + crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, crate::doc::DOC_MARKDOWN_INFO, diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 1eebfc22af2..c449a1a875b 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -7,15 +7,15 @@ use clippy_utils::{ peel_middle_ty_refs, }; use core::mem; -use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{Visitor, walk_ty}; use rustc_hir::{ self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TyKind, UnOp, }; -use rustc_hir::def_id::DefId; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; @@ -453,7 +453,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { )); } else if stability.is_deref_stable() // Auto-deref doesn't combine with other adjustments - && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) + && next_adjust.is_none_or(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) { self.state = Some((State::Borrow { mutability }, StateData { @@ -963,7 +963,7 @@ fn report<'tcx>( // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. /* - expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX { + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix { Cow::Owned(format!("({expr_str})")) } else { expr_str @@ -999,13 +999,13 @@ fn report<'tcx>( data.first_expr.span, state.msg, |diag| { - let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { + let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { Node::Expr(e) => match e.kind { - ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), - ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))), - _ => (e.precedence(), false), + ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false, + ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)), + _ => expr.precedence() < e.precedence(), }, - _ => (0, false), + _ => false, }; let is_in_tuple = matches!( get_parent_expr(cx, data.first_expr), @@ -1016,7 +1016,7 @@ fn report<'tcx>( ); let sugg = if !snip_is_macro - && (calls_field || expr.precedence() < precedence) + && needs_paren && !has_enclosing_paren(&snip) && !is_in_tuple { @@ -1049,16 +1049,16 @@ fn report<'tcx>( } } - let (prefix, precedence) = match mutability { + let (prefix, needs_paren) = match mutability { Some(mutability) if !ty.is_ref() => { let prefix = match mutability { Mutability::Not => "&", Mutability::Mut => "&mut ", }; - (prefix, PREC_PREFIX) + (prefix, expr.precedence() < ExprPrecedence::Prefix) }, - None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0), - _ => ("", 0), + None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false), + _ => ("", false), }; span_lint_hir_and_then( cx, @@ -1070,12 +1070,11 @@ fn report<'tcx>( let mut app = Applicability::MachineApplicable; let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); - let sugg = - if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) { - format!("{prefix}({snip})") - } else { - format!("{prefix}{snip}") - }; + let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) { + format!("{prefix}({snip})") + } else { + format!("{prefix}{snip}") + }; diag.span_suggestion(data.first_expr.span, "try", sugg, app); }, ); @@ -1158,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence() == PREC_UNAMBIGUOUS { + if parent.precedence() == ExprPrecedence::Unambiguous { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 767dda552bc..9569081ad08 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_errors::Applicability; @@ -132,17 +132,15 @@ fn check_struct<'tcx>( if should_emit { let struct_span = cx.tcx.def_span(adt_def.did()); + let suggestions = vec![ + (item.span, String::new()), // Remove the manual implementation + (struct_span.shrink_to_lo(), "#[derive(Default)]\n".to_string()), // Add the derive attribute + ]; + span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { - diag.span_suggestion_hidden( - item.span, - "remove the manual implementation...", - String::new(), - Applicability::MachineApplicable, - ); - diag.span_suggestion( - struct_span.shrink_to_lo(), - "...and instead derive it", - "#[derive(Default)]\n".to_string(), + diag.multipart_suggestion( + "replace the manual implementation with a derive attribute", + suggestions, Applicability::MachineApplicable, ); }); @@ -161,23 +159,23 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex let indent_enum = indent_of(cx, enum_span).unwrap_or(0); let variant_span = cx.tcx.def_span(variant_def.def_id); let indent_variant = indent_of(cx, variant_span).unwrap_or(0); - span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { - diag.span_suggestion_hidden( - item.span, - "remove the manual implementation...", - String::new(), - Applicability::MachineApplicable, - ); - diag.span_suggestion( + + let suggestions = vec![ + (item.span, String::new()), // Remove the manual implementation + ( enum_span.shrink_to_lo(), - "...and instead derive it...", - format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),), - Applicability::MachineApplicable, - ); - diag.span_suggestion( + format!("#[derive(Default)]\n{}", " ".repeat(indent_enum)), + ), // Add the derive attribute + ( variant_span.shrink_to_lo(), - "...and mark the default variant", - format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),), + format!("#[default]\n{}", " ".repeat(indent_variant)), + ), // Mark the default variant + ]; + + span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { + diag.multipart_suggestion( + "replace the manual implementation with a derive attribute and mark the default variant", + suggestions, Applicability::MachineApplicable, ); }); diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 1a34b87e42a..8125dab8adf 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -505,17 +505,15 @@ fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId } } - let param_env = ParamEnv::new( - tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( - params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { - ClauseKind::Trait(TraitPredicate { - trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), - polarity: ty::PredicatePolarity::Positive, - }) - .upcast(tcx) - }), - )), - ); + let param_env = ParamEnv::new(tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { + ClauseKind::Trait(TraitPredicate { + trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), + polarity: ty::PredicatePolarity::Positive, + }) + .upcast(tcx) + }), + ))); ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index bdd49bf8aa7..a0cb36f88dc 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::create_disallowed_map; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_data_structures::fx::FxHashSet; diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs index 5a01d76a2a6..1e660b1957a 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::create_disallowed_map; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefIdMap; diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs new file mode 100644 index 00000000000..2182689f985 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -0,0 +1,45 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute}; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::DOC_INCLUDE_WITHOUT_CFG; + +pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { + for attr in attrs { + if !attr.span.from_expansion() + && let AttrKind::Normal(ref normal) = attr.kind + && normal.item.path == sym::doc + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args + && !attr.span.contains(meta.span) + // Since the `include_str` is already expanded at this point, we can only take the + // whole attribute snippet and then modify for our suggestion. + && let Some(snippet) = snippet_opt(cx, attr.span) + // We cannot remove this because a `#[doc = include_str!("...")]` attribute can occupy + // several lines. + && let Some(start) = snippet.find('[') + && let Some(end) = snippet.rfind(']') + && let snippet = &snippet[start + 1..end] + // We check that the expansion actually comes from `include_str!` and not just from + // another macro. + && let Some(sub_snippet) = snippet.trim().strip_prefix("doc") + && let Some(sub_snippet) = sub_snippet.trim().strip_prefix("=") + && sub_snippet.trim().starts_with("include_str!") + { + span_lint_and_sugg( + cx, + DOC_INCLUDE_WITHOUT_CFG, + attr.span, + "included a file in documentation unconditionally", + "use `cfg_attr(doc, doc = \"...\")`", + format!( + "#{}[cfg_attr(doc, {snippet})]", + if attr.style == AttrStyle::Inner { "!" } else { "" } + ), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index df7c37a192a..88ac871acf6 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::lint_without_lint_pass)] + mod lazy_continuation; mod too_long_first_doc_paragraph; @@ -33,6 +35,7 @@ use std::ops::Range; use url::Url; mod empty_line_after; +mod include_in_doc_without_cfg; mod link_with_quotes; mod markdown; mod missing_headers; @@ -532,6 +535,35 @@ declare_clippy_lint! { "empty line after doc comments" } +declare_clippy_lint! { + /// ### What it does + /// Checks if included files in doc comments are included only for `cfg(doc)`. + /// + /// ### Why restrict this? + /// These files are not useful for compilation but will still be included. + /// Also, if any of these non-source code file is updated, it will trigger a + /// recompilation. + /// + /// ### Known problems + /// + /// Excluding this will currently result in the file being left out if + /// the item's docs are inlined from another crate. This may be fixed in a + /// future version of rustdoc. + /// + /// ### Example + /// ```ignore + /// #![doc = include_str!("some_file.md")] + /// ``` + /// Use instead: + /// ```no_run + /// #![cfg_attr(doc, doc = include_str!("some_file.md"))] + /// ``` + #[clippy::version = "1.84.0"] + pub DOC_INCLUDE_WITHOUT_CFG, + restriction, + "check if files included in documentation are behind `cfg(doc)`" +} + pub struct Documentation { valid_idents: FxHashSet<String>, check_private_items: bool, @@ -561,6 +593,7 @@ impl_lint_pass!(Documentation => [ EMPTY_LINE_AFTER_OUTER_ATTR, EMPTY_LINE_AFTER_DOC_COMMENTS, TOO_LONG_FIRST_DOC_PARAGRAPH, + DOC_INCLUDE_WITHOUT_CFG, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { @@ -690,6 +723,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[ Some(("fake".into(), "fake".into())) } + include_in_doc_without_cfg::check(cx, attrs); if suspicious_doc_comments::check(cx, attrs) || empty_line_after::check(cx, attrs) || is_doc_hidden(attrs) { return None; } @@ -917,6 +951,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize } let trimmed_text = text.trim(); headers.safety |= in_heading && trimmed_text == "Safety"; + headers.safety |= in_heading && trimmed_text == "SAFETY"; headers.safety |= in_heading && trimmed_text == "Implementation safety"; headers.safety |= in_heading && trimmed_text == "Implementation Safety"; headers.errors |= in_heading && trimmed_text == "Errors"; diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 6c87a05ace3..8c22e43349f 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -276,7 +276,7 @@ fn check_inputs( && typeck .expr_adjustments(arg) .last() - .map_or(true, |a| a.target == typeck.expr_ty(arg)) + .is_none_or(|a| a.target == typeck.expr_ty(arg)) }) } diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index c88fb50b5af..0011da03dda 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { && fn_header.abi == Abi::Rust && fn_decl.inputs.len() as u64 > self.max_fn_params_bools && get_parent_as_impl(cx.tcx, cx.tcx.local_def_id_to_hir_id(def_id)) - .map_or(true, |impl_item| impl_item.of_trait.is_none()) + .is_none_or(|impl_item| impl_item.of_trait.is_none()) { check_fn_decl(cx, fn_decl, span, self.max_fn_params_bools); } diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index 81152da8c85..ae4b6680065 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty}; use rustc_hir::{ BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, - PredicateOrigin, Ty, WherePredicate, WherePredicateKind + PredicateOrigin, Ty, WherePredicate, WherePredicateKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 4c043f8dc14..da5825b7ab2 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -1,6 +1,5 @@ use arrayvec::ArrayVec; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ @@ -8,6 +7,7 @@ use clippy_utils::macros::{ format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, }; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use itertools::Itertools; diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 14da0b515a5..e43c311eb85 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -1,9 +1,9 @@ use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::span_is_local; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::path_def_id; use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { |diag| { // If the target type is likely foreign mention the orphan rules as it's a common source of // confusion - if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) { + if path_def_id(cx, target_ty.peel_refs()).is_none_or(|id| !id.is_local()) { diag.help( "`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\ https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence" diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index cf08c16458b..bb2dc9995df 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::return_ty; use rustc_hir::intravisit::FnKind; @@ -5,7 +7,9 @@ use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::print::PrintTraitRefExt; -use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; +use rustc_middle::ty::{ + self, AliasTy, Binder, ClauseKind, PredicateKind, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor, +}; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; @@ -15,9 +19,16 @@ use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt}; declare_clippy_lint! { /// ### What it does /// This lint requires Future implementations returned from - /// functions and methods to implement the `Send` marker trait. It is mostly - /// used by library authors (public and internal) that target an audience where - /// multithreaded executors are likely to be used for running these Futures. + /// functions and methods to implement the `Send` marker trait, + /// ignoring type parameters. + /// + /// If a function is generic and its Future conditionally implements `Send` + /// based on a generic parameter then it is considered `Send` and no warning is emitted. + /// + /// This can be used by library authors (public and internal) to ensure + /// their functions are compatible with both multi-threaded runtimes that require `Send` futures, + /// as well as single-threaded runtimes where callers may choose `!Send` types + /// for generic parameters. /// /// ### Why is this bad? /// A Future implementation captures some state that it @@ -64,22 +75,46 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { return; } let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner()); - if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() { + if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() + && let Some(future_trait) = cx.tcx.lang_items().future_trait() + && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) + { let preds = cx.tcx.explicit_item_super_predicates(def_id); let is_future = preds.iter_instantiated_copied(cx.tcx, args).any(|(p, _)| { - p.as_trait_clause().is_some_and(|trait_pred| { - Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() - }) + p.as_trait_clause() + .is_some_and(|trait_pred| trait_pred.skip_binder().trait_ref.def_id == future_trait) }); if is_future { - let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let cause = traits::ObligationCause::misc(span, fn_def_id); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); let send_errors = ocx.select_all_or_error(); - if !send_errors.is_empty() { + + // Allow errors that try to prove `Send` for types that "mention" a generic parameter at the "top + // level". + // For example, allow errors that `T: Send` can't be proven, but reject `Rc<T>: Send` errors, + // which is always unconditionally `!Send` for any possible type `T`. + // + // We also allow associated type projections if the self type is either itself a projection or a + // type parameter. + // This is to prevent emitting warnings for e.g. holding a `<Fut as Future>::Output` across await + // points, where `Fut` is a type parameter. + + let is_send = send_errors.iter().all(|err| { + err.obligation + .predicate + .as_trait_clause() + .map(Binder::skip_binder) + .is_some_and(|pred| { + pred.def_id() == send_trait + && pred.self_ty().has_param() + && TyParamAtTopLevelVisitor.visit_ty(pred.self_ty()) == ControlFlow::Break(true) + }) + }); + + if !is_send { span_lint_and_then( cx, FUTURE_NOT_SEND, @@ -107,3 +142,15 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } } } + +struct TyParamAtTopLevelVisitor; +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TyParamAtTopLevelVisitor { + type Result = ControlFlow<bool>; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match ty.kind() { + ty::Param(_) => ControlFlow::Break(true), + ty::Alias(ty::AliasTyKind::Projection, ty) => ty.visit_with(self), + _ => ControlFlow::Break(false), + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index ba80c099a01..6444e99ae9c 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -7,6 +7,7 @@ use rustc_errors::Diag; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::edition::Edition::Edition2024; use rustc_span::sym; declare_clippy_lint! { @@ -14,6 +15,12 @@ declare_clippy_lint! { /// Checks for `Mutex::lock` calls in `if let` expression /// with lock calls in any of the else blocks. /// + /// ### Disabled starting in Edition 2024 + /// This lint is effectively disabled starting in + /// Edition 2024 as `if let ... else` scoping was reworked + /// such that this is no longer an issue. See + /// [Proposal: stabilize if_let_rescope for Edition 2024](https://github.com/rust-lang/rust/issues/131154) + /// /// ### Why is this bad? /// The Mutex lock remains held for the whole /// `if let ... else` block and deadlocks. @@ -45,6 +52,10 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]); impl<'tcx> LateLintPass<'tcx> for IfLetMutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if cx.tcx.sess.edition() >= Edition2024 { + return; + } + if let Some(higher::IfLet { let_expr, if_then, @@ -86,7 +97,7 @@ fn mutex_lock_call<'tcx>( && path.ident.as_str() == "lock" && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs() && is_type_diagnostic_item(cx, ty, sym::Mutex) - && op_mutex.map_or(true, |op| eq_expr_value(cx, self_arg, op)) + && op_mutex.is_none_or(|op| eq_expr_value(cx, self_arg, op)) { ControlFlow::Break(self_arg) } else { diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs index d63c18c0eda..3fc0a696522 100644 --- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs +++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::{ diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 3b84b569c3e..37481dc7feb 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::{ SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index 0b3a6ee1bea..f3467adacc5 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_in_test; +use clippy_utils::msrvs::Msrv; use rustc_attr::{StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 96550c4d1cb..c2030a5ab09 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::is_copy; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs index 66931a7f98c..f4e41dc826b 100644 --- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs +++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::ty; diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 644365c9fe5..623b6b4fcc1 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -3,8 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty; +use rustc_middle::ty::layout::LayoutOf; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 4f22931a4de..b38e362410e 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile { && let AttrKind::Normal(ref normal) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 4ef881f11d5..46d7df6995a 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::macros::macro_backtrace; use clippy_utils::source::snippet; -use rustc_hir::{ArrayLen, Expr, ExprKind, Item, ItemKind, Node}; +use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; @@ -118,13 +118,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { /// Only giving help messages if the expr does not contains macro expanded codes. fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { - /// Check if the span of `ArrayLen` of a repeat expression is within the expr's span, + /// Check if the span of `ConstArg` of a repeat expression is within the expr's span, /// if not, meaning this repeat expr is definitely from some proc-macro. /// /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the /// correct result. fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool { - let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else { + let ExprKind::Repeat(_, len_ct) = expr.kind else { return false; }; !expr.span.contains(len_ct.span()) diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index e17d6213679..fb46bdcab6e 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{get_parent_expr, is_from_proc_macro}; use hir::def_id::DefId; use rustc_errors::Applicability; @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind - && self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) + && self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !in_external_macro(cx.sess(), item.span) && let Some(def_id) = path.res[0].opt_def_id() { @@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { return; }; - if self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) + if self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !in_external_macro(cx.sess(), expr.span) && !is_from_proc_macro(cx, expr) { diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 6ff1a1e5ec7..35b14776e59 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; use itertools::Itertools; +use rustc_ast::visit::{try_visit, walk_list}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; @@ -11,8 +12,9 @@ use rustc_hir::intravisit::{ }; use rustc_hir::{ BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, - Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, - PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, WherePredicateKind, lang_items, + HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, + PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, + WherePredicateKind, lang_items, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -483,6 +485,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ struct Usage { lifetime: Lifetime, in_where_predicate: bool, + in_bounded_ty: bool, in_generics_arg: bool, } @@ -490,11 +493,15 @@ struct LifetimeChecker<'cx, 'tcx, F> { cx: &'cx LateContext<'tcx>, map: FxIndexMap<LocalDefId, Vec<Usage>>, where_predicate_depth: usize, + bounded_ty_depth: usize, generic_args_depth: usize, phantom: std::marker::PhantomData<F>, } -impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> { +impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> +where + F: NestedFilter<'tcx>, +{ fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> { let map = generics .params @@ -510,10 +517,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> { cx, map, where_predicate_depth: 0, + bounded_ty_depth: 0, generic_args_depth: 0, phantom: std::marker::PhantomData, } } + + // `visit_where_bound_predicate` is based on: + // https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939 + fn visit_where_bound_predicate( + &mut self, + hir_id: HirId, + bounded_ty: &'tcx Ty<'tcx>, + bounds: &'tcx [GenericBound<'tcx>], + bound_generic_params: &'tcx [GenericParam<'tcx>], + ) { + try_visit!(self.visit_id(hir_id)); + + self.bounded_ty_depth += 1; + try_visit!(self.visit_ty(bounded_ty)); + self.bounded_ty_depth -= 1; + + walk_list!(self, visit_param_bound, bounds); + walk_list!(self, visit_generic_param, bound_generic_params); + } } impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F> @@ -531,6 +558,7 @@ where usages.push(Usage { lifetime: *lifetime, in_where_predicate: self.where_predicate_depth != 0, + in_bounded_ty: self.bounded_ty_depth != 0, in_generics_arg: self.generic_args_depth != 0, }); } @@ -538,7 +566,17 @@ where fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) { self.where_predicate_depth += 1; - walk_where_predicate(self, predicate); + if let &WherePredicateKind::BoundPredicate(WhereBoundPredicate { + bounded_ty, + bounds, + bound_generic_params, + origin: _, + }) = predicate.kind + { + self.visit_where_bound_predicate(predicate.hir_id, bounded_ty, bounds, bound_generic_params); + } else { + walk_where_predicate(self, predicate); + } self.where_predicate_depth -= 1; } @@ -562,7 +600,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, for (def_id, usages) in checker.map { if usages .iter() - .all(|usage| usage.in_where_predicate && !usage.in_generics_arg) + .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg) { span_lint( cx, @@ -589,7 +627,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' for (&def_id, usages) in &checker.map { if usages .iter() - .all(|usage| usage.in_where_predicate && !usage.in_generics_arg) + .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg) { span_lint( cx, @@ -605,8 +643,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' // An `impl` lifetime is elidable if it satisfies the following conditions: // - It is used exactly once. -// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are -// different from `GenericParam`s.) +// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that +// `GenericArgs` are different from `GenericParam`s.) fn report_elidable_impl_lifetimes<'tcx>( cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>, @@ -623,6 +661,7 @@ fn report_elidable_impl_lifetimes<'tcx>( } | Usage { lifetime, + in_bounded_ty: false, in_generics_arg: false, .. }, diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index d999e1a0585..06cf901bfb2 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,6 +1,6 @@ use super::EXPLICIT_ITER_LOOP; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{ implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection, @@ -29,7 +29,7 @@ pub(super) fn check( if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { return; } - } else if count.try_to_target_usize(cx.tcx).map_or(true, |x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { + } else if count.try_to_target_usize(cx.tcx).is_none_or(|x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { return; } } @@ -181,7 +181,8 @@ fn is_ref_iterable<'tcx>( // Attempt to borrow let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl); if implements_trait(cx, self_ty, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::borrow(mutbl), self_ty)); diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 17215621d2a..f3ca4a4a571 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -23,8 +23,8 @@ mod while_let_loop; mod while_let_on_iterator; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::higher; +use clippy_utils::msrvs::Msrv; use rustc_ast::Label; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 35dc8e9aa4e..12719c4f94b 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet, snippet_with_applicability}; use clippy_utils::visitors::contains_break_or_continue; use rustc_ast::Mutability; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal}; use rustc_lint::LateContext; @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( if !prefix.is_empty() && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. - arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression) + arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression) ) { arg_snip = format!("({arg_snip})").into(); diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index fd71167f814..c31656f8a05 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs index 016ec7320a6..484a7ba256b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::higher::If; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::is_const_evaluatable; diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs index 4c171e6d890..bbb89bee835 100644 --- a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs +++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::SpanlessEq; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use rustc_ast::{BinOpKind, LitKind}; @@ -35,7 +35,7 @@ declare_clippy_lint! { /// let y: i32 = 4; /// let div = x.div_ceil(y); /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.83.0"] pub MANUAL_DIV_CEIL, complexity, "manually reimplementing `div_ceil`" diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index a269ea11397..b12f575e81a 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -1,7 +1,7 @@ -use clippy_config::msrvs::Msrv; -use clippy_config::{Conf, msrvs}; +use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index 7a9c9963742..7e092d11f1b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::visitors::{is_local_used, local_used_once}; use clippy_utils::{is_trait_method, path_to_local_id}; diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index dec8c5d85de..3f01f3cf30a 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators}; use rustc_ast::LitKind::{Byte, Char}; diff --git a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs index a11d3e4624c..4fee3bf7aa9 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs @@ -27,7 +27,7 @@ declare_clippy_lint! { /// let a: u32 = 4; /// let result = a.is_power_of_two(); /// ``` - #[clippy::version = "1.82.0"] + #[clippy::version = "1.83.0"] pub MANUAL_IS_POWER_OF_TWO, pedantic, "manually reimplementing `is_power_of_two`" diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 17185df5d76..a70955a7c78 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -1,11 +1,10 @@ use crate::question_mark::{QUESTION_MARK, QuestionMark}; -use clippy_config::msrvs; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{is_lint_allowed, is_never_expr, pat_and_expr_can_be_question_mark, peel_blocks}; +use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind}; diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs index 85e99a92cf5..b7563a2508d 100644 --- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs +++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{is_trait_method, peel_hir_expr_refs}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 25868ccae40..00800231fe4 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_doc_hidden; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_indent; use itertools::Itertools; use rustc_ast::attr; diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 86293169ea2..5e58054a986 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::{is_in_const_context, path_to_local}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index a60163be770..708980ac503 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::SpanlessEq; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 3f401eff6bd..79de41db343 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; use clippy_utils::{eq_expr_value, higher}; diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 50e6dfc6298..99a7b8c74be 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet; use clippy_utils::visitors::is_local_used; use clippy_utils::{ @@ -72,14 +72,13 @@ fn check_arm<'tcx>( (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b), } // the binding must not be used in the if guard - && outer_guard.map_or( - true, + && outer_guard.is_none_or( |e| !is_local_used(cx, e, binding_id) ) // ...or anywhere in the inner expression && match inner { IfLetOrMatch::IfLet(_, _, body, els, _) => { - !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id)) + !is_local_used(cx, body, binding_id) && els.is_none_or(|e| !is_local_used(cx, e, binding_id)) }, IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)), } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 9c6df4d8ac0..bac5cf88cfb 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -7,7 +7,7 @@ use clippy_utils::{ CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, }; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::def::Res; @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous { format!("({scrutinee_str})") } else { scrutinee_str.into() diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 28adcc2f227..64969271764 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -25,7 +25,7 @@ mod try_err; mod wild_in_or_pats; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::walk_span_to_context; use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg}; use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind}; diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 9e54475033c..dfc0513add9 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet; use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used}; use clippy_utils::{is_in_const_context, path_to_local}; @@ -243,11 +243,6 @@ fn emit_redundant_guards<'tcx>( } /// Checks if the given `Expr` can also be represented as a `Pat`. -/// -/// All literals generally also work as patterns, however float literals are special. -/// They are currently (as of 2023/08/08) still allowed in patterns, but that will become -/// an error in the future, and rustc already actively warns against this (see rust#41620), -/// so we don't consider those as usable within patterns for linting purposes. fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { for_each_expr_without_closures(expr, |expr| { if match expr.kind { @@ -267,7 +262,7 @@ fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { | ExprKind::Tup(..) | ExprKind::Struct(..) | ExprKind::Unary(UnOp::Neg, _) => true, - ExprKind::Lit(lit) if !matches!(lit.node, LitKind::Float(..)) => true, + ExprKind::Lit(lit) if !matches!(lit.node, LitKind::CStr(..)) => true, _ => false, } { return ControlFlow::Continue(()); diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 146748734cf..5597cd85abc 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index c9604c7b2e2..1ee27d90d05 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -30,7 +30,7 @@ pub(super) fn check( .type_dependent_def_id(expr.hir_id) .and_then(|id| cx.tcx.trait_of_item(id)) .zip(cx.tcx.lang_items().clone_trait()) - .map_or(true, |(x, y)| x != y) + .is_none_or(|(x, y)| x != y) { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs index fa04f74eec1..2a0a9d3710d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{get_iterator_item_ty, is_copy}; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs index 3b1adb16b80..44b55570eea 100644 --- a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs @@ -1,6 +1,6 @@ use super::ERR_EXPECT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item}; use rustc_errors::Applicability; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs index f94fe221833..3f89e593148 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs index 40b48ccca5d..d8bb9e377a0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,7 +1,7 @@ use super::IS_DIGIT_ASCII_RADIX; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs index 390dd24b505..299f6d10112 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs @@ -1,6 +1,6 @@ use super::ITER_KV_MAP; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::pat_is_wild; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs index 22f4748de70..7d5ebdedd0c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_ast::{LitKind, StrStyle}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index 7aa13d8d5b6..20e4d233525 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{IntoSpan, SpanRangeExt}; use clippy_utils::ty::get_field_by_name; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures}; @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + requires_copy |= !cx.type_is_copy_modulo_regions(ty); break; } }, @@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) + && (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty)) // This case could be handled, but a fair bit of care would need to be taken. && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs index c377abd6237..90e502f244f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{Msrv, OPTION_RESULT_IS_VARIANT_AND}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; @@ -36,7 +36,7 @@ pub(super) fn check<'tcx>( } // 4. msrv doesn't meet `OPTION_RESULT_IS_VARIANT_AND` - if !msrv.meets(OPTION_RESULT_IS_VARIANT_AND) { + if !msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs index 31449d41770..4a48d4b547c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_from_proc_macro, is_trait_method}; diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs index d5594b21db5..1252f7ccd35 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function}; use clippy_utils::{is_diag_trait_item, peel_blocks}; diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 3226fa9cd3f..428da0cf107 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::mutated_variables; diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index fc656fd78ba..80703618a11 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -1,6 +1,6 @@ use crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{eager_or_lazy, higher, usage}; diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 795e041ffd9..7d1d5d69c99 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -137,10 +137,10 @@ mod wrong_self_convention; mod zst_offset; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::FormatArgsStorage; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty}; pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES; @@ -4107,24 +4107,32 @@ declare_clippy_lint! { /// ### Why is this bad? /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome, /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`. + /// Also, calls such as `opt.map_or(true, |val| val == 5)` can be reduced to + /// `opt.is_none_or(|val| val == 5)`. /// This lint offers readability and conciseness improvements. /// /// ### Example /// ```no_run - /// pub fn a(x: Option<i32>) -> bool { - /// x.map_or(false, |n| n == 5) + /// pub fn a(x: Option<i32>) -> (bool, bool) { + /// ( + /// x.map_or(false, |n| n == 5), + /// x.map_or(true, |n| n > 5), + /// ) /// } /// ``` /// Use instead: /// ```no_run - /// pub fn a(x: Option<i32>) -> bool { - /// x == Some(5) + /// pub fn a(x: Option<i32>) -> (bool, bool) { + /// ( + /// x == Some(5), + /// x.is_none_or(|n| n > 5), + /// ) /// } /// ``` - #[clippy::version = "1.75.0"] + #[clippy::version = "1.84.0"] pub UNNECESSARY_MAP_OR, style, - "reduce unnecessary pattern matching for constructs that implement `PartialEq`" + "reduce unnecessary calls to `.map_or(bool, …)`" } declare_clippy_lint! { @@ -4531,7 +4539,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { && method_config.output_type.matches(&sig.decl.output) // in case there is no first arg, since we already have checked the number of arguments // it's should be always true - && first_arg_ty_opt.map_or(true, |first_arg_ty| method_config + && first_arg_ty_opt.is_none_or(|first_arg_ty| method_config .self_kind.matches(cx, self_ty, first_arg_ty) ) && fn_header_equals(method_config.fn_header, sig.header) diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index c00b9b368c4..ea4984f83ad 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -203,7 +203,8 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool { if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty]) + && let Some(iter_item_ty) = + make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty]) && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( cx.typing_env(), diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 998bdee0157..8d97d1c72a6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{path_to_local_id, peel_blocks}; diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 528e2204cf8..7c4dc4ffb20 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; use rustc_data_structures::fx::FxHashSet; diff --git a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs index cfb823dbf5d..febd7fd5cf2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs +++ b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs @@ -1,6 +1,6 @@ use super::PATH_ENDS_WITH_EXT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::{LitKind, StrStyle}; diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 1cee28e1986..c91be33b1cd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::usage::local_used_after_expr; use clippy_utils::visitors::{Descend, for_each_expr}; diff --git a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs index cc0d432b799..cb719b34b1f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local}; use itertools::Itertools; diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index bab439015c5..3de51bc661e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { let body = cx.tcx.hir().body(body); let arg_id = body.params[0].pat.hir_id; - let mutates_arg = mutated_variables(body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id)); + let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id)); let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value); let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs index adc27cd437f..1199d289761 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; @@ -60,7 +60,7 @@ pub(super) fn check<'a>( Some(_) | None => return, }; - let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind + let (sugg, method, applicability) = if let ExprKind::Closure(map_closure) = map.kind && let closure_body = cx.tcx.hir().body(map_closure.body) && let closure_body_value = closure_body.value.peel_blocks() && let ExprKind::Binary(op, l, r) = closure_body_value.kind @@ -100,7 +100,7 @@ pub(super) fn check<'a>( .maybe_par() .into_string(); - (binop, "a standard comparison") + (binop, "a standard comparison", Applicability::MaybeIncorrect) } else if !def_bool && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite()) @@ -110,6 +110,18 @@ pub(super) fn check<'a>( ( format!("{recv_callsite}.{suggested_name}({span_callsite})",), suggested_name, + Applicability::MachineApplicable, + ) + } else if def_bool + && matches!(variant, Variant::Some) + && msrv.meets(msrvs::IS_NONE_OR) + && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite()) + && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite()) + { + ( + format!("{recv_callsite}.is_none_or({span_callsite})"), + "is_none_or", + Applicability::MachineApplicable, ) } else { return; @@ -123,9 +135,9 @@ pub(super) fn check<'a>( cx, UNNECESSARY_MAP_OR, expr.span, - "this `map_or` is redundant", + "this `map_or` can be simplified", format!("use {method} instead"), sugg, - Applicability::MaybeIncorrect, + applicability, ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 84ea3554a35..d19064fd57e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -1,7 +1,7 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 408dbef9cb1..b856c929cf6 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -114,7 +114,7 @@ declare_clippy_lint! { /// let _ = FooStruct{}; /// } /// ``` - #[clippy::version = "pre 1.29.0"] + #[clippy::version = "1.83.0"] pub USED_UNDERSCORE_ITEMS, pedantic, "using a item which is prefixed with an underscore" @@ -351,7 +351,7 @@ fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { /// `unused_variables`'s idea /// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind { + get_parent_expr(cx, expr).is_none_or(|parent| match parent.kind { ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), _ => is_used(cx, parent), }) diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index eea0459e026..121c4326d64 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs index c2f524a6353..9a44a3c980c 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::source::snippet; use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks}; diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 9ebef531bc5..f69913ddbfd 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir, expr_local, local_assignments, used_exactly_once}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs}; @@ -362,7 +362,7 @@ fn referent_used_exactly_once<'tcx>( let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); if possible_borrowers .last() - .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id) + .is_none_or(|&(local_def_id, _)| local_def_id != body_owner_local_def_id) { possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index b65ec8c3c48..cd90d2f90f7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -182,14 +182,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { && !is_copy(cx, ty) && ty.is_sized(cx.tcx, cx.typing_env()) && !allowed_traits.iter().any(|&t| { - implements_trait_with_env_from_iter( - cx.tcx, - cx.typing_env(), - ty, - t, - None, - [None::<ty::GenericArg<'tcx>>] - ) + implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, t, None, [None::< + ty::GenericArg<'tcx>, + >]) }) && !implements_borrow_trait && !all_borrowable_trait diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index a0ba2aaf552..429afff9b66 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::has_enclosing_paren; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) { + let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) { format!("-({snip})") } else { format!("-{snip}") diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 74536028b5d..8ecff9c3f9b 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -238,7 +238,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { ExprKind::Struct(_, fields, ref base) => { !has_drop(cx, cx.typeck_results().expr_ty(expr)) && fields.iter().all(|field| has_no_effect(cx, field.expr)) - && base.as_ref().map_or(true, |base| has_no_effect(cx, base)) + && base.as_ref().is_none_or(|base| has_no_effect(cx, base)) }, ExprKind::Call(callee, args) => { if let ExprKind::Path(ref qpath) = callee.kind { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 5416e00fe0c..5f253b9e5d5 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -278,7 +278,12 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); - let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); + let result = Self::const_eval_resolve( + cx.tcx, + cx.typing_env(), + ty::UnevaluatedConst::new(def_id, args), + DUMMY_SP, + ); Self::is_value_unfrozen_raw(cx, result, ty) } @@ -335,7 +340,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // i.e. having an enum doesn't necessary mean a type has a frozen variant. // And, implementing it isn't a trivial task; it'll probably end up // re-implementing the trait predicate evaluation specific to `Freeze`. - && body_id_opt.map_or(true, |body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized)) + && body_id_opt.is_none_or(|body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized)) { lint(cx, Source::Assoc { item: trait_item.span }); } diff --git a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs index aefb665b52e..f6ce1d1d586 100644 --- a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs +++ b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs @@ -39,7 +39,7 @@ declare_clippy_lint! { /// let r2 = x % NonZeroU64::from(y); /// } /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.83.0"] pub NON_ZERO_SUGGESTIONS, restriction, "suggests using `NonZero#` from `u#` or `i#` for more efficient and type-safe conversions" diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 13b3d240700..6de203e068b 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -200,7 +200,7 @@ impl Params { if self .get_by_fn(param.fn_id, usage.idx) // If the parameter can't be found, then it's used for more than just recursion. - .map_or(true, |p| self.try_disable_lint_for_param(p, eval_stack)) + .is_none_or(|p| self.try_disable_lint_for_param(p, eval_stack)) { param.apply_lint.set(false); eval_stack.pop(); diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 0dcaec1c9a7..1315c3dfc12 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( if let Some((_, lang_item)) = binop_traits(op.node) && let Some(trait_id) = cx.tcx.lang_items().get(lang_item) && let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id - && trait_ref_of_method(cx, parent_fn).map_or(true, |t| t.path.res.def_id() != trait_id) + && trait_ref_of_method(cx, parent_fn).is_none_or(|t| t.path.res.def_id() != trait_id) && implements_trait(cx, ty, trait_id, &[rty.into()]) { // Primitive types execute assign-ops right-to-left. Every other type is left-to-right. diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs index 4414056a467..e87cfd103c3 100644 --- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs @@ -1,5 +1,6 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_from_proc_macro; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::Span; @@ -35,9 +36,9 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } } -fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { +fn check_compare<'a>(cx: &LateContext<'a>, bit_op: &Expr<'a>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(op, left, right) = &bit_op.kind { - if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { + if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr || is_from_proc_macro(cx, bit_op) { return; } if let Some(mask) = fetch_int_literal(cx, right).or_else(|| fetch_int_literal(cx, left)) { diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index ecc095f3859..dec4c18a309 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -541,9 +541,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio .collect(); if let Some(args) = args && !args.is_empty() - && body.map_or(true, |body| { - sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value) - }) + && body.is_none_or(|body| sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value)) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index f69cb9be4ca..77abe7151f0 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -1,9 +1,9 @@ use crate::manual_let_else::MANUAL_LET_ELSE; use crate::question_mark_used::QUESTION_MARK_USED; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{ @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + let by_ref = !cx.type_is_copy_modulo_regions(caller_ty) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index 21cd3367262..1b0c0a4956f 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local}; diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 313e4083256..3ade6bcee84 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -88,7 +88,7 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op cx.typeck_results() .closure_min_captures .get(def_id) - .map_or(true, |m| { + .is_none_or(|m| { m.values().all(|places| { places .iter() diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs index d0dbff081f9..347540e7344 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 79baa914b03..8e3472b1b5a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{get_parent_expr, peel_middle_ty_refs}; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX); + let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index b27bb2e78af..06c85433806 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index abe13a97c0d..0176077c70e 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -93,7 +93,7 @@ impl SingleCallFn { .tcx .hir() .maybe_body_owned_by(fn_def_id) - .map_or(true, |body| is_in_test_function(cx.tcx, body.value.hir_id)) + .is_none_or(|body| is_in_test_function(cx.tcx, body.value.hir_id)) || match cx.tcx.hir_node(fn_hir_id) { Node::Item(item) => is_from_proc_macro(cx, item), Node::ImplItem(item) => is_from_proc_macro(cx, item), diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 8dd99858793..2941b9c3960 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::Msrv; use rustc_attr::{StabilityLevel, StableSince}; use rustc_errors::Applicability; use rustc_hir::def::Res; diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs index ba2ddac2ec3..0d85b1b858a 100644 --- a/src/tools/clippy/clippy_lints/src/string_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs @@ -1,10 +1,10 @@ use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::path_to_local_id; use clippy_utils::source::{snippet, str_literal_to_char_literal}; use clippy_utils::visitors::{Descend, for_each_expr}; diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 50a1577b288..a1d92c3ac71 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -56,9 +56,10 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Struct(data, _) = &item.kind && let Some(last_field) = data.fields().last() - && let field_ty = cx - .tcx - .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity()) + && let field_ty = cx.tcx.normalize_erasing_regions( + cx.typing_env(), + cx.tcx.type_of(last_field.def_id).instantiate_identity(), + ) && let ty::Array(_, array_len) = *field_ty.kind() && let Some(0) = array_len.try_to_target_usize(cx.tcx) { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 6f3c6682305..99844beb8f0 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro}; use core::hash::{Hash, Hasher}; diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 25fec9f688c..1cb0f837227 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -20,8 +20,8 @@ mod utils; mod wrong_transmute; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::is_in_const_context; +use clippy_utils::msrvs::Msrv; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs index 3507eb9a124..f0b8abf9af6 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_FLOAT_TO_INT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_ast as ast; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs index c5c7ed6d398..e5b9aea6423 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_INT_TO_FLOAT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs index a94cd27c7fd..6d828bad9b3 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_NUM_TO_BYTES; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index bf6700b1b6b..c4a2e20fa9d 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_PTR_TO_PTR; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index eaf927c0005..ef18633d945 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_PTR_TO_REF; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index cad15b1e982..0d5cf45a5e6 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -1,7 +1,7 @@ use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; use rustc_hir_typeck::cast::check_cast; @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( }; if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) - && parent.precedence() > AssocOp::As.precedence() as i8 + && parent.precedence() > ExprPrecedence::Cast { sugg = format!("({sugg})"); } diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs index 07d0f59b91c..99a55f9fc35 100644 --- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{is_from_proc_macro, path_to_local}; use itertools::Itertools; diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 0bba611116b..b79e59f857b 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -337,7 +337,7 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { .src .as_deref() .and_then(|src| src.get(file_pos.pos.to_usize()..)) - .map_or(true, |src| !src.starts_with("unsafe")) + .is_none_or(|src| !src.starts_with("unsafe")) } // Checks if any parent {expression, statement, block, local, const, static} diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index 6eef582b4b2..0702f6d1e74 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -145,7 +145,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) - } while let Some(id) = locals_to_check.pop() { if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) { - if !l.ty.map_or(true, |ty| matches!(ty.kind, TyKind::Infer)) { + if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer)) { return false; } if let Some(e) = l.init { diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index c7c837de505..9d26bf930a1 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -1,9 +1,9 @@ #![allow(clippy::wildcard_imports, clippy::enum_glob_use)] use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::over; use rustc_ast::PatKind::*; use rustc_ast::mut_visit::*; diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index 9fd6ebccd02..17ee5fc20ca 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 8de062a8fc1..c3843279ba2 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -93,7 +93,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive while let Some(c) = s.next() { r.push( if replace(&mut prev_upper, c.is_ascii_uppercase()) - && s.clone().next().map_or(true, |c| c.is_ascii_uppercase()) + && s.clone().next().is_none_or(|c| c.is_ascii_uppercase()) { c.to_ascii_lowercase() } else { diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index f5cf4a586fd..05c5be03002 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::same_type_and_consts; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args && parameters .as_ref() - .map_or(true, |params| params.parenthesized == GenericArgsParentheses::No) + .is_none_or(|params| params.parenthesized == GenericArgsParentheses::No) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) // expensive, should be last check diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 1bf24083665..51001d374b4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -3,7 +3,7 @@ use rustc_ast::LitIntType; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{ - self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, + self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -278,6 +278,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind"); self.body(field!(anon_const.body)); }, + ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), } } @@ -611,14 +612,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { bind!(self, value, length); kind!("Repeat({value}, {length})"); self.expr(value); - match length.value { - ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"), - ArrayLen::Body(const_arg) => { - bind!(self, const_arg); - chain!(self, "let ArrayLen::Body({const_arg}) = {length}"); - self.const_arg(const_arg); - }, - } + self.const_arg(length); }, ExprKind::Err(_) => kind!("Err(_)"), ExprKind::DropTemps(expr) => { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 96397375d5e..a5fad68eea1 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -5,8 +5,8 @@ use rustc_hir as hir; use rustc_hir::Item; use rustc_hir::def::DefKind; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::FloatTy; use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::{self, FloatTy}; use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; @@ -32,9 +32,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { let mod_name = &cx.tcx.item_name(local_def_id.to_def_id()); if mod_name.as_str() == "paths" && let hir::ItemKind::Const(.., body_id) = item.kind - && let Some(Constant::Vec(path)) = - ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(item.owner_id), cx.tcx.typeck(item.owner_id)) - .eval_simple(cx.tcx.hir().body(body_id).value) + && let Some(Constant::Vec(path)) = ConstEvalCtxt::with_env( + cx.tcx, + ty::TypingEnv::post_analysis(cx.tcx, item.owner_id), + cx.tcx.typeck(item.owner_id), + ) + .eval_simple(cx.tcx.hir().body(body_id).value) && let Some(path) = path .iter() .map(|x| { diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 9bcff9d7bce..ef1c46154d2 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -2,9 +2,9 @@ use std::collections::BTreeMap; use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs index fdc1d06e67a..05f85650769 100644 --- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs @@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures; use rustc_ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node}; +use rustc_hir::{ConstArgKind, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::declare_lint_pass; @@ -60,8 +60,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects { // doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg. // the const item depends on `#[cfg]s` and has different values in different compilation // sessions). - else if let ExprKind::Repeat(inner_expr, length) = expr.kind - && let ArrayLen::Body(const_arg) = length + else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind && let ConstArgKind::Anon(anon_const) = const_arg.kind && let length_expr = hir_map.body(anon_const.body).value && !length_expr.span.from_expansion() diff --git a/src/tools/clippy/clippy_lints/src/zombie_processes.rs b/src/tools/clippy/clippy_lints/src/zombie_processes.rs index 8d9241cc7d9..4a13c10166f 100644 --- a/src/tools/clippy/clippy_lints/src/zombie_processes.rs +++ b/src/tools/clippy/clippy_lints/src/zombie_processes.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// let mut child = Command::new("ls").spawn().expect("failed to execute child"); /// child.wait().expect("failed to wait on child"); /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.83.0"] pub ZOMBIE_PROCESSES, suspicious, "not waiting on a spawned child process" diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index d8d5733da1c..945827c98c1 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,15 +1,22 @@ [package] name = "clippy_utils" -version = "0.1.84" +# begin autogenerated version +version = "0.1.85" +# end autogenerated version edition = "2021" -publish = false +description = "Helpful tools for writing lints, provided as they are used in Clippy" +repository = "https://github.com/rust-lang/rust-clippy" +readme = "README.md" +license = "MIT OR Apache-2.0" +keywords = ["clippy", "lint", "utils"] +categories = ["development-tools"] [dependencies] -clippy_config = { path = "../clippy_config" } arrayvec = { version = "0.7", default-features = false } itertools = "0.12" # FIXME(f16_f128): remove when no longer needed for parsing rustc_apfloat = "0.2.0" +serde = { version = "1.0", features = ["derive"] } [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md new file mode 100644 index 00000000000..61476a82ba0 --- /dev/null +++ b/src/tools/clippy/clippy_utils/README.md @@ -0,0 +1,40 @@ +# `clippy-utils` + +Helpful tools for writing lints, provided as they are used in Clippy. + +## Usage + +This crate is only guaranteed to build with this `nightly` toolchain: + +<!-- begin autogenerated nightly --> +``` +nightly-2024-11-28 +``` +<!-- end autogenerated nightly --> + +To use `clippy-utils` in your lint, add the following to your `Cargo.toml`: + +``` +clippy_utils = "0.1.XY" +``` + +`XY` is the version of the nightly toolchain above and can be determined with `rustc +nightly-YYYY-MM-DD -V`. + +## :warning: Stability :warning: + +No stability guarantees are made for this crate! Use at your own risk. + +Function signatures can change or be removed without replacement without any prior notice. + +## LICENSE + +<!-- REUSE-IgnoreStart --> + +Copyright 2014-2024 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 +<[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license +<[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your option. Files in the project may +not be copied, modified, or distributed except according to those terms. + +<!-- REUSE-IgnoreEnd --> diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index c90f4a6ebfe..620a9b56eb5 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), - (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re), - (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind, + (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), + (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, _ => false, } } diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index edc9c6ccdff..b2a6657baad 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -27,7 +27,10 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, DeprecationStatus)] = &[ ("cyclomatic_complexity", DeprecationStatus::Replaced("cognitive_complexity")), ("dump", DeprecationStatus::None), ("msrv", DeprecationStatus::None), + // The following attributes are for the 3rd party crate authors. + // See book/src/attribs.md ("has_significant_drop", DeprecationStatus::None), + ("format_args", DeprecationStatus::None), ]; pub struct LimitStack { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 52c98646289..43ddf06730d 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -226,7 +226,7 @@ impl Constant<'_> { .zip(r) .zip(tys) .map(|((li, ri), cmp_type)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.is_none_or(|o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), _ => None, }, @@ -236,7 +236,7 @@ impl Constant<'_> { }; iter::zip(l, r) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.is_none_or(|o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))) }, (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index ea866a78d87..7f3e331e7f6 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHasher; use rustc_hir::MatchSource::TryDesugar; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, + AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty, TyKind, @@ -266,14 +266,6 @@ impl HirEqInterExpr<'_, '_, '_> { }) } - pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool { - match (left, right) { - (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, - (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct), - (_, _) => false, - } - } - pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.inner.maybe_typeck_results.replace(( @@ -383,7 +375,7 @@ impl HirEqInterExpr<'_, '_, '_> { }, (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r), (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { - self.eq_expr(le, re) && self.eq_array_length(ll, rl) + self.eq_expr(le, re) && self.eq_const_arg(ll, rl) }, (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)), (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => { @@ -469,8 +461,10 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), + (ConstArgKind::Infer(..), ConstArgKind::Infer(..)) => true, // Use explicit match for now since ConstArg is undergoing flux. - (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => { + (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) + | (ConstArgKind::Infer(..), _) | (_, ConstArgKind::Infer(..)) => { false }, } @@ -545,7 +539,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool { if left.parenthesized == right.parenthesized { over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work - && over(left.constraints, right.constraints, |l, r| self.eq_assoc_type_binding(l, r)) + && over(left.constraints, right.constraints, |l, r| self.eq_assoc_eq_constraint(l, r)) } else { false } @@ -589,7 +583,7 @@ impl HirEqInterExpr<'_, '_, '_> { pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { match (&left.kind, &right.kind) { (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl), + (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) @@ -602,12 +596,13 @@ impl HirEqInterExpr<'_, '_, '_> { } } - fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { + /// Checks whether two constraints designate the same equality constraint (same name, and same + /// type or const). + fn eq_assoc_eq_constraint(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { + // TODO: this could be extended to check for identical associated item bound constraints left.ident.name == right.ident.name - && self.eq_ty( - left.ty().expect("expected assoc type binding"), - right.ty().expect("expected assoc type binding"), - ) + && (both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r)) + || both_some_and(left.ct(), right.ct(), |l, r| self.eq_const_arg(l, r))) } fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool { @@ -727,6 +722,11 @@ pub fn both<X>(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bo .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y))) } +/// Checks if the two `Option`s are both `Some` and pass the predicate function. +pub fn both_some_and<X, Y>(l: Option<X>, r: Option<Y>, mut pred: impl FnMut(X, Y) -> bool) -> bool { + l.is_some_and(|l| r.is_some_and(|r| pred(l, r))) +} + /// Checks if two slices are equal as per `eq_fn`. pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) @@ -1002,7 +1002,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, ExprKind::Repeat(e, len) => { self.hash_expr(e); - self.hash_array_length(len); + self.hash_const_arg(len); }, ExprKind::Ret(ref e) => { if let Some(e) = *e { @@ -1195,7 +1195,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, &TyKind::Array(ty, len) => { self.hash_ty(ty); - self.hash_array_length(len); + self.hash_const_arg(len); }, TyKind::Pat(ty, pat) => { self.hash_ty(ty); @@ -1246,13 +1246,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_array_length(&mut self, length: ArrayLen<'_>) { - match length { - ArrayLen::Infer(..) => {}, - ArrayLen::Body(ct) => self.hash_const_arg(ct), - } - } - pub fn hash_body(&mut self, body_id: BodyId) { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id)); @@ -1264,6 +1257,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Path(path) => self.hash_qpath(path), ConstArgKind::Anon(anon) => self.hash_body(anon.body), + ConstArgKind::Infer(..) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 6408cc938cb..8d48cdd3cbb 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; extern crate rustc_trait_selection; +extern crate smallvec; #[macro_use] pub mod sym_helper; @@ -65,6 +66,7 @@ pub mod higher; mod hir_utils; pub mod macros; pub mod mir; +pub mod msrvs; pub mod numeric_literal; pub mod paths; pub mod ptr; @@ -89,7 +91,6 @@ use std::hash::BuildHasherDefault; use std::iter::{once, repeat}; use std::sync::{Mutex, MutexGuard, OnceLock}; -use clippy_config::types::DisallowedPath; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; @@ -97,12 +98,12 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::definitions::{DefPath, DefPathData}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ - self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, + self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, @@ -116,8 +117,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, - Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, + self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, Ty, TyCtxt, + TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; @@ -748,18 +749,6 @@ pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item = def_path_res(tcx, path).into_iter().filter_map(|res| res.opt_def_id()) } -/// Creates a map of disallowed items to the reason they were disallowed. -pub fn create_disallowed_map( - tcx: TyCtxt<'_>, - disallowed: &'static [DisallowedPath], -) -> DefIdMap<(&'static str, Option<&'static str>)> { - disallowed - .iter() - .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x.reason())) - .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason)))) - .collect() -} - /// Convenience function to get the `DefId` of a trait by path. /// It could be a trait or trait alias. /// @@ -921,7 +910,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { _ => false, }, ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), - ExprKind::Repeat(x, ArrayLen::Body(len)) => { + ExprKind::Repeat(x, len) => { if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node @@ -951,7 +940,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: & .. }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), - ExprKind::Repeat(_, ArrayLen::Body(len)) => { + ExprKind::Repeat(_, len) => { if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node @@ -1581,7 +1570,7 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool { let ty = cx.typeck_results().expr_ty(expr); if let Some(Range { start, end, limits }) = Range::hir(expr) { - let start_is_none_or_min = start.map_or(true, |start| { + let start_is_none_or_min = start.is_none_or(|start| { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) @@ -1593,7 +1582,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti false } }); - let end_is_none_or_max = end.map_or(true, |end| match limits { + let end_is_none_or_max = end.is_none_or(|end| match limits { RangeLimits::Closed => { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) @@ -2715,10 +2704,10 @@ pub enum DefinedTy<'tcx> { /// Used for function signatures, and constant and static values. The type is /// in the context of its definition site. We also track the `def_id` of its /// definition site. - /// + /// /// WARNING: As the `ty` in in the scope of the definition, not of the function /// using it, you must be very careful with how you use it. Using it in the wrong - /// scope easily results in ICEs. + /// scope easily results in ICEs. Mir { def_site_def_id: Option<DefId>, ty: Binder<'tcx, Ty<'tcx>>, @@ -2844,7 +2833,7 @@ impl<'tcx> ExprUseNode<'tcx> { Self::ConstStatic(id) => Some(DefinedTy::Mir { def_site_def_id: Some(id.def_id.to_def_id()), ty: Binder::dummy(cx.tcx.type_of(id).instantiate_identity()), - }), + }), Self::Return(id) => { if let Node::Expr(Expr { kind: ExprKind::Closure(c), @@ -2857,7 +2846,10 @@ impl<'tcx> ExprUseNode<'tcx> { } } else { let ty = cx.tcx.fn_sig(id).instantiate_identity().output(); - Some(DefinedTy::Mir { def_site_def_id: Some(id.def_id.to_def_id()), ty }) + Some(DefinedTy::Mir { + def_site_def_id: Some(id.def_id.to_def_id()), + ty, + }) } }, Self::Field(field) => match get_parent_expr_for_hir(cx, field.hir_id) { @@ -2874,8 +2866,8 @@ impl<'tcx> ExprUseNode<'tcx> { .map(|f| (adt, f)) }) .map(|(adt, field_def)| DefinedTy::Mir { - def_site_def_id: Some(adt.did()), - ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()), + def_site_def_id: Some(adt.did()), + ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()), }), _ => None, }, @@ -2885,9 +2877,9 @@ impl<'tcx> ExprUseNode<'tcx> { Some(match hir_ty { Some(hir_ty) => DefinedTy::Hir(hir_ty), None => DefinedTy::Mir { - def_site_def_id: sig.predicates_id(), + def_site_def_id: sig.predicates_id(), ty, - } + }, }) }, Self::MethodArg(id, _, i) => { diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index 9c4d19ac1f1..45beb146eb6 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -1,5 +1,6 @@ #![allow(clippy::similar_names)] // `expr` and `expn` +use crate::get_unique_attr; use crate::visitors::{Descend, for_each_expr_without_closures}; use arrayvec::ArrayVec; @@ -7,7 +8,7 @@ use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{Lrc, OnceLock}; use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym}; @@ -36,7 +37,9 @@ pub fn is_format_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool { if let Some(name) = cx.tcx.get_diagnostic_name(macro_def_id) { FORMAT_MACRO_DIAG_ITEMS.contains(&name) } else { - false + // Allow users to tag any macro as being format!-like + // TODO: consider deleting FORMAT_MACRO_DIAG_ITEMS and using just this method + get_unique_attr(cx.sess(), cx.tcx.get_attrs_unchecked(macro_def_id), "format_args").is_some() } } @@ -93,7 +96,7 @@ pub fn expn_is_local(expn: ExpnId) -> bool { std::iter::once((expn, data)) .chain(backtrace) .find_map(|(_, data)| data.macro_def_id) - .map_or(true, DefId::is_local) + .is_none_or(DefId::is_local) } /// Returns an iterator of macro expansions that created the given span. diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 6b3078f52af..17e6558a41c 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -2,7 +2,7 @@ use super::possible_origin::PossibleOriginVisitor; use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::{BitSet, HybridBitSet}; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{self, Mutability}; @@ -21,14 +21,14 @@ struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { possible_borrower: TransitiveRelation, body: &'b mir::Body<'tcx>, cx: &'a LateContext<'tcx>, - possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, + possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>, } impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> { fn new( cx: &'a LateContext<'tcx>, body: &'b mir::Body<'tcx>, - possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, + possible_origin: FxHashMap<mir::Local, BitSet<mir::Local>>, ) -> Self { Self { possible_borrower: TransitiveRelation::default(), @@ -119,7 +119,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> { let mut mutable_variables: Vec<mir::Local> = mutable_borrowers .iter() .filter_map(|r| self.possible_origin.get(r)) - .flat_map(HybridBitSet::iter) + .flat_map(BitSet::iter) .collect(); if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() { @@ -171,7 +171,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { #[allow(clippy::module_name_repetitions)] pub struct PossibleBorrowerMap<'b, 'tcx> { /// Mapping `Local -> its possible borrowers` - pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, + pub map: FxHashMap<mir::Local, BitSet<mir::Local>>, maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>, // Caches to avoid allocation of `BitSet` on every query pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>), diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs index 4157b3f4930..47b93aad20c 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs @@ -1,7 +1,7 @@ use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir; @@ -22,7 +22,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> { } } - pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> { + pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, BitSet<mir::Local>> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { if is_copy(cx, self.body.local_decls[row].ty) { diff --git a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs index 7fe2960739f..74d1f60af71 100644 --- a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs +++ b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_middle::mir; #[derive(Default)] @@ -12,8 +12,8 @@ impl TransitiveRelation { self.relations.entry(a).or_default().push(b); } - pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> { - let mut seen = HybridBitSet::new_empty(domain_size); + pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> BitSet<mir::Local> { + let mut seen = BitSet::new_empty(domain_size); let mut stack = vec![a]; while let Some(u) = stack.pop() { if let Some(edges) = self.relations.get(&u) { diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 764ca8fb50a..1eb7d54e133 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -121,7 +121,7 @@ impl Msrv { } pub fn meets(&self, required: RustcVersion) -> bool { - self.current().map_or(true, |msrv| msrv >= required) + self.current().is_none_or(|msrv| msrv >= required) } fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> { diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 11a98b02f33..bb40a9430a7 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -36,7 +36,7 @@ pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"]; pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; // Paths in clippy itself -pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"]; +pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; // Paths in external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates 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 3c9ea4bfaf4..df3f10d6179 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 @@ -3,7 +3,7 @@ // of terminologies might not be relevant in the context of Clippy. Note that its behavior might // differ from the time of `rustc` even if the name stays the same. -use clippy_config::msrvs::{self, Msrv}; +use crate::msrvs::{self, Msrv}; use hir::LangItem; use rustc_attr::StableSince; use rustc_const_eval::check_consts::ConstCx; @@ -409,8 +409,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return false; } - let (infcx, param_env) = - tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); // FIXME(const_trait_impl) constness let obligation = Obligation::new( tcx, diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 03e1a814a86..260d1b801e3 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + cx.type_is_copy_modulo_regions(ty) } /// This checks whether a given type is known to implement Debug. @@ -226,7 +226,14 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, trait_id, None, args.iter().map(|&x| Some(x))) + implements_trait_with_env_from_iter( + cx.tcx, + cx.typing_env(), + ty, + trait_id, + None, + args.iter().map(|&x| Some(x)), + ) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. @@ -1262,7 +1269,8 @@ pub fn make_normalized_projection_with_regions<'tcx>( } let cause = ObligationCause::dummy(); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); - match infcx.at(&cause, param_env) + match infcx + .at(&cause, param_env) .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty.value), @@ -1278,7 +1286,10 @@ pub fn make_normalized_projection_with_regions<'tcx>( pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let cause = ObligationCause::dummy(); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); - infcx.at(&cause, param_env).query_normalize(ty).map_or(ty, |ty| ty.value) + infcx + .at(&cause, param_env) + .query_normalize(ty) + .map_or(ty, |ty| ty.value) } /// Checks if the type is `core::mem::ManuallyDrop<_>` diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index c8c25456f69..37f72966892 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -27,7 +27,7 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> } pub fn is_potentially_mutated<'tcx>(variable: HirId, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool { - mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&variable)) + mutated_variables(expr, cx).is_none_or(|mutated| mutated.contains(&variable)) } pub fn is_potentially_local_place(local_id: HirId, place: &Place<'_>) -> bool { diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index e32e0cb3604..fb159ca2ae0 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,4 +1,6 @@ [toolchain] -channel = "nightly-2024-11-14" +# begin autogenerated nightly +channel = "nightly-2024-11-28" +# end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed index 9b5bf736f13..928596d0809 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -8,8 +8,8 @@ extern crate rustc_lint; extern crate rustc_middle; #[macro_use] extern crate rustc_session; -use clippy_config::msrvs::Msrv; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs index c5bde47e4ce..50b28648ccc 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -8,8 +8,8 @@ extern crate rustc_lint; extern crate rustc_middle; #[macro_use] extern crate rustc_session; -use clippy_config::msrvs::Msrv; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout index d9e3f864f12..1a608734ada 100644 --- a/src/tools/clippy/tests/ui/author/repeat.stdout +++ b/src/tools/clippy/tests/ui/author/repeat.stdout @@ -1,8 +1,7 @@ if let ExprKind::Repeat(value, length) = expr.kind && let ExprKind::Lit(ref lit) = value.kind && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node - && let ArrayLen::Body(const_arg) = length - && let ConstArgKind::Anon(anon_const) = const_arg.kind + && let ConstArgKind::Anon(anon_const) = length.kind && expr1 = &cx.tcx.hir().body(anon_const.body).value && let ExprKind::Lit(ref lit1) = expr1.kind && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.rs b/src/tools/clippy/tests/ui/crashes/ice-10645.rs deleted file mode 100644 index 6e126aff751..00000000000 --- a/src/tools/clippy/tests/ui/crashes/ice-10645.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@compile-flags: --cap-lints=warn -// https://github.com/rust-lang/rust-clippy/issues/10645 - -#![warn(clippy::future_not_send)] -pub async fn bar<'a, T: 'a>(_: T) {} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr deleted file mode 100644 index 0269072b88b..00000000000 --- a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: future cannot be sent between threads safely - --> tests/ui/crashes/ice-10645.rs:5:1 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `bar` is not `Send` - | -note: captured value is not `Send` - --> tests/ui/crashes/ice-10645.rs:5:29 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^ has type `T` which is not `Send` - = note: `T` doesn't implement `std::marker::Send` - = note: `-D clippy::future-not-send` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` - -warning: 1 warning emitted - diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed new file mode 100644 index 00000000000..c85f384fd6e --- /dev/null +++ b/src/tools/clippy/tests/ui/derivable_impls.fixed @@ -0,0 +1,295 @@ +#![allow(dead_code)] + +use std::collections::HashMap; + +#[derive(Default)] +struct FooDefault<'a> { + a: bool, + b: i32, + c: u64, + d: Vec<i32>, + e: FooND1, + f: FooND2, + g: HashMap<i32, i32>, + h: (i32, Vec<i32>), + i: [Vec<i32>; 3], + j: [i32; 5], + k: Option<i32>, + l: &'a [i32], +} + + +#[derive(Default)] +struct TupleDefault(bool, i32, u64); + + +struct FooND1 { + a: bool, +} + +impl std::default::Default for FooND1 { + fn default() -> Self { + Self { a: true } + } +} + +struct FooND2 { + a: i32, +} + +impl std::default::Default for FooND2 { + fn default() -> Self { + Self { a: 5 } + } +} + +struct FooNDNew { + a: bool, +} + +impl FooNDNew { + fn new() -> Self { + Self { a: true } + } +} + +impl Default for FooNDNew { + fn default() -> Self { + Self::new() + } +} + +struct FooNDVec(Vec<i32>); + +impl Default for FooNDVec { + fn default() -> Self { + Self(vec![5, 12]) + } +} + +#[derive(Default)] +struct StrDefault<'a>(&'a str); + + +#[derive(Default)] +struct AlreadyDerived(i32, bool); + +macro_rules! mac { + () => { + 0 + }; + ($e:expr) => { + struct X(u32); + impl Default for X { + fn default() -> Self { + Self($e) + } + } + }; +} + +mac!(0); + +#[derive(Default)] +struct Y(u32); + +struct RustIssue26925<T> { + a: Option<T>, +} + +// We should watch out for cases where a manual impl is needed because a +// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925). +// For example, a struct with Option<T> does not require T: Default, but a derive adds +// that type bound anyways. So until #26925 get fixed we should disable lint +// for the following case +impl<T> Default for RustIssue26925<T> { + fn default() -> Self { + Self { a: None } + } +} + +struct SpecializedImpl<A, B> { + a: A, + b: B, +} + +impl<T: Default> Default for SpecializedImpl<T, T> { + fn default() -> Self { + Self { + a: T::default(), + b: T::default(), + } + } +} + +#[derive(Default)] +struct WithoutSelfCurly { + a: bool, +} + + +#[derive(Default)] +struct WithoutSelfParan(bool); + + +// https://github.com/rust-lang/rust-clippy/issues/7655 + +pub struct SpecializedImpl2<T> { + v: Vec<T>, +} + +impl Default for SpecializedImpl2<String> { + fn default() -> Self { + Self { v: Vec::new() } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/7654 + +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, +} + +/// `#000000` +impl Default for Color { + fn default() -> Self { + Color { r: 0, g: 0, b: 0 } + } +} + +pub struct Color2 { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl Default for Color2 { + /// `#000000` + fn default() -> Self { + Self { r: 0, g: 0, b: 0 } + } +} + +#[derive(Default)] +pub struct RepeatDefault1 { + a: [i8; 32], +} + + +pub struct RepeatDefault2 { + a: [i8; 33], +} + +impl Default for RepeatDefault2 { + fn default() -> Self { + RepeatDefault2 { a: [0; 33] } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/7753 + +pub enum IntOrString { + Int(i32), + String(String), +} + +impl Default for IntOrString { + fn default() -> Self { + IntOrString::Int(0) + } +} + +#[derive(Default)] +pub enum SimpleEnum { + Foo, + #[default] + Bar, +} + + +pub enum NonExhaustiveEnum { + Foo, + #[non_exhaustive] + Bar, +} + +impl Default for NonExhaustiveEnum { + fn default() -> Self { + NonExhaustiveEnum::Bar + } +} + +// https://github.com/rust-lang/rust-clippy/issues/10396 + +#[derive(Default)] +struct DefaultType; + +struct GenericType<T = DefaultType> { + t: T, +} + +impl Default for GenericType { + fn default() -> Self { + Self { t: Default::default() } + } +} + +struct InnerGenericType<T> { + t: T, +} + +impl Default for InnerGenericType<DefaultType> { + fn default() -> Self { + Self { t: Default::default() } + } +} + +struct OtherGenericType<T = DefaultType> { + inner: InnerGenericType<T>, +} + +impl Default for OtherGenericType { + fn default() -> Self { + Self { + inner: Default::default(), + } + } +} + +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box<dyn T>, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::<S>::default() adjusts to Box<dyn T> + inner: Box::<S>::default(), + } + } + } +} + +mod issue11368 { + pub struct A { + a: u32, + } + + impl Default for A { + #[track_caller] + fn default() -> Self { + Self { a: 0 } + } + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs index 58f7771b627..21d73ba8b77 100644 --- a/src/tools/clippy/tests/ui/derivable_impls.rs +++ b/src/tools/clippy/tests/ui/derivable_impls.rs @@ -1,7 +1,5 @@ #![allow(dead_code)] -//@no-rustfix: need to change the suggestion to a multipart suggestion - use std::collections::HashMap; struct FooDefault<'a> { diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr index d3adfa60e10..c22569145bd 100644 --- a/src/tools/clippy/tests/ui/derivable_impls.stderr +++ b/src/tools/clippy/tests/ui/derivable_impls.stderr @@ -1,5 +1,5 @@ error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:22:1 + --> tests/ui/derivable_impls.rs:20:1 | LL | / impl std::default::Default for FooDefault<'_> { LL | | fn default() -> Self { @@ -12,15 +12,14 @@ LL | | } | = note: `-D clippy::derivable-impls` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::derivable_impls)]` - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct FooDefault<'a> { +LL ~ struct FooDefault<'a> { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:43:1 + --> tests/ui/derivable_impls.rs:41:1 | LL | / impl std::default::Default for TupleDefault { LL | | fn default() -> Self { @@ -29,15 +28,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct TupleDefault(bool, i32, u64); +LL ~ struct TupleDefault(bool, i32, u64); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:95:1 + --> tests/ui/derivable_impls.rs:93:1 | LL | / impl Default for StrDefault<'_> { LL | | fn default() -> Self { @@ -46,15 +44,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct StrDefault<'a>(&'a str); +LL ~ struct StrDefault<'a>(&'a str); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:121:1 + --> tests/ui/derivable_impls.rs:119:1 | LL | / impl Default for Y { LL | | fn default() -> Self { @@ -63,15 +60,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct Y(u32); +LL ~ struct Y(u32); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:160:1 + --> tests/ui/derivable_impls.rs:158:1 | LL | / impl Default for WithoutSelfCurly { LL | | fn default() -> Self { @@ -80,15 +76,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct WithoutSelfCurly { +LL ~ struct WithoutSelfCurly { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:168:1 + --> tests/ui/derivable_impls.rs:166:1 | LL | / impl Default for WithoutSelfParan { LL | | fn default() -> Self { @@ -97,15 +92,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct WithoutSelfParan(bool); +LL ~ struct WithoutSelfParan(bool); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:218:1 + --> tests/ui/derivable_impls.rs:216:1 | LL | / impl Default for RepeatDefault1 { LL | | fn default() -> Self { @@ -114,15 +108,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | pub struct RepeatDefault1 { +LL ~ pub struct RepeatDefault1 { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:252:1 + --> tests/ui/derivable_impls.rs:250:1 | LL | / impl Default for SimpleEnum { LL | | fn default() -> Self { @@ -131,14 +124,11 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it... +help: replace the manual implementation with a derive attribute and mark the default variant | LL + #[derive(Default)] -LL | pub enum SimpleEnum { - | -help: ...and mark the default variant - | +LL ~ pub enum SimpleEnum { +LL | Foo, LL ~ #[default] LL ~ Bar, | diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed new file mode 100644 index 00000000000..d4ae810d738 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.fixed @@ -0,0 +1,40 @@ +#![warn(clippy::doc_include_without_cfg)] +// Should not lint. +#![doc(html_playground_url = "https://playground.example.com/")] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +// Should not lint. +#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#![doc = "some doc"] +//! more doc + +macro_rules! man_link { + ($a:literal, $b:literal) => { + concat!($a, $b) + }; +} + +// Should not lint! +macro_rules! tst { + ($(#[$attr:meta])*) => { + $(#[$attr])* + fn blue() { + println!("Hello, world!"); + } + } +} + +tst! { + /// This is a test with no included file +} + +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +// Should not lint. +#[doc = man_link!("bla", "blob")] +#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#[doc = "some doc"] +/// more doc +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs new file mode 100644 index 00000000000..c82f6bf2035 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.rs @@ -0,0 +1,40 @@ +#![warn(clippy::doc_include_without_cfg)] +// Should not lint. +#![doc(html_playground_url = "https://playground.example.com/")] +#![doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +// Should not lint. +#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#![doc = "some doc"] +//! more doc + +macro_rules! man_link { + ($a:literal, $b:literal) => { + concat!($a, $b) + }; +} + +// Should not lint! +macro_rules! tst { + ($(#[$attr:meta])*) => { + $(#[$attr])* + fn blue() { + println!("Hello, world!"); + } + } +} + +tst! { + /// This is a test with no included file +} + +#[doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +// Should not lint. +#[doc = man_link!("bla", "blob")] +#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#[doc = "some doc"] +/// more doc +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr new file mode 100644 index 00000000000..17ea53c7c31 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_include_without_cfg.stderr @@ -0,0 +1,17 @@ +error: included a file in documentation unconditionally + --> tests/ui/doc/doc_include_without_cfg.rs:4:1 + | +LL | #![doc = include_str!("../approx_const.rs")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))]` + | + = note: `-D clippy::doc-include-without-cfg` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_include_without_cfg)]` + +error: included a file in documentation unconditionally + --> tests/ui/doc/doc_include_without_cfg.rs:31:1 + | +LL | #[doc = include_str!("../approx_const.rs")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs index 17d2ed9f50c..aa964af3fc2 100644 --- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs +++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs @@ -134,4 +134,11 @@ struct Human<'a> { pub name: &'a str, } +// https://github.com/rust-lang/rust-clippy/issues/13578 +mod issue_13578 { + pub trait Foo {} + + impl<'a, T: 'a> Foo for Option<T> where &'a T: Foo {} +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs index f04715f4f01..7590de3751a 100644 --- a/src/tools/clippy/tests/ui/format_args_unfixable.rs +++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs @@ -119,3 +119,32 @@ fn test2() { format!("something failed at {}", Location::caller()) ); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let error = Error::new(ErrorKind::Other, "bad thing"); + let x = 'x'; + + usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args +} diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.stderr b/src/tools/clippy/tests/ui/format_args_unfixable.stderr index 20cd0bb8c55..1b4b683fd6c 100644 --- a/src/tools/clippy/tests/ui/format_args_unfixable.stderr +++ b/src/tools/clippy/tests/ui/format_args_unfixable.stderr @@ -174,5 +174,68 @@ LL | panic!("error: {}", format!("something failed at {}", Location::caller( = help: combine the `format!(..)` arguments with the outer `panic!(..)` call = help: or consider changing `format!` to `format_args!` -error: aborting due to 18 previous errors +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:136:5 + | +LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:138:5 + | +LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:140:5 + | +LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:142:5 + | +LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:144:5 + | +LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:146:5 + | +LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:148:5 + | +LL | usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: aborting due to 25 previous errors diff --git a/src/tools/clippy/tests/ui/future_not_send.rs b/src/tools/clippy/tests/ui/future_not_send.rs index 9274340b5ca..626ee6de9e4 100644 --- a/src/tools/clippy/tests/ui/future_not_send.rs +++ b/src/tools/clippy/tests/ui/future_not_send.rs @@ -1,6 +1,7 @@ #![warn(clippy::future_not_send)] use std::cell::Cell; +use std::future::Future; use std::rc::Rc; use std::sync::Arc; @@ -63,6 +64,22 @@ where t } +async fn maybe_send_generic_future<T>(t: T) -> T { + async { true }.await; + t +} + +async fn maybe_send_generic_future2<F: Fn() -> Fut, Fut: Future>(f: F) { + async { true }.await; + let res = f(); + async { true }.await; +} + +async fn generic_future_always_unsend<T>(_: Rc<T>) { + //~^ ERROR: future cannot be sent between threads safely + async { true }.await; +} + async fn generic_future_send<T>(t: T) where T: Send, @@ -71,7 +88,6 @@ where } async fn unclear_future<T>(t: T) {} -//~^ ERROR: future cannot be sent between threads safely fn main() { let rc = Rc::new([1, 2, 3]); diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr index 67677d6367a..3807c747013 100644 --- a/src/tools/clippy/tests/ui/future_not_send.stderr +++ b/src/tools/clippy/tests/ui/future_not_send.stderr @@ -1,11 +1,11 @@ error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:7:1 + --> tests/ui/future_not_send.rs:8:1 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:9:20 + --> tests/ui/future_not_send.rs:10:20 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -14,7 +14,7 @@ LL | async { true }.await | ^^^^^ await occurs here, with `rc` maybe used later = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:7:39 + --> tests/ui/future_not_send.rs:8:39 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync` @@ -23,13 +23,13 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:12:1 + --> tests/ui/future_not_send.rs:13:1 | LL | pub async fn public_future(rc: Rc<[u8]>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:14:20 + --> tests/ui/future_not_send.rs:15:20 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -39,45 +39,45 @@ LL | async { true }.await; = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:21:1 + --> tests/ui/future_not_send.rs:22:1 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:21:26 + --> tests/ui/future_not_send.rs:22:26 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:21:40 + --> tests/ui/future_not_send.rs:22:40 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync` = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:26:1 + --> tests/ui/future_not_send.rs:27:1 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:26:29 + --> tests/ui/future_not_send.rs:27:29 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:38:5 + --> tests/ui/future_not_send.rs:39:5 | LL | async fn private_future(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:40:24 + --> tests/ui/future_not_send.rs:41:24 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` @@ -87,20 +87,20 @@ LL | async { true }.await; = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:44:5 + --> tests/ui/future_not_send.rs:45:5 | LL | pub async fn public_future(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:44:32 + --> tests/ui/future_not_send.rs:45:32 | LL | pub async fn public_future(&self) { | ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:55:1 + --> tests/ui/future_not_send.rs:56:1 | LL | / async fn generic_future<T>(t: T) -> T LL | | @@ -109,7 +109,7 @@ LL | | T: Send, | |____________^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:61:20 + --> tests/ui/future_not_send.rs:62:20 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -118,17 +118,20 @@ LL | async { true }.await; = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:73:1 + --> tests/ui/future_not_send.rs:78:1 | -LL | async fn unclear_future<T>(t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `unclear_future` is not `Send` +LL | async fn generic_future_always_unsend<T>(_: Rc<T>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send` | -note: captured value is not `Send` - --> tests/ui/future_not_send.rs:73:28 +note: future is not `Send` as this value is used across an await + --> tests/ui/future_not_send.rs:80:20 | -LL | async fn unclear_future<T>(t: T) {} - | ^ has type `T` which is not `Send` - = note: `T` doesn't implement `std::marker::Send` +LL | async fn generic_future_always_unsend<T>(_: Rc<T>) { + | - has type `std::rc::Rc<T>` which is not `Send` +LL | +LL | async { true }.await; + | ^^^^^ await occurs here, with `_` maybe used later + = note: `std::rc::Rc<T>` doesn't implement `std::marker::Send` error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/if_let_mutex.stderr b/src/tools/clippy/tests/ui/if_let_mutex.edition2021.stderr index 45df4ac4d67..984d6adbb2a 100644 --- a/src/tools/clippy/tests/ui/if_let_mutex.stderr +++ b/src/tools/clippy/tests/ui/if_let_mutex.edition2021.stderr @@ -1,5 +1,5 @@ error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:11:5 + --> tests/ui/if_let_mutex.rs:16:5 | LL | if let Err(locked) = m.lock() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -19,7 +19,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]` error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:24:5 + --> tests/ui/if_let_mutex.rs:29:5 | LL | if let Some(locked) = m.lock().unwrap().deref() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -37,7 +37,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:46:5 + --> tests/ui/if_let_mutex.rs:51:5 | LL | if let Ok(i) = mutex.lock() { | ^ ----- this Mutex will remain locked for the entire `if let`-block... @@ -54,7 +54,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:55:5 + --> tests/ui/if_let_mutex.rs:60:5 | LL | if let Ok(_) = m1.lock() { | ^ -- this Mutex will remain locked for the entire `if let`-block... diff --git a/src/tools/clippy/tests/ui/if_let_mutex.rs b/src/tools/clippy/tests/ui/if_let_mutex.rs index bb0eadfca1c..80eee293989 100644 --- a/src/tools/clippy/tests/ui/if_let_mutex.rs +++ b/src/tools/clippy/tests/ui/if_let_mutex.rs @@ -1,3 +1,8 @@ +//@ compile-flags: -Zunstable-options + +//@revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 #![warn(clippy::if_let_mutex)] #![allow(clippy::redundant_pattern_matching)] @@ -9,7 +14,7 @@ fn do_stuff<T>(_: T) {} fn if_let() { let m = Mutex::new(1_u8); if let Err(locked) = m.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -22,7 +27,7 @@ fn if_let() { fn if_let_option() { let m = Mutex::new(Some(0_u8)); if let Some(locked) = m.lock().unwrap().deref() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -44,7 +49,7 @@ fn if_let_different_mutex() { fn mutex_ref(mutex: &Mutex<i32>) { if let Ok(i) = mutex.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(i); } else { let _x = mutex.lock(); diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed index 754fe061c4a..014fbb85c7a 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_trait_impl, abi_vectorcall)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -211,8 +211,4 @@ mod extern_fn { //~^ ERROR: this could be a `const fn` const extern "system-unwind" fn system_unwind() {} //~^ ERROR: this could be a `const fn` - pub const extern "vectorcall" fn std_call() {} - //~^ ERROR: this could be a `const fn` - pub const extern "vectorcall-unwind" fn std_call_unwind() {} - //~^ ERROR: this could be a `const fn` } diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs index 460be0733e0..4f7c2cbcf0b 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_trait_impl, abi_vectorcall)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -211,8 +211,4 @@ mod extern_fn { //~^ ERROR: this could be a `const fn` extern "system-unwind" fn system_unwind() {} //~^ ERROR: this could be a `const fn` - pub extern "vectorcall" fn std_call() {} - //~^ ERROR: this could be a `const fn` - pub extern "vectorcall-unwind" fn std_call_unwind() {} - //~^ ERROR: this could be a `const fn` } diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr index d553c522556..cc7dfd0888d 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -316,27 +316,5 @@ help: make the function `const` LL | const extern "system-unwind" fn system_unwind() {} | +++++ -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5 - | -LL | pub extern "vectorcall" fn std_call() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "vectorcall" fn std_call() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5 - | -LL | pub extern "vectorcall-unwind" fn std_call_unwind() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "vectorcall-unwind" fn std_call_unwind() {} - | +++++ - -error: aborting due to 26 previous errors +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/missing_doc_crate.rs b/src/tools/clippy/tests/ui/missing_doc_crate.rs index e00c7fbfed1..fdb23af279d 100644 --- a/src/tools/clippy/tests/ui/missing_doc_crate.rs +++ b/src/tools/clippy/tests/ui/missing_doc_crate.rs @@ -1,4 +1,5 @@ #![warn(clippy::missing_docs_in_private_items)] +#![allow(clippy::doc_include_without_cfg)] #![doc = include_str!("../../README.md")] fn main() {} diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed index ed4b1c21915..ff7b233f004 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.fixed +++ b/src/tools/clippy/tests/ui/redundant_guards.fixed @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![feature(if_let_guard)] -#![allow(clippy::no_effect, unused, clippy::single_match)] +#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] #[macro_use] @@ -19,15 +19,24 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { - x if x == 0.0 => todo!(), + 0.0 => todo!(), + // Pattern matching NAN is illegal + x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { - x if x == FloatWrapper(0.0) => todo!(), + FloatWrapper(0.0) => todo!(), _ => todo!(), } } +fn issue13681() { + match c"hi" { + x if x == c"hi" => (), + _ => (), + } +} + fn main() { let c = C(1, 2); match c { diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs index adbc4ed16cd..b4d4ef5b170 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.rs +++ b/src/tools/clippy/tests/ui/redundant_guards.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![feature(if_let_guard)] -#![allow(clippy::no_effect, unused, clippy::single_match)] +#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] #[macro_use] @@ -20,6 +20,8 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { x if x == 0.0 => todo!(), + // Pattern matching NAN is illegal + x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { @@ -28,6 +30,13 @@ fn issue11304() { } } +fn issue13681() { + match c"hi" { + x if x == c"hi" => (), + _ => (), + } +} + fn main() { let c = C(1, 2); match c { diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr index fd12e083282..7512546450b 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.stderr +++ b/src/tools/clippy/tests/ui/redundant_guards.stderr @@ -1,19 +1,43 @@ error: redundant guard - --> tests/ui/redundant_guards.rs:34:20 + --> tests/ui/redundant_guards.rs:22:14 | -LL | C(x, y) if let 1 = y => .., - | ^^^^^^^^^ +LL | x if x == 0.0 => todo!(), + | ^^^^^^^^ | = note: `-D clippy::redundant-guards` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::redundant_guards)]` help: try | +LL - x if x == 0.0 => todo!(), +LL + 0.0 => todo!(), + | + +error: redundant guard + --> tests/ui/redundant_guards.rs:28:14 + | +LL | x if x == FloatWrapper(0.0) => todo!(), + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - x if x == FloatWrapper(0.0) => todo!(), +LL + FloatWrapper(0.0) => todo!(), + | + +error: redundant guard + --> tests/ui/redundant_guards.rs:43:20 + | +LL | C(x, y) if let 1 = y => .., + | ^^^^^^^^^ + | +help: try + | LL - C(x, y) if let 1 = y => .., LL + C(x, 1) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:40:20 + --> tests/ui/redundant_guards.rs:49:20 | LL | Some(x) if matches!(x, Some(1) if true) => .., | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +48,7 @@ LL | Some(Some(1)) if true => .., | ~~~~~~~ ~~~~~~~ error: redundant guard - --> tests/ui/redundant_guards.rs:41:20 + --> tests/ui/redundant_guards.rs:50:20 | LL | Some(x) if matches!(x, Some(1)) => { | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +60,7 @@ LL + Some(Some(1)) => { | error: redundant guard - --> tests/ui/redundant_guards.rs:45:20 + --> tests/ui/redundant_guards.rs:54:20 | LL | Some(x) if let Some(1) = x => .., | ^^^^^^^^^^^^^^^ @@ -48,7 +72,7 @@ LL + Some(Some(1)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:46:20 + --> tests/ui/redundant_guards.rs:55:20 | LL | Some(x) if x == Some(2) => .., | ^^^^^^^^^^^^ @@ -60,7 +84,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:47:20 + --> tests/ui/redundant_guards.rs:56:20 | LL | Some(x) if Some(2) == x => .., | ^^^^^^^^^^^^ @@ -72,7 +96,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:72:20 + --> tests/ui/redundant_guards.rs:81:20 | LL | B { e } if matches!(e, Some(A(2))) => .., | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +108,7 @@ LL + B { e: Some(A(2)) } => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:109:20 + --> tests/ui/redundant_guards.rs:118:20 | LL | E::A(y) if y == "not from an or pattern" => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +120,7 @@ LL + E::A("not from an or pattern") => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:116:14 + --> tests/ui/redundant_guards.rs:125:14 | LL | x if matches!(x, Some(0)) => .., | ^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +132,7 @@ LL + Some(0) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:123:14 + --> tests/ui/redundant_guards.rs:132:14 | LL | i if i == -1 => {}, | ^^^^^^^ @@ -120,7 +144,7 @@ LL + -1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:124:14 + --> tests/ui/redundant_guards.rs:133:14 | LL | i if i == 1 => {}, | ^^^^^^ @@ -132,7 +156,7 @@ LL + 1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:186:28 + --> tests/ui/redundant_guards.rs:195:28 | LL | Some(ref x) if x == &1 => {}, | ^^^^^^^ @@ -144,7 +168,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:187:28 + --> tests/ui/redundant_guards.rs:196:28 | LL | Some(ref x) if &1 == x => {}, | ^^^^^^^ @@ -156,7 +180,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:188:28 + --> tests/ui/redundant_guards.rs:197:28 | LL | Some(ref x) if let &2 = x => {}, | ^^^^^^^^^^ @@ -168,7 +192,7 @@ LL + Some(2) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:189:28 + --> tests/ui/redundant_guards.rs:198:28 | LL | Some(ref x) if matches!(x, &3) => {}, | ^^^^^^^^^^^^^^^ @@ -180,7 +204,7 @@ LL + Some(3) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:209:32 + --> tests/ui/redundant_guards.rs:218:32 | LL | B { ref c, .. } if c == &1 => {}, | ^^^^^^^ @@ -192,7 +216,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:210:32 + --> tests/ui/redundant_guards.rs:219:32 | LL | B { ref c, .. } if &1 == c => {}, | ^^^^^^^ @@ -204,7 +228,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:211:32 + --> tests/ui/redundant_guards.rs:220:32 | LL | B { ref c, .. } if let &1 = c => {}, | ^^^^^^^^^^ @@ -216,7 +240,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:212:32 + --> tests/ui/redundant_guards.rs:221:32 | LL | B { ref c, .. } if matches!(c, &1) => {}, | ^^^^^^^^^^^^^^^ @@ -228,7 +252,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:222:26 + --> tests/ui/redundant_guards.rs:231:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -240,7 +264,7 @@ LL + Some(Some("")) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:233:26 + --> tests/ui/redundant_guards.rs:242:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -252,7 +276,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:238:26 + --> tests/ui/redundant_guards.rs:247:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -264,7 +288,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:249:26 + --> tests/ui/redundant_guards.rs:258:26 | LL | Some(Some(x)) if x.starts_with(&[]) => {}, | ^^^^^^^^^^^^^^^^^^ @@ -276,7 +300,7 @@ LL + Some(Some([..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:254:26 + --> tests/ui/redundant_guards.rs:263:26 | LL | Some(Some(x)) if x.starts_with(&[1]) => {}, | ^^^^^^^^^^^^^^^^^^^ @@ -288,7 +312,7 @@ LL + Some(Some([1, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:259:26 + --> tests/ui/redundant_guards.rs:268:26 | LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,7 +324,7 @@ LL + Some(Some([1, 2, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:264:26 + --> tests/ui/redundant_guards.rs:273:26 | LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +336,7 @@ LL + Some(Some([.., 1, 2])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:286:18 + --> tests/ui/redundant_guards.rs:295:18 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -324,7 +348,7 @@ LL + "" => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:305:22 + --> tests/ui/redundant_guards.rs:314:22 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -335,5 +359,5 @@ LL - y if y.is_empty() => {}, LL + "" => {}, | -error: aborting due to 28 previous errors +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed index 779431303ae..708512793d5 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] -#![feature(const_trait_impl)] +#![feature(associated_const_equality, const_trait_impl)] use std::any::Any; @@ -179,3 +179,19 @@ fn main() { let _x: fn(_) = f::<()>; let _x: fn(_) = f::<i32>; } + +// #13706 +fn assoc_tys_bounds<T>() +where + T: Iterator<Item: Clone> + Iterator<Item: Clone>, +{ +} +trait AssocConstTrait { + const ASSOC: usize; +} +fn assoc_const_args<T>() +where + T: AssocConstTrait<ASSOC = 0>, + //~^ trait_duplication_in_bounds +{ +} diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs index 3e974dc0a8f..12db6b65a7a 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] -#![feature(const_trait_impl)] +#![feature(associated_const_equality, const_trait_impl)] use std::any::Any; @@ -179,3 +179,19 @@ fn main() { let _x: fn(_) = f::<()>; let _x: fn(_) = f::<i32>; } + +// #13706 +fn assoc_tys_bounds<T>() +where + T: Iterator<Item: Clone> + Iterator<Item: Clone>, +{ +} +trait AssocConstTrait { + const ASSOC: usize; +} +fn assoc_const_args<T>() +where + T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>, + //~^ trait_duplication_in_bounds +{ +} diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr index 0dd508e4745..83c06eaccd4 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr @@ -70,5 +70,11 @@ error: these where clauses contain repeated elements LL | T: IntoIterator<Item = U::Owned> + IntoIterator<Item = U::Owned>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator<Item = U::Owned>` -error: aborting due to 11 previous errors +error: these where clauses contain repeated elements + --> tests/ui/trait_duplication_in_bounds.rs:194:8 + | +LL | T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait<ASSOC = 0>` + +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed index 3f5b0e52ece..111a2e1987c 100644 --- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed +++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed @@ -257,8 +257,6 @@ fn tester2() { my_concat!("{}", local_i32); my_good_macro!("{}", local_i32); my_good_macro!("{}", local_i32,); - - // FIXME: Broken false positives, currently unhandled my_bad_macro!("{}", local_i32); my_bad_macro2!("{}", local_i32); used_twice! { @@ -267,3 +265,22 @@ fn tester2() { local_i32, }; } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let local_i32 = 1; + let local_f64 = 2.0; + + usr_println!(true, "val='{local_i32}'"); + usr_println!(true, "{local_i32}"); + usr_println!(true, "{local_i32:#010x}"); + usr_println!(true, "{local_f64:.1}"); +} diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs index b311aa4912c..81fe2476567 100644 --- a/src/tools/clippy/tests/ui/uninlined_format_args.rs +++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs @@ -262,8 +262,6 @@ fn tester2() { my_concat!("{}", local_i32); my_good_macro!("{}", local_i32); my_good_macro!("{}", local_i32,); - - // FIXME: Broken false positives, currently unhandled my_bad_macro!("{}", local_i32); my_bad_macro2!("{}", local_i32); used_twice! { @@ -272,3 +270,22 @@ fn tester2() { local_i32, }; } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let local_i32 = 1; + let local_f64 = 2.0; + + usr_println!(true, "val='{}'", local_i32); + usr_println!(true, "{}", local_i32); + usr_println!(true, "{:#010x}", local_i32); + usr_println!(true, "{:.1}", local_f64); +} diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.stderr b/src/tools/clippy/tests/ui/uninlined_format_args.stderr index 5a7ff3bc4f5..77961fea2c5 100644 --- a/src/tools/clippy/tests/ui/uninlined_format_args.stderr +++ b/src/tools/clippy/tests/ui/uninlined_format_args.stderr @@ -845,5 +845,53 @@ LL - println!("expand='{}'", local_i32); LL + println!("expand='{local_i32}'"); | -error: aborting due to 71 previous errors +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:287:5 + | +LL | usr_println!(true, "val='{}'", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "val='{}'", local_i32); +LL + usr_println!(true, "val='{local_i32}'"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:288:5 + | +LL | usr_println!(true, "{}", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{}", local_i32); +LL + usr_println!(true, "{local_i32}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:289:5 + | +LL | usr_println!(true, "{:#010x}", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{:#010x}", local_i32); +LL + usr_println!(true, "{local_i32:#010x}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:290:5 + | +LL | usr_println!(true, "{:.1}", local_f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{:.1}", local_f64); +LL + usr_println!(true, "{local_f64:.1}"); + | + +error: aborting due to 75 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed index 2d932a70e9d..70b78ceca50 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed @@ -23,10 +23,9 @@ fn main() { let _ = Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5]); let _ = (Ok::<i32, i32>(5) == Ok(5)); let _ = (Some(5) == Some(5)).then(|| 1); + let _ = Some(5).is_none_or(|n| n == 5); + let _ = Some(5).is_none_or(|n| 5 == n); - // shouldnt trigger - let _ = Some(5).map_or(true, |n| n == 5); - let _ = Some(5).map_or(true, |n| 5 == n); macro_rules! x { () => { Some(1) @@ -51,10 +50,21 @@ fn main() { let r: Result<i32, S> = Ok(3); let _ = r.is_ok_and(|x| x == 7); + // lint constructs that are not comparaisons as well + let func = |_x| true; + let r: Result<i32, S> = Ok(3); + let _ = r.is_ok_and(func); + let _ = Some(5).is_some_and(func); + let _ = Some(5).is_none_or(func); + #[derive(PartialEq)] struct S2; let r: Result<i32, S2> = Ok(4); let _ = (r == Ok(8)); + + // do not lint `Result::map_or(true, …)` + let r: Result<i32, S2> = Ok(4); + let _ = r.map_or(true, |x| x == 8); } #[clippy::msrv = "1.69.0"] @@ -62,3 +72,9 @@ fn msrv_1_69() { // is_some_and added in 1.70.0 let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); } + +#[clippy::msrv = "1.81.0"] +fn msrv_1_81() { + // is_none_or added in 1.82.0 + let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs index 4a9d69be1e9..50757715977 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.rs +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs @@ -26,10 +26,9 @@ fn main() { let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]); let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5); let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); - - // shouldnt trigger let _ = Some(5).map_or(true, |n| n == 5); let _ = Some(5).map_or(true, |n| 5 == n); + macro_rules! x { () => { Some(1) @@ -54,10 +53,21 @@ fn main() { let r: Result<i32, S> = Ok(3); let _ = r.map_or(false, |x| x == 7); + // lint constructs that are not comparaisons as well + let func = |_x| true; + let r: Result<i32, S> = Ok(3); + let _ = r.map_or(false, func); + let _ = Some(5).map_or(false, func); + let _ = Some(5).map_or(true, func); + #[derive(PartialEq)] struct S2; let r: Result<i32, S2> = Ok(4); let _ = r.map_or(false, |x| x == 8); + + // do not lint `Result::map_or(true, …)` + let r: Result<i32, S2> = Ok(4); + let _ = r.map_or(true, |x| x == 8); } #[clippy::msrv = "1.69.0"] @@ -65,3 +75,9 @@ fn msrv_1_69() { // is_some_and added in 1.70.0 let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); } + +#[clippy::msrv = "1.81.0"] +fn msrv_1_81() { + // is_none_or added in 1.82.0 + let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr index 299a4e5da7a..890abb01228 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr @@ -1,4 +1,4 @@ -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:12:13 | LL | let _ = Some(5).map_or(false, |n| n == 5); @@ -7,13 +7,13 @@ LL | let _ = Some(5).map_or(false, |n| n == 5); = note: `-D clippy::unnecessary-map-or` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:13:13 | LL | let _ = Some(5).map_or(true, |n| n != 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:14:13 | LL | let _ = Some(5).map_or(false, |n| { @@ -23,7 +23,7 @@ LL | | n == 5 LL | | }); | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:18:13 | LL | let _ = Some(5).map_or(false, |n| { @@ -41,59 +41,89 @@ LL + 6 >= 5 LL ~ }); | -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:22:13 | LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:23:13 | LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:24:13 | LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:25:13 | LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:26:13 | LL | let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5])` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:27:13 | LL | let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::<i32, i32>(5) == Ok(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:28:13 | LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))` -error: this `map_or` is redundant - --> tests/ui/unnecessary_map_or.rs:55:13 +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:29:13 + | +LL | let _ = Some(5).map_or(true, |n| n == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| n == 5)` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:30:13 + | +LL | let _ = Some(5).map_or(true, |n| 5 == n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| 5 == n)` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:54:13 | LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)` -error: this `map_or` is redundant +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:59:13 + | +LL | let _ = r.map_or(false, func); + | ^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(func)` + +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:60:13 | +LL | let _ = Some(5).map_or(false, func); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(func)` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:61:13 + | +LL | let _ = Some(5).map_or(true, func); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(func)` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:66:13 + | LL | let _ = r.map_or(false, |x| x == 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))` -error: aborting due to 13 previous errors +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/unused_format_specs.1.fixed b/src/tools/clippy/tests/ui/unused_format_specs.1.fixed index b7d1cce2870..157c2b08d3c 100644 --- a/src/tools/clippy/tests/ui/unused_format_specs.1.fixed +++ b/src/tools/clippy/tests/ui/unused_format_specs.1.fixed @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{:5}.", format!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{:.3}", format!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/src/tools/clippy/tests/ui/unused_format_specs.2.fixed b/src/tools/clippy/tests/ui/unused_format_specs.2.fixed index 94bb6b7036b..92c7b951f3c 100644 --- a/src/tools/clippy/tests/ui/unused_format_specs.2.fixed +++ b/src/tools/clippy/tests/ui/unused_format_specs.2.fixed @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{}.", format_args!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{}", format_args!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/src/tools/clippy/tests/ui/unused_format_specs.rs b/src/tools/clippy/tests/ui/unused_format_specs.rs index 2c85e371149..a5df4d8a866 100644 --- a/src/tools/clippy/tests/ui/unused_format_specs.rs +++ b/src/tools/clippy/tests/ui/unused_format_specs.rs @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{:5}.", format_args!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{:.3}", format_args!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{:5}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args:5}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/src/tools/clippy/tests/ui/unused_format_specs.stderr b/src/tools/clippy/tests/ui/unused_format_specs.stderr index 2b5c81c63d6..df61d59130e 100644 --- a/src/tools/clippy/tests/ui/unused_format_specs.stderr +++ b/src/tools/clippy/tests/ui/unused_format_specs.stderr @@ -58,5 +58,63 @@ LL - println!("{args:5}"); LL + println!("{args}"); | -error: aborting due to 4 previous errors +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:48:25 + | +LL | usr_println!(true, "{:5}.", format_args!("")); + | ^^^^ + | +help: for the width to apply consider using `format!()` + | +LL | usr_println!(true, "{:5}.", format!("")); + | ~~~~~~ +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:5}.", format_args!("")); +LL + usr_println!(true, "{}.", format_args!("")); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:51:25 + | +LL | usr_println!(true, "{:.3}", format_args!("abcde")); + | ^^^^^ + | +help: for the precision to apply consider using `format!()` + | +LL | usr_println!(true, "{:.3}", format!("abcde")); + | ~~~~~~ +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:.3}", format_args!("abcde")); +LL + usr_println!(true, "{}", format_args!("abcde")); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:54:25 + | +LL | usr_println!(true, "{:5}.", format_args_from_macro!()); + | ^^^^ + | + = help: for the width to apply consider using `format!()` +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:5}.", format_args_from_macro!()); +LL + usr_println!(true, "{}.", format_args_from_macro!()); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:58:25 + | +LL | usr_println!(true, "{args:5}"); + | ^^^^^^^^ + | + = help: for the width to apply consider using `format!()` +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{args:5}"); +LL + usr_println!(true, "{args}"); + | + +error: aborting due to 8 previous errors diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index e6fbba943a4..36f876bcdc6 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::process::Command; @@ -486,6 +486,9 @@ impl Config { } } +/// Known widths of `target_has_atomic`. +pub const KNOWN_TARGET_HAS_ATOMIC_WIDTHS: &[&str] = &["8", "16", "32", "64", "128", "ptr"]; + #[derive(Debug, Clone)] pub struct TargetCfgs { pub current: TargetCfg, @@ -611,6 +614,17 @@ impl TargetCfgs { ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort, ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind, ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"), + + ("target_has_atomic", Some(width)) + if KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width) => + { + cfg.target_has_atomic.insert(width.to_string()); + } + ("target_has_atomic", Some(other)) => { + panic!("unexpected value for `target_has_atomic` cfg: {other:?}") + } + // Nightly-only std-internal impl detail. + ("target_has_atomic", None) => {} _ => {} } } @@ -645,6 +659,12 @@ pub struct TargetCfg { pub(crate) xray: bool, #[serde(default = "default_reloc_model")] pub(crate) relocation_model: String, + + // Not present in target cfg json output, additional derived information. + #[serde(skip)] + /// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin + /// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`. + pub(crate) target_has_atomic: BTreeSet<String>, } impl TargetCfg { diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 0c47ef871d2..5638d471890 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -17,7 +17,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-run-results", "check-stdout", "check-test-line-numbers-match", - "compare-output-lines-by-subset", "compile-flags", "doc-flags", "dont-check-compiler-stderr", @@ -154,6 +153,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-thread", "needs-std-debug-assertions", "needs-symlink", + "needs-target-has-atomic", "needs-threads", "needs-unwind", "needs-wasmtime", @@ -215,6 +215,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "pp-exact", "pretty-compare-only", "pretty-mode", + "proc-macro", "reference", "regex-error-pattern", "remap-src-base", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e945797647e..91558d0c898 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -115,9 +115,6 @@ pub struct TestProps { pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr pub dont_check_compiler_stderr: bool, - // When checking the output of stdout or stderr check - // that the lines of expected output are a subset of the actual output. - pub compare_output_lines_by_subset: bool, // Don't force a --crate-type=dylib flag on the command line // // Set this for example if you have an auxiliary test file that contains @@ -221,6 +218,7 @@ mod directives { pub const AUX_BIN: &'static str = "aux-bin"; pub const AUX_BUILD: &'static str = "aux-build"; pub const AUX_CRATE: &'static str = "aux-crate"; + pub const PROC_MACRO: &'static str = "proc-macro"; pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend"; pub const EXEC_ENV: &'static str = "exec-env"; pub const RUSTC_ENV: &'static str = "rustc-env"; @@ -239,7 +237,6 @@ mod directives { pub const KNOWN_BUG: &'static str = "known-bug"; pub const TEST_MIR_PASS: &'static str = "test-mir-pass"; pub const REMAP_SRC_BASE: &'static str = "remap-src-base"; - pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset"; pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags"; pub const FILECHECK_FLAGS: &'static str = "filecheck-flags"; pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg"; @@ -273,7 +270,6 @@ impl TestProps { check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, - compare_output_lines_by_subset: false, no_prefer_dynamic: false, pretty_mode: "normal".to_string(), pretty_compare_only: false, @@ -549,11 +545,6 @@ impl TestProps { |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); - config.set_name_directive( - ln, - COMPARE_OUTPUT_LINES_BY_SUBSET, - &mut self.compare_output_lines_by_subset, - ); if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { self.llvm_cov_flags.extend(split_flags(&flags)); @@ -1134,6 +1125,8 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> { .captures(header)?; let regex = captures["regex"].to_owned(); let replacement = captures["replacement"].to_owned(); + // FIXME: Support escaped new-line in strings. + let replacement = replacement.replace("\\n", "\n"); Some((regex, replacement)) } diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs index 6f6538ce196..0e1f3a785f8 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -4,7 +4,7 @@ use std::iter; use crate::common::Config; -use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; +use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] @@ -17,6 +17,8 @@ pub(crate) struct AuxProps { /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies /// to build and pass with the `--extern` flag. pub(crate) crates: Vec<(String, String)>, + /// Same as `builds`, but for proc-macros. + pub(crate) proc_macros: Vec<String>, /// Similar to `builds`, but also uses the resulting dylib as a /// `-Zcodegen-backend` when compiling the test file. pub(crate) codegen_backend: Option<String>, @@ -26,12 +28,13 @@ impl AuxProps { /// Yields all of the paths (relative to `./auxiliary/`) that have been /// specified in `aux-*` directives for this test. pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> { - let Self { builds, bins, crates, codegen_backend } = self; + let Self { builds, bins, crates, proc_macros, codegen_backend } = self; iter::empty() .chain(builds.iter().map(String::as_str)) .chain(bins.iter().map(String::as_str)) .chain(crates.iter().map(|(_, path)| path.as_str())) + .chain(proc_macros.iter().map(String::as_str)) .chain(codegen_backend.iter().map(String::as_str)) } } @@ -39,13 +42,15 @@ impl AuxProps { /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { - if !ln.starts_with("aux-") { + if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) { return; } config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); + config + .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { aux.codegen_backend = Some(r.trim().to_owned()); } diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 77570c58db5..e19dcd992fc 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, Sanitizer}; +use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; use crate::header::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( @@ -171,11 +171,54 @@ pub(super) fn handle_needs( }, ]; - let (name, comment) = match ln.split_once([':', ' ']) { - Some((name, comment)) => (name, Some(comment)), + let (name, rest) = match ln.split_once([':', ' ']) { + Some((name, rest)) => (name, Some(rest)), None => (ln, None), }; + // FIXME(jieyouxu): tighten up this parsing to reject using both `:` and ` ` as means to + // delineate value. + if name == "needs-target-has-atomic" { + let Some(rest) = rest else { + return IgnoreDecision::Error { + message: "expected `needs-target-has-atomic` to have a comma-separated list of atomic widths".to_string(), + }; + }; + + // Expect directive value to be a list of comma-separated atomic widths. + let specified_widths = rest + .split(',') + .map(|width| width.trim()) + .map(ToString::to_string) + .collect::<Vec<String>>(); + + for width in &specified_widths { + if !KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width.as_str()) { + return IgnoreDecision::Error { + message: format!( + "unknown width specified in `needs-target-has-atomic`: `{width}` is not a \ + known `target_has_atomic_width`, known values are `{:?}`", + KNOWN_TARGET_HAS_ATOMIC_WIDTHS + ), + }; + } + } + + let satisfies_all_specified_widths = specified_widths + .iter() + .all(|specified| config.target_cfg().target_has_atomic.contains(specified)); + if satisfies_all_specified_widths { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!( + "skipping test as target does not support all of the required `target_has_atomic` widths `{:?}`", + specified_widths + ), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -193,7 +236,7 @@ pub(super) fn handle_needs( break; } else { return IgnoreDecision::Ignore { - reason: if let Some(comment) = comment { + reason: if let Some(comment) = rest { format!("{} ({})", need.ignore_reason, comment.trim()) } else { need.ignore_reason.into() diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 4d75c38dd32..cd7c6f8361e 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -787,3 +787,40 @@ fn test_not_trailing_directive() { run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental"); assert!(!poisoned); } + +#[test] +fn test_needs_target_has_atomic() { + use std::collections::BTreeSet; + + // `x86_64-unknown-linux-gnu` supports `["8", "16", "32", "64", "ptr"]` but not `128`. + + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + // Expectation sanity check. + assert_eq!( + config.target_cfg().target_has_atomic, + BTreeSet::from([ + "8".to_string(), + "16".to_string(), + "32".to_string(), + "64".to_string(), + "ptr".to_string() + ]), + "expected `x86_64-unknown-linux-gnu` to not have 128-bit atomic support" + ); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 16")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 32")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 64")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 128")); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr,128")); + + // Check whitespace between widths is permitted. + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr")); + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128")); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bc80c8246ad..84269fd44a1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -102,7 +102,7 @@ fn get_lib_name(name: &str, aux_type: AuxType) -> Option<String> { // In this case, the only path we can pass // with '--extern-meta' is the '.rlib' file AuxType::Lib => Some(format!("lib{name}.rlib")), - AuxType::Dylib => Some(dylib_name(name)), + AuxType::Dylib | AuxType::ProcMacro => Some(dylib_name(name)), } } @@ -350,10 +350,13 @@ impl<'test> TestCx<'test> { } } else { if proc_res.status.success() { - self.fatal_proc_rec( - &format!("{} test compiled successfully!", self.config.mode)[..], - proc_res, - ); + { + self.error(&format!("{} test did not emit an error", self.config.mode)); + if self.config.mode == crate::common::Mode::Ui { + println!("note: by default, ui tests are expected not to compile"); + } + proc_res.fatal(None, || ()); + }; } if !self.props.dont_check_failure_status { @@ -1097,7 +1100,9 @@ impl<'test> TestCx<'test> { } fn has_aux_dir(&self) -> bool { - !self.props.aux.builds.is_empty() || !self.props.aux.crates.is_empty() + !self.props.aux.builds.is_empty() + || !self.props.aux.crates.is_empty() + || !self.props.aux.proc_macros.is_empty() } fn aux_output_dir(&self) -> PathBuf { @@ -1118,31 +1123,48 @@ impl<'test> TestCx<'test> { fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { for rel_ab in &self.props.aux.builds { - self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, None); } for rel_ab in &self.props.aux.bins { - self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin)); } + let path_to_crate_name = |path: &str| -> String { + path.rsplit_once('/') + .map_or(path, |(_, tail)| tail) + .trim_end_matches(".rs") + .replace('-', "_") + }; + + let add_extern = + |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| { + let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); + if let Some(lib_name) = lib_name { + rustc.arg("--extern").arg(format!( + "{}={}/{}", + aux_name, + aux_dir.display(), + lib_name + )); + } + }; + for (aux_name, aux_path) in &self.props.aux.crates { - let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); - let lib_name = - get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); - if let Some(lib_name) = lib_name { - rustc.arg("--extern").arg(format!( - "{}={}/{}", - aux_name, - aux_dir.display(), - lib_name - )); - } + let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None); + add_extern(rustc, aux_name, aux_path, aux_type); + } + + for proc_macro in &self.props.aux.proc_macros { + self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro)); + let crate_name = path_to_crate_name(proc_macro); + add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro); } // Build any `//@ aux-codegen-backend`, and pass the resulting library // to `-Zcodegen-backend` when compiling the test file. if let Some(aux_file) = &self.props.aux.codegen_backend { - let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); + let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); rustc.arg(format!("-Zcodegen-backend={}", lib_path.display())); @@ -1209,17 +1231,23 @@ impl<'test> TestCx<'test> { } /// Builds an aux dependency. + /// + /// If `aux_type` is `None`, then this will determine the aux-type automatically. fn build_auxiliary( &self, of: &TestPaths, source_path: &str, aux_dir: &Path, - is_bin: bool, + aux_type: Option<AuxType>, ) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + let mut aux_props = + self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + if aux_type == Some(AuxType::ProcMacro) { + aux_props.force_host = true; + } let mut aux_dir = aux_dir.to_path_buf(); - if is_bin { + if aux_type == Some(AuxType::Bin) { // On unix, the binary of `auxiliary/foo.rs` will be named // `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so // put bins in a `bin` subfolder. @@ -1250,8 +1278,12 @@ impl<'test> TestCx<'test> { aux_rustc.env_remove(key); } - let (aux_type, crate_type) = if is_bin { + let (aux_type, crate_type) = if aux_type == Some(AuxType::Bin) { (AuxType::Bin, Some("bin")) + } else if aux_type == Some(AuxType::ProcMacro) { + (AuxType::ProcMacro, Some("proc-macro")) + } else if aux_type.is_some() { + panic!("aux_type {aux_type:?} not expected"); } else if aux_props.no_prefer_dynamic { (AuxType::Dylib, None) } else if self.config.target.contains("emscripten") @@ -1287,6 +1319,11 @@ impl<'test> TestCx<'test> { aux_rustc.args(&["--crate-type", crate_type]); } + if aux_type == AuxType::ProcMacro { + // For convenience, but this only works on 2018. + aux_rustc.args(&["--extern", "proc_macro"]); + } + aux_rustc.arg("-L").arg(&aux_dir); let auxres = aux_cx.compose_and_run( @@ -2507,13 +2544,10 @@ impl<'test> TestCx<'test> { return 0; } - // If `compare-output-lines-by-subset` is not explicitly enabled then - // auto-enable it when a `runner` is in use since wrapper tools might - // provide extra output on failure, for example a WebAssembly runtime - // might print the stack trace of an `unreachable` instruction by - // default. - let compare_output_by_lines = - self.props.compare_output_lines_by_subset || self.config.runner.is_some(); + // Wrapper tools set by `runner` might provide extra output on failure, + // for example a WebAssembly runtime might print the stack trace of an + // `unreachable` instruction by default. + let compare_output_by_lines = self.config.runner.is_some(); let tmp; let (expected, actual): (&str, &str) = if compare_output_by_lines { @@ -2768,8 +2802,10 @@ enum LinkToAux { No, } +#[derive(Debug, PartialEq)] enum AuxType { Bin, Lib, Dylib, + ProcMacro, } diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 01e32229f25..363b96fdff1 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -404,16 +404,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - -[[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -540,7 +530,6 @@ dependencies = [ "colored", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -550,6 +539,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -1003,6 +993,16 @@ dependencies = [ ] [[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index d1cd3640346..6e8e270985e 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -30,8 +30,8 @@ directories = "5" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't # easily use that since we support of-tree builds. -[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.jemalloc-sys] -version = "0.5.0" +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys] +version = "0.6.0" features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e193c786eff..377639882c5 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -eddb717281a9031f645d88dd3b8323a7e25632cc +3b382642aba7cffbb2f47829b24635fad87bcf5c diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 15f05ba909c..2c4b02e2873 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -317,6 +317,8 @@ fn jemalloc_magic() { // See there for further comments. use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs index 2dd87ea6083..42943d58191 100644 --- a/src/tools/miri/tests/fail/breakpoint.rs +++ b/src/tools/miri/tests/fail/breakpoint.rs @@ -1,7 +1,5 @@ #![feature(core_intrinsics)] fn main() { - unsafe { - core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap - }; + core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap } diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr index ca98e81f1f4..f203cb0c15f 100644 --- a/src/tools/miri/tests/fail/breakpoint.stderr +++ b/src/tools/miri/tests/fail/breakpoint.stderr @@ -1,8 +1,8 @@ error: abnormal termination: trace/breakpoint trap --> tests/fail/breakpoint.rs:LL:CC | -LL | core::intrinsics::breakpoint() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap +LL | core::intrinsics::breakpoint(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap | = note: BACKTRACE: = note: inside `main` at tests/fail/breakpoint.rs:LL:CC diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs new file mode 100644 index 00000000000..bd02e7f5fb4 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs @@ -0,0 +1,27 @@ +// Validity makes this fail at the wrong place. +//@compile-flags: -Zmiri-disable-validation +use std::mem; + +// This enum has untagged variant idx 1, with niche_variants being 0..=2 +// and niche_start being 2. +// That means the untagged variants is in the niche variant range! +// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant. +#[derive(Copy, Clone, PartialEq)] +enum Foo { + Var1, + Var2(bool), + Var3, +} + +fn main() { + unsafe { + assert!(Foo::Var2(false) == mem::transmute(0u8)); + assert!(Foo::Var2(true) == mem::transmute(1u8)); + assert!(Foo::Var1 == mem::transmute(2u8)); + assert!(Foo::Var3 == mem::transmute(4u8)); + + let invalid: Foo = mem::transmute(3u8); + assert!(matches!(invalid, Foo::Var2(_))); + //~^ ERROR: invalid tag + } +} diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr new file mode 100644 index 00000000000..759dbc36380 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: enum value has invalid tag: 0x03 + --> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC + | +LL | assert!(matches!(invalid, Foo::Var2(_))); + | ^^^^^^^ enum value has invalid tag: 0x03 + | + = 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: BACKTRACE: + = note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.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-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index a35c92636ce..fd7fc801dc2 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -47,9 +47,12 @@ fn test_readlink() { assert_eq!(res, small_buf.len() as isize); // Test that we report a proper error for a missing path. - let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap(); let res = unsafe { - libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) + libc::readlink( + c"MIRI_MISSING_FILE_NAME".as_ptr(), + small_buf.as_mut_ptr().cast(), + small_buf.len(), + ) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs index ab3fd6733ff..cffcf4a867f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs @@ -2,7 +2,6 @@ //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" -use std::ffi::CString; use std::fs; use std::io::{Error, ErrorKind}; @@ -13,10 +12,9 @@ fn main() { } // test `readlink` - let symlink_c_str = CString::new("foo.txt").unwrap(); let mut buf = vec![0; "foo_link.txt".len() + 1]; unsafe { - assert_eq!(libc::readlink(symlink_c_str.as_ptr(), buf.as_mut_ptr(), buf.len()), -1); + assert_eq!(libc::readlink(c"foo.txt".as_ptr(), buf.as_mut_ptr(), buf.len()), -1); assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES)); } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index 10be78798a6..727533a9de6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -55,12 +55,12 @@ fn test_memcpy() { } fn test_strcpy() { - use std::ffi::{CStr, CString}; + use std::ffi::CStr; // case: src_size equals dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); @@ -69,8 +69,8 @@ fn test_strcpy() { // case: src_size is less than dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size + 1); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs index cac26bfe146..423ef7a5cf7 100644 --- a/src/tools/miri/tests/pass/async-closure-captures.rs +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -1,6 +1,6 @@ // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync -#![feature(async_closure, noop_waker)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs index 9b2fc2948bf..264da5a9518 100644 --- a/src/tools/miri/tests/pass/async-closure-drop.rs +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -1,4 +1,4 @@ -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake index 218d88d8721..9def420f05c 100644 --- a/src/tools/nix-dev-shell/envrc-flake +++ b/src/tools/nix-dev-shell/envrc-flake @@ -1,7 +1,7 @@ # If you want to use this as an .envrc file to create a shell with necessery components # to develop rustc, use the following command in the root of the rusr checkout: # -# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && echo .envrc >> .git/info/exclude +# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell && echo .envrc >> .git/info/exclude if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then use flake path:./src/tools/nix-dev-shell diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 494daeca963..ffe10092cc2 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -227,6 +227,12 @@ impl Rustc { self } + /// Normalize the line number in the stderr output + pub fn ui_testing(&mut self) -> &mut Self { + self.cmd.arg(format!("-Zui-testing")); + self + } + /// Specify the target triple, or a path to a custom target json spec file. pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self { let target = target.as_ref(); diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 019609e6a5b..2bd4d17fe22 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1492,9 +1492,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fde78db053c78c87776ec738677649f791645883f82ff145f68caf9f18e1a" +checksum = "613760a3071b25a67a8d7bc97b37c7fd4722562e9479137b83ae9cf8f8c1601a" dependencies = [ "bitflags 2.6.0", "ra-ap-rustc_index", @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da115d496e5abd65e2dceb6883d7597593badfe23fea3439202b8da5a11ea250" +checksum = "5b2bc6b4ecede8ff28295041e22c2e66853f8e0125990c05135bad3c30bad12c" dependencies = [ "arrayvec", "ra-ap-rustc_index_macros", @@ -1514,9 +1514,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be86d06a75a8125c1ace197d5030e6e02721348d32e572baea35c891669ad1e2" +checksum = "2374a39fb2d92d0509178c2b442eadca3cc10e403ef9729a040c1855b08ff261" dependencies = [ "proc-macro2", "quote", @@ -1525,9 +1525,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64b46ae0d8f59acc32e64e0085532b831f0d6182d870a7cd86c046c2c46e722" +checksum = "5a2cf8e48b69af3ecc29ed3449892e8a999111d2f75212a78aa242e117cf1711" dependencies = [ "unicode-properties", "unicode-xid", @@ -1535,9 +1535,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbdaad19ddbd0ff46e947ca8dbb6ae678a112d3938669fb3ad6bfd244917e24b" +checksum = "8d6f59a22b559263c5c42747ae362cf5d4fb272293fa119a4623f8ec288f9656" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1545,9 +1545,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5761e37c78d98ede9f20f6b66526093d0be66aa256d5cbdf214495843ba74d" +checksum = "a7d0575b54ffe09bc5d2f158454bc05f0c30c01d9992310965f854be50ae22b8" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.0.0", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 94e7de553bf..632b290ba98 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.76", default-features = false } -ra-ap-rustc_parse_format = { version = "0.76", default-features = false } -ra-ap-rustc_index = { version = "0.76", default-features = false } -ra-ap-rustc_abi = { version = "0.76", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.76", default-features = false } +ra-ap-rustc_lexer = { version = "0.80", default-features = false } +ra-ap-rustc_parse_format = { version = "0.80", default-features = false } +ra-ap-rustc_index = { version = "0.80", default-features = false } +ra-ap-rustc_abi = { version = "0.80", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.80", default-features = false } # local crates that aren't published to crates.io. These should not have versions. test-fixture = { path = "./crates/test-fixture" } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index e4881d75201..54aa18ce207 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -916,6 +916,32 @@ impl<'a> InferenceTable<'a> { /// Check if given type is `Sized` or not pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { + let mut ty = ty.clone(); + { + let mut structs = SmallVec::<[_; 8]>::new(); + // Must use a loop here and not recursion because otherwise users will conduct completely + // artificial examples of structs that have themselves as the tail field and complain r-a crashes. + while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { + let struct_data = self.db.struct_data(id); + if let Some((last_field, _)) = struct_data.variant_data.fields().iter().next_back() + { + let last_field_ty = self.db.field_types(id.into())[last_field] + .clone() + .substitute(Interner, subst); + if structs.contains(&ty) { + // A struct recursively contains itself as a tail field somewhere. + return true; // Don't overload the users with too many errors. + } + structs.push(ty); + // Structs can have DST as its last field and such cases are not handled + // as unsized by the chalk, so we do this manually. + ty = last_field_ty; + } else { + break; + }; + } + } + // Early return for some obvious types if matches!( ty.kind(Interner), @@ -930,16 +956,6 @@ impl<'a> InferenceTable<'a> { return true; } - if let Some((AdtId::StructId(id), subst)) = ty.as_adt() { - let struct_data = self.db.struct_data(id); - if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() { - let last_field_ty = - self.db.field_types(id.into())[last_field].clone().substitute(Interner, subst); - // Structs can have DST as its last field and such cases are not handled - // as unsized by the chalk, so we do this manually - return self.is_sized(&last_field_ty); - } - } let Some(sized) = self .db .lang_item(self.trait_env.krate, LangItem::Sized) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index 9b982a124e7..624148cab20 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -4790,3 +4790,24 @@ fn allowed3(baz: impl Baz<Assoc = Qux<impl Foo>>) {} "#]], ) } + +#[test] +fn recursive_tail_sized() { + check_infer( + r#" +struct WeirdFoo(WeirdBar); +struct WeirdBar(WeirdFoo); + +fn bar(v: *const ()) { + let _ = v as *const WeirdFoo; +} + "#, + expect![[r#" + 62..63 'v': *const () + 76..113 '{ ...Foo; }': () + 86..87 '_': *const WeirdFoo + 90..91 'v': *const () + 90..110 'v as *...irdFoo': *const WeirdFoo + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 1d2d3350f7c..0146369f298 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -116,6 +116,9 @@ impl<'a> AssistContext<'a> { pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> { find_node_at_offset(self.source_file.syntax(), self.offset()) } + pub(crate) fn find_node_at_trimmed_offset<N: AstNode>(&self) -> Option<N> { + find_node_at_offset(self.source_file.syntax(), self.trimmed_range.start()) + } pub(crate) fn find_node_at_range<N: AstNode>(&self) -> Option<N> { find_node_at_range(self.source_file.syntax(), self.trimmed_range) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index 2f4a263ee07..42f615e71da 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{self, edit::AstNodeEdit, make}, + ast::{self, edit_in_place::Indent, syntax_factory::SyntaxFactory}, AstNode, }; @@ -39,12 +39,16 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( }, expr.syntax().text_range(), |builder| { - let block_expr = AstNodeEdit::indent( - &make::block_expr(None, Some(expr.clone())), - AstNodeEdit::indent_level(&expr), - ); + let make = SyntaxFactory::new(); + let mut editor = builder.make_editor(expr.syntax()); - builder.replace(expr.syntax().text_range(), block_expr.syntax().text()); + let block_expr = make.block_expr(None, Some(expr.clone())); + block_expr.indent(expr.indent_level()); + + editor.replace(expr.syntax(), block_expr.syntax()); + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index a211ca8f2d6..236d33878ed 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -30,8 +30,8 @@ use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; // // fn handle(action: Action) { // match action { -// $0Action::Move { distance } => todo!(), -// Action::Stop => todo!(), +// Action::Move { distance } => ${1:todo!()}, +// Action::Stop => ${2:todo!()},$0 // } // } // ``` @@ -234,10 +234,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) } } - let mut first_new_arm = None; + let mut added_arms = Vec::new(); + let mut todo_placeholders = Vec::new(); for arm in missing_arms { - first_new_arm.get_or_insert_with(|| arm.clone()); - new_match_arm_list.add_arm(arm); + todo_placeholders.push(arm.expr().unwrap()); + added_arms.push(arm); } if needs_catch_all_arm && !has_catch_all_arm { @@ -248,14 +249,28 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) make::ext::expr_todo(), ) .clone_for_update(); - first_new_arm.get_or_insert_with(|| arm.clone()); + todo_placeholders.push(arm.expr().unwrap()); + added_arms.push(arm); + } + + let first_new_arm = added_arms.first().cloned(); + let last_new_arm = added_arms.last().cloned(); + + for arm in added_arms { new_match_arm_list.add_arm(arm); } - if let (Some(first_new_arm), Some(cap)) = (first_new_arm, ctx.config.snippet_cap) { - match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) { - Some(it) => edit.add_placeholder_snippet(cap, it), - None => edit.add_tabstop_before(cap, first_new_arm), + if let Some(cap) = ctx.config.snippet_cap { + if let Some(it) = first_new_arm.and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast)) { + edit.add_placeholder_snippet(cap, it); + } + + for placeholder in todo_placeholders { + edit.add_placeholder_snippet(cap, placeholder); + } + + if let Some(arm) = last_new_arm { + edit.add_tabstop_after(cap, arm); } } @@ -581,8 +596,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match a { - $0true => todo!(), - false => todo!(), + true => ${1:todo!()}, + false => ${2:todo!()},$0 } } "#, @@ -604,7 +619,7 @@ fn foo(a: bool) { fn foo(a: bool) { match a { true => {} - $0false => todo!(), + false => ${1:todo!()},$0 } } "#, @@ -654,10 +669,10 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match (a, a) { - $0(true, true) => todo!(), - (true, false) => todo!(), - (false, true) => todo!(), - (false, false) => todo!(), + (true, true) => ${1:todo!()}, + (true, false) => ${2:todo!()}, + (false, true) => ${3:todo!()}, + (false, false) => ${4:todo!()},$0 } } "#, @@ -677,8 +692,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a] { - $0[true] => todo!(), - [false] => todo!(), + [true] => ${1:todo!()}, + [false] => ${2:todo!()},$0 } } "#, @@ -695,8 +710,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a,] { - $0[true] => todo!(), - [false] => todo!(), + [true] => ${1:todo!()}, + [false] => ${2:todo!()},$0 } } "#, @@ -715,9 +730,9 @@ fn foo(a: bool) { fn foo(a: bool) { match [a, a] { [true, true] => todo!(), - $0[true, false] => todo!(), - [false, true] => todo!(), - [false, false] => todo!(), + [true, false] => ${1:todo!()}, + [false, true] => ${2:todo!()}, + [false, false] => ${3:todo!()},$0 } } "#, @@ -734,10 +749,10 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a, a] { - $0[true, true] => todo!(), - [true, false] => todo!(), - [false, true] => todo!(), - [false, false] => todo!(), + [true, true] => ${1:todo!()}, + [true, false] => ${2:todo!()}, + [false, true] => ${3:todo!()}, + [false, false] => ${4:todo!()},$0 } } "#, @@ -759,8 +774,8 @@ fn foo(a: bool) { fn foo(a: bool) { match (a, a) { (true | false, true) => {} - $0(true, false) => todo!(), - (false, false) => todo!(), + (true, false) => ${1:todo!()}, + (false, false) => ${2:todo!()},$0 } } "#, @@ -779,9 +794,9 @@ fn foo(a: bool) { fn foo(a: bool) { match (a, a) { (false, true) => {} - $0(true, true) => todo!(), - (true, false) => todo!(), - (false, false) => todo!(), + (true, true) => ${1:todo!()}, + (true, false) => ${2:todo!()}, + (false, false) => ${3:todo!()},$0 } } "#, @@ -815,7 +830,7 @@ fn main() { match A::As { A::Bs { x, y: Some(_) } => {} A::Cs(_, Some(_)) => {} - $0A::As => todo!(), + A::As => ${1:todo!()},$0 } } "#, @@ -838,7 +853,7 @@ fn main() { fn main() { match None { None => {} - Some(${0:_}) => todo!(), + Some(${1:_}) => ${2:todo!()},$0 } } "#, @@ -862,7 +877,7 @@ enum A { As, Bs, Cs(Option<i32>) } fn main() { match A::As { A::Cs(_) | A::Bs => {} - $0A::As => todo!(), + A::As => ${1:todo!()},$0 } } "#, @@ -892,8 +907,8 @@ fn main() { A::Bs if 0 < 1 => {} A::Ds(_value) => { let x = 1; } A::Es(B::Xs) => (), - $0A::As => todo!(), - A::Cs => todo!(), + A::As => ${1:todo!()}, + A::Cs => ${2:todo!()},$0 } } "#, @@ -919,7 +934,7 @@ fn main() { match A::As { A::As(_) => {} a @ A::Bs(_) => {} - A::Cs(${0:_}) => todo!(), + A::Cs(${1:_}) => ${2:todo!()},$0 } } "#, @@ -945,11 +960,11 @@ enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } } fn main() { let a = A::As; match a { - $0A::As => todo!(), - A::Bs => todo!(), - A::Cs(_) => todo!(), - A::Ds(_, _) => todo!(), - A::Es { x, y } => todo!(), + A::As => ${1:todo!()}, + A::Bs => ${2:todo!()}, + A::Cs(_) => ${3:todo!()}, + A::Ds(_, _) => ${4:todo!()}, + A::Es { x, y } => ${5:todo!()},$0 } } "#, @@ -982,9 +997,9 @@ fn main() { let b = B::One; match (a, b) { (A::Two, B::One) => {}, - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::Two) => ${3:todo!()},$0 } } "#, @@ -1013,10 +1028,10 @@ fn main() { let a = A::One; let b = B::One; match (a, b) { - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::One) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::One) => ${3:todo!()}, + (A::Two, B::Two) => ${4:todo!()},$0 } } "#, @@ -1045,10 +1060,10 @@ fn main() { let a = A::One; let b = B::One; match (&a, &b) { - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::One) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::One) => ${3:todo!()}, + (A::Two, B::Two) => ${4:todo!()},$0 } } "#, @@ -1080,9 +1095,9 @@ fn main() { let b = B::One; match (a, b) { (A::Two, B::One) => {} - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::Two) => ${3:todo!()},$0 } } "#, @@ -1107,9 +1122,9 @@ fn main() { match (A, B, C) { (A | B , A, A | B | C) => (), (A | B | C , B | C, A | B | C) => (), - $0(C, A, A) => todo!(), - (C, A, B) => todo!(), - (C, A, C) => todo!(), + (C, A, A) => ${1:todo!()}, + (C, A, B) => ${2:todo!()}, + (C, A, C) => ${3:todo!()},$0 } } "#, @@ -1138,7 +1153,7 @@ fn main() { match (a, b) { (Some(_), _) => {} (None, Some(_)) => {} - $0(None, None) => todo!(), + (None, None) => ${1:todo!()},$0 } } "#, @@ -1203,8 +1218,8 @@ enum A { One, Two } fn main() { let a = A::One; match (a, ) { - $0(A::One,) => todo!(), - (A::Two,) => todo!(), + (A::One,) => ${1:todo!()}, + (A::Two,) => ${2:todo!()},$0 } } "#, @@ -1228,7 +1243,7 @@ enum A { As } fn foo(a: &A) { match a { - $0A::As => todo!(), + A::As => ${1:todo!()},$0 } } "#, @@ -1253,7 +1268,7 @@ enum A { fn foo(a: &mut A) { match a { - $0A::Es { x, y } => todo!(), + A::Es { x, y } => ${1:todo!()},$0 } } "#, @@ -1313,8 +1328,8 @@ enum E { X, Y } fn main() { match E::X { - $0E::X => todo!(), - E::Y => todo!(), + E::X => ${1:todo!()}, + E::Y => ${2:todo!()},$0 } } "#, @@ -1360,8 +1375,8 @@ use foo::E::X; fn main() { match X { - $0X => todo!(), - foo::E::Y => todo!(), + X => ${1:todo!()}, + foo::E::Y => ${2:todo!()},$0 } } "#, @@ -1388,7 +1403,7 @@ fn foo(a: A) { match a { // foo bar baz A::One => {} - $0A::Two => todo!(), + A::Two => ${1:todo!()},$0 // This is where the rest should be } } @@ -1412,8 +1427,8 @@ fn foo(a: A) { enum A { One, Two } fn foo(a: A) { match a { - $0A::One => todo!(), - A::Two => todo!(), + A::One => ${1:todo!()}, + A::Two => ${2:todo!()},$0 // foo bar baz } } @@ -1437,8 +1452,8 @@ fn foo(a: A) { enum A { One, Two, } fn foo(a: A) { match a { - $0A::One => todo!(), - A::Two => todo!(), + A::One => ${1:todo!()}, + A::Two => ${2:todo!()},$0 } } "#, @@ -1460,8 +1475,8 @@ fn foo(opt: Option<i32>) { r#" fn foo(opt: Option<i32>) { match opt { - Some(${0:_}) => todo!(), - None => todo!(), + Some(${1:_}) => ${2:todo!()}, + None => ${3:todo!()},$0 } } "#, @@ -1493,9 +1508,9 @@ enum Test { fn foo(t: Test) { m!(match t { - $0Test::A => todo!(), - Test::B => todo!(), - Test::C => todo!(), + Test::A => ${1:todo!()}, + Test::B => ${2:todo!()}, + Test::C => ${3:todo!()},$0 }); }"#, ); @@ -1530,7 +1545,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - $0false => todo!(), + false => ${1:todo!()},$0 } }"#, ); @@ -1550,7 +1565,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - $0false => todo!(), + false => ${1:todo!()},$0 } }"#, ); @@ -1571,8 +1586,8 @@ fn foo(t: bool) { fn foo(t: bool) { match t { _ => 1 + 2, - $0true => todo!(), - false => todo!(), + true => ${1:todo!()}, + false => ${2:todo!()},$0 } }"#, ); @@ -1595,8 +1610,8 @@ pub enum E { A, #[doc(hidden)] B, } r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1620,9 +1635,9 @@ pub enum E { A, #[doc(hidden)] B, } r#" fn foo(t: (bool, ::e::E)) { match t { - $0(true, e::E::A) => todo!(), - (false, e::E::A) => todo!(), - _ => todo!(), + (true, e::E::A) => ${1:todo!()}, + (false, e::E::A) => ${2:todo!()}, + _ => ${3:todo!()},$0 } } "#, @@ -1646,7 +1661,7 @@ pub enum E { #[doc(hidden)] A, } r#" fn foo(t: ::e::E) { match t { - ${0:_} => todo!(), + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1707,7 +1722,7 @@ pub enum E { A, } fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${0:_} => todo!(), + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1732,8 +1747,8 @@ pub enum E { A, } r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1757,8 +1772,8 @@ pub enum E { A, #[doc(hidden)] B }"#, r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1784,7 +1799,7 @@ pub enum E { A, #[doc(hidden)] B }"#, fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${0:_} => todo!(), + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1809,7 +1824,7 @@ pub enum E { #[doc(hidden)] A, }"#, fn foo(t: ::e::E, b: bool) { match t { _ if b => todo!(), - ${0:_} => todo!(), + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1850,8 +1865,8 @@ pub enum E { A, #[doc(hidden)] B, }"#, r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1874,8 +1889,8 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1899,8 +1914,8 @@ enum E { A, B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1924,8 +1939,8 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1975,8 +1990,8 @@ enum A { fn a() { let b = A::A; match b { - $0A::A => todo!(), - A::Missing { a, u32, c } => todo!(), + A::A => ${1:todo!()}, + A::Missing { a, u32, c } => ${2:todo!()},$0 } }"#, ) @@ -2013,8 +2028,8 @@ pub enum E { fn f() { let value = E::A; match value { - $0E::A => todo!(), - E::B(s) => todo!(), + E::A => ${1:todo!()}, + E::B(s) => ${2:todo!()},$0 } } "#, @@ -2051,8 +2066,8 @@ pub enum E { fn f() { let value = E::A; match value { - $0E::A => todo!(), - E::B(s1, s2) => todo!(), + E::A => ${1:todo!()}, + E::B(s1, s2) => ${2:todo!()},$0 } } "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index 4608e9494bc..f83de931eab 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -34,7 +34,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; // } // ``` pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?; + let current_arm = ctx.find_node_at_trimmed_offset::<ast::MatchArm>()?; // Don't try to handle arms with guards for now - can add support for this later if current_arm.guard().is_some() { return None; @@ -42,12 +42,21 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let current_expr = current_arm.expr()?; let current_text_range = current_arm.syntax().text_range(); let current_arm_types = get_arm_types(ctx, ¤t_arm); + let multi_arm_selection = !ctx.has_empty_selection() + && ctx.selection_trimmed().end() > current_arm.syntax().text_range().end(); // We check if the following match arms match this one. We could, but don't, // compare to the previous match arm as well. let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next)) .take_while(|arm| match arm.expr() { Some(expr) if arm.guard().is_none() => { + // don't include match arms that start after our selection + if multi_arm_selection + && arm.syntax().text_range().start() >= ctx.selection_trimmed().end() + { + return false; + } + let same_text = expr.syntax().text() == current_expr.syntax().text(); if !same_text { return false; @@ -299,6 +308,96 @@ fn main() { } #[test] + fn merge_match_arms_selection_has_leading_whitespace() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0,$0 + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_stops_at_end_of_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0, + $0X::C => 0, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 0, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_works_despite_accidental_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::$0A$0 => 0, + X::B => 0, + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + + #[test] fn merge_match_arms_rejects_guards() { check_assist_not_applicable( merge_match_arms, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs index ada89ce7c40..d7fa8826125 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs @@ -3,7 +3,7 @@ use ide_db::{FxHashMap, RootDatabase}; use itertools::Itertools; use syntax::{ ast::{self, HasName}, - ted, AstNode, + AstNode, SyntaxElement, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -46,6 +46,11 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> let impl_ast = ctx.find_node_at_offset::<ast::Impl>()?; let items = impl_ast.assoc_item_list()?; + let parent_node = match ctx.covering_element() { + SyntaxElement::Node(n) => n, + SyntaxElement::Token(t) => t.parent()?, + }; + // restrict the range // if cursor is in assoc_items, abort let assoc_range = items.syntax().text_range(); @@ -94,12 +99,14 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> "Sort items by trait definition", target, |builder| { - let assoc_items = - assoc_items.into_iter().map(|item| builder.make_mut(item)).collect::<Vec<_>>(); - assoc_items - .into_iter() - .zip(sorted) - .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax())); + let mut editor = builder.make_editor(&parent_node); + + assoc_items.into_iter().zip(sorted).for_each(|(old, new)| { + // FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us + editor.replace(old.syntax(), new.clone_for_update().syntax()) + }); + + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 64b7ab1a123..eef4da55e94 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -187,8 +187,8 @@ enum Action { Move { distance: u32 }, Stop } fn handle(action: Action) { match action { - $0Action::Move { distance } => todo!(), - Action::Stop => todo!(), + Action::Move { distance } => ${1:todo!()}, + Action::Stop => ${2:todo!()},$0 } } "#####, diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs index 660afff3dca..006748ddb08 100644 --- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs +++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs @@ -62,15 +62,13 @@ fn memusage_linux() -> MemoryUsage { // mallinfo2 is very recent, so its presence needs to be detected at runtime. // Both are abysmally slow. - use std::ffi::CStr; use std::sync::atomic::{AtomicUsize, Ordering}; static MALLINFO2: AtomicUsize = AtomicUsize::new(1); let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed); if mallinfo2 == 1 { - let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap(); - mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize; + mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"mallinfo2".as_ptr()) } as usize; // NB: races don't matter here, since they'll always store the same value MALLINFO2.store(mallinfo2, Ordering::Relaxed); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 2dc6f0357e3..cb5738a3b40 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -13,7 +13,7 @@ use serde_json::from_value; use span::Edition; use toolchain::Tool; -use crate::{utf8_stdout, ManifestPath, Sysroot}; +use crate::{utf8_stdout, ManifestPath, Sysroot, SysrootQueryMetadata}; use crate::{CfgOverrides, InvocationStrategy}; /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo @@ -85,6 +85,8 @@ pub struct CargoConfig { pub target: Option<String>, /// Sysroot loading behavior pub sysroot: Option<RustLibSource>, + /// How to query metadata for the sysroot crate. + pub sysroot_query_metadata: SysrootQueryMetadata, pub sysroot_src: Option<AbsPathBuf>, /// rustc private crate source pub rustc_source: Option<RustLibSource>, diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index 91bdef4889c..da8afc5d3a1 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -240,3 +240,10 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> { }; Ok(res) } + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum SysrootQueryMetadata { + #[default] + CargoMetadata, + None, +} diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 19f4c35b5ad..8426e689a64 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -14,7 +14,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; use rustc_hash::FxHashMap; use toolchain::{probe_for_binary, Tool}; -use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath}; +use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, SysrootQueryMetadata}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Sysroot { @@ -123,27 +123,43 @@ impl Sysroot { // FIXME: Expose a builder api as loading the sysroot got way too modular and complicated. impl Sysroot { /// Attempts to discover the toolchain's sysroot from the given `dir`. - pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot { + pub fn discover( + dir: &AbsPath, + extra_env: &FxHashMap<String, String>, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { let sysroot_dir = discover_sysroot_dir(dir, extra_env); let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| { discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env) }); - Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir) + Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, sysroot_query_metadata) } pub fn discover_with_src_override( current_dir: &AbsPath, extra_env: &FxHashMap<String, String>, sysroot_src_dir: AbsPathBuf, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { let sysroot_dir = discover_sysroot_dir(current_dir, extra_env); - Sysroot::load_core_check(Some(sysroot_dir), Some(Ok(sysroot_src_dir))) + Sysroot::load_core_check( + Some(sysroot_dir), + Some(Ok(sysroot_src_dir)), + sysroot_query_metadata, + ) } - pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot { + pub fn discover_sysroot_src_dir( + sysroot_dir: AbsPathBuf, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir) .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}")); - Sysroot::load_core_check(Some(Ok(sysroot_dir)), Some(sysroot_src_dir)) + Sysroot::load_core_check( + Some(Ok(sysroot_dir)), + Some(sysroot_src_dir), + sysroot_query_metadata, + ) } pub fn discover_rustc_src(&self) -> Option<ManifestPath> { @@ -186,15 +202,20 @@ impl Sysroot { }) } - pub fn load(sysroot_dir: Option<AbsPathBuf>, sysroot_src_dir: Option<AbsPathBuf>) -> Sysroot { - Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok)) + pub fn load( + sysroot_dir: Option<AbsPathBuf>, + sysroot_src_dir: Option<AbsPathBuf>, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { + Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), sysroot_query_metadata) } fn load_core_check( sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>, sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { - let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir); + let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, sysroot_query_metadata); if sysroot.error.is_none() { if let Some(src_root) = &sysroot.src_root { let has_core = match &sysroot.mode { @@ -220,6 +241,7 @@ impl Sysroot { fn load_( sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>, sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { let sysroot_dir = match sysroot_dir { Some(Ok(sysroot_dir)) => Some(sysroot_dir), @@ -252,12 +274,15 @@ impl Sysroot { } } }; - let library_manifest = ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap(); - if fs::metadata(&library_manifest).is_ok() { - if let Some(sysroot) = - Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir) - { - return sysroot; + if sysroot_query_metadata == SysrootQueryMetadata::CargoMetadata { + let library_manifest = + ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap(); + if fs::metadata(&library_manifest).is_ok() { + if let Some(sysroot) = + Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir) + { + return sysroot; + } } } tracing::debug!("Stitching sysroot library: {sysroot_src_dir}"); @@ -444,13 +469,14 @@ fn discover_sysroot_src_dir_or_add_component( get_rust_src(sysroot_path) }) .ok_or_else(|| { - let error = "\ + tracing::error!(%sysroot_path, "can't load standard library, try installing `rust-src`"); + format_err!( + "\ can't load standard library from sysroot {sysroot_path} (discovered via `rustc --print sysroot`) -try installing the Rust source the same way you installed rustc"; - tracing::error!(error); - format_err!(error) +try installing `rust-src` the same way you installed `rustc`" + ) }) } diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index ef115494a88..f3cf2d83eac 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -13,7 +13,8 @@ use triomphe::Arc; use crate::{ sysroot::SysrootMode, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides, - ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, WorkspaceBuildScripts, + ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, SysrootQueryMetadata, + WorkspaceBuildScripts, }; fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { @@ -116,7 +117,7 @@ fn get_fake_sysroot() -> Sysroot { // fake sysroot, so we give them both the same path: let sysroot_dir = AbsPathBuf::assert(sysroot_path); let sysroot_src_dir = sysroot_dir.clone(); - Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir)) + Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), SysrootQueryMetadata::CargoMetadata) } fn rooted_project_json(data: ProjectJsonData) -> ProjectJson { @@ -231,6 +232,7 @@ fn smoke_test_real_sysroot_cargo() { let sysroot = Sysroot::discover( AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))), &Default::default(), + SysrootQueryMetadata::CargoMetadata, ); assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_))); let project_workspace = ProjectWorkspace { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index d53639e2423..f5ba71fcd05 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -211,34 +211,35 @@ impl ProjectWorkspace { let project_location = project_json.parent().to_path_buf(); let project_json: ProjectJson = ProjectJson::new(Some(project_json.clone()), &project_location, data); - ProjectWorkspace::load_inline( - project_json, - config.target.as_deref(), - &config.extra_env, - &config.cfg_overrides, - ) + ProjectWorkspace::load_inline(project_json, config) } ProjectManifest::CargoScript(rust_file) => { ProjectWorkspace::load_detached_file(rust_file, config)? } ProjectManifest::CargoToml(cargo_toml) => { let sysroot = match (&config.sysroot, &config.sysroot_src) { - (Some(RustLibSource::Discover), None) => { - Sysroot::discover(cargo_toml.parent(), &config.extra_env) - } + (Some(RustLibSource::Discover), None) => Sysroot::discover( + cargo_toml.parent(), + &config.extra_env, + config.sysroot_query_metadata, + ), (Some(RustLibSource::Discover), Some(sysroot_src)) => { Sysroot::discover_with_src_override( cargo_toml.parent(), &config.extra_env, sysroot_src.clone(), + config.sysroot_query_metadata, ) } - (Some(RustLibSource::Path(path)), None) => { - Sysroot::discover_sysroot_src_dir(path.clone()) - } - (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => { - Sysroot::load(Some(sysroot.clone()), Some(sysroot_src.clone())) - } + (Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir( + path.clone(), + config.sysroot_query_metadata, + ), + (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load( + Some(sysroot.clone()), + Some(sysroot_src.clone()), + config.sysroot_query_metadata, + ), (None, _) => Sysroot::empty(), }; tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); @@ -352,20 +353,19 @@ impl ProjectWorkspace { Ok(res) } - pub fn load_inline( - project_json: ProjectJson, - target: Option<&str>, - extra_env: &FxHashMap<String, String>, - cfg_overrides: &CfgOverrides, - ) -> ProjectWorkspace { - let sysroot = Sysroot::load(project_json.sysroot.clone(), project_json.sysroot_src.clone()); + pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace { + let sysroot = Sysroot::load( + project_json.sysroot.clone(), + project_json.sysroot_src.clone(), + config.sysroot_query_metadata, + ); let cfg_config = RustcCfgConfig::Rustc(&sysroot); let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot); let toolchain = match get_toolchain_version( project_json.path(), &sysroot, Tool::Rustc, - extra_env, + &config.extra_env, "rustc ", ) { Ok(it) => it, @@ -375,15 +375,16 @@ impl ProjectWorkspace { } }; - let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config); - let data_layout = target_data_layout::get(data_layout_config, target, extra_env); + let target = config.target.as_deref(); + let rustc_cfg = rustc_cfg::get(target, &config.extra_env, cfg_config); + let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env); ProjectWorkspace { kind: ProjectWorkspaceKind::Json(project_json), sysroot, rustc_cfg, toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), - cfg_overrides: cfg_overrides.clone(), + cfg_overrides: config.cfg_overrides.clone(), } } @@ -393,8 +394,12 @@ impl ProjectWorkspace { ) -> anyhow::Result<ProjectWorkspace> { let dir = detached_file.parent(); let sysroot = match &config.sysroot { - Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()), - Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env), + Some(RustLibSource::Path(path)) => { + Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata) + } + Some(RustLibSource::Discover) => { + Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata) + } None => Sysroot::empty(), }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 155fb6f7c88..802d0c69a47 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -65,6 +65,10 @@ impl flags::AnalysisStats { true => None, false => Some(RustLibSource::Discover), }, + sysroot_query_metadata: match self.no_query_sysroot_metadata { + true => project_model::SysrootQueryMetadata::None, + false => project_model::SysrootQueryMetadata::CargoMetadata, + }, all_targets: true, set_test: !self.no_test, cfg_overrides: CfgOverrides { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index ff24602144a..920a2a37efb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -71,6 +71,9 @@ xflags::xflags! { optional --with-deps /// Don't load sysroot crates (`std`, `core` & friends). optional --no-sysroot + /// Don't run cargo metadata on the sysroot to analyze its third-party dependencies. + /// Requires --no-sysroot to not be set. + optional --no-query-sysroot-metadata /// Don't set #[cfg(test)]. optional --no-test @@ -235,6 +238,7 @@ pub struct AnalysisStats { pub only: Option<String>, pub with_deps: bool, pub no_sysroot: bool, + pub no_query_sysroot_metadata: bool, pub no_test: bool, pub disable_build_scripts: bool, pub disable_proc_macros: bool, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 30378db0b38..6483afc85b2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -13,7 +13,7 @@ use profile::StopWatch; use project_model::target_data_layout::RustcDataLayoutConfig; use project_model::{ target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, - RustLibSource, Sysroot, + RustLibSource, Sysroot, SysrootQueryMetadata, }; use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; @@ -74,7 +74,11 @@ impl Tester { ..Default::default() }; - let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); + let sysroot = Sysroot::discover( + tmp_file.parent().unwrap(), + &cargo_config.extra_env, + SysrootQueryMetadata::CargoMetadata, + ); let data_layout = target_data_layout::get( RustcDataLayoutConfig::Rustc(&sysroot), None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index f5b0fcecf39..37d45255e29 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -558,6 +558,9 @@ config_data! { /// /// This option does not take effect until rust-analyzer is restarted. cargo_sysroot: Option<String> = Some("discover".to_owned()), + /// How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer + /// to analyze third-party dependencies of the standard libraries. + cargo_sysrootQueryMetadata: SysrootQueryMetadata = SysrootQueryMetadata::CargoMetadata, /// Relative path to the sysroot library sources. If left unset, this will default to /// `{cargo.sysroot}/lib/rustlib/src/rust/library`. /// @@ -1868,6 +1871,12 @@ impl Config { }, target: self.cargo_target(source_root).clone(), sysroot, + sysroot_query_metadata: match self.cargo_sysrootQueryMetadata(None) { + SysrootQueryMetadata::CargoMetadata => { + project_model::SysrootQueryMetadata::CargoMetadata + } + SysrootQueryMetadata::None => project_model::SysrootQueryMetadata::None, + }, sysroot_src, rustc_source, cfg_overrides: project_model::CfgOverrides { @@ -2559,6 +2568,13 @@ pub enum NumThreads { Concrete(usize), } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum SysrootQueryMetadata { + CargoMetadata, + None, +} + macro_rules! _default_val { (@verbatim: $s:literal, $ty:ty) => {{ let default_: $ty = serde_json::from_str(&$s).unwrap(); @@ -3410,6 +3426,14 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json } ] }, + "SysrootQueryMetadata" => set! { + "type": "string", + "enum": ["none", "cargo_metadata"], + "enumDescriptions": [ + "Do not query sysroot metadata, always use stitched sysroot.", + "Use `cargo metadata` to query sysroot metadata." + ], + }, _ => panic!("missing entry for {ty}: {default} (field {field})"), } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 0b24833358d..bc85afa0e49 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -316,9 +316,7 @@ impl GlobalState { LinkedProject::InlineJsonProject(it) => { let workspace = project_model::ProjectWorkspace::load_inline( it.clone(), - cargo_config.target.as_deref(), - &cargo_config.extra_env, - &cargo_config.cfg_overrides, + &cargo_config, ); Ok(workspace) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 97c76bf8d17..c1ca5960637 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1085,6 +1085,7 @@ fn resolve_proc_macro() { let sysroot = project_model::Sysroot::discover( &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()), &Default::default(), + project_model::SysrootQueryMetadata::CargoMetadata, ); let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap(); diff --git a/src/tools/rust-analyzer/docs/dev/architecture.md b/src/tools/rust-analyzer/docs/dev/architecture.md index 6aa57b2f9be..9c9e05a429b 100644 --- a/src/tools/rust-analyzer/docs/dev/architecture.md +++ b/src/tools/rust-analyzer/docs/dev/architecture.md @@ -42,7 +42,7 @@ The underlying engine makes sure that model is computed lazily (on-demand) and c `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP. This is *the* entry point, but it front-loads a lot of complexity, so it's fine to just skim through it. -`crates/rust-analyzer/src/handlers/requests.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. +`crates/rust-analyzer/src/handlers/request.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. `Analysis` and `AnalysisHost` types define the main API for consumers of IDE services. diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 463718835b9..052d0a2a41d 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -135,6 +135,12 @@ Unsetting this disables sysroot loading. This option does not take effect until rust-analyzer is restarted. -- +[[rust-analyzer.cargo.sysrootQueryMetadata]]rust-analyzer.cargo.sysrootQueryMetadata (default: `"cargo_metadata"`):: ++ +-- +How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer +to analyze third-party dependencies of the standard libraries. +-- [[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index b868622b3a5..82c43b76fdd 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -819,6 +819,24 @@ { "title": "cargo", "properties": { + "rust-analyzer.cargo.sysrootQueryMetadata": { + "markdownDescription": "How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer\nto analyze third-party dependencies of the standard libraries.", + "default": "cargo_metadata", + "type": "string", + "enum": [ + "none", + "cargo_metadata" + ], + "enumDescriptions": [ + "Do not query sysroot metadata, always use stitched sysroot.", + "Use `cargo metadata` to query sysroot metadata." + ] + } + } + }, + { + "title": "cargo", + "properties": { "rust-analyzer.cargo.sysrootSrc": { "markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.", "default": null, diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 00f4f743a7c..8f41ed9e14f 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -145f9cf95de1fbde3fa11e98461310e0373253e6 +f005c7437def424a1c43cbc380352a58d8ac920b diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e065f01ebba..afa0b9a6760 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -307,7 +307,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "intl_pluralrules", "itertools", "itoa", - "jemalloc-sys", "jobserver", "lazy_static", "leb128", @@ -392,6 +391,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", + "tikv-jemalloc-sys", "time", "time-core", "time-macros", diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 14da876eda7..9a51979a2f0 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -1,5 +1,4 @@ #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index dd064c59283..46010692fe5 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -97,10 +97,6 @@ impl RawEmitter { self.blank_line(); - writeln!( - &mut self.file, - r#"#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]"# - ).unwrap(); writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); if first_code_point > 0x7f { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} &&").unwrap(); diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index acdb1aa1ab7..965e9b01a44 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.10" +wasm-component-ld = "0.5.11" diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index 85321e5f345..aa35c4d8865 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -1,9 +1,15 @@ -//@ revisions: powerpc powerpc64 +//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx //@ assembly-output: emit-asm //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //@[powerpc] needs-llvm-components: powerpc -//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec +//@[powerpc_altivec] needs-llvm-components: powerpc +//@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx +//@[powerpc_vsx] needs-llvm-components: powerpc +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec //@[powerpc64] needs-llvm-components: powerpc +//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx +//@[powerpc64_vsx] needs-llvm-components: powerpc //@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] @@ -11,6 +17,13 @@ #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +#[cfg_attr(altivec, cfg(not(target_feature = "altivec")))] +#[cfg_attr(not(altivec), cfg(target_feature = "altivec"))] +compile_error!("altivec cfg and target feature mismatch"); +#[cfg_attr(vsx, cfg(not(target_feature = "vsx")))] +#[cfg_attr(not(vsx), cfg(target_feature = "vsx"))] +compile_error!("vsx cfg and target feature mismatch"); + #[rustc_builtin_macro] macro_rules! asm { () => {}; @@ -29,8 +42,23 @@ trait Sized {} #[lang = "copy"] trait Copy {} +impl<T: Copy, const N: usize> Copy for [T; N] {} + type ptr = *const i32; +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i16x8([i16; 8]); +#[repr(simd)] +pub struct i32x4([i32; 4]); +#[repr(simd)] +pub struct i64x2([i64; 2]); +#[repr(simd)] +pub struct f32x4([f32; 4]); +#[repr(simd)] +pub struct f64x2([f64; 2]); + impl Copy for i8 {} impl Copy for u8 {} impl Copy for i16 {} @@ -39,6 +67,13 @@ impl Copy for i64 {} impl Copy for f32 {} impl Copy for f64 {} impl Copy for ptr {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -124,6 +159,94 @@ check!(reg_f32, f32, freg, "fmr"); // CHECK: #NO_APP check!(reg_f64, f64, freg, "fmr"); +// powerpc_altivec-LABEL: vreg_i8x16: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i8x16, i8x16, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i16x8, i16x8, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i32x4, i32x4, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_i64x2, i64x2, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_f32x4, f32x4, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f64x2, f64x2, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f32: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f32, f32, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f64: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f64, f64, vreg, "vmr"); + // CHECK-LABEL: reg_i8_r0: // CHECK: #APP // CHECK: mr 0, 0 @@ -197,3 +320,179 @@ check_reg!(reg_f32_f18, f32, "18", "f18", "fmr"); // CHECK: fmr 18, 18 // CHECK: #NO_APP check_reg!(reg_f64_f18, f64, "18", "f18", "fmr"); + +// powerpc_altivec-LABEL: vreg_i8x16_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f32_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i8x16_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f32_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr"); diff --git a/tests/assembly/breakpoint.rs b/tests/assembly/breakpoint.rs new file mode 100644 index 00000000000..e0cc2d1eebb --- /dev/null +++ b/tests/assembly/breakpoint.rs @@ -0,0 +1,14 @@ +//@ revisions: aarch64 x86_64 +//@ assembly-output: emit-asm +//@[aarch64] only-aarch64 +//@[x86_64] only-x86_64 + +#![feature(breakpoint)] +#![crate_type = "lib"] + +// CHECK-LABEL: use_bp +// aarch64: brk #0xf000 +// x86_64: int3 +pub fn use_bp() { + core::arch::breakpoint(); +} diff --git a/tests/assembly/x86_64-bigint-helpers.rs b/tests/assembly/x86_64-bigint-helpers.rs new file mode 100644 index 00000000000..198e5543539 --- /dev/null +++ b/tests/assembly/x86_64-bigint-helpers.rs @@ -0,0 +1,54 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O -C target-cpu=x86-64-v4 +//@ compile-flags: -C llvm-args=-x86-asm-syntax=intel + +#![no_std] +#![feature(bigint_helper_methods)] + +// This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain, +// to catch issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815> + +// This forces the ABI to avoid the windows-vs-linux ABI differences. + +// CHECK-LABEL: bigint_chain_carrying_add: +#[no_mangle] +pub unsafe extern "sysv64" fn bigint_chain_carrying_add( + dest: *mut u64, + src1: *const u64, + src2: *const u64, + n: usize, + mut carry: bool, +) -> bool { + // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + for i in 0..n { + (*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry); + } + carry +} + +// CHECK-LABEL: bigint_chain_borrowing_sub: +#[no_mangle] +pub unsafe extern "sysv64" fn bigint_chain_borrowing_sub( + dest: *mut u64, + src1: *const u64, + src2: *const u64, + n: usize, + mut carry: bool, +) -> bool { + // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + for i in 0..n { + (*dest.add(i), carry) = u64::borrowing_sub(*src1.add(i), *src2.add(i), carry); + } + carry +} diff --git a/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs index 3926f295742..8bb78eb788a 100644 --- a/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs +++ b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs @@ -11,10 +11,21 @@ pub fn foo<T>(x: T) -> (T, u32, i8) { #[inline(never)] fn bar<T>(x: T) -> (T, Struct) { let _ = not_exported_and_not_generic(0); + exported_and_generic::<u32>(0); (x, Struct(1)) } +pub static F: fn(u32) -> u32 = exported_and_generic::<u32>; + // These should not contribute to the codegen items of other crates. + +// This is generic, but it's only instantiated with a u32 argument and that instantiation is present +// in the local crate (see F above). +#[inline(never)] +pub fn exported_and_generic<T>(x: T) -> T { + x +} + #[inline(never)] pub fn exported_but_not_generic(x: i32) -> i64 { x as i64 diff --git a/tests/codegen/asm/aarch64-clobbers.rs b/tests/codegen/asm/aarch64-clobbers.rs new file mode 100644 index 00000000000..900e6629fd2 --- /dev/null +++ b/tests/codegen/asm/aarch64-clobbers.rs @@ -0,0 +1,51 @@ +//@ revisions: aarch64 aarch64_fixed_x18 aarch64_no_x18 aarch64_reserve_x18 arm64ec +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@[aarch64_fixed_x18] compile-flags: --target aarch64-unknown-linux-gnu -Zfixed-x18 +//@[aarch64_fixed_x18] needs-llvm-components: aarch64 +//@[aarch64_no_x18] compile-flags: --target aarch64-pc-windows-msvc +//@[aarch64_no_x18] needs-llvm-components: aarch64 +// aarch64-unknown-trusty uses aarch64-unknown-unknown-musl which doesn't +// reserve x18 by default as llvm_target, and pass +reserve-x18 in target-spec. +//@[aarch64_reserve_x18] compile-flags: --target aarch64-unknown-trusty +//@[aarch64_reserve_x18] needs-llvm-components: aarch64 +//@[arm64ec] compile-flags: --target arm64ec-pc-windows-msvc +//@[arm64ec] needs-llvm-components: aarch64 +// ignore-tidy-linelength + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cc_clobber +// CHECK: call void asm sideeffect "", "~{cc}"() +#[no_mangle] +pub unsafe fn cc_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// aarch64: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w18},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_fixed_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_no_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_reserve_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// arm64ec: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/asm/arm64ec-clobbers.rs b/tests/codegen/asm/arm64ec-clobbers.rs deleted file mode 100644 index 80059331642..00000000000 --- a/tests/codegen/asm/arm64ec-clobbers.rs +++ /dev/null @@ -1,36 +0,0 @@ -//@ assembly-output: emit-asm -//@ compile-flags: --target arm64ec-pc-windows-msvc -//@ needs-llvm-components: aarch64 - -#![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} - -// CHECK-LABEL: @cc_clobber -// CHECK: call void asm sideeffect "", "~{cc}"() -#[no_mangle] -pub unsafe fn cc_clobber() { - asm!("", options(nostack, nomem)); -} - -// CHECK-LABEL: @no_clobber -// CHECK: call void asm sideeffect "", ""() -#[no_mangle] -pub unsafe fn no_clobber() { - asm!("", options(nostack, nomem, preserves_flags)); -} - -// CHECK-LABEL: @clobber_abi -// CHECK: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"() -#[no_mangle] -pub unsafe fn clobber_abi() { - asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); -} diff --git a/tests/codegen/asm/avr-clobbers.rs b/tests/codegen/asm/avr-clobbers.rs new file mode 100644 index 00000000000..6e0c75368e2 --- /dev/null +++ b/tests/codegen/asm/avr-clobbers.rs @@ -0,0 +1,43 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ needs-llvm-components: avr + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @sreg_is_clobbered +// CHECK: void asm sideeffect "", "~{sreg}"() +#[no_mangle] +pub unsafe fn sreg_is_clobbered() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @sreg_is_not_clobbered_if_preserve_flags_is_used +// CHECK: void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn sreg_is_not_clobbered_if_preserve_flags_is_used() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r18},={r19},={r20},={r21},={r22},={r23},={r24},={r25},={r26},={r27},={r30},={r31},~{sreg}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem)); +} + +// CHECK-LABEL: @clobber_abi_with_preserved_flags +// CHECK: asm sideeffect "", "={r18},={r19},={r20},={r21},={r22},={r23},={r24},={r25},={r26},={r27},={r30},={r31}"() +#[no_mangle] +pub unsafe fn clobber_abi_with_preserved_flags() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/asm/hexagon-clobbers.rs b/tests/codegen/asm/hexagon-clobbers.rs new file mode 100644 index 00000000000..6bb662ead99 --- /dev/null +++ b/tests/codegen/asm/hexagon-clobbers.rs @@ -0,0 +1,37 @@ +//@ revisions: hexagon +//@[hexagon] compile-flags: --target hexagon-unknown-linux-musl +//@[hexagon] needs-llvm-components: hexagon +//@ compile-flags: -Zmerge-functions=disabled + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @flags_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn flags_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @p0_clobber +// CHECK: call void asm sideeffect "", "~{p0}"() +#[no_mangle] +pub unsafe fn p0_clobber() { + asm!("", out("p0") _, options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs index e97e8300ca7..2832377cef0 100644 --- a/tests/codegen/asm/powerpc-clobbers.rs +++ b/tests/codegen/asm/powerpc-clobbers.rs @@ -7,6 +7,7 @@ //@[powerpc64le] needs-llvm-components: powerpc //@[aix64] compile-flags: --target powerpc64-ibm-aix //@[aix64] needs-llvm-components: powerpc +// ignore-tidy-linelength #![crate_type = "rlib"] #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] @@ -48,15 +49,23 @@ pub unsafe fn xer_clobber() { asm!("", out("xer") _, options(nostack, nomem, preserves_flags)); } +// Output format depends on the availability of altivec. // CHECK-LABEL: @v0_clobber -// CHECK: call void asm sideeffect "", "~{v0}"() +// powerpc: call void asm sideeffect "", "~{v0}"() +// powerpc64: call <4 x i32> asm sideeffect "", "=&{v0}"() +// powerpc64le: call <4 x i32> asm sideeffect "", "=&{v0}"() +// aix64: call <4 x i32> asm sideeffect "", "=&{v0}"() #[no_mangle] pub unsafe fn v0_clobber() { asm!("", out("v0") _, options(nostack, nomem, preserves_flags)); } +// Output format depends on the availability of altivec. // CHECK-LABEL: @clobber_abi -// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() #[no_mangle] pub unsafe fn clobber_abi() { asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); diff --git a/tests/codegen/asm/riscv-clobbers.rs b/tests/codegen/asm/riscv-clobbers.rs new file mode 100644 index 00000000000..59b2705a449 --- /dev/null +++ b/tests/codegen/asm/riscv-clobbers.rs @@ -0,0 +1,44 @@ +//@ assembly-output: emit-asm +//@ revisions: rv32i rv64i rv32e +//@[rv32i] compile-flags: --target riscv32i-unknown-none-elf +//@[rv32i] needs-llvm-components: riscv +//@[rv64i] compile-flags: --target riscv64imac-unknown-none-elf +//@[rv64i] needs-llvm-components: riscv +//@[rv32e] compile-flags: --target riscv32e-unknown-none-elf +//@[rv32e] needs-llvm-components: riscv +// ignore-tidy-linelength + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @flags_clobber +// CHECK: call void asm sideeffect "", "~{vtype},~{vl},~{vxsat},~{vxrm}"() +#[no_mangle] +pub unsafe fn flags_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// rv32i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +// rv64i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +// rv32e: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs index 9cb1e623295..644df169a36 100644 --- a/tests/codegen/async-closure-debug.rs +++ b/tests/codegen/async-closure-debug.rs @@ -9,7 +9,7 @@ #![feature(async_closure)] -fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { +fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ { async move || { let hello = String::from("hello"); println!("{hello}, {upvar}"); diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index a2dcb1c0924..7a36490fe93 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -86,7 +86,7 @@ pub extern "C" fn test() { // A call through the Fn trait must use address space 1. // - // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait() + // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait({{.*}}) call_through_fn_trait(&mut update_bar_value); // A call through a global variable must use address space 1. diff --git a/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs index 159ecfd0974..c0691b23275 100644 --- a/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs +++ b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs index c3858044c0c..0f6e99f9b1e 100644 --- a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs +++ b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs @@ -3,7 +3,7 @@ // MSVC is different because of the individual allocas. //@ ignore-msvc -//@ aux-build:macro_def.rs +//@ proc-macro: macro_def.rs // Find the variable. // CHECK-DAG: ![[#var_dbg:]] = !DILocalVariable(name: "n",{{( arg: 1,)?}} scope: ![[#var_scope:]] diff --git a/tests/codegen/issues/issue-13018.rs b/tests/codegen/issues/issue-13018.rs index 66282dc4274..a29452436d2 100644 --- a/tests/codegen/issues/issue-13018.rs +++ b/tests/codegen/issues/issue-13018.rs @@ -2,7 +2,10 @@ // A drop([...].clone()) sequence on an Rc should be a no-op // In particular, no call to __rust_dealloc should be emitted -#![crate_type = "lib"] +// +// We use a cdylib since it's a leaf unit for Rust purposes, so doesn't codegen -Zshare-generics +// code. +#![crate_type = "cdylib"] use std::rc::Rc; pub fn foo(t: &Rc<Vec<usize>>) { diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs new file mode 100644 index 00000000000..75f5d82eee5 --- /dev/null +++ b/tests/codegen/issues/issue-98678-async.rs @@ -0,0 +1,25 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for async blocks and +// async functions. +// +//@ edition:2021 +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true + +// ignore-tidy-linelength + +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-async.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-async.rs{{".*}}) + +// NONMSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub async fn foo() -> u8 { + 5 +} + +pub fn bar() -> impl std::future::Future<Output = u8> { + // NONMSVC: !DICompositeType({{.*"}}{async_block_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*"}}enum2$<issue_98678_async::bar::async_block_env$0>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + async { + let x: u8 = foo().await; + x + 5 + } +} diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs new file mode 100644 index 00000000000..0730e56bf31 --- /dev/null +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -0,0 +1,22 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for closures and +// coroutines. +// +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true +#![feature(coroutines, stmt_expr_attributes)] + +// ignore-tidy-linelength + +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-closure-coroutine.rs{{".*}}) +// MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) + +pub fn foo() { + // NONMSVC-DAG: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*"}}closure_env$0{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let closure = |x| x; + closure(0); + + // NONMSVC-DAG: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 3]], + // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + let _coroutine = #[coroutine] + || yield 1; +} diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs new file mode 100644 index 00000000000..62c6cded866 --- /dev/null +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -0,0 +1,40 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata enums. +// +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true + +// ignore-tidy-linelength + +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-enum.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-enum.rs{{".*}}) + +// NONMSVC: !DICompositeType({{.*"}}SingleCase{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::SingleCase>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum SingleCase { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + One, +} + +// NONMSVC: !DICompositeType({{.*"}}MultipleDataCases{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::MultipleDataCases>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum MultipleDataCases { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Case1(u32), + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Case2(i64), +} + +// NONMSVC: !DICompositeType({{.*"}}NicheLayout{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::NicheLayout>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum NicheLayout { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Something(&'static u32), + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Nothing, +} + +pub fn foo(_: SingleCase, _: MultipleDataCases, _: NicheLayout) {} diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs new file mode 100644 index 00000000000..bf2d6e731aa --- /dev/null +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -0,0 +1,25 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for structs and +// unions. +// +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true + +// ignore-tidy-linelength + +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-struct-union.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-struct-union.rs{{".*}}) + +// CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub struct MyType { + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, +} + +// CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub union MyUnion { + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, + // CHECK: !DIDerivedType({{.*"}}f{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + f: f32, +} + +pub fn foo(_: MyType, _: MyUnion) {} diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 4d00f0d9b33..9ff29af8e8e 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -1,19 +1,19 @@ Function name: async_closure::call_once::<async_closure::main::{closure#0}> -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43) Highest counter ID seen: c0 Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14) +- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index fd6edf7c29e..75da1a01fc1 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -4,7 +4,7 @@ LL| |//@ aux-build: executor.rs LL| |extern crate executor; LL| | - LL| 1|async fn call_once(f: impl async FnOnce()) { + LL| 1|async fn call_once(f: impl AsyncFnOnce()) { LL| 1| f().await; LL| 1|} LL| | diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs index c076d03eef4..cbac592d957 100644 --- a/tests/coverage/async_closure.rs +++ b/tests/coverage/async_closure.rs @@ -4,7 +4,7 @@ //@ aux-build: executor.rs extern crate executor; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 411f16725bb..5a20de3d4d4 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -8,18 +8,18 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: inline_dead::live::<false> -Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- Code(Zero) at (prev + 2, 9) to (start + 0, 15) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) - = (c0 - Zero) + = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) -Highest counter ID seen: c0 +Highest counter ID seen: c1 Function name: inline_dead::main Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index 04451596eae..7789114c239 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -21,13 +21,13 @@ Number of file 0 mappings: 3 Highest counter ID seen: (none) Function name: let_else_loop::loopy -Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 00, 01, 1c, 00, 23, 05, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 09, 01, 1c, 00, 23, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 9, 1) to (start + 1, 20) -- Code(Zero) at (prev + 1, 28) to (start + 0, 35) +- Code(Counter(2)) at (prev + 1, 28) to (start + 0, 35) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) -Highest counter ID seen: c1 +Highest counter ID seen: c2 diff --git a/tests/crashes/109681.rs b/tests/crashes/109681.rs deleted file mode 100644 index 73ff1007094..00000000000 --- a/tests/crashes/109681.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #109681 - -#![crate_type="lib"] -#![feature(linkage)] - -#[linkage = "common"] -pub static TEST3: bool = true; - -fn main() {} diff --git a/tests/crashes/119701.rs b/tests/crashes/119701.rs deleted file mode 100644 index bdb326ea76b..00000000000 --- a/tests/crashes/119701.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: #119701 -#![feature(const_trait_impl, generic_const_exprs)] - -fn main() { - let _ = process::<()>([()]); -} - -fn process<T: const Trait>() -> [(); T::make(2)] { - input -} - -#[const_trait] -trait Trait { - fn make(input: u8) -> usize; -} - -impl const Trait for () { - fn make(input: usize) -> usize { - input / 2 - } -} diff --git a/tests/crashes/121127.rs b/tests/crashes/121127.rs deleted file mode 100644 index e50dc7763fc..00000000000 --- a/tests/crashes/121127.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #121127 -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes -C debuginfo=2 -// Note that as of PR#123949 this only crashes with debuginfo enabled - -#![feature(specialization)] - -pub trait Foo { - fn abc() -> u32; -} - -pub trait Marker {} - -impl<T> Foo for T { - default fn abc(f: fn(&T), t: &T) -> u32 { - 16 - } -} - -impl<T: Marker> Foo for T { - fn def() -> u32 { - Self::abc() - } -} diff --git a/tests/crashes/121411.rs b/tests/crashes/121411.rs deleted file mode 100644 index 2456910e6fa..00000000000 --- a/tests/crashes/121411.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #121411 -#![feature(const_trait_impl)] - -#[const_trait] -trait Foo { - fn into_iter(&self) {} -} - -impl const Foo for () { - fn into_iter(a: u32, b: u32) {} -} - -const _: () = Foo::into_iter(&()); diff --git a/tests/crashes/121429.rs b/tests/crashes/121429.rs index 09bd343e0ba..e407754db5c 100644 --- a/tests/crashes/121429.rs +++ b/tests/crashes/121429.rs @@ -1,14 +1,11 @@ //@ known-bug: #121429 -#![feature(generic_const_exprs)] - -pub trait True {} -impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where - If<{}>: True -{ -} #![feature(generic_const_exprs)] +struct FixedI8<const X: usize>; +const FRAC_LHS: usize = 0; +const FRAC_RHS: usize = 1; + pub trait True {} impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs index f461f32f59d..1b875497465 100644 --- a/tests/crashes/124020.rs +++ b/tests/crashes/124020.rs @@ -1,7 +1,7 @@ //@ known-bug: #124020 //@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; @@ -19,7 +19,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T { } } -async fn call_once(f: impl async FnOnce(DropMe)) { +async fn call_once(f: impl AsyncFnOnce(DropMe)) { f(DropMe("world")).await; } diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs deleted file mode 100644 index ad739639b72..00000000000 --- a/tests/crashes/125476.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: rust-lang/rust#125476 -//@ only-x86_64 -pub struct Data([u8; usize::MAX >> 2]); -const _: &'static [Data] = &[]; diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs deleted file mode 100644 index 728578179ed..00000000000 --- a/tests/crashes/126267.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: rust-lang/rust#126267 - -#![feature(transmutability)] -#![crate_type = "lib"] - -pub enum ApiError {} -pub struct TokioError { - b: bool, -} -pub enum Error { - Api { source: ApiError }, - Ethereum, - Tokio { source: TokioError }, -} - -mod assert { - use std::mem::TransmuteFrom; - - pub fn is_transmutable<Src, Dst>() - where - Dst: TransmuteFrom<Src>, // safety is NOT assumed - { - } -} - -fn test() { - struct Src; - type Dst = Error; - assert::is_transmutable::<Src, Dst>(); -} diff --git a/tests/crashes/126646.rs b/tests/crashes/126646.rs deleted file mode 100644 index 24e3530320a..00000000000 --- a/tests/crashes/126646.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: rust-lang/rust#126646 -mod foo { - pub trait Callable { - type Output; - fn call() -> Self::Output; - } - - impl<'a, V: ?Sized> Callable for &'a () { - type Output = (); - } -} -use foo::*; - -fn test<'a>() -> impl Sized { - <&'a () as Callable>::call() -} - -fn main() {} diff --git a/tests/crashes/129075.rs b/tests/crashes/129075.rs deleted file mode 100644 index 4a0e920914c..00000000000 --- a/tests/crashes/129075.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#129075 -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes - -struct Foo<T>([T; 2]); - -impl<T: Default + Copy> Default for Foo<T> { - fn default(&mut self) -> Self { - Foo([Default::default(); 2]) - } -} - -fn field_array() { - let a: i32; - let b; - Foo([a, b]) = Default::default(); -} diff --git a/tests/crashes/129127.rs b/tests/crashes/129127.rs deleted file mode 100644 index 8ec848dbd05..00000000000 --- a/tests/crashes/129127.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: rust-lang/rust#129127 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - - - - -pub struct Rows<'a>(); - -impl<'a> Iterator for Rows<'a> { - type Item = (); - - fn next() -> Option<Self::Item> { - let mut rows = Rows(); - rows.map(|row| row).next() - } -} - -fn main() { - let mut rows = Rows(); - rows.next(); -} diff --git a/tests/crashes/129214.rs b/tests/crashes/129214.rs deleted file mode 100644 index e14b9f379d6..00000000000 --- a/tests/crashes/129214.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: rust-lang/rust#129214 -//@ compile-flags: -Zvalidate-mir -Copt-level=3 --crate-type=lib - -trait to_str {} - -trait map<T> { - fn map<U, F>(&self, f: F) -> Vec<U> - where - F: FnMut(&Box<usize>) -> U; -} -impl<T> map<T> for Vec<T> { - fn map<U, F>(&self, mut f: F) -> Vec<U> - where - F: FnMut(&T) -> U, - { - let mut r = Vec::new(); - for i in self { - r.push(f(i)); - } - r - } -} - -fn foo<U, T: map<U>>(x: T) -> Vec<String> { - x.map(|_e| "hi".to_string()) -} - -pub fn main() { - assert_eq!(foo(vec![1]), ["hi".to_string()]); -} diff --git a/tests/crashes/131294-2.rs b/tests/crashes/131294-2.rs deleted file mode 100644 index 130a8b10fb7..00000000000 --- a/tests/crashes/131294-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #131294 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - -// https://github.com/rust-lang/rust/issues/131294#issuecomment-2395088049 second comment -struct Rows; - -impl Iterator for Rows { - type Item = String; - - fn next() -> Option<String> { - let args = format_args!("Hello world"); - - { - match args.as_str() { - Some(t) => t.to_owned(), - None => String::new(), - } - } - .into() - } -} - -fn main() { - Rows.next(); -} diff --git a/tests/crashes/131294.rs b/tests/crashes/131294.rs deleted file mode 100644 index ec6c9567467..00000000000 --- a/tests/crashes/131294.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #131294 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - -struct Rows; - -impl Iterator for Rows { - type Item = String; - - fn next() -> Option<Self::Item> { - std::fmt::format(format_args!("Hello world")).into() - } -} - -fn main() { - Rows.next(); -} diff --git a/tests/crashes/131538.rs b/tests/crashes/131538.rs deleted file mode 100644 index f971d8b7791..00000000000 --- a/tests/crashes/131538.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #131538 -#![feature(generic_associated_types_extended)] -#![feature(trivial_bounds)] - -trait HealthCheck { - async fn check<const N: usize>(); -} - -fn do_health_check_par() -where - HealthCheck: HealthCheck, -{ -} diff --git a/tests/crashes/131668.rs b/tests/crashes/131668.rs deleted file mode 100644 index 90aa4494425..00000000000 --- a/tests/crashes/131668.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #131668 - -#![feature(generic_associated_types_extended)] -trait B { - type Y<const N: i16>; -} - -struct Erase<T: B>(T); - -fn make_static() { - Erase::<dyn for<'c> B<&'c ()>>(()); -} diff --git a/tests/crashes/132320.rs b/tests/crashes/132320.rs deleted file mode 100644 index 79181c3a2c5..00000000000 --- a/tests/crashes/132320.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #132320 -//@ compile-flags: -Znext-solver=globally - -trait Foo { - type Item; - fn foo(&mut self); -} - -impl Foo for () { - type Item = Option<()>; - - fn foo(&mut self) { - let _ = Self::Item::None; - } -} diff --git a/tests/crashes/34127.rs b/tests/crashes/34127.rs index 88a2cf30ec5..ea36b48ecba 100644 --- a/tests/crashes/34127.rs +++ b/tests/crashes/34127.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -g -Copt-level=0 +//@ compile-flags: -g -Copt-level=0 -Z verify-llvm-ir //@ known-bug: #34127 //@ only-x86_64 diff --git a/tests/incremental/auxiliary/incremental_proc_macro_aux.rs b/tests/incremental/auxiliary/incremental_proc_macro_aux.rs index 505a9ee27a4..d0730eb00ee 100644 --- a/tests/incremental/auxiliary/incremental_proc_macro_aux.rs +++ b/tests/incremental/auxiliary/incremental_proc_macro_aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/incremental/auxiliary/issue-49482-macro-def.rs b/tests/incremental/auxiliary/issue-49482-macro-def.rs index 9218d6b62cb..6cd565c3a11 100644 --- a/tests/incremental/auxiliary/issue-49482-macro-def.rs +++ b/tests/incremental/auxiliary/issue-49482-macro-def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type="proc-macro"] #![allow(non_snake_case)] extern crate proc_macro; diff --git a/tests/incremental/auxiliary/issue-49482-reexport.rs b/tests/incremental/auxiliary/issue-49482-reexport.rs index 39f19e3f15f..686766de54f 100644 --- a/tests/incremental/auxiliary/issue-49482-reexport.rs +++ b/tests/incremental/auxiliary/issue-49482-reexport.rs @@ -1,3 +1,4 @@ +//@ proc-macro: issue-49482-macro-def.rs #[macro_use] extern crate issue_49482_macro_def; diff --git a/tests/incremental/auxiliary/issue-54059.rs b/tests/incremental/auxiliary/issue-54059.rs index 5f45403735c..6bbc94149e8 100644 --- a/tests/incremental/auxiliary/issue-54059.rs +++ b/tests/incremental/auxiliary/issue-54059.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - // check that having extern "C" functions in a proc macro doesn't crash. -#![crate_type="proc-macro"] #![allow(non_snake_case)] extern crate proc_macro; diff --git a/tests/incremental/incremental_proc_macro.rs b/tests/incremental/incremental_proc_macro.rs index 97faf8e698a..3cf89cae652 100644 --- a/tests/incremental/incremental_proc_macro.rs +++ b/tests/incremental/incremental_proc_macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:incremental_proc_macro_aux.rs +//@ proc-macro: incremental_proc_macro_aux.rs //@ revisions: cfail1 cfail2 //@ build-pass (FIXME(62277): could be check-pass?) diff --git a/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs index 3b4933811d3..877d74d731d 100644 --- a/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs +++ b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; diff --git a/tests/incremental/issue-110457-same-span-closures/main.rs b/tests/incremental/issue-110457-same-span-closures/main.rs index c36b7e3ca80..6a5e4b315ce 100644 --- a/tests/incremental/issue-110457-same-span-closures/main.rs +++ b/tests/incremental/issue-110457-same-span-closures/main.rs @@ -1,4 +1,4 @@ -//@ aux-build: egui_inspect_derive.rs +//@ proc-macro: egui_inspect_derive.rs //@ revisions: cpass1 cpass2 extern crate egui_inspect_derive; diff --git a/tests/incremental/issue-49482.rs b/tests/incremental/issue-49482.rs index 2dddde6c171..849f1c66600 100644 --- a/tests/incremental/issue-49482.rs +++ b/tests/incremental/issue-49482.rs @@ -1,4 +1,3 @@ -//@ aux-build:issue-49482-macro-def.rs //@ aux-build:issue-49482-reexport.rs //@ revisions: rpass1 diff --git a/tests/incremental/issue-54059.rs b/tests/incremental/issue-54059.rs index bfce4d487db..b6668b4be28 100644 --- a/tests/incremental/issue-54059.rs +++ b/tests/incremental/issue-54059.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-54059.rs +//@ proc-macro: issue-54059.rs //@ ignore-windows - dealing with weird symbols issues on dylibs isn't worth it //@ revisions: rpass1 diff --git a/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs index f84c4fe9895..704193cffd0 100644 --- a/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs +++ b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs @@ -1,3 +1,4 @@ +//@ proc-macro: respan.rs //@ revisions: rpass1 rpass2 extern crate respan; diff --git a/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs index c56d9052e32..5bedca8a265 100644 --- a/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs +++ b/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs b/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs index eaad44780c7..6db5107cbe4 100644 --- a/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs +++ b/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs @@ -1,5 +1,4 @@ //@ revisions: rpass1 rpass2 -//@ aux-build:respan.rs //@ aux-build:invalid-span-helper-lib.rs // This issue has several different parts. The high level idea is: diff --git a/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir b/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir new file mode 100644 index 00000000000..00702b5b99c --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `constant` after built + +fn constant() -> () { + debug scalar => const 5_usize; + let mut _0: (); + + bb0: { + return; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir index d8639253718..fba611818ef 100644 --- a/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir +++ b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir @@ -2,7 +2,7 @@ fn numbered(_1: (u32, i32)) -> () { debug first => (_1.0: u32); - debug second => (_1.0: u32); + debug second => (_1.1: i32); let mut _0: (); bb0: { diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs index 5ab83fd4214..c4ea2162e0b 100644 --- a/tests/mir-opt/building/custom/debuginfo.rs +++ b/tests/mir-opt/building/custom/debuginfo.rs @@ -1,4 +1,3 @@ -// skip-filecheck #![feature(custom_mir, core_intrinsics)] extern crate core; @@ -7,6 +6,8 @@ use core::intrinsics::mir::*; // EMIT_MIR debuginfo.pointee.built.after.mir #[custom_mir(dialect = "built")] fn pointee(opt: &mut Option<i32>) { + // CHECK-LABEL: fn pointee( + // CHECK: debug foo => (((*_1) as variant#1).0: i32); mir! { debug foo => Field::<i32>(Variant(*opt, 1), 0); { @@ -18,9 +19,12 @@ fn pointee(opt: &mut Option<i32>) { // EMIT_MIR debuginfo.numbered.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn numbered(i: (u32, i32)) { + // CHECK-LABEL: fn numbered( + // CHECK: debug first => (_1.0: u32); + // CHECK: debug second => (_1.1: i32); mir! { debug first => i.0; - debug second => i.0; + debug second => i.1; { Return() } @@ -34,6 +38,8 @@ struct S { // EMIT_MIR debuginfo.structured.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn structured(i: S) { + // CHECK-LABEL: fn structured( + // CHECK: debug x => (_1.0: f32); mir! { debug x => i.x; { @@ -45,6 +51,8 @@ fn structured(i: S) { // EMIT_MIR debuginfo.variant.built.after.mir #[custom_mir(dialect = "built")] fn variant(opt: Option<i32>) { + // CHECK-LABEL: fn variant( + // CHECK: debug inner => ((_1 as variant#1).0: i32); mir! { debug inner => Field::<i32>(Variant(opt, 1), 0); { @@ -56,6 +64,9 @@ fn variant(opt: Option<i32>) { // EMIT_MIR debuginfo.variant_deref.built.after.mir #[custom_mir(dialect = "built")] fn variant_deref(opt: Option<&i32>) { + // CHECK-LABEL: fn variant_deref( + // CHECK: debug pointer => ((_1 as variant#1).0: &i32); + // CHECK: debug deref => (*((_1 as variant#1).0: &i32)); mir! { debug pointer => Field::<&i32>(Variant(opt, 1), 0); debug deref => *Field::<&i32>(Variant(opt, 1), 0); @@ -65,10 +76,24 @@ fn variant_deref(opt: Option<&i32>) { } } +// EMIT_MIR debuginfo.constant.built.after.mir +#[custom_mir(dialect = "built")] +fn constant() { + // CHECK-LABEL: fn constant( + // CHECK: debug scalar => const 5_usize; + mir!( + debug scalar => 5_usize; + { + Return() + } + ) +} + fn main() { numbered((5, 6)); structured(S { x: 5. }); variant(Some(5)); variant_deref(Some(&5)); pointee(&mut Some(5)); + constant(); } diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 39d52ba698a..cbb11d50f79 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -33,12 +33,12 @@ + coverage ExpressionId(3) => Expression { lhs: Counter(3), op: Add, rhs: Counter(2) }; + coverage ExpressionId(4) => Expression { lhs: Expression(3), op: Add, rhs: Counter(1) }; + coverage ExpressionId(5) => Expression { lhs: Expression(4), op: Add, rhs: Expression(2) }; -+ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code(Counter(3)) => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); -+ coverage Code(Counter(2)) => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); -+ coverage Code(Counter(1)) => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); -+ coverage Code(Expression(2)) => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); -+ coverage Code(Expression(5)) => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); ++ coverage Code(Counter(0)) => 14:1 - 15:21; ++ coverage Code(Counter(3)) => 16:17 - 16:33; ++ coverage Code(Counter(2)) => 17:17 - 17:33; ++ coverage Code(Counter(1)) => 18:17 - 18:33; ++ coverage Code(Expression(2)) => 19:17 - 19:33; ++ coverage Code(Expression(5)) => 21:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 148ff86354b..2efb1fd0a17 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,7 +5,7 @@ let mut _0: bool; + coverage body span: $DIR/instrument_coverage.rs:19:18: 21:2 (#0) -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:19:1: 21:2 (#0); ++ coverage Code(Counter(0)) => 19:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index b480d1ac13a..a179824d6c7 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage.rs:10:11: 16:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1: 10:11 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:12:12: 12:17 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13: 13:18 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:14:10: 14:10 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:2: 16:2 (#0); ++ coverage Code(Counter(0)) => 10:1 - 10:11; ++ coverage Code(Expression(0)) => 12:12 - 12:17; ++ coverage Code(Counter(0)) => 13:13 - 13:18; ++ coverage Code(Counter(1)) => 14:9 - 14:10; ++ coverage Code(Counter(0)) => 16:1 - 16:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 2c7ec6e85eb..082539369f7 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -9,11 +9,11 @@ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); - coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); - coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); - coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + coverage Code(Counter(0)) => 13:1 - 14:36; + coverage Code(Expression(0)) => 14:37 - 14:39; + coverage Code(Counter(1)) => 14:38 - 14:39; + coverage Code(Counter(0)) => 15:1 - 15:2; + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; bb0: { Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index c08265eb0e9..8635818c6a7 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); -+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); ++ coverage Code(Counter(0)) => 13:1 - 14:36; ++ coverage Code(Expression(0)) => 14:37 - 14:39; ++ coverage Code(Counter(1)) => 14:38 - 14:39; ++ coverage Code(Counter(0)) => 15:1 - 15:2; ++ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot new file mode 100644 index 00000000000..7c7d8921fb3 --- /dev/null +++ b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot @@ -0,0 +1,6 @@ +digraph graph_for_def_id_0_3 { + graph[fontname="Courier, monospace"]; + node[fontname="Courier, monospace"]; + edge[fontname="Courier, monospace"]; + bb_0[label=<<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb"><tr><td colspan="3" sides="tl">bb0</td></tr><tr><td colspan="2" bgcolor="#a0a0a0" sides="tl">MIR</td><td bgcolor="#a0a0a0" sides="tl">STATE</td></tr><tr><td valign="bottom" sides="tl" align="right"></td><td valign="bottom" sides="tl" align="left">(on start)</td><td colspan="1" valign="bottom" sides="tl" align="left">{}</td></tr><tr><td valign="top" sides="tl" bgcolor="#f0f0f0" align="right">0</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left">_0 = const ()</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left"><font color="darkgreen">+_0</font></td></tr><tr><td valign="top" sides="tl" align="right">T</td><td valign="top" sides="tl" align="left">return</td><td valign="top" sides="tl" align="left"></td></tr><tr><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="right"></td><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">(on end)</td><td colspan="1" valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">{_0}</td></tr></table>>][shape="none"]; +} diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dataflow.rs new file mode 100644 index 00000000000..3a28f5d47b9 --- /dev/null +++ b/tests/mir-opt/dataflow.rs @@ -0,0 +1,6 @@ +// skip-filecheck +// Test graphviz dataflow output +//@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow + +// EMIT_MIR dataflow.main.maybe_init.borrowck.dot +fn main() {} diff --git a/tests/pretty/attr-derive.rs b/tests/pretty/attr-derive.rs index 79b6ea51446..afb86b29315 100644 --- a/tests/pretty/attr-derive.rs +++ b/tests/pretty/attr-derive.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-foo.rs +//@ proc-macro: derive-foo.rs //@ pp-exact // Testing that both the inner item and next outer item are // preserved, and that the first outer item parsed in main is not diff --git a/tests/pretty/auxiliary/derive-foo.rs b/tests/pretty/auxiliary/derive-foo.rs index dc682beafad..16027508281 100644 --- a/tests/pretty/auxiliary/derive-foo.rs +++ b/tests/pretty/auxiliary/derive-foo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index fed6d310770..0ae95cb1f4b 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -24,21 +24,31 @@ fn minos(file: &str, version: &str) { fn main() { // These versions should generally be higher than the default versions - let (env_var, example_version, higher_example_version) = match apple_os() { - "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"), + let (example_version, higher_example_version) = match apple_os() { + "macos" => ("12.0", "13.0"), // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0 - "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => { - ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0") - } - "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"), - "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"), - "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"), - "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"), + "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => ("10.0", "10.0"), + "ios" => ("15.0", "16.0"), + "watchos" => ("7.0", "9.0"), + "tvos" => ("14.0", "15.0"), + "visionos" => ("1.1", "1.2"), _ => unreachable!(), }; - let default_version = - rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8(); - let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim(); + + // Remove env vars to get `rustc`'s default + let output = rustc() + .target(target()) + .env_remove("MACOSX_DEPLOYMENT_TARGET") + .env_remove("IPHONEOS_DEPLOYMENT_TARGET") + .env_remove("WATCHOS_DEPLOYMENT_TARGET") + .env_remove("TVOS_DEPLOYMENT_TARGET") + .env_remove("XROS_DEPLOYMENT_TARGET") + .print("deployment-target") + .run() + .stdout_utf8(); + let (env_var, default_version) = output.split_once('=').unwrap(); + let env_var = env_var.trim(); + let default_version = default_version.trim(); // Test that version makes it to the object file. run_in_tmpdir(|| { diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs index 6463ec00403..43e80577204 100644 --- a/tests/run-make/apple-sdk-version/rmake.rs +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -26,8 +26,7 @@ fn main() { // Fetch rustc's inferred deployment target. let current_deployment_target = rustc().target(target()).print("deployment-target").run().stdout_utf8(); - let current_deployment_target = - current_deployment_target.strip_prefix("deployment_target=").unwrap().trim(); + let current_deployment_target = current_deployment_target.split('=').last().unwrap().trim(); // Fetch current SDK version via. xcrun. // diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs new file mode 100644 index 00000000000..71b27cd85bf --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +extern crate foo; + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} + +fn check_trait<T: Trait>() {} + +fn ice() { + check_trait::<foo::Struct>(); +} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs new file mode 100644 index 00000000000..19d3f3c972b --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr new file mode 100644 index 00000000000..36379429530 --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr @@ -0,0 +1,34 @@ +error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied + --> foo-current.rs:13:19 + | +13 | check_trait::<foo::Struct>(); + | ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct` + | +note: there are multiple different versions of crate `foo` in the dependency graph + --> foo-current.rs:7:1 + | +4 | extern crate foo; + | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate +5 | +6 | pub struct Struct; + | ----------------- this type implements the required trait +7 | pub trait Trait {} + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: foo-prev.rs:X:Y + | +4 | pub struct Struct; + | ----------------- this type doesn't implement the required trait +5 | pub trait Trait {} + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `check_trait` + --> foo-current.rs:10:19 + | +10 | fn check_trait<T: Trait>() {} + | ^^^^^ required by this bound in `check_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs new file mode 100644 index 00000000000..57e0cab92f1 --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -0,0 +1,31 @@ +//@ only-linux +//@ ignore-wasm32 +//@ ignore-wasm64 +// ignore-tidy-linelength + +// Verify that if the current crate depends on a different version of the same crate, *and* types +// and traits of the different versions are mixed, we produce diagnostic output and not an ICE. +// #133563 + +use run_make_support::{diff, rust_lib_name, rustc}; + +fn main() { + rustc().input("foo-prev.rs").run(); + + let out = rustc() + .extra_filename("current") + .metadata("current") + .input("foo-current.rs") + .extern_("foo", rust_lib_name("foo")) + .run_fail() + .stderr_utf8(); + + // We don't remap the path of the `foo-prev` crate, so we remap it here. + let mut lines: Vec<_> = out.lines().collect(); + for line in &mut lines { + if line.starts_with(" ::: ") { + *line = " ::: foo-prev.rs:X:Y"; + } + } + diff().expected_file("foo.stderr").actual_text("(rustc)", &lines.join("\n")).run(); +} diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr new file mode 100644 index 00000000000..5888aad8f37 --- /dev/null +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -0,0 +1,127 @@ +error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied + --> replaced + | +LL | do_something(Type); + | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub struct Type(pub i32); + | --------------- this type implements the required trait +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct Type; + | --------------- this type doesn't implement the required trait +LL | pub trait Trait { + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type.foo(); + | ^^^ method not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); + | -------------- the method is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type::bar(); + | ^^^ function or associated item not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); +LL | fn bar(); + | --------- the associated function is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0277]: the trait bound `OtherType: Trait` is not satisfied + --> replaced + | +LL | do_something(OtherType); + | ------------ ^^^^^^^^^ the trait `Trait` is not implemented for `OtherType` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct OtherType; + | -------------------- this type doesn't implement the required trait + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 544bf9ab957..6ad456e3e3e 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -3,7 +3,7 @@ //@ ignore-wasm64 // ignore-tidy-linelength -use run_make_support::{rust_lib_name, rustc}; +use run_make_support::{diff, rust_lib_name, rustc}; fn main() { rustc().input("multiple-dep-versions-1.rs").run(); @@ -13,83 +13,26 @@ fn main() { .extern_("dependency", rust_lib_name("dependency2")) .run(); - rustc() + let out = rustc() .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) + .ui_testing() .run_fail() - .assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied - --> multiple-dep-versions.rs:7:18 - | -7 | do_something(Type); - | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` - | | - | required by a bound introduced by this call - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -3 | pub struct Type(pub i32); - | --------------- this type implements the required trait -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the required trait -"#) - .assert_stderr_contains(r#" -1 | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` -2 | extern crate dependency; - | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#) - .assert_stderr_contains(r#" -3 | pub struct Type; - | --------------- this type doesn't implement the required trait -4 | pub trait Trait { - | --------------- this is the found trait - = note: two types coming from two different versions of the same crate are different types even if they look the same - = help: you can use `cargo tree` to explore your dependency tree"#) - .assert_stderr_contains(r#"note: required by a bound in `do_something`"#) - .assert_stderr_contains(r#" -12 | pub fn do_something<X: Trait>(_: X) {} - | ^^^^^ required by this bound in `do_something`"#) - .assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:8:10 - | -8 | Type.foo(); - | ^^^ method not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); - | -------------- the method is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | --------------- this is the trait that was imported"#) - .assert_stderr_contains(r#" -error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:9:11 - | -9 | Type::bar(); - | ^^^ function or associated item not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); -6 | fn bar(); - | --------- the associated function is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains( - r#" -6 | pub struct OtherType; - | -------------------- this type doesn't implement the required trait"#); + .stderr_utf8(); + + // We don't remap all the paths, so we remap it here. + let mut lines: Vec<_> = out.lines().collect(); + for line in &mut lines { + if line.starts_with(" --> ") { + *line = " --> replaced"; + } + if line.starts_with(" ::: ") { + *line = " ::: replaced"; + } + } + diff() + .expected_file("multiple-dep-versions.stderr") + .actual_text("(rustc)", &lines.join("\n")) + .run(); } diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs index 5decd802b34..fe14d2c046c 100644 --- a/tests/run-make/libtest-thread-limit/rmake.rs +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -38,7 +38,7 @@ fn main() { // If the process ID is 0, this is the child process responsible for running the test // program. if pid == 0 { - let test = CString::new("test").unwrap(); + let test = c"test"; // The argv array should be terminated with a NULL pointer. let argv = [test.as_ptr(), std::ptr::null()]; // rlim_cur is soft limit, rlim_max is hard limit. diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index 8dd19e613bf..f98a2036544 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, asm_const, linkage)] +#![feature(naked_functions, linkage)] #![crate_type = "dylib"] use std::arch::naked_asm; @@ -38,7 +38,7 @@ pub extern "C" fn public_vanilla() -> u32 { #[naked] #[no_mangle] -pub extern "C" fn public_naked() -> u32 { +pub extern "C" fn public_naked_nongeneric() -> u32 { unsafe { naked_asm!("mov rax, 42", "ret") } } diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index d026196f43b..c69a9ef9eeb 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -17,10 +17,12 @@ fn main() { not_exported(&rdylib, "private_naked"); global_function(&rdylib, "public_vanilla"); - global_function(&rdylib, "public_naked"); + global_function(&rdylib, "public_naked_nongeneric"); not_exported(&rdylib, "public_vanilla_generic"); - not_exported(&rdylib, "public_naked_generic"); + // #[naked] functions are implicitly #[inline(never)], so they get shared regardless of + // -Zshare-generics. + global_function(&rdylib, "public_naked_generic"); global_function(&rdylib, "vanilla_external_linkage"); global_function(&rdylib, "naked_external_linkage"); diff --git a/tests/run-make/thumb-none-qemu/rmake.rs b/tests/run-make/thumb-none-qemu/rmake.rs index a505bb013f9..9d4b426f4a1 100644 --- a/tests/run-make/thumb-none-qemu/rmake.rs +++ b/tests/run-make/thumb-none-qemu/rmake.rs @@ -27,7 +27,6 @@ fn main() { std::env::set_current_dir(CRATE).unwrap(); let target_dir = path("target"); - let manifest_path = path("Cargo.toml"); // Debug cargo() diff --git a/tests/rustdoc-gui/deref-block.goml b/tests/rustdoc-gui/deref-block.goml index 24f612f8a6f..97930b61ef4 100644 --- a/tests/rustdoc-gui/deref-block.goml +++ b/tests/rustdoc-gui/deref-block.goml @@ -20,8 +20,12 @@ assert-css: (".big-toggle summary::before", { "left": "-11px", "top": "9px", }) -// It should have the same X position as the other toggles. -compare-elements-position: (".big-toggle summary::before", ".method-toggle summary::before", ["x"]) +// It should have a slightly different X position as the other toggles. +store-position: (".big-toggle summary::before", {"x": big_toggle}) +store-position: (".method-toggle summary::before", {"x": small_toggle}) +assert: |big_toggle| < |small_toggle| +// Margin is 0.5em so around 8 px. +assert: |small_toggle| - |big_toggle| < 10 // But still shouldn't have the same Y position. compare-elements-position-false: ( ".big-toggle summary::before", diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml index 1ca919d1eab..abfa820ef27 100644 --- a/tests/rustdoc-gui/docblock-table-overflow.goml +++ b/tests/rustdoc-gui/docblock-table-overflow.goml @@ -16,6 +16,6 @@ compare-elements-property: ( "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "816"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "835"}) // However, since there is overflow in the <table>, its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/tests/rustdoc-gui/item-info-alignment.goml b/tests/rustdoc-gui/item-info-alignment.goml index cd0624056b9..075722bb539 100644 --- a/tests/rustdoc-gui/item-info-alignment.goml +++ b/tests/rustdoc-gui/item-info-alignment.goml @@ -4,7 +4,9 @@ go-to: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html" // First, we try it in "desktop" mode. set-window-size: (1200, 870) +wait-for-size: ("body", {"width": 1200}) compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) // Next, we try it in "mobile" mode (max-width: 700px). set-window-size: (650, 650) +wait-for-size: ("body", {"width": 650}) compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 1636e149692..b5b0052fe61 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -19,7 +19,7 @@ store-position: ( "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']", {"x": second_line_x, "y": second_line_y}, ) -assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 +assert: |first_line_x| != |second_line_x| && |first_line_x| == 521 && |second_line_x| == 277 assert: |first_line_y| != |second_line_y| && |first_line_y| == 718 && |second_line_y| == 741 // Now we ensure that they're not rendered on the same line. diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml index 1003cec33f9..31b53faf756 100644 --- a/tests/rustdoc-gui/methods-left-margin.goml +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -1,7 +1,6 @@ // This test is to ensure that methods are correctly aligned on the left side. go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" - // First we ensure that we have methods with and without documentation. assert: ".impl-items > details.method-toggle > summary > section.method" assert: ".impl-items > section.method" diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index e02974e6082..4624fb80b37 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -62,9 +62,9 @@ define-function: ( // We start with a wide screen. set-window-size: (1100, 600) call-function: ("check-notable-tooltip-position-complete", { - "x": 677, - "i_x": 955, - "popover_x": 463, + "x": 682, + "i_x": 960, + "popover_x": 468, }) // Now only the `i` should be on the next line. @@ -78,16 +78,16 @@ compare-elements-position-false: ( // Now both the `i` and the struct name should be on the next line. set-window-size: (980, 600) call-function: ("check-notable-tooltip-position", { - "x": 245, - "i_x": 523, + "x": 250, + "i_x": 528, }) // Checking on mobile now. set-window-size: (650, 600) wait-for-size: ("body", {"width": 650}) call-function: ("check-notable-tooltip-position-complete", { - "x": 25, - "i_x": 303, + "x": 26, + "i_x": 305, "popover_x": 0, }) diff --git a/tests/rustdoc-gui/toggle-docs-mobile.goml b/tests/rustdoc-gui/toggle-docs-mobile.goml index b69aa6e30ca..be12e4c19b3 100644 --- a/tests/rustdoc-gui/toggle-docs-mobile.goml +++ b/tests/rustdoc-gui/toggle-docs-mobile.goml @@ -18,7 +18,7 @@ assert-position: ("#implementations-list > details > summary::before", {"x": 4}) // Assert the position of the toggle on a method. assert-position: ( "#trait-implementations-list .impl-items .method-toggle > summary::before", - {"x": 4}, + {"x": 6}, ) // Now we do the same but with a little bigger width diff --git a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs new file mode 100644 index 00000000000..0fbb4df0028 --- /dev/null +++ b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs @@ -0,0 +1,15 @@ +//@ set t1 = '$.index[*][?(@.name=="T1")].id' +pub trait T1 {} + +//@ set t2 = '$.index[*][?(@.name=="T2")].id' +pub trait T2 {} + +/// Fun impl +impl T1 for dyn T2 {} + +//@ set impl = '$.index[*][?(@.docs=="Fun impl")].id' +//@ is '$.index[*][?(@.name=="T1")].inner.trait.implementations[*]' $impl +//@ is '$.index[*][?(@.name=="T2")].inner.trait.implementations' [] + +//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.trait.id' $t1 +//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2 diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs new file mode 100644 index 00000000000..d38fdf1cd1c --- /dev/null +++ b/tests/rustdoc-json/statics/extern.rs @@ -0,0 +1,39 @@ +// ignore-tidy-linelength +//@ edition: 2021 + +extern "C" { + //@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false + pub static A: i32; + //@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true + pub static mut B: i32; + + // items in unadorned `extern` blocks cannot have safety qualifiers +} + +unsafe extern "C" { + //@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false + pub static C: i32; + //@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true + pub static mut D: i32; + + //@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe' false + //@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false + pub safe static E: i32; + //@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe' false + //@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true + pub safe static mut F: i32; + + //@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false + pub unsafe static G: i32; + //@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true + pub unsafe static mut H: i32; +} + +//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""' +//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs new file mode 100644 index 00000000000..a8af23cc87d --- /dev/null +++ b/tests/rustdoc-json/statics/statics.rs @@ -0,0 +1,12 @@ +//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"' +//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false +//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"' +//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false +pub static A: i32 = 5; + +//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"' +//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true +// Expr value isn't gaurenteed, it'd be fine to change it. +//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"' +//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false +pub static mut B: u32 = 2 + 3; diff --git a/tests/rustdoc-ui/coverage/doc-examples-json.stdout b/tests/rustdoc-ui/coverage/doc-examples-json.stdout index 92f58556975..070fed0783e 100644 --- a/tests/rustdoc-ui/coverage/doc-examples-json.stdout +++ b/tests/rustdoc-ui/coverage/doc-examples-json.stdout @@ -1 +1 @@ -{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}} +{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":1,"with_examples":1}} diff --git a/tests/rustdoc-ui/coverage/doc-examples.stdout b/tests/rustdoc-ui/coverage/doc-examples.stdout index 8188740f873..793adeb3518 100644 --- a/tests/rustdoc-ui/coverage/doc-examples.stdout +++ b/tests/rustdoc-ui/coverage/doc-examples.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 25.0% | +| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 33.3% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 4 | 100.0% | 1 | 25.0% | +| Total | 4 | 100.0% | 1 | 33.3% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/tests/rustdoc-ui/coverage/json.stdout b/tests/rustdoc-ui/coverage/json.stdout index c2be73ce3ed..25fd896baf1 100644 --- a/tests/rustdoc-ui/coverage/json.stdout +++ b/tests/rustdoc-ui/coverage/json.stdout @@ -1 +1 @@ -{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}} +{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":13,"with_examples":6}} diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs index bae61992eb2..58612b682a0 100644 --- a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs +++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs @@ -1,5 +1,5 @@ //@ edition:2024 -//@ compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@ compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/doctest/doctest-output.rs b/tests/rustdoc-ui/doctest/doctest-output.rs index 0e5ccf0b090..946bc550b12 100644 --- a/tests/rustdoc-ui/doctest/doctest-output.rs +++ b/tests/rustdoc-ui/doctest/doctest-output.rs @@ -4,7 +4,7 @@ //@[edition2015]compile-flags:--test --test-args=--test-threads=1 //@[edition2024]edition:2015 //@[edition2024]aux-build:extern_macros.rs -//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@[edition2024]compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ check-pass diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs index b393d126306..5a1d4d0a60d 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs @@ -6,7 +6,7 @@ //@[edition2015]compile-flags:--test --test-args=--test-threads=1 //@[edition2024]edition:2024 //@[edition2024]check-pass -//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@[edition2024]compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/lints/check.rs b/tests/rustdoc-ui/lints/check.rs index 391ba517077..058c5d6c468 100644 --- a/tests/rustdoc-ui/lints/check.rs +++ b/tests/rustdoc-ui/lints/check.rs @@ -4,7 +4,6 @@ #![feature(rustdoc_missing_doc_code_examples)] //~^ WARN -//~^^ WARN #![warn(missing_docs)] #![warn(rustdoc::missing_doc_code_examples)] diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr index acdb8128443..f1f36e8830d 100644 --- a/tests/rustdoc-ui/lints/check.stderr +++ b/tests/rustdoc-ui/lints/check.stderr @@ -4,19 +4,20 @@ warning: missing documentation for the crate LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | +LL | | #![warn(missing_docs)] ... | LL | | LL | | pub fn foo() {} | |_______________^ | note: the lint level is defined here - --> $DIR/check.rs:9:9 + --> $DIR/check.rs:8:9 | LL | #![warn(missing_docs)] | ^^^^^^^^^^^^ warning: missing documentation for a function - --> $DIR/check.rs:13:1 + --> $DIR/check.rs:12:1 | LL | pub fn foo() {} | ^^^^^^^^^^^^ @@ -26,34 +27,23 @@ warning: no documentation found for this crate's top-level module = help: The following guide may be of use: https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html note: the lint level is defined here - --> $DIR/check.rs:11:9 + --> $DIR/check.rs:10:9 | LL | #![warn(rustdoc::all)] | ^^^^^^^^^^^^ = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]` warning: missing code example in this documentation - --> $DIR/check.rs:5:1 + --> $DIR/check.rs:12:1 | -LL | / #![feature(rustdoc_missing_doc_code_examples)] -LL | | -LL | | -... | -LL | | -LL | | pub fn foo() {} - | |_______________^ +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/check.rs:10:9 + --> $DIR/check.rs:9:9 | LL | #![warn(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: missing code example in this documentation - --> $DIR/check.rs:13:1 - | -LL | pub fn foo() {} - | ^^^^^^^^^^^^^^^ - -warning: 5 warnings emitted +warning: 4 warnings emitted diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.rs b/tests/rustdoc-ui/lints/doc-without-codeblock.rs index 86d7c83d335..ccb241d4037 100644 --- a/tests/rustdoc-ui/lints/doc-without-codeblock.rs +++ b/tests/rustdoc-ui/lints/doc-without-codeblock.rs @@ -1,4 +1,4 @@ -#![feature(rustdoc_missing_doc_code_examples)] //~ ERROR missing code example in this documentation +#![feature(rustdoc_missing_doc_code_examples)] #![deny(rustdoc::missing_doc_code_examples)] /// Some docs. @@ -6,7 +6,6 @@ pub struct Foo; /// And then, the princess died. -//~^ ERROR missing code example in this documentation pub mod foo { /// Or maybe not because she saved herself! //~^ ERROR missing code example in this documentation diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.stderr b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr index ebf2a2d54f7..d230f160693 100644 --- a/tests/rustdoc-ui/lints/doc-without-codeblock.stderr +++ b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr @@ -1,14 +1,8 @@ error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:1:1 + --> $DIR/doc-without-codeblock.rs:10:5 | -LL | / #![feature(rustdoc_missing_doc_code_examples)] -LL | | #![deny(rustdoc::missing_doc_code_examples)] -LL | | -LL | | /// Some docs. -... | -LL | | } -LL | | } - | |_^ +LL | /// Or maybe not because she saved herself! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/doc-without-codeblock.rs:2:9 @@ -17,22 +11,10 @@ LL | #![deny(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:8:1 - | -LL | /// And then, the princess died. - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:11:5 - | -LL | /// Or maybe not because she saved herself! - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing code example in this documentation --> $DIR/doc-without-codeblock.rs:4:1 | LL | /// Some docs. | ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs index 40f35728d79..8e5c31d50ed 100644 --- a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs +++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs @@ -17,7 +17,7 @@ pub fn test() { } #[allow(missing_docs)] -pub mod module1 { //~ ERROR +pub mod module1 { } #[allow(rustdoc::missing_doc_code_examples)] diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr index f9331250154..22533b9816a 100644 --- a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr +++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr @@ -1,8 +1,8 @@ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:20:1 + --> $DIR/lint-missing-doc-code-example.rs:38:3 | -LL | pub mod module1 { - | ^^^^^^^^^^^^^^^ +LL | /// doc + | ^^^^^^^ | note: the lint level is defined here --> $DIR/lint-missing-doc-code-example.rs:3:9 @@ -11,12 +11,6 @@ LL | #![deny(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:38:3 - | -LL | /// doc - | ^^^^^^^ - -error: missing code example in this documentation --> $DIR/lint-missing-doc-code-example.rs:50:1 | LL | /// Doc @@ -34,5 +28,5 @@ error: missing code example in this documentation LL | /// Doc | ^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/rustdoc-ui/show-coverage-json.stdout b/tests/rustdoc-ui/show-coverage-json.stdout index ed5b5a60212..e6e882b2c57 100644 --- a/tests/rustdoc-ui/show-coverage-json.stdout +++ b/tests/rustdoc-ui/show-coverage-json.stdout @@ -1 +1 @@ -{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":2,"with_examples":1}} +{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":1,"with_examples":1}} diff --git a/tests/rustdoc-ui/show-coverage.stdout b/tests/rustdoc-ui/show-coverage.stdout index b3b7679771f..b9e0316545e 100644 --- a/tests/rustdoc-ui/show-coverage.stdout +++ b/tests/rustdoc-ui/show-coverage.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 50.0% | +| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 100.0% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 1 | 50.0% | 1 | 50.0% | +| Total | 1 | 50.0% | 1 | 100.0% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs index e813fba4717..8d6239296bf 100644 --- a/tests/rustdoc-ui/unescaped_backticks.rs +++ b/tests/rustdoc-ui/unescaped_backticks.rs @@ -218,7 +218,7 @@ pub mod rustc { pub fn with_options() {} /// Subtracts `set from `row`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. //~^ ERROR unescaped backtick /// /// Returns true if the row was changed. diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index 67b87f353a1..1e2b3528d4a 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -124,10 +124,10 @@ LL | /// also avoids the need to import `OpenOptions\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:221:46 + --> $DIR/unescaped_backticks.rs:221:47 | -LL | /// `HybridBitSet`. Has no effect if `row` does not exist. - | ^ +LL | /// `ChunkedBitSet`. Has no effect if `row` does not exist. + | ^ | help: a previous inline code might be longer than expected | @@ -135,8 +135,8 @@ LL | /// Subtracts `set` from `row`. `set` can be either `BitSet` or | + help: if you meant to use a literal backtick, escape it | -LL | /// `HybridBitSet`. Has no effect if `row\` does not exist. - | + +LL | /// `ChunkedBitSet`. Has no effect if `row\` does not exist. + | + error: unescaped backtick --> $DIR/unescaped_backticks.rs:247:12 diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs new file mode 100644 index 00000000000..fd6644d73c1 --- /dev/null +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -0,0 +1,242 @@ +//@ run-pass +//@ ignore-cross-compile + +// This test covers the AST pretty-printer's automatic insertion of parentheses +// into unparenthesized syntax trees according to precedence and various grammar +// restrictions and edge cases. +// +// For example if the following syntax tree represents the expression a*(b+c), +// in which the parenthesis is necessary for precedence: +// +// Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c")))) +// +// then the pretty-printer needs to be able to print the following +// unparenthesized syntax tree with an automatically inserted parenthesization. +// +// Binary('*', Path("a"), Binary('+', Path("b"), Path("c"))) +// +// Handling this correctly is relevant in real-world code when pretty-printing +// macro-generated syntax trees, in which expressions can get interpolated into +// one another without any parenthesization being visible in the syntax tree. +// +// macro_rules! repro { +// ($rhs:expr) => { +// a * $rhs +// }; +// } +// +// let _ = repro!(b + c); + +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_ast_pretty; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_parse; +extern crate rustc_session; +extern crate rustc_span; +extern crate smallvec; + +use std::mem; +use std::process::ExitCode; + +use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind, Stmt}; +use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor}; +use rustc_ast::node_id::NodeId; +use rustc_ast::ptr::P; +use rustc_ast_pretty::pprust; +use rustc_errors::Diag; +use rustc_parse::parser::Recovery; +use rustc_session::parse::ParseSess; +use rustc_span::{DUMMY_SP, FileName, Span}; +use smallvec::SmallVec; + +// Every parenthesis in the following expressions is re-inserted by the +// pretty-printer. +// +// FIXME: Some of them shouldn't be. +static EXPRS: &[&str] = &[ + // Straightforward binary operator precedence. + "2 * 2 + 2", + "2 + 2 * 2", + "(2 + 2) * 2", + "2 * (2 + 2)", + "2 + 2 + 2", + // Return has lower precedence than a binary operator. + "(return 2) + 2", + "2 + (return 2)", // FIXME: no parenthesis needed. + "(return) + 2", // FIXME: no parenthesis needed. + // These mean different things. + "return - 2", + "(return) - 2", + // These mean different things. + "if let _ = true && false {}", + "if let _ = (true && false) {}", + // Conditions end at the first curly brace, so struct expressions need to be + // parenthesized. Except in a match guard, where conditions end at arrow. + "if let _ = (Struct {}) {}", + "match 2 { _ if let _ = Struct {} => {} }", + // Match arms terminate eagerly, so parenthesization is needed around some + // expressions. + "match 2 { _ => 1 - 1 }", + "match 2 { _ => ({ 1 }) - 1 }", + // Grammar restriction: break value starting with a labeled loop is not + // allowed, except if the break is also labeled. + "break 'outer 'inner: loop {} + 2", + "break ('inner: loop {} + 2)", + // Grammar restriction: the value in let-else is not allowed to end in a + // curly brace. + "{ let _ = 1 + 1 else {}; }", + "{ let _ = (loop {}) else {}; }", + "{ let _ = mac!() else {}; }", + "{ let _ = (mac! {}) else {}; }", + // Parentheses are necessary to prevent an eager statement boundary. + "{ 2 - 1 }", + "{ (match 2 {}) - 1 }", + "{ (match 2 {})() - 1 }", + "{ (match 2 {})[0] - 1 }", + "{ (loop {}) - 1 }", + // Angle bracket is eagerly parsed as a path's generic argument list. + "(2 as T) < U", + "(2 as T<U>) < V", // FIXME: no parentheses needed. + /* + // FIXME: pretty-printer produces invalid syntax. `2 + 2 as T < U` + "(2 + 2 as T) < U", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `if (let _ = () && Struct {}.x) {}` + "if let _ = () && (Struct {}).x {}", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `(1 < 2 == false) as usize` + "((1 < 2) == false) as usize", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `for _ in 1..{ 2 } {}` + "for _ in (1..{ 2 }) {}", + */ + /* + // FIXME: pretty-printer loses the attribute. `{ let Struct { field } = s; }` + "{ let Struct { #[attr] field } = s; }", + */ + /* + // FIXME: pretty-printer turns this into a range. `0..to_string()` + "(0.).to_string()", + "0. .. 1.", + */ + /* + // FIXME: pretty-printer loses the dyn*. `i as Trait` + "i as dyn* Trait", + */ +]; + +// Flatten the content of parenthesis nodes into their parent node. For example +// this syntax tree representing the expression a*(b+c): +// +// Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c")))) +// +// would unparenthesize to: +// +// Binary('*', Path("a"), Binary('+', Path("b"), Path("c"))) +struct Unparenthesize; + +impl MutVisitor for Unparenthesize { + fn visit_expr(&mut self, e: &mut P<Expr>) { + while let ExprKind::Paren(paren) = &mut e.kind { + **e = mem::replace(&mut *paren, Expr::dummy()); + } + mut_visit::walk_expr(self, e); + } +} + +// Erase Span information that could distinguish between identical expressions +// parsed from different source strings. +struct Normalize; + +impl MutVisitor for Normalize { + const VISIT_TOKENS: bool = true; + + fn visit_id(&mut self, id: &mut NodeId) { + *id = DUMMY_NODE_ID; + } + + fn visit_span(&mut self, span: &mut Span) { + *span = DUMMY_SP; + } + + fn visit_expr(&mut self, expr: &mut P<Expr>) { + if let ExprKind::Binary(binop, _left, _right) = &mut expr.kind { + self.visit_span(&mut binop.span); + } + mut_visit::walk_expr(self, expr); + } + + fn flat_map_stmt(&mut self, mut stmt: Stmt) -> SmallVec<[Stmt; 1]> { + self.visit_span(&mut stmt.span); + mut_visit::walk_flat_map_stmt(self, stmt) + } +} + +fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> { + let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str( + psess, + FileName::anon_source_code(source_code), + source_code.to_owned(), + )); + + let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?; + Normalize.visit_expr(&mut expr); + Some(expr) +} + +fn main() -> ExitCode { + let mut status = ExitCode::SUCCESS; + let mut fail = |description: &str, before: &str, after: &str| { + status = ExitCode::FAILURE; + eprint!( + "{description}\n BEFORE: {before}\n AFTER: {after}\n\n", + before = before.replace('\n', "\n "), + after = after.replace('\n', "\n "), + ); + }; + + rustc_span::create_default_session_globals_then(|| { + let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); + + for &source_code in EXPRS { + let expr = parse_expr(psess, source_code).unwrap(); + + // Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed. + // Pseudocode: + // assert(expr == parse(print(expr))) + let printed = &pprust::expr_to_string(&expr); + let Some(expr2) = parse_expr(psess, printed) else { + fail("Pretty-printer produced invalid syntax", source_code, printed); + continue; + }; + if format!("{expr:#?}") != format!("{expr2:#?}") { + fail("Pretty-printer inserted unnecessary parenthesis", source_code, printed); + continue; + } + + // Check for FALSE NEGATIVE: pretty-printer failing to place necessary parentheses. + // Pseudocode: + // assert(unparenthesize(expr) == unparenthesize(parse(print(unparenthesize(expr))))) + let mut expr = expr; + Unparenthesize.visit_expr(&mut expr); + let printed = &pprust::expr_to_string(&expr); + let Some(mut expr2) = parse_expr(psess, printed) else { + fail("Pretty-printer with no parens produced invalid syntax", source_code, printed); + continue; + }; + Unparenthesize.visit_expr(&mut expr2); + if format!("{expr:#?}") != format!("{expr2:#?}") { + fail("Pretty-printer lost necessary parentheses", source_code, printed); + continue; + } + } + }); + + status +} diff --git a/tests/ui/README.md b/tests/ui/README.md index c14d0ee78c8..aa36481ae06 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -6,9 +6,9 @@ This folder contains `rustc`'s ## Test Directives (Headers) Typically, a UI test will have some test directives / headers which are -special comments that tell compiletest how to build and intepret a test. +special comments that tell compiletest how to build and interpret a test. -As part of an on-going effort to rewrite compiletest +As part of an ongoing effort to rewrite compiletest (see <https://github.com/rust-lang/compiler-team/issues/536>), a major change proposal to change legacy compiletest-style headers `// <directive>` to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers @@ -30,6 +30,6 @@ but in `ui_test` style, the header would be written as compiletest is changed to accept only `//@` directives for UI tests (currently), and will reject and report an error if it encounters any -comments `// <content>` that may be parsed as an legacy compiletest-style +comments `// <content>` that may be parsed as a legacy compiletest-style test header. To fix this, you should migrate to the `ui_test`-style header `//@ <content>`. diff --git a/tests/ui/annotate-snippet/auxiliary/multispan.rs b/tests/ui/annotate-snippet/auxiliary/multispan.rs index b5f1ed9b56a..1eb379d3877 100644 --- a/tests/ui/annotate-snippet/auxiliary/multispan.rs +++ b/tests/ui/annotate-snippet/auxiliary/multispan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/annotate-snippet/multispan.rs b/tests/ui/annotate-snippet/multispan.rs index c9ec4043e37..b7cf22eebcb 100644 --- a/tests/ui/annotate-snippet/multispan.rs +++ b/tests/ui/annotate-snippet/multispan.rs @@ -1,4 +1,4 @@ -//@ aux-build:multispan.rs +//@ proc-macro: multispan.rs //@ error-pattern:hello to you, too! //@ compile-flags: --error-format human-annotate-rs -Z unstable-options diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr new file mode 100644 index 00000000000..0e544119650 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr @@ -0,0 +1,38 @@ +error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:22:18 + | +LL | asm!("", out("$r0") _); + | ^^^^^^^^^^^^ + +error: invalid register `$tp`: reserved for TLS + --> $DIR/bad-reg.rs:24:18 + | +LL | asm!("", out("$tp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", out("$sp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r21`: reserved by the ABI + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", out("$r21") _); + | ^^^^^^^^^^^^^ + +error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("$fp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("$r31") _); + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr new file mode 100644 index 00000000000..6d0410dc6a1 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr @@ -0,0 +1,62 @@ +error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:22:18 + | +LL | asm!("", out("$r0") _); + | ^^^^^^^^^^^^ + +error: invalid register `$tp`: reserved for TLS + --> $DIR/bad-reg.rs:24:18 + | +LL | asm!("", out("$tp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", out("$sp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r21`: reserved by the ABI + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", out("$r21") _); + | ^^^^^^^^^^^^^ + +error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("$fp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("$r31") _); + | ^^^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:36:26 + | +LL | asm!("/* {} */", in(freg) f); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:38:26 + | +LL | asm!("/* {} */", out(freg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:40:26 + | +LL | asm!("/* {} */", in(freg) d); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:42:26 + | +LL | asm!("/* {} */", out(freg) d); + | ^^^^^^^^^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs new file mode 100644 index 00000000000..c5288cc78b7 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.rs @@ -0,0 +1,45 @@ +//@ add-core-stubs +//@ needs-asm-support +//@ revisions: loongarch64_lp64d loongarch64_lp64s +//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64_lp64d] needs-llvm-components: loongarch +//@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat +//@[loongarch64_lp64s] needs-llvm-components: loongarch + +#![crate_type = "lib"] +#![feature(no_core, rustc_attrs)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn f() { + let mut x = 0; + let mut f = 0.0_f32; + let mut d = 0.0_f64; + unsafe { + // Unsupported registers + asm!("", out("$r0") _); + //~^ ERROR constant zero cannot be used as an operand for inline asm + asm!("", out("$tp") _); + //~^ ERROR invalid register `$tp`: reserved for TLS + asm!("", out("$sp") _); + //~^ ERROR invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + asm!("", out("$r21") _); + //~^ ERROR invalid register `$r21`: reserved by the ABI + asm!("", out("$fp") _); + //~^ ERROR invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + asm!("", out("$r31") _); + //~^ ERROR invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + + asm!("", out("$f0") _); // ok + asm!("/* {} */", in(freg) f); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", out(freg) _); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", in(freg) d); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", out(freg) d); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + } +} diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index 34105ceac04..036641951cc 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,37 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +197,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +205,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +213,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +221,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +229,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 34 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr index 34105ceac04..13fc5a048d8 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,73 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("v0") v32x4); // requires altivec + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:68:18 + | +LL | asm!("", out("v0") v32x4); // requires altivec + | ^^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:70:18 + | +LL | asm!("", in("v0") v64x2); // requires vsx + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:73:18 + | +LL | asm!("", out("v0") v64x2); // requires vsx + | ^^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:76:18 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:82:26 + | +LL | asm!("/* {} */", in(vreg) v32x4); // requires altivec + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:84:26 + | +LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:90:26 + | +LL | asm!("/* {} */", out(vreg) _); // requires altivec + | ^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +233,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +241,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +249,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +257,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +265,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 41 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index 34105ceac04..6a9d552bfe2 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,61 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:70:27 + | +LL | asm!("", in("v0") v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:73:28 + | +LL | asm!("", out("v0") v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:84:35 + | +LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +221,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +229,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +237,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +245,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +253,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 37 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index 34105ceac04..036641951cc 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,37 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +197,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +205,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +213,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +221,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +229,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 34 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs index 5023ad51838..f34c45663a0 100644 --- a/tests/ui/asm/powerpc/bad-reg.rs +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -8,17 +8,28 @@ //@[aix64] compile-flags: --target powerpc64-ibm-aix //@[aix64] needs-llvm-components: powerpc //@ needs-asm-support +// ignore-tidy-linelength #![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![feature(no_core, rustc_attrs, lang_items, repr_simd, asm_experimental_arch)] #![no_core] +#![allow(non_camel_case_types)] #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} +#[repr(simd)] +pub struct i32x4([i32; 4]); +#[repr(simd)] +pub struct i64x2([i64; 2]); + +impl<T: Copy, const N: usize> Copy for [T; N] {} impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} #[rustc_builtin_macro] macro_rules! asm { @@ -27,6 +38,8 @@ macro_rules! asm { fn f() { let mut x = 0; + let mut v32x4 = i32x4([0; 4]); + let mut v64x2 = i64x2([0; 2]); unsafe { // Unsupported registers asm!("", out("sp") _); @@ -47,6 +60,36 @@ fn f() { //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm asm!("", out("vrsave") _); //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + + // vreg + asm!("", out("v0") _); // always ok + asm!("", in("v0") v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("", out("v0") v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("", in("v0") v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("", out("v0") v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("", in("v0") x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("", out("v0") x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(vreg) v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("/* {} */", in(vreg) v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(vreg) _); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + // v20-v31 are reserved on AIX with vec-default ABI (this ABI is not currently used in Rust's builtin AIX targets). asm!("", out("v20") _); asm!("", out("v21") _); asm!("", out("v22") _); @@ -87,20 +130,6 @@ fn f() { //~| ERROR type `i32` cannot be used with this register class asm!("/* {} */", out(xer) _); //~^ ERROR can only be used as a clobber - // vreg - asm!("", out("v0") _); // ok - // FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551 - asm!("", in("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("", out("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", in(vreg) x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", out(vreg) _); - //~^ ERROR can only be used as a clobber // Overlapping-only registers asm!("", out("cr") _, out("cr0") _); diff --git a/tests/ui/associated-type-bounds/all-generics-lookup.rs b/tests/ui/associated-type-bounds/all-generics-lookup.rs new file mode 100644 index 00000000000..c5940c14f44 --- /dev/null +++ b/tests/ui/associated-type-bounds/all-generics-lookup.rs @@ -0,0 +1,31 @@ +//@ check-pass + +#![feature(return_type_notation)] + +trait Trait { + fn method(&self) -> impl Sized; +} + +impl Trait for () { + fn method(&self) -> impl Sized {} +} + +struct Struct<T>(T); + +// This test used to fail a debug assertion since we weren't resolving the item +// for `T::method(..)` correctly, leading to two bound vars being given the +// index 0. The solution is to look at both generics of `test` and its parent impl. + +impl<T> Struct<T> +where + T: Trait, +{ + fn test() + where + T::method(..): Send + {} +} + +fn main() { + Struct::<()>::test(); +} diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs index c0012564843..ee75cb96afd 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs @@ -5,7 +5,6 @@ trait Item { pub struct Flatten<I> { inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core, //~^ ERROR E0191 - //~| ERROR E0223 } fn main() {} diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 39a2b98e2e2..c80b32dc3d8 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -4,18 +4,6 @@ error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIt LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>` -error[E0223]: ambiguous associated type - --> $DIR/overlaping-bound-suggestion.rs:6:13 - | -LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `IntoIterator` implemented for `(dyn IntoIterator + 'static)`, you could use the fully-qualified path - | -LL | inner: <<(dyn IntoIterator + 'static) as Example>::IntoIterator as Item>::Core, - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0191, E0223. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs index 5ed65425f34..8309cfbd58f 100644 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -10,7 +10,7 @@ fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_mut(mut x: impl async FnMut()) { + async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) { x().await; } needs_async_fn_mut(x).await; diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs index be436465315..e7644e3dfe0 100644 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -8,7 +8,7 @@ extern crate block_on; fn main() { block_on::block_on(async { - async fn needs_async_fn_once(x: impl async FnOnce()) { + async fn needs_async_fn_once(x: impl AsyncFnOnce()) { x().await; } diff --git a/tests/ui/async-await/async-closures/auxiliary/foreign.rs b/tests/ui/async-await/async-closures/auxiliary/foreign.rs index 2c935f5e1fa..33548a1b30d 100644 --- a/tests/ui/async-await/async-closures/auxiliary/foreign.rs +++ b/tests/ui/async-await/async-closures/auxiliary/foreign.rs @@ -2,6 +2,6 @@ #![feature(async_closure)] -pub fn closure() -> impl async Fn() { +pub fn closure() -> impl AsyncFn() { async || { /* Don't really need to do anything here. */ } } diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs index 4382a689e75..a72ff8e5dce 100644 --- a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs +++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs @@ -11,7 +11,7 @@ extern crate block_on; async fn empty() {} -pub async fn call_once<F: async FnOnce()>(f: F) { +pub async fn call_once<F: AsyncFnOnce()>(f: F) { f().await; } diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs index 8b2de578b24..5ec1c5ee50e 100644 --- a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs +++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs @@ -16,7 +16,7 @@ impl Trait for (i32,) { } } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs index 5168f3696d7..db1f5d271c6 100644 --- a/tests/ui/async-await/async-closures/brand.rs +++ b/tests/ui/async-await/async-closures/brand.rs @@ -13,7 +13,7 @@ struct S; struct B<'b>(PhantomData<&'b mut &'b mut ()>); impl S { - async fn q<F: async Fn(B<'_>)>(self, f: F) { + async fn q<F: AsyncFn(B<'_>)>(self, f: F) { f(B(PhantomData)).await; } } diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs index 0a9d0529bf5..2bd4b685997 100644 --- a/tests/ui/async-await/async-closures/captures.rs +++ b/tests/ui/async-await/async-closures/captures.rs @@ -13,11 +13,11 @@ fn main() { block_on::block_on(async_main()); } -async fn call<T>(f: &impl async Fn() -> T) -> T { +async fn call<T>(f: &impl AsyncFn() -> T) -> T { f().await } -async fn call_once<T>(f: impl async FnOnce() -> T) -> T { +async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T { f().await } @@ -80,7 +80,7 @@ async fn async_main() { call_once(c).await; } - fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T { + fn force_fnonce<T>(f: impl AsyncFnOnce() -> T) -> impl AsyncFnOnce() -> T { f } diff --git a/tests/ui/async-await/async-closures/clone-closure.rs b/tests/ui/async-await/async-closures/clone-closure.rs index 807897e3e03..a9e1d6bccc7 100644 --- a/tests/ui/async-await/async-closures/clone-closure.rs +++ b/tests/ui/async-await/async-closures/clone-closure.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn for_each(f: impl async FnOnce(&str) + Clone) { +async fn for_each(f: impl AsyncFnOnce(&str) + Clone) { f.clone()("world").await; f.clone()("world2").await; } diff --git a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs index 3b222d00bae..1acbf0311b3 100644 --- a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs +++ b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs @@ -6,7 +6,7 @@ #![feature(async_closure)] -fn constrain<T: async FnOnce()>(t: T) -> T { +fn constrain<T: AsyncFnOnce()>(t: T) -> T { t } @@ -14,7 +14,7 @@ fn call_once<T>(f: impl FnOnce() -> T) -> T { f() } -async fn async_call_once<T>(f: impl async FnOnce() -> T) -> T { +async fn async_call_once<T>(f: impl AsyncFnOnce() -> T) -> T { f().await } diff --git a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs index 6f339f0c8ef..f71cc1ef537 100644 --- a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs +++ b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs index 2884a20f244..9c99550e3b7 100644 --- a/tests/ui/async-await/async-closures/drop.rs +++ b/tests/ui/async-await/async-closures/drop.rs @@ -16,7 +16,7 @@ impl Drop for DropMe { } } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { println!("before call"); let fut = Box::pin(f()); println!("after call"); diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs index de62fc8bf7e..eb554650b7c 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.rs +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs @@ -10,7 +10,7 @@ use std::future::Future; #[target_feature(enable = "sse2")] fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() } -fn test(f: impl async Fn()) {} +fn test(f: impl AsyncFn()) {} fn main() { test(target_feature); //~ ERROR the trait bound diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr index e965c40fb5b..db5895108bb 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr @@ -9,8 +9,8 @@ LL | test(target_feature); note: required by a bound in `test` --> $DIR/fn-exception-target-features.rs:13:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs index 0e06ebf48a4..36cb955cd5c 100644 --- a/tests/ui/async-await/async-closures/fn-exception.rs +++ b/tests/ui/async-await/async-closures/fn-exception.rs @@ -13,7 +13,7 @@ unsafe extern "C" { pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>; } -fn test(f: impl async Fn()) {} +fn test(f: impl AsyncFn()) {} fn main() { test(unsafety); //~ ERROR the trait bound diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr index 20132e42833..b3118664c15 100644 --- a/tests/ui/async-await/async-closures/fn-exception.stderr +++ b/tests/ui/async-await/async-closures/fn-exception.stderr @@ -9,8 +9,8 @@ LL | test(unsafety); note: required by a bound in `test` --> $DIR/fn-exception.rs:16:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied --> $DIR/fn-exception.rs:20:10 @@ -23,8 +23,8 @@ LL | test(abi); note: required by a bound in `test` --> $DIR/fn-exception.rs:16:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs index 7ce210a33c3..c20e3664d8b 100644 --- a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs +++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs @@ -6,7 +6,7 @@ extern crate block_on; -fn force_fnonce<T: async FnOnce()>(t: T) -> T { t } +fn force_fnonce<T: AsyncFnOnce()>(t: T) -> T { t } fn main() { block_on::block_on(async { diff --git a/tests/ui/async-await/async-closures/foreign.rs b/tests/ui/async-await/async-closures/foreign.rs index ab6fe06a3f4..a244eef4102 100644 --- a/tests/ui/async-await/async-closures/foreign.rs +++ b/tests/ui/async-await/async-closures/foreign.rs @@ -12,7 +12,7 @@ extern crate foreign; struct NoCopy; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs index 8e780ce9889..f49d1423c40 100644 --- a/tests/ui/async-await/async-closures/implements-fnmut.rs +++ b/tests/ui/async-await/async-closures/implements-fnmut.rs @@ -1,7 +1,7 @@ //@ build-pass //@ edition: 2021 -// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!) +// Demonstrates that an async closure may implement `FnMut` (not just `AsyncFnMut`!) // if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env, // since it's fine to reborrow it with its original lifetime. See the doc comment on // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs index a842d98d1de..1bd2da6e899 100644 --- a/tests/ui/async-await/async-closures/inline-body.rs +++ b/tests/ui/async-await/async-closures/inline-body.rs @@ -24,7 +24,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T { } } -async fn call_once<T>(f: impl async FnOnce() -> T) -> T { +async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T { f().await } diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs index a428905e40b..3032ca3c02b 100644 --- a/tests/ui/async-await/async-closures/mangle.rs +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -13,11 +13,11 @@ use std::future::Future; use std::pin::pin; use std::task::*; -async fn call_mut(f: &mut impl async FnMut()) { +async fn call_mut(f: &mut impl AsyncFnMut()) { f().await; } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/moro-example.rs b/tests/ui/async-await/async-closures/moro-example.rs index 5a8f42c7ca5..c331b8e5b5e 100644 --- a/tests/ui/async-await/async-closures/moro-example.rs +++ b/tests/ui/async-await/async-closures/moro-example.rs @@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> { fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()> where - for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>), + for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>), { todo!() } diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs index 79e2298f609..d0e2bc24b52 100644 --- a/tests/ui/async-await/async-closures/move-is-async-fn.rs +++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs @@ -19,7 +19,7 @@ fn main() { is_static(&c); // Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures. - fn call_once<F: async FnOnce()>(f: F) -> F::CallOnceFuture { f() } + fn call_once<F: AsyncFnOnce()>(f: F) -> F::CallOnceFuture { f() } is_static(&call_once(c)); }); } diff --git a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs index 9f2cbd7ce1c..c37048398e9 100644 --- a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs +++ b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs @@ -9,7 +9,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { f().await; } +async fn call_once(f: impl AsyncFnOnce()) { f().await; } pub async fn async_closure(x: &mut i32) { let c = async move || { diff --git a/tests/ui/async-await/async-closures/no-borrow-from-env.rs b/tests/ui/async-await/async-closures/no-borrow-from-env.rs index 3f9d26b9713..36b10c06dca 100644 --- a/tests/ui/async-await/async-closures/no-borrow-from-env.rs +++ b/tests/ui/async-await/async-closures/no-borrow-from-env.rs @@ -5,7 +5,7 @@ fn outlives<'a>(_: impl Sized + 'a) {} -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs index cd9d98d0799..cfb50dd5574 100644 --- a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs +++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs @@ -6,7 +6,7 @@ extern crate block_on; -fn wrapper(f: impl Fn(String)) -> impl async Fn(String) { +fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) { async move |s| f(s) } diff --git a/tests/ui/async-await/async-closures/overlapping-projs.rs b/tests/ui/async-await/async-closures/overlapping-projs.rs index 6dd00b16103..f778534cfe2 100644 --- a/tests/ui/async-await/async-closures/overlapping-projs.rs +++ b/tests/ui/async-await/async-closures/overlapping-projs.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/precise-captures.rs b/tests/ui/async-await/async-closures/precise-captures.rs index c4c67df544f..7dcbf2595f0 100644 --- a/tests/ui/async-await/async-closures/precise-captures.rs +++ b/tests/ui/async-await/async-closures/precise-captures.rs @@ -5,7 +5,7 @@ //@ revisions: call call_once force_once // call - Call the closure regularly. -// call_once - Call the closure w/ `async FnOnce`, so exercising the by_move shim. +// call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim. // force_once - Force the closure mode to `FnOnce`, so exercising what was fixed // in <https://github.com/rust-lang/rust/pull/123350>. @@ -20,7 +20,7 @@ macro_rules! call { } #[cfg(call_once)] -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await } @@ -35,7 +35,7 @@ macro_rules! guidance { } #[cfg(force_once)] -fn infer_fnonce(c: impl async FnOnce()) -> impl async FnOnce() { c } +fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c } #[cfg(force_once)] macro_rules! guidance { diff --git a/tests/ui/async-await/async-closures/refd.rs b/tests/ui/async-await/async-closures/refd.rs index 0b8d3d7aff5..8c16ecb1531 100644 --- a/tests/ui/async-await/async-closures/refd.rs +++ b/tests/ui/async-await/async-closures/refd.rs @@ -10,15 +10,15 @@ struct NoCopy; fn main() { block_on::block_on(async { - async fn call_once(x: impl async Fn()) { x().await } + async fn call_once(x: impl AsyncFn()) { x().await } - // check that `&{async-closure}` implements `async Fn`. + // check that `&{async-closure}` implements `AsyncFn`. call_once(&async || {}).await; - // check that `&{closure}` implements `async Fn`. + // check that `&{closure}` implements `AsyncFn`. call_once(&|| async {}).await; - // check that `&fndef` implements `async Fn`. + // check that `&fndef` implements `AsyncFn`. async fn foo() {} call_once(&foo).await; }); diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs index 856f3963ee6..4e9a6747f1f 100644 --- a/tests/ui/async-await/async-closures/signature-deduction.rs +++ b/tests/ui/async-await/async-closures/signature-deduction.rs @@ -3,7 +3,7 @@ #![feature(async_closure)] -async fn foo(x: impl async Fn(&str) -> &str) {} +async fn foo(x: impl AsyncFn(&str) -> &str) {} fn main() { foo(async |x| x); diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs index be3f032b8ff..19f366cc903 100644 --- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs @@ -8,7 +8,7 @@ fn outlives<'a>(_: impl Sized + 'a) {} -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index 3d6f856874f..a566b8aa663 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -2,7 +2,7 @@ #![feature(async_closure)] -fn needs_async_fn(_: impl async Fn()) {} +fn needs_async_fn(_: impl AsyncFn()) {} fn a() { let mut x = 1; @@ -15,7 +15,7 @@ fn a() { fn b() { let x = String::new(); needs_async_fn(move || async move { - //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` + //~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce` println!("{x}"); }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index 4b626c1bed6..d03b10ca2cc 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,29 +1,29 @@ -error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` +error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce` --> $DIR/wrong-fn-kind.rs:17:20 | LL | needs_async_fn(move || async move { | -------------- -^^^^^^ | | | - | _____|______________this closure implements `async FnOnce`, not `async Fn` + | _____|______________this closure implements `AsyncFnOnce`, not `AsyncFn` | | | | | required by a bound introduced by this call LL | | LL | | println!("{x}"); - | | - closure is `async FnOnce` because it moves the variable `x` out of its environment + | | - closure is `AsyncFnOnce` because it moves the variable `x` out of its environment LL | | }); - | |_____- the requirement to implement `async Fn` derives from here + | |_____- the requirement to implement `AsyncFn` derives from here | note: required by a bound in `needs_async_fn` --> $DIR/wrong-fn-kind.rs:5:27 | -LL | fn needs_async_fn(_: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `needs_async_fn` +LL | fn needs_async_fn(_: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `needs_async_fn` error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/wrong-fn-kind.rs:9:20 | -LL | fn needs_async_fn(_: impl async Fn()) {} - | --------------- change this to accept `FnMut` instead of `Fn` +LL | fn needs_async_fn(_: impl AsyncFn()) {} + | -------------- change this to accept `FnMut` instead of `Fn` ... LL | needs_async_fn(async || { | -------------- ^^^^^^^^ diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs index 772c7d15cfd..129ea282936 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.rs +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -2,10 +2,7 @@ #![feature(async_closure)] -fn foo(x: &dyn async Fn()) {} -//~^ ERROR the trait `AsyncFn` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object +fn foo(x: &dyn AsyncFn()) {} +//~^ ERROR the trait `AsyncFnMut` cannot be made into an object fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr index 78e915d49e7..aaa8eb2634d 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.stderr +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `AsyncFnMut` cannot be made into an object --> $DIR/dyn-pos.rs:5:16 | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object +LL | fn foo(x: &dyn AsyncFn()) {} + | ^^^^^^^^^ `AsyncFnMut` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL @@ -13,52 +13,6 @@ note: for a trait to be "dyn-compatible" it needs to allow building a vtable to &mut F std::boxed::Box<F, A> -error[E0038]: the trait `AsyncFnMut` cannot be made into an object - --> $DIR/dyn-pos.rs:5:16 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead: - &F - &mut F - std::boxed::Box<F, A> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `AsyncFnMut` cannot be made into an object - --> $DIR/dyn-pos.rs:5:16 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead: - &F - &mut F - std::boxed::Box<F, A> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `AsyncFn` cannot be made into an object - --> $DIR/dyn-pos.rs:5:12 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFn` for this new enum and using it instead: - &F - std::boxed::Box<F, A> - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index e38179758f6..7fc62a8dd93 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -1,8 +1,8 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x } //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later -//~| ERROR async closures are unstable -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable +//~| ERROR `async` trait bounds are unstable //~| ERROR use of unstable library feature `async_closure` //~| ERROR use of unstable library feature `async_closure` diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index 9fbceafd75d..96fb4c9e979 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = help: pass `--edition 2024` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:16 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:36 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: use of unstable library feature `async_closure` --> $DIR/edition-2015.rs:1:42 diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs index f8da517213a..5d675921028 100644 --- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs +++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs @@ -15,7 +15,7 @@ async fn f(arg: &i32) {} async fn func<F>(f: F) where - F: for<'a> async Fn(&'a i32), + F: for<'a> AsyncFn(&'a i32), { let x: i32 = 0; f(&x).await; diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs index 686addcb1a9..11faf9ac983 100644 --- a/tests/ui/async-await/async-fn/impl-trait.rs +++ b/tests/ui/async-await/async-fn/impl-trait.rs @@ -3,13 +3,13 @@ #![feature(async_closure, type_alias_impl_trait)] -type Tait = impl async Fn(); +type Tait = impl AsyncFn(); fn tait() -> Tait { || async {} } -fn foo(x: impl async Fn()) -> impl async Fn() { x } +fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x } -fn param<T: async Fn()>() {} +fn param<T: AsyncFn()>() {} fn main() {} diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs index abc429772fd..ea67831b68e 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs @@ -13,9 +13,9 @@ macro_rules! demo { } demo! { impl async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable demo! { dyn async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr index 13b8e72b49d..a463944d113 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr @@ -20,27 +20,27 @@ LL | demo! { dyn async Trait } | = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14 | LL | demo! { impl async Trait } | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13 | LL | demo! { dyn async Trait } | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs index 0d22cbd2c07..5cf23f2456a 100644 --- a/tests/ui/async-await/async-fn/not-a-trait.rs +++ b/tests/ui/async-await/async-fn/not-a-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] struct S; diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs index 5cbdc378dda..b6068a916ae 100644 --- a/tests/ui/async-await/async-fn/project.rs +++ b/tests/ui/async-await/async-fn/project.rs @@ -6,7 +6,9 @@ #![feature(async_closure, unboxed_closures, async_fn_traits)] -fn project<F: async Fn<()>>(_: F) -> Option<F::Output> { None } +use std::ops::AsyncFn; + +fn project<F: AsyncFn<()>>(_: F) -> Option<F::Output> { None } fn main() { let x: Option<i32> = project(|| async { 1i32 }); diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs index 29b6abc814a..0225b666ac5 100644 --- a/tests/ui/async-await/async-fn/sugar.rs +++ b/tests/ui/async-await/async-fn/sugar.rs @@ -1,7 +1,7 @@ //@ edition: 2021 //@ check-pass -#![feature(async_closure)] +#![feature(async_closure, async_trait_bounds)] async fn foo() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs index 329a1528e8b..654883966f4 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs @@ -6,7 +6,7 @@ macro_rules! x { x! { async fn foo() -> impl async Fn() { } - //~^ ERROR async closures are unstable + //~^ ERROR `async` trait bounds are unstable } fn main() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr index f68c09737db..259e13cd1fe 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr @@ -1,13 +1,13 @@ -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/trait-bounds-in-macro.rs:8:28 | LL | async fn foo() -> impl async Fn() { } | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs index e6fb0b46712..38d6bb1d01a 100644 --- a/tests/ui/async-await/async-fn/wrong-trait.rs +++ b/tests/ui/async-await/async-fn/wrong-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] trait Foo {} diff --git a/tests/ui/async-await/issues/auxiliary/issue-60674.rs b/tests/ui/async-await/issues/auxiliary/issue-60674.rs index da11142a3a4..a22f90e9516 100644 --- a/tests/ui/async-await/issues/auxiliary/issue-60674.rs +++ b/tests/ui/async-await/issues/auxiliary/issue-60674.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/async-await/issues/issue-60674.rs b/tests/ui/async-await/issues/issue-60674.rs index 9def3552e67..d04fa23840e 100644 --- a/tests/ui/async-await/issues/issue-60674.rs +++ b/tests/ui/async-await/issues/issue-60674.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-60674.rs +//@ proc-macro: issue-60674.rs //@ build-pass (FIXME(62277): could be check-pass?) //@ edition:2018 diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs new file mode 100644 index 00000000000..a95665f126d --- /dev/null +++ b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![feature(pin_ergonomics)] +//~^ WARN the feature `pin_ergonomics` is incomplete + +use std::pin::Pin; + +fn main() { + let _: Pin<Box<()>> = Box::pin(()); +} diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr new file mode 100644 index 00000000000..2deb5b09884 --- /dev/null +++ b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr @@ -0,0 +1,11 @@ +warning: the feature `pin_ergonomics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/coerce-non-pointer-pin.rs:3:12 + | +LL | #![feature(pin_ergonomics)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/pin-reborrow-arg.rs b/tests/ui/async-await/pin-ergonomics/reborrow-arg.rs index 2008bd1f52d..2008bd1f52d 100644 --- a/tests/ui/async-await/pin-reborrow-arg.rs +++ b/tests/ui/async-await/pin-ergonomics/reborrow-arg.rs diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.rs b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs index 27c70a7b4df..27c70a7b4df 100644 --- a/tests/ui/async-await/pin-reborrow-const-as-mut.rs +++ b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr index 2c2d9ec2717..36bbf1c493a 100644 --- a/tests/ui/async-await/pin-reborrow-const-as-mut.stderr +++ b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pin-reborrow-const-as-mut.rs:14:9 + --> $DIR/reborrow-const-as-mut.rs:14:9 | LL | foo(x); | --- ^ types differ in mutability @@ -9,7 +9,7 @@ LL | foo(x); = note: expected struct `Pin<&mut Foo>` found struct `Pin<&Foo>` note: function defined here - --> $DIR/pin-reborrow-const-as-mut.rs:10:4 + --> $DIR/reborrow-const-as-mut.rs:10:4 | LL | fn foo(_: Pin<&mut Foo>) { | ^^^ ---------------- diff --git a/tests/ui/async-await/pin-reborrow-once.rs b/tests/ui/async-await/pin-ergonomics/reborrow-once.rs index 241efadef7d..241efadef7d 100644 --- a/tests/ui/async-await/pin-reborrow-once.rs +++ b/tests/ui/async-await/pin-ergonomics/reborrow-once.rs diff --git a/tests/ui/async-await/pin-reborrow-once.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr index b8fde8ffee8..a1ea2b4a57a 100644 --- a/tests/ui/async-await/pin-reborrow-once.stderr +++ b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `*x.__pointer` as mutable more than once at a time - --> $DIR/pin-reborrow-once.rs:12:14 + --> $DIR/reborrow-once.rs:12:14 | LL | twice(x, x); | ----- - ^ second mutable borrow occurs here diff --git a/tests/ui/async-await/pin-reborrow-self.rs b/tests/ui/async-await/pin-ergonomics/reborrow-self.rs index ee617617da0..ee617617da0 100644 --- a/tests/ui/async-await/pin-reborrow-self.rs +++ b/tests/ui/async-await/pin-ergonomics/reborrow-self.rs diff --git a/tests/ui/async-await/pin-reborrow-shorter.rs b/tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs index 06c266e0035..06c266e0035 100644 --- a/tests/ui/async-await/pin-reborrow-shorter.rs +++ b/tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs diff --git a/tests/ui/async-await/pin-sugar-ambiguity.rs b/tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs index d183000931e..d183000931e 100644 --- a/tests/ui/async-await/pin-sugar-ambiguity.rs +++ b/tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs diff --git a/tests/ui/async-await/pin-sugar-no-const.rs b/tests/ui/async-await/pin-ergonomics/sugar-no-const.rs index dd6456b6034..dd6456b6034 100644 --- a/tests/ui/async-await/pin-sugar-no-const.rs +++ b/tests/ui/async-await/pin-ergonomics/sugar-no-const.rs diff --git a/tests/ui/async-await/pin-sugar-no-const.stderr b/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr index 5f01156c1f0..822cfffcb8c 100644 --- a/tests/ui/async-await/pin-sugar-no-const.stderr +++ b/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `::`, `;`, `<`, or `=`, found `i32` - --> $DIR/pin-sugar-no-const.rs:7:18 + --> $DIR/sugar-no-const.rs:7:18 | LL | let _x: &pin i32 = todo!(); | - ^^^ expected one of `!`, `(`, `::`, `;`, `<`, or `=` diff --git a/tests/ui/async-await/pin-sugar.rs b/tests/ui/async-await/pin-ergonomics/sugar.rs index 8dbdec418b1..8dbdec418b1 100644 --- a/tests/ui/async-await/pin-sugar.rs +++ b/tests/ui/async-await/pin-ergonomics/sugar.rs diff --git a/tests/ui/attributes/auxiliary/key-value-expansion.rs b/tests/ui/attributes/auxiliary/key-value-expansion.rs index 9db82cec635..5ecc62ed3fa 100644 --- a/tests/ui/attributes/auxiliary/key-value-expansion.rs +++ b/tests/ui/attributes/auxiliary/key-value-expansion.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/attributes/dump_def_parents.rs b/tests/ui/attributes/dump_def_parents.rs index de0c88bb6c3..04a725f6c14 100644 --- a/tests/ui/attributes/dump_def_parents.rs +++ b/tests/ui/attributes/dump_def_parents.rs @@ -3,16 +3,17 @@ fn bar() { fn foo() { + #[rustc_dump_def_parents] fn baz() { - #[rustc_dump_def_parents] + //~^ ERROR: rustc_dump_def_parents: DefId || { - //~^ ERROR: rustc_dump_def_parents: DefId qux::< { //~^ ERROR: rustc_dump_def_parents: DefId fn inhibits_dump() { qux::< { + //~^ ERROR: rustc_dump_def_parents: DefId "hi"; 1 }, diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr index b2cc32d09b0..a928e8e33a4 100644 --- a/tests/ui/attributes/dump_def_parents.stderr +++ b/tests/ui/attributes/dump_def_parents.stderr @@ -1,11 +1,50 @@ error: rustc_dump_def_parents: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 + --> $DIR/dump_def_parents.rs:7:9 + | +LL | fn baz() { + | ^^^^^^^^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:5:5 + | +LL | fn foo() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:4:1 + | +LL | fn bar() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:2:1 + | +LL | / #![feature(rustc_attrs)] +LL | | +LL | | fn bar() { +LL | | fn foo() { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:11:21 + | +LL | / { +LL | | +LL | | fn inhibits_dump() { +LL | | qux::< +... | +LL | | 1 +LL | | }, + | |_____________________^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:9:13 | LL | || { | ^^ - | note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ @@ -32,6 +71,21 @@ LL | | fn main() {} | |____________^ error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:15:33 + | +LL | / ... { +LL | | ... +LL | | ... "hi"; +LL | | ... 1 +LL | | ... }, + | |_______________________^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:13:25 + | +LL | fn inhibits_dump() { + | ^^^^^^^^^^^^^^^^^^ +note: DefId(..) --> $DIR/dump_def_parents.rs:11:21 | LL | / { @@ -42,14 +96,13 @@ LL | | qux::< LL | | 1 LL | | }, | |_____________________^ - | note: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 + --> $DIR/dump_def_parents.rs:9:13 | LL | || { | ^^ note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ @@ -76,7 +129,7 @@ LL | | fn main() {} | |____________^ error: rustc_dump_def_parents: DefId(..) - --> $DIR/dump_def_parents.rs:22:31 + --> $DIR/dump_def_parents.rs:23:31 | LL | qux::<{ 1 + 1 }>(); | ^^^^^^^^^ @@ -93,12 +146,12 @@ LL | | 1 LL | | }, | |_____________________^ note: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 + --> $DIR/dump_def_parents.rs:9:13 | LL | || { | ^^ note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ @@ -124,5 +177,5 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/attributes/key-value-expansion.rs b/tests/ui/attributes/key-value-expansion.rs index dd408ebb77e..e5700a75935 100644 --- a/tests/ui/attributes/key-value-expansion.rs +++ b/tests/ui/attributes/key-value-expansion.rs @@ -1,7 +1,7 @@ // Regression tests for issue #55414, expansion happens in the value of a key-value attribute, // and the expanded expression is more complex than simply a macro call. -//@ aux-build:key-value-expansion.rs +//@ proc-macro: key-value-expansion.rs #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs index 25879d17027..038183a80b8 100644 --- a/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs +++ b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/attributes/main-removed-2/main.rs b/tests/ui/attributes/main-removed-2/main.rs index e4a3de79ec9..53696d68ced 100644 --- a/tests/ui/attributes/main-removed-2/main.rs +++ b/tests/ui/attributes/main-removed-2/main.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:tokyo.rs +//@ proc-macro: tokyo.rs //@ compile-flags:--extern tokyo //@ edition:2021 diff --git a/tests/ui/autodiff/auxiliary/my_macro.rs b/tests/ui/autodiff/auxiliary/my_macro.rs index 417199611cc..217631a33c9 100644 --- a/tests/ui/autodiff/auxiliary/my_macro.rs +++ b/tests/ui/autodiff/auxiliary/my_macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/autodiff/visibility.rs b/tests/ui/autodiff/visibility.rs index 6a4851de2dc..dfaec03aef0 100644 --- a/tests/ui/autodiff/visibility.rs +++ b/tests/ui/autodiff/visibility.rs @@ -1,7 +1,7 @@ //@ ignore-enzyme //@ revisions: std_autodiff no_std_autodiff //@[no_std_autodiff] check-pass -//@ aux-build: my_macro.rs +//@ proc-macro: my_macro.rs #![crate_type = "lib"] #![feature(autodiff)] diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs deleted file mode 100644 index d47a8e085fd..00000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ only-x86_64 - -fn efiapi(f: extern "efiapi" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} -fn sysv(f: extern "sysv64" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} -fn win(f: extern "win64" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} - -fn main() {} diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr deleted file mode 100644 index 41be3784245..00000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ /dev/null @@ -1,52 +0,0 @@ -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0045, E0658. -For more information about an error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs new file mode 100644 index 00000000000..d0ef91b22b2 --- /dev/null +++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/69232 + +extern "C" { + fn foo(x: usize, ...); +} + +fn test() -> u8 { + 127 +} + +fn main() { + unsafe { foo(1, test) }; //~ ERROR can't pass a function item to a variadic function +} diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr new file mode 100644 index 00000000000..6aa1c8a1091 --- /dev/null +++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr @@ -0,0 +1,16 @@ +error[E0617]: can't pass a function item to a variadic function + --> $DIR/fn-item-diagnostic-issue-69232.rs:12:21 + | +LL | unsafe { foo(1, test) }; + | ^^^^ + | + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead + | +LL | unsafe { foo(1, test as fn() -> u8) }; + | +++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0617`. diff --git a/tests/ui/c-variadic/issue-32201.rs b/tests/ui/c-variadic/issue-32201.rs index f27bb1c2eb5..434711b7523 100644 --- a/tests/ui/c-variadic/issue-32201.rs +++ b/tests/ui/c-variadic/issue-32201.rs @@ -7,7 +7,8 @@ fn bar(_: *const u8) {} fn main() { unsafe { foo(0, bar); - //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function - //~| HELP cast the value to `fn(*const u8)` + //~^ ERROR can't pass a function item to a variadic function + //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + ////~| HELP use a function pointer instead } } diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr index 352db9f62f6..1cd85d7f07a 100644 --- a/tests/ui/c-variadic/issue-32201.stderr +++ b/tests/ui/c-variadic/issue-32201.stderr @@ -1,8 +1,15 @@ -error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function +error[E0617]: can't pass a function item to a variadic function --> $DIR/issue-32201.rs:9:16 | LL | foo(0, bar); - | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)` + | ^^^ + | + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead + | +LL | foo(0, bar as fn(*const u8)); + | ++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index 72d60a1439a..7a54d043356 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/variadic-ffi-1.rs:9:5 | LL | fn printf(_: *const u8, ...); @@ -62,37 +62,67 @@ error[E0617]: can't pass `f32` to variadic function --> $DIR/variadic-ffi-1.rs:28:19 | LL | foo(1, 2, 3f32); - | ^^^^ help: cast the value to `c_double`: `3f32 as c_double` + | ^^^^ + | +help: cast the value to `c_double` + | +LL | foo(1, 2, 3f32 as c_double); + | +++++++++++ error[E0617]: can't pass `bool` to variadic function --> $DIR/variadic-ffi-1.rs:29:19 | LL | foo(1, 2, true); - | ^^^^ help: cast the value to `c_int`: `true as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, true as c_int); + | ++++++++ error[E0617]: can't pass `i8` to variadic function --> $DIR/variadic-ffi-1.rs:30:19 | LL | foo(1, 2, 1i8); - | ^^^ help: cast the value to `c_int`: `1i8 as c_int` + | ^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, 1i8 as c_int); + | ++++++++ error[E0617]: can't pass `u8` to variadic function --> $DIR/variadic-ffi-1.rs:31:19 | LL | foo(1, 2, 1u8); - | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint` + | ^^^ + | +help: cast the value to `c_uint` + | +LL | foo(1, 2, 1u8 as c_uint); + | +++++++++ error[E0617]: can't pass `i16` to variadic function --> $DIR/variadic-ffi-1.rs:32:19 | LL | foo(1, 2, 1i16); - | ^^^^ help: cast the value to `c_int`: `1i16 as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, 1i16 as c_int); + | ++++++++ error[E0617]: can't pass `u16` to variadic function --> $DIR/variadic-ffi-1.rs:33:19 | LL | foo(1, 2, 1u16); - | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint` + | ^^^^ + | +help: cast the value to `c_uint` + | +LL | foo(1, 2, 1u16 as c_uint); + | +++++++++ error: aborting due to 11 previous errors diff --git a/tests/ui/c-variadic/variadic-ffi-2-arm.rs b/tests/ui/c-variadic/variadic-ffi-2-arm.rs index 3b0a71007a0..82f9df5053c 100644 --- a/tests/ui/c-variadic/variadic-ffi-2-arm.rs +++ b/tests/ui/c-variadic/variadic-ffi-2-arm.rs @@ -1,6 +1,5 @@ //@ only-arm //@ build-pass -#![feature(extended_varargs_abi_support)] fn aapcs(f: extern "aapcs" fn(usize, ...)) { f(22, 44); diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs index bafb7e2b20c..17a1065279f 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.rs +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -1,5 +1,4 @@ //@ ignore-arm stdcall isn't supported -#![feature(extended_varargs_abi_support)] #[allow(unsupported_fn_ptr_calling_conventions)] fn baz(f: extern "stdcall" fn(usize, ...)) { diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index e52de93a926..fbf273b1f1d 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -1,5 +1,5 @@ error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` - --> $DIR/variadic-ffi-2.rs:5:11 + --> $DIR/variadic-ffi-2.rs:4:11 | LL | fn baz(f: extern "stdcall" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention diff --git a/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs index b04b1e0c326..cafb7389e29 100644 --- a/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs +++ b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:ver-cfg-rel.rs +//@ proc-macro: ver-cfg-rel.rs //@ revisions: assume no_assume //@ [assume]compile-flags: -Z assume-incomplete-release diff --git a/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs index e06ee94a1e9..5d3e9c7a32f 100644 --- a/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs +++ b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree as Tt}; use std::str::FromStr; diff --git a/tests/ui/check-cfg/and-more-diagnostic.rs b/tests/ui/check-cfg/and-more-diagnostic.rs new file mode 100644 index 00000000000..82867f3b435 --- /dev/null +++ b/tests/ui/check-cfg/and-more-diagnostic.rs @@ -0,0 +1,13 @@ +// This test makes sure that we don't emit a long list of possible values +// but that we stop at a fix point and say "and X more". +// +//@ check-pass +//@ no-auto-check-cfg +//@ compile-flags: --check-cfg=cfg() +//@ normalize-stderr-test: "and \d+ more" -> "and X more" +//@ normalize-stderr-test: "`[a-zA-Z0-9_-]+`" -> "`xxx`" + +fn main() { + cfg!(target_feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value +} diff --git a/tests/ui/check-cfg/and-more-diagnostic.stderr b/tests/ui/check-cfg/and-more-diagnostic.stderr new file mode 100644 index 00000000000..2ac80c84c37 --- /dev/null +++ b/tests/ui/check-cfg/and-more-diagnostic.stderr @@ -0,0 +1,12 @@ +warning: unexpected `xxx` condition value: `xxx` + --> $DIR/and-more-diagnostic.rs:11:10 + | +LL | cfg!(target_feature = "zebra"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `xxx` are: `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, and `xxx` and X more + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index ac244f4fc09..e9a2de2f672 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -75,8 +75,6 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value - cfg!(target_feature = "zebra"); - //~^ WARNING unexpected `cfg` condition value } fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 0a993214f5a..231236799c6 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -245,14 +245,5 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration -warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:78:10 - | -LL | cfg!(target_feature = "zebra"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 251 more - = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration - -warning: 27 warnings emitted +warning: 26 warnings emitted diff --git a/tests/ui/check-cfg/target_feature.rs b/tests/ui/check-cfg/target_feature.rs new file mode 100644 index 00000000000..6028dae66c4 --- /dev/null +++ b/tests/ui/check-cfg/target_feature.rs @@ -0,0 +1,18 @@ +// This test prints all the possible values for the `target_feature` cfg +// as a way to assert the expected values and reflect on any changes made +// to the `target_feature` cfg in the compiler. +// +// The output of this test does not reflect the actual output seen by +// users which will see a truncated list of possible values (at worst). +// +// In case of test output differences, just `--bless` the test. +// +//@ check-pass +//@ no-auto-check-cfg +//@ compile-flags: --check-cfg=cfg() -Zcheck-cfg-all-expected +//@ normalize-stderr-test: "`, `" -> "`\n`" + +fn main() { + cfg!(target_feature = "_UNEXPECTED_VALUE"); + //~^ WARNING unexpected `cfg` condition value +} diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr new file mode 100644 index 00000000000..2674a97a551 --- /dev/null +++ b/tests/ui/check-cfg/target_feature.stderr @@ -0,0 +1,297 @@ +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/target_feature.rs:16:10 + | +LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_feature` are: `10e60` +`2e3` +`3e3r1` +`3e3r2` +`3e3r3` +`3e7` +`7e10` +`a` +`aclass` +`adx` +`aes` +`altivec` +`alu32` +`amx-bf16` +`amx-complex` +`amx-fp16` +`amx-int8` +`amx-tile` +`atomics` +`avx` +`avx2` +`avx512bf16` +`avx512bitalg` +`avx512bw` +`avx512cd` +`avx512dq` +`avx512f` +`avx512fp16` +`avx512ifma` +`avx512vbmi` +`avx512vbmi2` +`avx512vl` +`avx512vnni` +`avx512vp2intersect` +`avx512vpopcntdq` +`avxifma` +`avxneconvert` +`avxvnni` +`avxvnniint16` +`avxvnniint8` +`backchain` +`bf16` +`bmi1` +`bmi2` +`bti` +`bulk-memory` +`c` +`cache` +`cmpxchg16b` +`crc` +`crt-static` +`cssc` +`d` +`d32` +`dit` +`doloop` +`dotprod` +`dpb` +`dpb2` +`dsp` +`dsp1e2` +`dspe60` +`e` +`e1` +`e2` +`ecv` +`edsp` +`elrw` +`ermsb` +`exception-handling` +`extended-const` +`f` +`f16c` +`f32mm` +`f64mm` +`faminmax` +`fcma` +`fdivdu` +`fhm` +`flagm` +`flagm2` +`float1e2` +`float1e3` +`float3e4` +`float7e60` +`floate1` +`fma` +`fp-armv8` +`fp16` +`fp64` +`fp8` +`fp8dot2` +`fp8dot4` +`fp8fma` +`fpuv2_df` +`fpuv2_sf` +`fpuv3_df` +`fpuv3_hf` +`fpuv3_hi` +`fpuv3_sf` +`frecipe` +`frintts` +`fxsr` +`gfni` +`hard-float` +`hard-float-abi` +`hard-tp` +`hbc` +`high-registers` +`hvx` +`hvx-length128b` +`hwdiv` +`i8mm` +`jsconv` +`lahfsahf` +`lasx` +`lbt` +`leoncasa` +`lor` +`lse` +`lse128` +`lse2` +`lsx` +`lut` +`lvz` +`lzcnt` +`m` +`mclass` +`mops` +`movbe` +`mp` +`mp1e2` +`msa` +`mte` +`multivalue` +`mutable-globals` +`neon` +`nontrapping-fptoint` +`nvic` +`paca` +`pacg` +`pan` +`partword-atomics` +`pauth-lr` +`pclmulqdq` +`pmuv3` +`popcnt` +`power10-vector` +`power8-altivec` +`power8-vector` +`power9-altivec` +`power9-vector` +`prfchw` +`quadword-atomics` +`rand` +`ras` +`rclass` +`rcpc` +`rcpc2` +`rcpc3` +`rdm` +`rdrand` +`rdseed` +`reference-types` +`relax` +`relaxed-simd` +`reserve-x18` +`rtm` +`sb` +`sha` +`sha2` +`sha3` +`sha512` +`sign-ext` +`simd128` +`sm3` +`sm4` +`sme` +`sme-b16b16` +`sme-f16f16` +`sme-f64f64` +`sme-f8f16` +`sme-f8f32` +`sme-fa64` +`sme-i16i64` +`sme-lutv2` +`sme2` +`sme2p1` +`spe` +`ssbs` +`sse` +`sse2` +`sse3` +`sse4.1` +`sse4.2` +`sse4a` +`ssse3` +`ssve-fp8dot2` +`ssve-fp8dot4` +`ssve-fp8fma` +`sve` +`sve-b16b16` +`sve2` +`sve2-aes` +`sve2-bitperm` +`sve2-sha3` +`sve2-sm4` +`sve2p1` +`tail-call` +`tbm` +`thumb-mode` +`thumb2` +`tme` +`trust` +`trustzone` +`ual` +`unaligned-scalar-mem` +`v` +`v5te` +`v6` +`v6k` +`v6t2` +`v7` +`v8` +`v8.1a` +`v8.2a` +`v8.3a` +`v8.4a` +`v8.5a` +`v8.6a` +`v8.7a` +`v8.8a` +`v8.9a` +`v8plus` +`v9` +`v9.1a` +`v9.2a` +`v9.3a` +`v9.4a` +`v9.5a` +`v9a` +`vaes` +`vdsp2e60f` +`vdspv1` +`vdspv2` +`vector` +`vfp2` +`vfp3` +`vfp4` +`vh` +`virt` +`virtualization` +`vpclmulqdq` +`vsx` +`wfxt` +`wide-arithmetic` +`xop` +`xsave` +`xsavec` +`xsaveopt` +`xsaves` +`zaamo` +`zabha` +`zalrsc` +`zba` +`zbb` +`zbc` +`zbkb` +`zbkc` +`zbkx` +`zbs` +`zdinx` +`zfh` +`zfhmin` +`zfinx` +`zhinx` +`zhinxmin` +`zk` +`zkn` +`zknd` +`zkne` +`zknh` +`zkr` +`zks` +`zksed` +`zksh`, and `zkt` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 1fda4b2089e..40b7b2db836 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -60,8 +60,8 @@ //~^ WARN unexpected `cfg` condition value target_family = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value - target_feature = "_UNEXPECTED_VALUE", - //~^ WARN unexpected `cfg` condition value + // target_feature = "_UNEXPECTED_VALUE", + // ^ tested in target_feature.rs target_has_atomic = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ca6a173d638..7c03d0570db 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -169,15 +169,6 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:63:5 - | -LL | target_feature = "_UNEXPECTED_VALUE", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tail-call`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` - = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration - -warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` --> $DIR/well-known-values.rs:65:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", @@ -297,5 +288,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration -warning: 30 warnings emitted +warning: 29 warnings emitted diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs index 9e0ffa75c22..da1327dace5 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -39,4 +39,4 @@ type WithTransparentTraitObject = //~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); -//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045] +//~^ ERROR C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` [E0045] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr index 7cb8e135ea3..f20e67e3d94 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -68,7 +68,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/generics.rs:41:20 | LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); diff --git a/tests/ui/codegen/mismatched-data-layout.json b/tests/ui/codegen/mismatched-data-layout.json index 4cb0602dc75..7adc8832524 100644 --- a/tests/ui/codegen/mismatched-data-layout.json +++ b/tests/ui/codegen/mismatched-data-layout.json @@ -5,7 +5,7 @@ "target-endian": "little", "target-pointer-width": "64", "target-c-int-width": "32", - "os": "unknown", + "os": "none", "linker-flavor": "ld.lld", "linker": "rust-lld", "executables": true diff --git a/tests/ui/codegen/mismatched-data-layouts.stderr b/tests/ui/codegen/mismatched-data-layouts.stderr index 1fe242266df..b7d5d82bee0 100644 --- a/tests/ui/codegen/mismatched-data-layouts.stderr +++ b/tests/ui/codegen/mismatched-data-layouts.stderr @@ -1,4 +1,4 @@ -error: data-layout for target `mismatched-data-layout-7814813422914914169`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout` +error: data-layout for target `mismatched-data-layout-7193370089426056427`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout` error: aborting due to 1 previous error diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs index e08884ad6a4..50a2aacc91a 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.rs +++ b/tests/ui/coercion/coerce-loop-issue-122561.rs @@ -39,8 +39,7 @@ fn for_single_line() -> bool { for i in 0.. { return false; } } // b. format the suggestion correctly so // that it's readable fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { -//~^ ERROR `for` is not allowed in a `const` -//~| ERROR mismatched types + //~^ ERROR mismatched types true } @@ -84,16 +83,14 @@ fn loop_() -> bool { const C: i32 = { for i in 0.. { - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } }; fn main() { let _ = [10; { for i in 0..5 { - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } }]; @@ -105,6 +102,5 @@ fn main() { let _ = |a: &[(); for x in 0..2 {}]| {}; - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index 0f77fd1364d..90e9f41c291 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:48:5 + --> $DIR/coerce-loop-issue-122561.rs:47:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` @@ -7,57 +7,11 @@ LL | while true { = note: `#[warn(while_true)]` on by default warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:72:5 + --> $DIR/coerce-loop-issue-122561.rs:71:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` -error[E0658]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:41:24 - | -LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:86:5 - | -LL | / for i in 0.. { -LL | | -LL | | -LL | | } - | |_____^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:94:9 - | -LL | / for i in 0..5 { -LL | | -LL | | -LL | | } - | |_________^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:107:23 - | -LL | let _ = |a: &[(); for x in 0..2 {}]| {}; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/coerce-loop-issue-122561.rs:41:24 | @@ -71,11 +25,10 @@ LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool { | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:86:5 + --> $DIR/coerce-loop-issue-122561.rs:85:5 | LL | / for i in 0.. { LL | | -LL | | LL | | } | |_____^ expected `i32`, found `()` | @@ -174,7 +127,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val | ++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:48:5 + --> $DIR/coerce-loop-issue-122561.rs:47:5 | LL | fn while_inifinite() -> bool { | ---- expected `bool` because of return type @@ -193,7 +146,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:57:5 + --> $DIR/coerce-loop-issue-122561.rs:56:5 | LL | fn while_finite() -> bool { | ---- expected `bool` because of return type @@ -213,7 +166,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:65:5 + --> $DIR/coerce-loop-issue-122561.rs:64:5 | LL | fn while_zero_times() -> bool { | ---- expected `bool` because of return type @@ -231,7 +184,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:72:5 + --> $DIR/coerce-loop-issue-122561.rs:71:5 | LL | fn while_never_type() -> ! { | - expected `!` because of return type @@ -251,11 +204,10 @@ LL + /* `loop {}` or `panic!("...")` */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:94:9 + --> $DIR/coerce-loop-issue-122561.rs:92:9 | LL | / for i in 0..5 { LL | | -LL | | LL | | } | |_________^ expected `usize`, found `()` | @@ -267,7 +219,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:101:9 + --> $DIR/coerce-loop-issue-122561.rs:98:9 | LL | / while false { LL | | @@ -282,7 +234,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:107:23 + --> $DIR/coerce-loop-issue-122561.rs:104:23 | LL | let _ = |a: &[(); for x in 0..2 {}]| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` @@ -293,7 +245,6 @@ help: consider returning a value here LL | let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {}; | +++++++++++++++++++ -error: aborting due to 18 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-1.rs index 2fdd703ab6f..5ea445520f1 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-1.rs @@ -85,6 +85,14 @@ macro_rules! braced_braced_expr { () => {{ braced_expr!() }}; } +macro_rules! closure { + () => { |()| () }; +} + +macro_rules! empty { + () => {}; +} + #[rustfmt::skip] mod array_paren_call { // Arrays where the expanded result is a `Res::Err` @@ -128,6 +136,14 @@ mod array_paren_call { fn array_33() -> [(); braced_expr!()] { loop {} } fn array_34() -> [(); { unbraced_expr!() }] { loop {} } fn array_35() -> [(); { braced_expr!() }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure!()] { loop {} } + fn array_37() -> [(); { closure!() }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty!()] { loop {} } + fn array_39() -> [(); { empty!() }] { loop {} } } #[rustfmt::skip] @@ -173,6 +189,14 @@ mod array_brace_call { fn array_33() -> [(); braced_expr!{}] { loop {} } fn array_34() -> [(); { unbraced_expr!{} }] { loop {} } fn array_35() -> [(); { braced_expr!{} }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure!{}] { loop {} } + fn array_37() -> [(); { closure!{} }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty!{}] { loop {} } + fn array_39() -> [(); { empty!{} }] { loop {} } } #[rustfmt::skip] @@ -218,6 +242,14 @@ mod array_square_call { fn array_33() -> [(); braced_expr![]] { loop {} } fn array_34() -> [(); { unbraced_expr![] }] { loop {} } fn array_35() -> [(); { braced_expr![] }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure![]] { loop {} } + fn array_37() -> [(); { closure![] }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty![]] { loop {} } + fn array_39() -> [(); { empty![] }] { loop {} } } struct Foo<const N: usize>; @@ -255,18 +287,26 @@ mod adt_paren_call { fn adt_23<const ident: usize>() -> Foo<{ braced_ident!() }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo<unbraced_unbraced_expr!()> { loop {} } - fn array_25() -> Foo<braced_unbraced_expr!()> { loop {} } - fn array_26() -> Foo<unbraced_braced_expr!()> { loop {} } - fn array_27() -> Foo<braced_braced_expr!()> { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr!() }> { loop {} } - fn array_32() -> Foo<unbraced_expr!()> { loop {} } - fn array_33() -> Foo<braced_expr!()> { loop {} } - fn array_34() -> Foo<{ unbraced_expr!() }> { loop {} } - fn array_35() -> Foo<{ braced_expr!() }> { loop {} } + fn adt_24() -> Foo<unbraced_unbraced_expr!()> { loop {} } + fn adt_25() -> Foo<braced_unbraced_expr!()> { loop {} } + fn adt_26() -> Foo<unbraced_braced_expr!()> { loop {} } + fn adt_27() -> Foo<braced_braced_expr!()> { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr!() }> { loop {} } + fn adt_32() -> Foo<unbraced_expr!()> { loop {} } + fn adt_33() -> Foo<braced_expr!()> { loop {} } + fn adt_34() -> Foo<{ unbraced_expr!() }> { loop {} } + fn adt_35() -> Foo<{ braced_expr!() }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo<closure!()> { loop {} } + fn adt_37() -> Foo<{ closure!() }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo<empty!()> { loop {} } + fn adt_39() -> Foo<{ empty!() }> { loop {} } } #[rustfmt::skip] @@ -302,18 +342,26 @@ mod adt_brace_call { fn adt_23<const ident: usize>() -> Foo<{ braced_ident!{} }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo<unbraced_unbraced_expr!{}> { loop {} } - fn array_25() -> Foo<braced_unbraced_expr!{}> { loop {} } - fn array_26() -> Foo<unbraced_braced_expr!{}> { loop {} } - fn array_27() -> Foo<braced_braced_expr!{}> { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } - fn array_32() -> Foo<unbraced_expr!{}> { loop {} } - fn array_33() -> Foo<braced_expr!{}> { loop {} } - fn array_34() -> Foo<{ unbraced_expr!{} }> { loop {} } - fn array_35() -> Foo<{ braced_expr!{} }> { loop {} } + fn adt_24() -> Foo<unbraced_unbraced_expr!{}> { loop {} } + fn adt_25() -> Foo<braced_unbraced_expr!{}> { loop {} } + fn adt_26() -> Foo<unbraced_braced_expr!{}> { loop {} } + fn adt_27() -> Foo<braced_braced_expr!{}> { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } + fn adt_32() -> Foo<unbraced_expr!{}> { loop {} } + fn adt_33() -> Foo<braced_expr!{}> { loop {} } + fn adt_34() -> Foo<{ unbraced_expr!{} }> { loop {} } + fn adt_35() -> Foo<{ braced_expr!{} }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo<closure!{}> { loop {} } + fn adt_37() -> Foo<{ closure!{} }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo<empty!{}> { loop {} } + fn adt_39() -> Foo<{ empty!{} }> { loop {} } } #[rustfmt::skip] @@ -349,18 +397,185 @@ mod adt_square_call { fn adt_23<const ident: usize>() -> Foo<{ braced_ident![] }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo<unbraced_unbraced_expr![]> { loop {} } - fn array_25() -> Foo<braced_unbraced_expr![]> { loop {} } - fn array_26() -> Foo<unbraced_braced_expr![]> { loop {} } - fn array_27() -> Foo<braced_braced_expr![]> { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr![] }> { loop {} } - fn array_32() -> Foo<unbraced_expr![]> { loop {} } - fn array_33() -> Foo<braced_expr![]> { loop {} } - fn array_34() -> Foo<{ unbraced_expr![] }> { loop {} } - fn array_35() -> Foo<{ braced_expr![] }> { loop {} } + fn adt_24() -> Foo<unbraced_unbraced_expr![]> { loop {} } + fn adt_25() -> Foo<braced_unbraced_expr![]> { loop {} } + fn adt_26() -> Foo<unbraced_braced_expr![]> { loop {} } + fn adt_27() -> Foo<braced_braced_expr![]> { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr![] }> { loop {} } + fn adt_32() -> Foo<unbraced_expr![]> { loop {} } + fn adt_33() -> Foo<braced_expr![]> { loop {} } + fn adt_34() -> Foo<{ unbraced_expr![] }> { loop {} } + fn adt_35() -> Foo<{ braced_expr![] }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo<closure![]> { loop {} } + fn adt_37() -> Foo<{ closure![] }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo<empty![]> { loop {} } + fn adt_39() -> Foo<{ empty![] }> { loop {} } +} + +#[rustfmt::skip] +mod repeat_paren_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident!()]; } + fn repeat_1() { [(); braced_unbraced_ident!()]; } + fn repeat_2() { [(); unbraced_braced_ident!()]; } + fn repeat_3() { [(); braced_braced_ident!()]; } + fn repeat_4() { [(); { unbraced_unbraced_ident!() }]; } + fn repeat_5() { [(); { braced_unbraced_ident!() }]; } + fn repeat_6() { [(); { unbraced_braced_ident!() }]; } + fn repeat_7() { [(); { braced_braced_ident!() }]; } + fn repeat_8() { [(); unbraced_ident!()]; } + fn repeat_9() { [(); braced_ident!()]; } + fn repeat_10() { [(); { unbraced_ident!() }]; } + fn repeat_11() { [(); { braced_ident!() }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12<const ident: usize>() { [(); unbraced_unbraced_ident!()]; } + fn repeat_13<const ident: usize>() { [(); braced_unbraced_ident!()]; } + fn repeat_14<const ident: usize>() { [(); unbraced_braced_ident!()]; } + fn repeat_15<const ident: usize>() { [(); braced_braced_ident!()]; } + fn repeat_16<const ident: usize>() { [(); { unbraced_unbraced_ident!() }]; } + fn repeat_17<const ident: usize>() { [(); { braced_unbraced_ident!() }]; } + fn repeat_18<const ident: usize>() { [(); { unbraced_braced_ident!() }]; } + fn repeat_19<const ident: usize>() { [(); { braced_braced_ident!() }]; } + fn repeat_20<const ident: usize>() { [(); unbraced_ident!()]; } + fn repeat_21<const ident: usize>() { [(); braced_ident!()]; } + fn repeat_22<const ident: usize>() { [(); { unbraced_ident!() }]; } + fn repeat_23<const ident: usize>() { [(); { braced_ident!() }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr!()]; } + fn repeat_25() { [(); braced_unbraced_expr!()]; } + fn repeat_26() { [(); unbraced_braced_expr!()]; } + fn repeat_27() { [(); braced_braced_expr!()]; } + fn repeat_28() { [(); { unbraced_unbraced_expr!() }]; } + fn repeat_29() { [(); { braced_unbraced_expr!() }]; } + fn repeat_30() { [(); { unbraced_braced_expr!() }]; } + fn repeat_31() { [(); { braced_braced_expr!() }]; } + fn repeat_32() { [(); unbraced_expr!()]; } + fn repeat_33() { [(); braced_expr!()]; } + fn repeat_34() { [(); { unbraced_expr!() }]; } + fn repeat_35() { [(); { braced_expr!() }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure!()] } + fn repeat_37() { [(); { closure!() }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty!()] } + fn repeat_39() { [(); { empty!() }] } +} + +#[rustfmt::skip] +mod repeat_brace_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident!{}]; } + fn repeat_1() { [(); braced_unbraced_ident!{}]; } + fn repeat_2() { [(); unbraced_braced_ident!{}]; } + fn repeat_3() { [(); braced_braced_ident!{}]; } + fn repeat_4() { [(); { unbraced_unbraced_ident!{} }]; } + fn repeat_5() { [(); { braced_unbraced_ident!{} }]; } + fn repeat_6() { [(); { unbraced_braced_ident!{} }]; } + fn repeat_7() { [(); { braced_braced_ident!{} }]; } + fn repeat_8() { [(); unbraced_ident!{}]; } + fn repeat_9() { [(); braced_ident!{}]; } + fn repeat_10() { [(); { unbraced_ident!{} }]; } + fn repeat_11() { [(); { braced_ident!{} }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12<const ident: usize>() { [(); unbraced_unbraced_ident!{}]; } + fn repeat_13<const ident: usize>() { [(); braced_unbraced_ident!{}]; } + fn repeat_14<const ident: usize>() { [(); unbraced_braced_ident!{}]; } + fn repeat_15<const ident: usize>() { [(); braced_braced_ident!{}]; } + fn repeat_16<const ident: usize>() { [(); { unbraced_unbraced_ident!{} }]; } + fn repeat_17<const ident: usize>() { [(); { braced_unbraced_ident!{} }]; } + fn repeat_18<const ident: usize>() { [(); { unbraced_braced_ident!{} }]; } + fn repeat_19<const ident: usize>() { [(); { braced_braced_ident!{} }]; } + fn repeat_20<const ident: usize>() { [(); unbraced_ident!{}]; } + fn repeat_21<const ident: usize>() { [(); braced_ident!{}]; } + fn repeat_22<const ident: usize>() { [(); { unbraced_ident!{} }]; } + fn repeat_23<const ident: usize>() { [(); { braced_ident!{} }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr!{}]; } + fn repeat_25() { [(); braced_unbraced_expr!{}]; } + fn repeat_26() { [(); unbraced_braced_expr!{}]; } + fn repeat_27() { [(); braced_braced_expr!{}]; } + fn repeat_28() { [(); { unbraced_unbraced_expr!{} }]; } + fn repeat_29() { [(); { braced_unbraced_expr!{} }]; } + fn repeat_30() { [(); { unbraced_braced_expr!{} }]; } + fn repeat_31() { [(); { braced_braced_expr!{} }]; } + fn repeat_32() { [(); unbraced_expr!{}]; } + fn repeat_33() { [(); braced_expr!{}]; } + fn repeat_34() { [(); { unbraced_expr!{} }]; } + fn repeat_35() { [(); { braced_expr!{} }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure!{}] } + fn repeat_37() { [(); { closure!{} }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty!{}] } + fn repeat_39() { [(); { empty!{} }] } +} + +#[rustfmt::skip] +mod repeat_square_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident![]]; } + fn repeat_1() { [(); braced_unbraced_ident![]]; } + fn repeat_2() { [(); unbraced_braced_ident![]]; } + fn repeat_3() { [(); braced_braced_ident![]]; } + fn repeat_4() { [(); { unbraced_unbraced_ident![] }]; } + fn repeat_5() { [(); { braced_unbraced_ident![] }]; } + fn repeat_6() { [(); { unbraced_braced_ident![] }]; } + fn repeat_7() { [(); { braced_braced_ident![] }]; } + fn repeat_8() { [(); unbraced_ident![]]; } + fn repeat_9() { [(); braced_ident![]]; } + fn repeat_10() { [(); { unbraced_ident![] }]; } + fn repeat_11() { [(); { braced_ident![] }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12<const ident: usize>() { [(); unbraced_unbraced_ident![]]; } + fn repeat_13<const ident: usize>() { [(); braced_unbraced_ident![]]; } + fn repeat_14<const ident: usize>() { [(); unbraced_braced_ident![]]; } + fn repeat_15<const ident: usize>() { [(); braced_braced_ident![]]; } + fn repeat_16<const ident: usize>() { [(); { unbraced_unbraced_ident![] }]; } + fn repeat_17<const ident: usize>() { [(); { braced_unbraced_ident![] }]; } + fn repeat_18<const ident: usize>() { [(); { unbraced_braced_ident![] }]; } + fn repeat_19<const ident: usize>() { [(); { braced_braced_ident![] }]; } + fn repeat_20<const ident: usize>() { [(); unbraced_ident![]]; } + fn repeat_21<const ident: usize>() { [(); braced_ident![]]; } + fn repeat_22<const ident: usize>() { [(); { unbraced_ident![] }]; } + fn repeat_23<const ident: usize>() { [(); { braced_ident![] }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr![]]; } + fn repeat_25() { [(); braced_unbraced_expr![]]; } + fn repeat_26() { [(); unbraced_braced_expr![]]; } + fn repeat_27() { [(); braced_braced_expr![]]; } + fn repeat_28() { [(); { unbraced_unbraced_expr![] }]; } + fn repeat_29() { [(); { braced_unbraced_expr![] }]; } + fn repeat_30() { [(); { unbraced_braced_expr![] }]; } + fn repeat_31() { [(); { braced_braced_expr![] }]; } + fn repeat_32() { [(); unbraced_expr![]]; } + fn repeat_33() { [(); braced_expr![]]; } + fn repeat_34() { [(); { unbraced_expr![] }]; } + fn repeat_35() { [(); { braced_expr![] }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure![]] } + fn repeat_37() { [(); { closure![] }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty![]] } + fn repeat_39() { [(); { empty![] }] } } fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs new file mode 100644 index 00000000000..fb6190324c6 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs @@ -0,0 +1,46 @@ +// Additional checks for macro expansion in const args + +//@ check-pass + +macro_rules! closure { + () => { |()| () }; +} + +macro_rules! indir_semi { + ($nested:ident) => { $nested!(); }; +} + +macro_rules! indir { + ($nested:ident) => { $nested!() }; +} + +macro_rules! empty { + () => {}; +} + +macro_rules! arg { + () => { N }; +} + +struct Adt<const N: usize>; + +fn array1() -> [(); { closure!(); 0 }] { loop {} } +fn array2() -> [(); { indir!(closure); 0}] { loop {} } +fn array3() -> [(); { indir_semi!{ closure } 0 }] { loop {} } +fn array4<const N: usize>() -> [(); { indir!{ empty } arg!{} }] { loop {} } +fn array5<const N: usize>() -> [(); { empty!{} arg!() }] { loop {} } +fn array6<const N: usize>() -> [(); { empty!{} N }] { loop {} } +fn array7<const N: usize>() -> [(); { arg!{} empty!{} }] { loop {} } +fn array8<const N: usize>() -> [(); { empty!{} arg!{} empty!{} }] { loop {} } + +fn adt1() -> Adt<{ closure!(); 0 }> { loop {} } +fn adt2() -> Adt<{ indir!(closure); 0}> { loop {} } +fn adt3() -> Adt<{ indir_semi!{ closure } 0 }> { loop {} } +fn adt4<const N: usize>() -> Adt<{ indir!{ empty } arg!{} }> { loop {} } +fn adt5<const N: usize>() -> Adt<{ empty!{} arg!() }> { loop {} } +fn adt6<const N: usize>() -> Adt<{ empty!{} N }> { loop {} } +fn adt7<const N: usize>() -> Adt<{ arg!{} empty!{} }> { loop {} } +fn adt8<const N: usize>() -> Adt<{ empty!{} arg!{} empty!{} }> { loop {} } + + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs new file mode 100644 index 00000000000..3353d6cf2da --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs @@ -0,0 +1,18 @@ +macro_rules! empty { + () => {}; +} + +macro_rules! arg { + () => { + N + //~^ ERROR generic parameters may not be used in const operations + //~| ERROR generic parameters may not be used in const operations + }; +} + +struct Foo<const N: usize>; +fn foo<const N: usize>() -> Foo<{ arg!{} arg!{} }> { loop {} } +fn bar<const N: usize>() -> [(); { empty!{}; N }] { loop {} } +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr new file mode 100644 index 00000000000..4722968b203 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr @@ -0,0 +1,37 @@ +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 + | +LL | N + | ^ cannot perform const operation using `N` +... +LL | fn foo<const N: usize>() -> Foo<{ arg!{} arg!{} }> { loop {} } + | ------ in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 + | +LL | N + | ^ cannot perform const operation using `N` +... +LL | fn foo<const N: usize>() -> Foo<{ arg!{} arg!{} }> { loop {} } + | ------ in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:15:46 + | +LL | fn bar<const N: usize>() -> [(); { empty!{}; N }] { loop {} } + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs new file mode 100644 index 00000000000..c1f725db126 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs @@ -0,0 +1,12 @@ +//@ check-pass + +#![feature(generic_arg_infer)] +#![crate_type = "lib"] + +// Test that encoding the hallucinated `DefId` for the `_` const argument doesn't +// ICE (see #133468). This requires this to be a library crate. + +pub fn foo() { + let s: [u8; 10]; + s = [0; _]; +} diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 30a45ce377e..4eb374b2020 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,6 +72,20 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | +note: erroneous constant encountered + --> $DIR/unevaluated-const-ice-119731.rs:22:19 + | +LL | impl v17<512, v0> { + | ^^ + +note: erroneous constant encountered + --> $DIR/unevaluated-const-ice-119731.rs:22:19 + | +LL | impl v17<512, v0> { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:28:37 | diff --git a/tests/crashes/128176.rs b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs index 970ad9ff2cd..d163238c6d5 100644 --- a/tests/crashes/128176.rs +++ b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs @@ -1,7 +1,11 @@ -//@ known-bug: rust-lang/rust#128176 +//@ check-pass + +// Regression test for #128176. #![feature(generic_const_exprs)] #![feature(dyn_compatible_for_dispatch)] +#![allow(incomplete_features)] + trait X { type Y<const N: i16>; } diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr index c3292314f23..6b62012c14f 100644 --- a/tests/ui/const-generics/issues/issue-83765.stderr +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -10,11 +10,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>` - --> $DIR/issue-83765.rs:4:1 +note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:50:1: 50:94>::size` is compatible with trait definition + --> $DIR/issue-83765.rs:51:5 | -LL | trait TensorDimension { - | ^^^^^^^^^^^^^^^^^^^^^ +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM` @@ -29,11 +29,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking that `<impl at $DIR/issue-83765.rs:56:1: 56:97>` is well-formed - --> $DIR/issue-83765.rs:56:1 +note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:56:1: 56:97>::bget` is compatible with trait definition + --> $DIR/issue-83765.rs:58:5 | -LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0308]: method not compatible with trait diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index b2b2f62c58f..0931eff2175 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `UnconstDrop: const Destruct` is not satisfied - --> $DIR/const-block-const-bound.rs:18:9 + --> $DIR/const-block-const-bound.rs:18:11 | LL | f(UnconstDrop); - | ^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/const-block-const-bound.rs:8:15 + | +LL | const fn f<T: ~const Destruct>(x: T) {} + | ^^^^^^ required by this bound in `f` error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval-fail-too-big.rs b/tests/ui/consts/const-eval-fail-too-big.rs new file mode 100644 index 00000000000..4b5dbc1d7a4 --- /dev/null +++ b/tests/ui/consts/const-eval-fail-too-big.rs @@ -0,0 +1,12 @@ +//Error output test for #78834: Type is too big for the target architecture +struct B< + A: Sized = [(); { + let x = [0u8; !0usize]; + //~^ ERROR evaluation of constant value failed + 1 + }], +> { + a: A, +} + +fn main() {} diff --git a/tests/ui/consts/const-eval-fail-too-big.stderr b/tests/ui/consts/const-eval-fail-too-big.stderr new file mode 100644 index 00000000000..ae666483233 --- /dev/null +++ b/tests/ui/consts/const-eval-fail-too-big.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-fail-too-big.rs:4:28 + | +LL | let x = [0u8; !0usize]; + | ^^^^^^^^^^^^^^ values of the type `[u8; usize::MAX]` are too big for the target architecture + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs index 42061ef0670..b7151782423 100644 --- a/tests/ui/consts/const-fn-error.rs +++ b/tests/ui/consts/const-fn-error.rs @@ -3,9 +3,8 @@ const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; for i in 0..x { - //~^ ERROR cannot convert - //~| ERROR `for` is not allowed in a `const fn` - //~| ERROR cannot call non-const fn + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` sum += i; } sum diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index 42a6f2704c9..3d4cf6539c8 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -1,37 +1,20 @@ -error[E0658]: `for` is not allowed in a `const fn` - --> $DIR/const-fn-error.rs:5:5 - | -LL | / for i in 0..x { -LL | | -LL | | -LL | | -LL | | sum += i; -LL | | } - | |_____^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<usize>` into an iterator in constant functions +error[E0015]: cannot use `for` loop on `std::ops::Range<usize>` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<std::ops::Range<usize> as Iterator>::next` in constant functions +error[E0015]: cannot use `for` loop on `std::ops::Range<usize>` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index d74178662b3..b643e63c096 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -2,9 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ error: `for` is not allowed in a `const` - //~| ERROR: cannot convert - //~| ERROR: cannot call + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 6e099a3159d..29db5d24ac8 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -1,32 +1,20 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/const-for-feature-gate.rs:4:5 - | -LL | for _ in 0..5 {} - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index 4f8034e73f0..6f7895457c5 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -2,8 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ error: cannot call - //~| error: cannot convert + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 78336dc93e8..d1308a8dedc 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -1,20 +1,19 @@ -error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr index 4e503e5a5c0..d58a8e93ff6 100644 --- a/tests/ui/consts/const-integer-bool-ops.stderr +++ b/tests/ui/consts/const-integer-bool-ops.stderr @@ -16,6 +16,12 @@ error[E0308]: mismatched types LL | const X: usize = 42 && 39; | ^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:8:18 + | +LL | const ARR: [i32; X] = [99; 34]; + | ^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:10:19 | @@ -34,6 +40,12 @@ error[E0308]: mismatched types LL | const X1: usize = 42 || 39; | ^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:17:19 + | +LL | const ARR1: [i32; X1] = [99; 47]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:19:19 | @@ -52,6 +64,12 @@ error[E0308]: mismatched types LL | const X2: usize = -42 || -39; | ^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:26:19 + | +LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:28:19 | @@ -70,42 +88,84 @@ error[E0308]: mismatched types LL | const X3: usize = -42 && -39; | ^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:35:19 + | +LL | const ARR3: [i32; X3] = [99; 6]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:37:18 | LL | const Y: usize = 42.0 == 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:40:19 + | +LL | const ARRR: [i32; Y] = [99; 1]; + | ^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:42:19 | LL | const Y1: usize = 42.0 >= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:45:20 + | +LL | const ARRR1: [i32; Y1] = [99; 1]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:47:19 | LL | const Y2: usize = 42.0 <= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:50:20 + | +LL | const ARRR2: [i32; Y2] = [99; 1]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:52:19 | LL | const Y3: usize = 42.0 > 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:55:20 + | +LL | const ARRR3: [i32; Y3] = [99; 0]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:57:19 | LL | const Y4: usize = 42.0 < 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:60:20 + | +LL | const ARRR4: [i32; Y4] = [99; 0]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:62:19 | LL | const Y5: usize = 42.0 != 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:65:20 + | +LL | const ARRR5: [i32; Y5] = [99; 0]; + | ^^ + error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr index aff86e83578..a63be676fda 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.stderr +++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr @@ -4,6 +4,12 @@ error[E0764]: mutable references are not allowed in the final value of constants LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/issue-76510.rs:7:70 + | +LL | let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3)); + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0764`. diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs index 4df3a793b4c..598904d3c44 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -1,6 +1,5 @@ #![feature(extern_types)] #![feature(core_intrinsics)] -#![feature(const_size_of_val, const_align_of_val)] use std::intrinsics::{min_align_of_val, size_of_val}; diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index ad2de0f4d31..4c0252123a4 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout error[E0080]: evaluation of constant value failed - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:32 | LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout diff --git a/tests/ui/consts/const-size_of_val-align_of_val.rs b/tests/ui/consts/const-size_of_val-align_of_val.rs index ee9dfca0170..d4b5a903517 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val.rs @@ -1,7 +1,6 @@ //@ run-pass -#![feature(const_size_of_val, const_align_of_val)] -#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)] +#![feature(layout_for_ptr)] use std::{mem, ptr}; diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs index 1cc045bf612..09985079e8e 100644 --- a/tests/ui/consts/const-try-feature-gate.rs +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -2,9 +2,8 @@ const fn t() -> Option<()> { Some(())?; - //~^ error: `?` is not allowed in a `const fn` - //~| ERROR: cannot convert - //~| ERROR: cannot determine + //~^ ERROR `?` is not allowed + //~| ERROR `?` is not allowed None } diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index dc1dabc2f4f..0ad19d05b38 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/const-try-feature-gate.rs:4:5 | LL | Some(())?; | ^^^^^^^^^ | - = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions - --> $DIR/const-try-feature-gate.rs:4:5 - | -LL | Some(())?; - | ^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/const-try-feature-gate.rs:4:5 | LL | Some(())?; | ^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index d30b22accef..26aa9230a39 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -33,8 +33,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; - //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions - //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on TryMe } diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index 1f4f814cb93..abb03a74c82 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -16,7 +16,7 @@ LL | impl const Try for TryMe { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/const-try.rs:35:5 | LL | TryMe?; @@ -24,7 +24,7 @@ LL | TryMe?; | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/const-try.rs:35:5 | LL | TryMe?; diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr index 792e18aa8fd..2a3f0cfb06d 100644 --- a/tests/ui/consts/const-tup-index-span.stderr +++ b/tests/ui/consts/const-tup-index-span.stderr @@ -11,6 +11,12 @@ help: use a trailing comma to create a tuple with one element LL | const TUP: (usize,) = (5usize << 64,); | + ++ +note: erroneous constant encountered + --> $DIR/const-tup-index-span.rs:6:18 + | +LL | const ARR: [i32; TUP.0] = []; + | ^^^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index 6add83dc52c..c778299560f 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `T: const Tr` is not satisfied --> $DIR/constifconst-call-in-const-position.rs:17:38 | LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] { - | ^^^^^^ + | ^ error[E0277]: the trait bound `T: const Tr` is not satisfied --> $DIR/constifconst-call-in-const-position.rs:18:9 | LL | [0; T::a()] - | ^^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index f8d9f3ddb9b..b02c31c4c25 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -50,15 +50,15 @@ const _: i32 = { const _: i32 = { let mut x = 0; - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR: cannot call - //~| ERROR: cannot convert + for i in 0..4 { + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR: cannot call - //~| ERROR: cannot convert + for i in 0..4 { + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 5e43c70e9df..b91371f9dc2 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -1,68 +1,37 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:53:5 - | -LL | / for i in 0..4 { -LL | | -LL | | -LL | | x += i; -LL | | } - | |_____^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:59:5 - | -LL | / for i in 0..4 { -LL | | -LL | | -LL | | x += i; -LL | | } - | |_____^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs index 5c6957df405..67083e1a39b 100644 --- a/tests/ui/consts/control-flow/try.rs +++ b/tests/ui/consts/control-flow/try.rs @@ -3,9 +3,9 @@ const fn opt() -> Option<i32> { let x = Some(2); - x?; //~ ERROR `?` is not allowed in a `const fn` - //~^ ERROR: cannot convert - //~| ERROR: cannot determine + x?; + //~^ ERROR: `?` is not allowed + //~| ERROR: `?` is not allowed None } diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index 5e2c77318e7..62a3e3ce6bc 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option<i32>` in constant functions --> $DIR/try.rs:6:5 | LL | x?; | ^^ | - = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<i32>` in constant functions - --> $DIR/try.rs:6:5 - | -LL | x?; - | ^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<i32>` in constant functions +error[E0015]: `?` is not allowed on `Option<i32>` in constant functions --> $DIR/try.rs:6:5 | LL | x?; | ^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 10850021713..11e13c3efdd 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -121,34 +121,89 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:70:24 + --> $DIR/fn_trait_refs.rs:70:32 | LL | let test_one = test_fn(one); - | ^^^^^^^^^^^^ + | ------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `test_fn` + --> $DIR/fn_trait_refs.rs:35:24 + | +LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output) + | ------- required by a bound in this function +LL | where +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ required by this bound in `test_fn` error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:73:24 + --> $DIR/fn_trait_refs.rs:73:36 | LL | let test_two = test_fn_mut(two); - | ^^^^^^^^^^^^^^^^ + | ----------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `test_fn_mut` + --> $DIR/fn_trait_refs.rs:49:27 + | +LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output) + | ----------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `test_fn_mut` error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:39:9 + --> $DIR/fn_trait_refs.rs:39:19 | LL | tester_fn(&f), - | ^^^^^^^^^^^^^ + | --------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn` + --> $DIR/fn_trait_refs.rs:14:24 + | +LL | const fn tester_fn<T>(f: T) -> T::Output + | --------- required by a bound in this function +LL | where +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn` error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:41:9 + --> $DIR/fn_trait_refs.rs:41:23 | LL | tester_fn_mut(&f), - | ^^^^^^^^^^^^^^^^^ + | ------------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn_mut` + --> $DIR/fn_trait_refs.rs:21:27 + | +LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output + | ------------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn_mut` error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:53:9 + --> $DIR/fn_trait_refs.rs:53:23 | LL | tester_fn_mut(&mut f), - | ^^^^^^^^^^^^^^^^^^^^^ + | ------------- ^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn_mut` + --> $DIR/fn_trait_refs.rs:21:27 + | +LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output + | ------------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn_mut` error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:16:5 diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 52d3e003f0a..8a7a0981f41 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr index b8c983eb7b8..ed6aa9c44a3 100644 --- a/tests/ui/consts/issue-54954.stderr +++ b/tests/ui/consts/issue-54954.stderr @@ -19,6 +19,24 @@ LL | | core::mem::size_of::<T>() LL | | } | |_____- `Tt::const_val` defined here +note: erroneous constant encountered + --> $DIR/issue-54954.rs:11:15 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-54954.rs:11:34 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-54954.rs:16:22 + | +LL | let _ = f([1f32; ARR_LEN]); + | ^^^^^^^ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0379, E0790. diff --git a/tests/ui/consts/missing_assoc_const_type2.stderr b/tests/ui/consts/missing_assoc_const_type2.stderr index 1255ca2d102..3279a077464 100644 --- a/tests/ui/consts/missing_assoc_const_type2.stderr +++ b/tests/ui/consts/missing_assoc_const_type2.stderr @@ -4,5 +4,11 @@ error: missing type for `const` item LL | const FIRST: = 10; | ^ help: provide a type for the associated constant: `u8` +note: erroneous constant encountered + --> $DIR/missing_assoc_const_type2.rs:18:5 + | +LL | TwoDigits::FIRST as usize + | ^^^^^^^^^^^^^^^^ + error: aborting due to 1 previous error diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index ea457c96f15..703cc7fbf89 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Z ui-testing=no -#![feature(const_swap)] +#![feature(const_swap_nonoverlapping)] use std::{ mem::{self, MaybeUninit}, ptr, diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr index 50e920f05f9..f5d767efceb 100644 --- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr +++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr @@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); | ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler -note: erroneous constant encountered - --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26 - | -LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/promoted_size_overflow.rs b/tests/ui/consts/promoted_size_overflow.rs new file mode 100644 index 00000000000..3d606905e78 --- /dev/null +++ b/tests/ui/consts/promoted_size_overflow.rs @@ -0,0 +1,7 @@ +//@ only-64bit +pub struct Data([u8; usize::MAX >> 2]); +const _: &'static [Data] = &[]; +//~^ERROR: evaluation of constant value failed +//~| too big for the target architecture + +fn main() {} diff --git a/tests/ui/consts/promoted_size_overflow.stderr b/tests/ui/consts/promoted_size_overflow.stderr new file mode 100644 index 00000000000..cfb8260bed0 --- /dev/null +++ b/tests/ui/consts/promoted_size_overflow.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/promoted_size_overflow.rs:3:29 + | +LL | const _: &'static [Data] = &[]; + | ^^ values of the type `[u8; 4611686018427387903]` are too big for the target architecture + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index 40d96ed3a10..fc37039d260 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,44 +4,36 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions +error[E0015]: `?` is not allowed on `Result<(), ()>` in constant functions --> $DIR/try-operator.rs:10:9 | LL | Err(())?; | ^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Result<bool, ()>` in constant functions +error[E0015]: `?` is not allowed on `Result<bool, ()>` in constant functions --> $DIR/try-operator.rs:10:9 | LL | Err(())?; | ^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | LL | None?; | ^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | LL | None?; | ^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 5 previous errors diff --git a/tests/ui/consts/uninhabited-const-issue-61744.rs b/tests/ui/consts/uninhabited-const-issue-61744.rs index 6168268bfed..19ee842c36b 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.rs +++ b/tests/ui/consts/uninhabited-const-issue-61744.rs @@ -5,15 +5,15 @@ pub const unsafe fn fake_type<T>() -> T { } pub const unsafe fn hint_unreachable() -> ! { - fake_type() + fake_type() //~ inside } trait Const { - const CONSTANT: i32 = unsafe { fake_type() }; + const CONSTANT: i32 = unsafe { fake_type() }; //~ inside } impl<T> Const for T {} pub fn main() -> () { - dbg!(i32::CONSTANT); //~ constant + dbg!(i32::CONSTANT); } diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr index c6dd11ee5db..7575ad730b3 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.stderr +++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr @@ -645,20 +645,6 @@ note: inside `<i32 as Const>::CONSTANT` LL | const CONSTANT: i32 = unsafe { fake_type() }; | ^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/uninhabited-const-issue-61744.rs:18:10 - | -LL | dbg!(i32::CONSTANT); - | ^^^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/uninhabited-const-issue-61744.rs:18:10 - | -LL | dbg!(i32::CONSTANT); - | ^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs index aee920e9773..f85e4a52e9b 100644 --- a/tests/ui/coroutine/async-gen-deduce-yield.rs +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 -Zunstable-options +//@ compile-flags: --edition 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 62b9bafcd60..3875e26b544 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 -Zunstable-options +//@ compile-flags: --edition 2024 //@ check-pass #![feature(async_iterator, gen_blocks, noop_waker)] diff --git a/tests/ui/crate-loading/auxiliary/proc-macro.rs b/tests/ui/crate-loading/auxiliary/proc-macro.rs index ad227c069d2..a87a2b243a1 100644 --- a/tests/ui/crate-loading/auxiliary/proc-macro.rs +++ b/tests/ui/crate-loading/auxiliary/proc-macro.rs @@ -1,7 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic #![crate_name = "reproduction"] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/crate-loading/cross-compiled-proc-macro.rs b/tests/ui/crate-loading/cross-compiled-proc-macro.rs index 51431c05865..b727f22e188 100644 --- a/tests/ui/crate-loading/cross-compiled-proc-macro.rs +++ b/tests/ui/crate-loading/cross-compiled-proc-macro.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ compile-flags:--extern reproduction -//@ aux-build:proc-macro.rs +//@ proc-macro: proc-macro.rs //@ check-pass reproduction::mac!(); diff --git a/tests/ui/derives/auxiliary/derive-marker-tricky.rs b/tests/ui/derives/auxiliary/derive-marker-tricky.rs index 0f1c30811a2..f31baa43c3d 100644 --- a/tests/ui/derives/auxiliary/derive-marker-tricky.rs +++ b/tests/ui/derives/auxiliary/derive-marker-tricky.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/derives/derive-marker-tricky.rs b/tests/ui/derives/derive-marker-tricky.rs index ad03b6c2cd2..3831bd48581 100644 --- a/tests/ui/derives/derive-marker-tricky.rs +++ b/tests/ui/derives/derive-marker-tricky.rs @@ -2,7 +2,7 @@ // a built-in derive in non-trivial scope (e.g. in a nested module). //@ check-pass -//@ aux-build:derive-marker-tricky.rs +//@ proc-macro: derive-marker-tricky.rs extern crate derive_marker_tricky; diff --git a/tests/ui/deriving/auxiliary/another-proc-macro.rs b/tests/ui/deriving/auxiliary/another-proc-macro.rs index c992cde4066..47f3c5b9c4b 100644 --- a/tests/ui/deriving/auxiliary/another-proc-macro.rs +++ b/tests/ui/deriving/auxiliary/another-proc-macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs index 6c473aefc5b..e67197b7e20 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.rs +++ b/tests/ui/deriving/built-in-proc-macro-scope.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout index 07767dc229f..db97c7145ea 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.stdout +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -1,7 +1,7 @@ #![feature(prelude_import)] #![no_std] //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.rs b/tests/ui/deriving/proc-macro-attribute-mixing.rs index 80a0d068ce7..2c11c3f72ca 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.rs +++ b/tests/ui/deriving/proc-macro-attribute-mixing.rs @@ -5,7 +5,7 @@ // are in scope. //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout index 03128c6c957..ad743d013d2 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.stdout +++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout @@ -7,7 +7,7 @@ // are in scope. //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs b/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs index 4edae48923a..3fe84317d70 100644 --- a/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs +++ b/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs index 014ec46f1b9..55b6b0ab441 100644 --- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs +++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:proc-macro-helper.rs +//@ proc-macro: proc-macro-helper.rs extern crate proc_macro_helper; diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 7a999c7c330..d1a5b9bc5e2 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -2,7 +2,6 @@ //@ compile-flags: -Z validate-mir //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] edition: 2024 #![feature(let_chains)] diff --git a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr index 48b7f3e11a6..7f9a0159950 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr @@ -1,5 +1,5 @@ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:27:8 + --> $DIR/lint-if-let-rescope-gated.rs:26:8 | LL | if let Some(_value) = Droppy.get() { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -9,12 +9,12 @@ LL | if let Some(_value) = Droppy.get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:31:5 + --> $DIR/lint-if-let-rescope-gated.rs:30:5 | LL | } else { | ^ note: the lint level is defined here - --> $DIR/lint-if-let-rescope-gated.rs:11:9 + --> $DIR/lint-if-let-rescope-gated.rs:10:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index ba0246573b4..f5538a37eef 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -5,7 +5,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] check-pass #![deny(if_let_rescope)] diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index fec2e3b2ae7..182190aa323 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -14,7 +14,7 @@ impl Drop for Droppy { } } impl Droppy { - fn get(&self) -> Option<u8> { + const fn get(&self) -> Option<u8> { None } } @@ -62,11 +62,10 @@ fn main() { //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } - if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { - //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: the value is now dropped here in Edition 2024 - //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + if let () = { if let Some(_value) = Droppy.get() {} } { + // This should not lint. + // This `if let` sits is a tail expression of a block. + // In Edition 2024, the temporaries are dropped before exiting the surrounding block. } #[rustfmt::skip] @@ -94,4 +93,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + // We want to keep the `if let`s below as direct descendents of match arms, + // so the formatting is suppressed. + #[rustfmt::skip] + match droppy().get() { + _ => if let Some(_value) = droppy().get() {}, + // Should not lint + // There is implicitly a block surrounding the `if let`. + // Given that it is a tail expression, the temporaries are dropped duly before + // the execution is exiting the `match`. + } + + if let Some(_value) = droppy().get() {} } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index ee184695b97..e1b38be0a0f 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -14,7 +14,7 @@ impl Drop for Droppy { } } impl Droppy { - fn get(&self) -> Option<u8> { + const fn get(&self) -> Option<u8> { None } } @@ -63,10 +63,9 @@ fn main() { } if let () = { if let Some(_value) = Droppy.get() {} } { - //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: the value is now dropped here in Edition 2024 - //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + // This should not lint. + // This `if let` sits is a tail expression of a block. + // In Edition 2024, the temporaries are dropped before exiting the surrounding block. } #[rustfmt::skip] @@ -94,4 +93,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + // We want to keep the `if let`s below as direct descendents of match arms, + // so the formatting is suppressed. + #[rustfmt::skip] + match droppy().get() { + _ => if let Some(_value) = droppy().get() {}, + // Should not lint + // There is implicitly a block surrounding the `if let`. + // Given that it is a tail expression, the temporaries are dropped duly before + // the execution is exiting the `match`. + } + + if let Some(_value) = droppy().get() {} } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index ef60d141b79..cfb7070c097 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -112,27 +112,7 @@ LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ = | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:65:22 - | -LL | if let () = { if let Some(_value) = Droppy.get() {} } { - | ^^^^^^^^^^^^^^^^^^^------^^^^^^ - | | - | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> -help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:65:55 - | -LL | if let () = { if let Some(_value) = Droppy.get() {} } { - | ^ -help: a `match` with a single arm can preserve the drop order up to Edition 2021 - | -LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { - | ~~~~~ +++++++++++++++++ ++++++++ - -error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:73:12 + --> $DIR/lint-if-let-rescope.rs:72:12 | LL | if (if let Some(_value) = droppy().get() { true } else { false }) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -142,7 +122,7 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:73:53 + --> $DIR/lint-if-let-rescope.rs:72:53 | LL | if (if let Some(_value) = droppy().get() { true } else { false }) { | ^ @@ -152,7 +132,7 @@ LL | if (match droppy().get() { Some(_value) => { true } _ => { false }}) { | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:79:21 + --> $DIR/lint-if-let-rescope.rs:78:21 | LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -162,7 +142,7 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:79:62 + --> $DIR/lint-if-let-rescope.rs:78:62 | LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) { | ^ @@ -172,7 +152,7 @@ LL | } else if (((match droppy().get() { Some(_value) => { true } _ => { fal | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:91:15 + --> $DIR/lint-if-let-rescope.rs:90:15 | LL | while (if let Some(_value) = droppy().get() { false } else { true }) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -182,7 +162,7 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:91:57 + --> $DIR/lint-if-let-rescope.rs:90:57 | LL | while (if let Some(_value) = droppy().get() { false } else { true }) { | ^ @@ -191,5 +171,5 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021 LL | while (match droppy().get() { Some(_value) => { false } _ => { true }}) { | ~~~~~ +++++++++++++++++ ~~~~ + -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr index bcce796570e..2c0b238eb5f 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr +++ b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/tail-expr-drop-order-negative.rs:9:15 + --> $DIR/tail-expr-drop-order-negative.rs:8:15 | LL | x.replace(std::cell::RefCell::new(123).borrow()).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement diff --git a/tests/ui/drop/tail-expr-drop-order-negative.rs b/tests/ui/drop/tail-expr-drop-order-negative.rs index 5ad04d0a67e..3b20691f8ea 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.rs +++ b/tests/ui/drop/tail-expr-drop-order-negative.rs @@ -1,5 +1,4 @@ //@ revisions: edition2021 edition2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ [edition2021] check-pass diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs index c83be544c0a..21f7fd92e80 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.rs +++ b/tests/ui/dyn-compatibility/missing-assoc-type.rs @@ -3,8 +3,5 @@ trait Foo { } fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` cannot be made into an object -//~^ ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object fn main() {} diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr index f8450ba212d..184201dd1ce 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.stderr +++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr @@ -13,53 +13,6 @@ LL | type Bar<T>; | ^^^ ...because it contains the generic associated type `Bar` = help: consider moving `Bar` to another trait -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:16 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar<T>; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:16 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar<T>; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:12 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar<T>; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 75bc598d17b..91d30de74c7 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass //@[e2021] run-rustfix diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 454e88d4569..6fdb548c431 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -1,5 +1,5 @@ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:17:1 + --> $DIR/never-type-fallback-breaking.rs:16:1 | LL | fn m() { | ^^^^^^ @@ -8,7 +8,7 @@ LL | fn m() { = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:21:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let x: () = match true { | ++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:29:1 + --> $DIR/never-type-fallback-breaking.rs:28:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | fn q() -> Option<()> { = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:36:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | deserialize::<()>()?; | ++++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:46:1 + --> $DIR/never-type-fallback-breaking.rs:45:1 | LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | fn meow() -> Result<(), ()> { = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> = help: specify the types explicitly note: in edition 2024, the requirement `(): From<!>` will fail - --> $DIR/never-type-fallback-breaking.rs:49:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 6258247f8b2..9d79dfb4099 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:21:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ LL | true => Default::default(), = help: did you intend to use the type `()` here instead? error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:36:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,13 +16,13 @@ LL | deserialize()?; = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:32:23 + --> $DIR/never-type-fallback-breaking.rs:31:23 | LL | fn deserialize<T: Default>() -> Option<T> { | ^^^^^^^ required by this bound in `deserialize` error[E0277]: the trait bound `(): From<!>` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:49:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ the trait `From<!>` is not implemented for `()` @@ -39,7 +39,7 @@ LL | help(1)?; and 4 others = note: required for `!` to implement `Into<()>` note: required by a bound in `help` - --> $DIR/never-type-fallback-breaking.rs:43:20 + --> $DIR/never-type-fallback-breaking.rs:42:20 | LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result<T, ()> { | ^^^^^^^^ required by this bound in `help` diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 32e83e74139..24e33ff6bf6 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass //@[e2021] run-rustfix diff --git a/tests/ui/editions/never-type-fallback.rs b/tests/ui/editions/never-type-fallback.rs index a5b75219295..987fb305763 100644 --- a/tests/ui/editions/never-type-fallback.rs +++ b/tests/ui/editions/never-type-fallback.rs @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@ run-pass //@ check-run-results diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr index e81562df04f..9bf4fc79b1b 100644 --- a/tests/ui/enum-discriminant/issue-41394.stderr +++ b/tests/ui/enum-discriminant/issue-41394.stderr @@ -6,6 +6,12 @@ LL | A = "" + 1 | | | &str +note: erroneous constant encountered + --> $DIR/issue-41394.rs:7:9 + | +LL | A = Foo::A as isize + | ^^^^^^^^^^^^^^^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/enum-discriminant/ptr_niche.rs b/tests/ui/enum-discriminant/ptr_niche.rs new file mode 100644 index 00000000000..32df08bce63 --- /dev/null +++ b/tests/ui/enum-discriminant/ptr_niche.rs @@ -0,0 +1,38 @@ +//@ run-pass +//! Check that we can codegen setting and getting discriminants, including non-null niches, +//! for enums with a pointer-like ABI. This used to crash llvm. + +#![feature(rustc_attrs)] +use std::{ptr, mem}; + + +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_layout_scalar_valid_range_end(100)] +#[derive(Copy, Clone)] +struct PointerWithRange(#[allow(dead_code)] *const u8); + + +fn main() { + let val = unsafe { PointerWithRange(ptr::without_provenance(90)) }; + + let ptr = Some(val); + assert!(ptr.is_some()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert_eq!(raw, 90); + + let ptr = Some(Some(val)); + assert!(ptr.is_some()); + assert!(ptr.unwrap().is_some()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert_eq!(raw, 90); + + let ptr: Option<PointerWithRange> = None; + assert!(ptr.is_none()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert!(!(1..=100).contains(&raw)); + + let ptr: Option<Option<PointerWithRange>> = None; + assert!(ptr.is_none()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert!(!(1..=100).contains(&raw)); +} diff --git a/tests/ui/error-codes/E0045.stderr b/tests/ui/error-codes/E0045.stderr index 25b2f2654da..b8ee31a4049 100644 --- a/tests/ui/error-codes/E0045.stderr +++ b/tests/ui/error-codes/E0045.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/E0045.rs:1:17 | LL | extern "Rust" { fn foo(x: u8, ...); } diff --git a/tests/ui/error-codes/E0617.rs b/tests/ui/error-codes/E0617.rs index b71ba0ed88b..4a38174bc6f 100644 --- a/tests/ui/error-codes/E0617.rs +++ b/tests/ui/error-codes/E0617.rs @@ -20,7 +20,8 @@ fn main() { //~^ ERROR can't pass `u16` to variadic function //~| HELP cast the value to `c_uint` printf(::std::ptr::null(), printf); - //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function - //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` + //~^ ERROR can't pass a function item to a variadic function + //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + //~| HELP use a function pointer instead } } diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr index ea91ad08292..b2eee129960 100644 --- a/tests/ui/error-codes/E0617.stderr +++ b/tests/ui/error-codes/E0617.stderr @@ -2,42 +2,69 @@ error[E0617]: can't pass `f32` to variadic function --> $DIR/E0617.rs:7:36 | LL | printf(::std::ptr::null(), 0f32); - | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` + | ^^^^ + | +help: cast the value to `c_double` + | +LL | printf(::std::ptr::null(), 0f32 as c_double); + | +++++++++++ error[E0617]: can't pass `i8` to variadic function --> $DIR/E0617.rs:10:36 | LL | printf(::std::ptr::null(), 0i8); - | ^^^ help: cast the value to `c_int`: `0i8 as c_int` + | ^^^ + | +help: cast the value to `c_int` + | +LL | printf(::std::ptr::null(), 0i8 as c_int); + | ++++++++ error[E0617]: can't pass `i16` to variadic function --> $DIR/E0617.rs:13:36 | LL | printf(::std::ptr::null(), 0i16); - | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | printf(::std::ptr::null(), 0i16 as c_int); + | ++++++++ error[E0617]: can't pass `u8` to variadic function --> $DIR/E0617.rs:16:36 | LL | printf(::std::ptr::null(), 0u8); - | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` + | ^^^ + | +help: cast the value to `c_uint` + | +LL | printf(::std::ptr::null(), 0u8 as c_uint); + | +++++++++ error[E0617]: can't pass `u16` to variadic function --> $DIR/E0617.rs:19:36 | LL | printf(::std::ptr::null(), 0u16); - | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` + | ^^^^ + | +help: cast the value to `c_uint` + | +LL | printf(::std::ptr::null(), 0u16 as c_uint); + | +++++++++ -error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function +error[E0617]: can't pass a function item to a variadic function --> $DIR/E0617.rs:22:36 | LL | printf(::std::ptr::null(), printf); | ^^^^^^ | -help: cast the value to `unsafe extern "C" fn(*const i8, ...)` + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead | LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++++++++++++++++++++++++++++++ error: aborting due to 6 previous errors diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs index ae7378a707e..08c6d171296 100644 --- a/tests/ui/error-codes/E0622.rs +++ b/tests/ui/error-codes/E0622.rs @@ -1,6 +1,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { - pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr index c59776b211f..739ec984fc6 100644 --- a/tests/ui/error-codes/E0622.stderr +++ b/tests/ui/error-codes/E0622.stderr @@ -1,8 +1,8 @@ error[E0622]: intrinsic must be a function --> $DIR/E0622.rs:3:5 | -LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function +LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function error: aborting due to 1 previous error diff --git a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr index 4a1e50b4111..46769cdea8a 100644 --- a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr +++ b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr @@ -25,12 +25,6 @@ note: inside `ID_ED` LL | const ID_ED: u32 = rec_id(ORIGINAL); | ^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/ctfe-id-unlimited.rs:31:40 - | -LL | const ASSERT: () = assert!(ORIGINAL == ID_ED); - | ^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/extern/extern-types-field-offset.run.stderr b/tests/ui/extern/extern-types-field-offset.run.stderr index f1407398980..1b04b860db5 100644 --- a/tests/ui/extern/extern-types-field-offset.run.stderr +++ b/tests/ui/extern/extern-types-field-offset.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `Opaque` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.align.run.stderr b/tests/ui/extern/extern-types-size_of_val.align.run.stderr index faad1aa13fa..20c4d8785e8 100644 --- a/tests/ui/extern/extern-types-size_of_val.align.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.align.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.size.run.stderr b/tests/ui/extern/extern-types-size_of_val.size.run.stderr index faad1aa13fa..20c4d8785e8 100644 --- a/tests/ui/extern/extern-types-size_of_val.size.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.size.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs new file mode 100644 index 00000000000..db5d7aa06d2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs @@ -0,0 +1,7 @@ +//@ edition: 2021 + +fn test(_: impl async Fn()) {} +//~^ ERROR `async` trait bounds are unstable +//~| ERROR use of unstable library feature `async_closure` + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr new file mode 100644 index 00000000000..abc7e37c45f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr @@ -0,0 +1,24 @@ +error[E0658]: `async` trait bounds are unstable + --> $DIR/feature-gate-async-trait-bounds.rs:3:17 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^^ + | + = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use the desugared name of the async trait, such as `AsyncFn` + +error[E0658]: use of unstable library feature `async_closure` + --> $DIR/feature-gate-async-trait-bounds.rs:3:23 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^ + | + = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information + = help: add `#![feature(async_closure)]` 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 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs deleted file mode 100644 index 7842d44ac4f..00000000000 --- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This feature doesn't *currently* fire on any specific code; it's just a -// behavior change. Future changes might. -#[rustc_error] //~ the -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr deleted file mode 100644 index a5ab1b0d631..00000000000 --- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-generic_associated_types_extended.rs:3:1 - | -LL | #[rustc_error] - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` 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 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/fmt/auxiliary/format-string-proc-macro.rs b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs index 5c00c9c0800..f473fee0987 100644 --- a/tests/ui/fmt/auxiliary/format-string-proc-macro.rs +++ b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; diff --git a/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs b/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs index 3a0b7ba4666..8ba6fcc46d4 100644 --- a/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs +++ b/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs index 24531e4ece4..26d483e43ae 100644 --- a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs +++ b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-issue-106408.rs b/tests/ui/fmt/format-args-capture-issue-106408.rs index 7c29e37441c..10f944dd9ba 100644 --- a/tests/ui/fmt/format-args-capture-issue-106408.rs +++ b/tests/ui/fmt/format-args-capture-issue-106408.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.rs b/tests/ui/fmt/format-args-capture-macro-hygiene.rs index 2ef81f2cd42..21e445624a5 100644 --- a/tests/ui/fmt/format-args-capture-macro-hygiene.rs +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-expanded-string.rs b/tests/ui/fmt/format-expanded-string.rs index d9b96bdece3..1466dabd7f7 100644 --- a/tests/ui/fmt/format-expanded-string.rs +++ b/tests/ui/fmt/format-expanded-string.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/indoc-issue-106408.rs b/tests/ui/fmt/indoc-issue-106408.rs index 36e5c23a394..8c302e5b03a 100644 --- a/tests/ui/fmt/indoc-issue-106408.rs +++ b/tests/ui/fmt/indoc-issue-106408.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs //@ check-pass extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/respanned-literal-issue-106191.rs b/tests/ui/fmt/respanned-literal-issue-106191.rs index 0a127b1a0ca..39f09b6e63a 100644 --- a/tests/ui/fmt/respanned-literal-issue-106191.rs +++ b/tests/ui/fmt/respanned-literal-issue-106191.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs index 7cd32413001..8d815f6dc78 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -1,9 +1,4 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ known-bug: #133805 pub trait FromLendingIterator<A>: Sized { fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; @@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized { impl<A> FromLendingIterator<A> for Vec<A> { fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { - //[base]~^ impl has stricter let mut v = vec![]; while let Some(item) = iter.next() { v.push(item); @@ -32,7 +26,6 @@ pub trait LendingIterator { Self: for<'q> LendingIterator<Item<'q> = A>, { <B as FromLendingIterator<A>>::from_iter(self) - //[base]~^ ERROR: does not live long enough } } diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.stderr index b19280b45c2..84f5ed07bda 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/lending_iterator.rs:13:45 + --> $DIR/lending_iterator.rs:8:45 | LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; | ------------------------------------------------------------------------ definition of `from_iter` from trait @@ -8,7 +8,7 @@ LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` error: `Self` does not live long enough - --> $DIR/lending_iterator.rs:34:9 + --> $DIR/lending_iterator.rs:28:9 | LL | <B as FromLendingIterator<A>>::from_iter(self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs index f4b0dae0a91..0545d4d12bb 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -1,9 +1,4 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ known-bug: #133805 pub trait FromLendingIterator<A>: Sized { fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; @@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized { impl<A> FromLendingIterator<A> for Vec<A> { fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { - //[base]~^ impl has stricter let mut v = vec![]; while let Some(item) = iter.next() { v.push(item); diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr index 717d867057e..47c32a28aea 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/lending_iterator_2.rs:13:45 + --> $DIR/lending_iterator_2.rs:8:45 | LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; | ------------------------------------------------------------------------ definition of `from_iter` from trait diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs index 7eb0aabb333..cd759a73cf2 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,10 +1,6 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass +//@ check-fail #![feature(associated_type_defaults)] -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] trait Foo { type A<'a> where Self: 'a; @@ -24,12 +20,12 @@ impl<T> Foo for Fooer<T> { } fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} -//[base]~^ the trait `Foo` cannot be made into an object +//~^ the trait `Foo` cannot be made into an object fn main() { let foo = Fooer(5); f(Box::new(foo)); - //[base]~^ the trait `Foo` cannot be made into an object - //[base]~| the trait `Foo` cannot be made into an object + //~^ the trait `Foo` cannot be made into an object + //~| the trait `Foo` cannot be made into an object } diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr new file mode 100644 index 00000000000..b2176fa6de3 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr @@ -0,0 +1,58 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:22:17 + | +LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer<T> + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:28:5 + | +LL | f(Box::new(foo)); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer<T> + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:28:5 + | +LL | f(Box::new(foo)); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer<T> + = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs index 1596f401bbc..a48d9c37cd4 100644 --- a/tests/ui/generic-associated-types/issue-67510-pass.rs +++ b/tests/ui/generic-associated-types/issue-67510-pass.rs @@ -1,15 +1,10 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ check-fail trait X { type Y<'a>; } fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} -//[base]~^ ERROR the trait `X` cannot be made into an object +//~^ ERROR the trait `X` cannot be made into an object fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510-pass.stderr b/tests/ui/generic-associated-types/issue-67510-pass.stderr new file mode 100644 index 00000000000..5560cb0f64d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:7:23 + | +LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-67510-pass.rs:4:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs index cf26b65c85f..9e18c82c7f1 100644 --- a/tests/ui/generic-associated-types/issue-76535.rs +++ b/tests/ui/generic-associated-types/issue-76535.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - pub trait SubTrait {} pub trait SuperTrait { @@ -38,6 +33,6 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); //~^ ERROR missing generics for associated type - //[base]~^^ ERROR the trait - //[base]~| ERROR the trait + //~^^ ERROR the trait + //~| ERROR the trait } diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr new file mode 100644 index 00000000000..613ded6f1ef --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.stderr @@ -0,0 +1,55 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:34:33 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:4:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:34:14 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:4:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead + = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:34:57 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:4:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead + = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs index ce4c040644a..0871def1731 100644 --- a/tests/ui/generic-associated-types/issue-78671.rs +++ b/tests/ui/generic-associated-types/issue-78671.rs @@ -1,15 +1,10 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait CollectionFamily { type Member<T>; } fn floatify() { Box::new(Family) as &dyn CollectionFamily<Member=usize> //~^ ERROR: missing generics for associated type - //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object + //~| ERROR: the trait `CollectionFamily` cannot be made into an object } struct Family; diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr new file mode 100644 index 00000000000..fbd76c73895 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:5:47 + | +LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:2:10 + | +LL | type Member<T>; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> + | +++ + +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:5:25 + | +LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-78671.rs:2:10 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member<T>; + | ^^^^^^ ...because it contains the generic associated type `Member` + = help: consider moving `Member` to another trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs index bf61dcaee3a..fba7a86990e 100644 --- a/tests/ui/generic-associated-types/issue-79422.rs +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait RefCont<'a, T> { fn t(&'a self) -> &'a T; } @@ -42,9 +37,8 @@ impl<K, V: Default> MapLike<K, V> for Source { fn main() { let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) - //[base]~^ ERROR the trait - //[extended]~^^ type mismatch + //~^ ERROR the trait as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; //~^ ERROR missing generics for associated type - //[base]~^^ ERROR the trait + //~| ERROR the trait } diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr new file mode 100644 index 00000000000..26567e5e927 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.stderr @@ -0,0 +1,57 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:41:36 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:18:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:41:12 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:18:10 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: + std::collections::BTreeMap<K, V> + Source + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:39:13 + | +LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:18:10 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: + std::collections::BTreeMap<K, V> + Source + = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/parse/in-trait-impl.rs b/tests/ui/generic-associated-types/parse/in-trait-impl.rs index 5ba42be3583..ef67fb18228 100644 --- a/tests/ui/generic-associated-types/parse/in-trait-impl.rs +++ b/tests/ui/generic-associated-types/parse/in-trait-impl.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only impl<T> Baz for T where T: Foo { type Quux<'a> = <T as Foo>::Bar<'a, 'static>; diff --git a/tests/ui/generic-associated-types/parse/in-trait.rs b/tests/ui/generic-associated-types/parse/in-trait.rs index 913eceec0da..2add908d727 100644 --- a/tests/ui/generic-associated-types/parse/in-trait.rs +++ b/tests/ui/generic-associated-types/parse/in-trait.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only use std::ops::Deref; use std::fmt::Debug; diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index 743a3df0acc..bad9289ee5e 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait StreamingIterator { type Item<'a> where Self: 'a; fn size_hint(&self) -> (usize, Option<usize>); @@ -11,11 +6,10 @@ trait StreamingIterator { } fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { - //[base]~^ the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` cannot be made into an object x.size_hint().0 - //[extended]~^ borrowed data escapes - //[base]~^^ the trait `StreamingIterator` cannot be made into an object - //[base]~| the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` cannot be made into an object + //~| the trait `StreamingIterator` cannot be made into an object } fn main() {} diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr new file mode 100644 index 00000000000..3e74776f999 --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.stderr @@ -0,0 +1,48 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:8:21 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:10:7 + | +LL | x.size_hint().0 + | ^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:10:5 + | +LL | x.size_hint().0 + | ^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/hello.rs b/tests/ui/hello.rs index d23cbb61157..f329ee086f9 100644 --- a/tests/ui/hello.rs +++ b/tests/ui/hello.rs @@ -5,8 +5,6 @@ //@[e2021] edition:2021 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options - fn main() { println!("hello"); } diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 73c2cd23d86..1ed3767643a 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -12,6 +12,5 @@ impl<T> Overlap<T> for T {} impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} //~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied -//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index e9d91e45e21..cf3e4cc85b9 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -10,17 +10,6 @@ help: consider restricting type parameter `T` LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} | ++++++++++++++++++++ -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:17 - | -LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/hygiene/auxiliary/def-site-async-await.rs b/tests/ui/hygiene/auxiliary/def-site-async-await.rs index 41c4b871e73..88042b484a1 100644 --- a/tests/ui/hygiene/auxiliary/def-site-async-await.rs +++ b/tests/ui/hygiene/auxiliary/def-site-async-await.rs @@ -1,6 +1,5 @@ //@ edition:2018 - -extern crate opaque_hygiene; +//@ proc-macro: opaque-hygiene.rs pub async fn serve() { opaque_hygiene::make_it!(); diff --git a/tests/ui/hygiene/auxiliary/opaque-hygiene.rs b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs index b6192d653f5..08dc592925a 100644 --- a/tests/ui/hygiene/auxiliary/opaque-hygiene.rs +++ b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::{TokenStream, quote}; diff --git a/tests/ui/hygiene/issue-77523-def-site-async-await.rs b/tests/ui/hygiene/issue-77523-def-site-async-await.rs index 102112381d3..ad6bd5e0b78 100644 --- a/tests/ui/hygiene/issue-77523-def-site-async-await.rs +++ b/tests/ui/hygiene/issue-77523-def-site-async-await.rs @@ -1,5 +1,4 @@ //@ build-pass -//@ aux-build:opaque-hygiene.rs //@ aux-build:def-site-async-await.rs // Regression test for issue #77523 diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs index 5441a015ac0..5575493a17d 100644 --- a/tests/ui/impl-trait/impl-trait-plus-priority.rs +++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn f() -> impl A + {} // OK fn f() -> impl A + B {} // OK diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 79581066a3a..1cfc2a6d944 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -8,10 +8,10 @@ LL | #![feature(lazy_type_alias)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `usize: Foo` is not satisfied - --> $DIR/alias-bounds-when-not-wf.rs:16:13 + --> $DIR/alias-bounds-when-not-wf.rs:16:15 | LL | fn hello(_: W<A<usize>>) {} - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize` + | ^^^^^^^^ the trait `Foo` is not implemented for `usize` | help: this trait has no implementations, consider adding one --> $DIR/alias-bounds-when-not-wf.rs:6:1 diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs new file mode 100644 index 00000000000..30ca3d271b8 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs @@ -0,0 +1,30 @@ +// Make sure that we don't accidentally collect an RPITIT hidden type that does not +// hold for all instantiations of the trait signature. + +trait MkStatic { + fn mk_static(self) -> &'static str; +} + +impl MkStatic for &'static str { + fn mk_static(self) -> &'static str { self } +} + +trait Foo { + fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; +} + +impl Foo for str { + fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + //~^ ERROR method not compatible with trait + self + } +} + +fn call_foo<T: Foo + ?Sized>(t: &T) -> &'static str { + t.foo().mk_static() +} + +fn main() { + let s = call_foo(String::from("hello, world").as_str()); + println!("> {s}"); +} diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr new file mode 100644 index 00000000000..95d8699e19f --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr @@ -0,0 +1,22 @@ +error[E0308]: method not compatible with trait + --> $DIR/do-not-imply-from-trait-impl.rs:17:38 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'late _) -> _` + found signature `fn(&'a _) -> _` +note: the lifetime `'late` as defined here... + --> $DIR/do-not-imply-from-trait-impl.rs:13:25 + | +LL | fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; + | ^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/do-not-imply-from-trait-impl.rs:17:12 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 6f6b787b6fe..a23879eb6c3 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -11,12 +11,12 @@ note: type in trait | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ - = note: expected signature `fn(&T)` - found signature `fn(&'late ())` + = note: expected signature `fn(&'early T)` + found signature `fn(&())` help: change the parameter type to match the trait | -LL | fn early<'late, T>(_: &T) {} - | ~~ +LL | fn early<'late, T>(_: &'early T) {} + | ~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/refine-cycle.rs b/tests/ui/impl-trait/in-trait/refine-cycle.rs new file mode 100644 index 00000000000..78d672a7ed6 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-cycle.rs @@ -0,0 +1,26 @@ +//@ check-pass + +// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve` +// which calls `compare_impl_item`. + +trait Foo { + fn test() -> impl IntoIterator<Item = ()> + Send; +} + +struct A; +impl Foo for A { + fn test() -> impl IntoIterator<Item = ()> + Send { + B::test() + } +} + +struct B; +impl Foo for B { + fn test() -> impl IntoIterator<Item = ()> + Send { + for () in A::test() {} + + [] + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr index 3430055dab1..4c10422f985 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr @@ -6,9 +6,9 @@ LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { | = note: the pointer is valid for the static lifetime note: but the referenced data is only valid for the anonymous lifetime defined here - --> $DIR/rpitit-hidden-types-self-implied-wf.rs:6:18 + --> $DIR/rpitit-hidden-types-self-implied-wf.rs:2:18 | -LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { +LL | fn extend(_: &str) -> (impl Sized + '_, &'static str); | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr index 56b83cbca77..b27d7870955 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr @@ -1,14 +1,15 @@ -error[E0623]: lifetime mismatch +error[E0477]: the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime --> $DIR/signature-mismatch.rs:77:10 | -LL | &'a self, - | -------- this parameter and the return type are declared with different lifetimes... -... LL | ) -> impl Future<Output = Vec<u8>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | ...but data from `buff` is returned here + | +note: type must outlive the lifetime `'a` as defined here as required by this binding + --> $DIR/signature-mismatch.rs:73:32 + | +LL | fn async_fn_reduce_outlive<'a, 'b, T>( + | ^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 55b9a0de5ff..a9885c6a298 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -75,7 +75,7 @@ impl AsyncTrait for Struct { buff: &'b [u8], t: T, ) -> impl Future<Output = Vec<u8>> { - //[failure]~^ ERROR lifetime mismatch + //[failure]~^ ERROR the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime async move { let _t = t; vec![] diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index bb874cbe41b..203fbfc1d2c 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -13,10 +13,18 @@ LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruc = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied - --> $DIR/normalize-tait-in-const.rs:33:5 + --> $DIR/normalize-tait-in-const.rs:33:19 | LL | with_positive(foo); - | ^^^^^^^^^^^^^^^^^^ + | ------------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `with_positive` + --> $DIR/normalize-tait-in-const.rs:26:62 + | +LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^^^^ required by this bound in `with_positive` error[E0015]: cannot call non-const closure in constant functions --> $DIR/normalize-tait-in-const.rs:27:5 diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs index e197dcfef80..fab55f11a53 100644 --- a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs @@ -1,11 +1,6 @@ // A proc-macro in 2015 that has an RPIT without `use<>` that would cause a // problem with 2024 capturing rules. -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs index 46121308fa0..cac5ae177d2 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs @@ -7,7 +7,7 @@ fn polarity() -> impl Sized + ?use<> {} fn asyncness() -> impl Sized + async use<> {} //~^ ERROR expected identifier, found keyword `use` //~| ERROR cannot find trait `r#use` in this scope -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn constness() -> impl Sized + const use<> {} //~^ ERROR expected identifier, found keyword `use` diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index 16e7470debf..d4b5b47b41b 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -46,16 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ not found in this scope -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bound-modifiers.rs:7:32 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: const trait impls are experimental --> $DIR/bound-modifiers.rs:12:32 diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.rs b/tests/ui/impl-trait/precise-capturing/external-macro.rs index 87bad7455eb..9d4d8a1bb11 100644 --- a/tests/ui/impl-trait/precise-capturing/external-macro.rs +++ b/tests/ui/impl-trait/precise-capturing/external-macro.rs @@ -2,7 +2,7 @@ // has an RPIT will not fail when the call-site is 2024. // https://github.com/rust-lang/rust/issues/132917 -//@ aux-crate: no_use_pm=no-use-pm.rs +//@ proc-macro: no-use-pm.rs //@ aux-crate: no_use_macro=no-use-macro.rs //@ edition: 2024 //@ check-pass diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr index e1856b92910..360f0d7e7f3 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -1,10 +1,11 @@ error: return type captures more lifetimes than trait definition --> $DIR/rpitit-impl-captures-too-much.rs:10:39 | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>; + | -- this lifetime was captured +... LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} - | -- ^^^^^^^^^^^^^^^^^^^^ - | | - | this lifetime was captured + | ^^^^^^^^^^^^^^^^^^^^ | note: hidden type must only reference lifetimes captured by this impl trait --> $DIR/rpitit-impl-captures-too-much.rs:6:39 diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr index 011ab3259c4..361a165da66 100644 --- a/tests/ui/impl-trait/variance.e2024.stderr +++ b/tests/ui/impl-trait/variance.e2024.stderr @@ -1,23 +1,23 @@ error: ['a: *, 'a: o] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr index 011ab3259c4..361a165da66 100644 --- a/tests/ui/impl-trait/variance.new.stderr +++ b/tests/ui/impl-trait/variance.new.stderr @@ -1,23 +1,23 @@ error: ['a: *, 'a: o] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr index ac3bcd2723f..578d6fd14cd 100644 --- a/tests/ui/impl-trait/variance.old.stderr +++ b/tests/ui/impl-trait/variance.old.stderr @@ -1,23 +1,23 @@ error: ['a: *] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index 43f7207a904..1e359f033ff 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -1,6 +1,5 @@ //@ revisions: old new e2024 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Z unstable-options #![cfg_attr(new, feature(lifetime_capture_rules_2024))] diff --git a/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs index a2970cb5c80..b87c4b14abc 100644 --- a/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs +++ b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt}; diff --git a/tests/ui/inherent-impls-overlap-check/no-overlap.rs b/tests/ui/inherent-impls-overlap-check/no-overlap.rs index 85565a221ac..df60031bae0 100644 --- a/tests/ui/inherent-impls-overlap-check/no-overlap.rs +++ b/tests/ui/inherent-impls-overlap-check/no-overlap.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:repeat.rs +//@ proc-macro: repeat.rs // This tests the allocating algo branch of the // inherent impls overlap checker. diff --git a/tests/ui/inherent-impls-overlap-check/overlap.rs b/tests/ui/inherent-impls-overlap-check/overlap.rs index 32653943698..114035a13b6 100644 --- a/tests/ui/inherent-impls-overlap-check/overlap.rs +++ b/tests/ui/inherent-impls-overlap-check/overlap.rs @@ -1,4 +1,4 @@ -//@ aux-build:repeat.rs +//@ proc-macro: repeat.rs #![allow(unused)] diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index a456e81e762..aea6d263a72 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -22,7 +22,7 @@ LL | std::intrinsics::floorf32, | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {floorf32}` + found fn item `unsafe fn(_) -> _ {floorf32}` error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-21950.rs b/tests/ui/issues/issue-21950.rs index 72a98bd8ddd..7a85ac91bca 100644 --- a/tests/ui/issues/issue-21950.rs +++ b/tests/ui/issues/issue-21950.rs @@ -8,6 +8,5 @@ impl Add for i32 { fn main() { let x = &10 as &dyn Add; - //~^ ERROR E0393 - //~| ERROR E0191 + //~^ ERROR E0191 } diff --git a/tests/ui/issues/issue-21950.stderr b/tests/ui/issues/issue-21950.stderr index 584370c7178..24230cfe17f 100644 --- a/tests/ui/issues/issue-21950.stderr +++ b/tests/ui/issues/issue-21950.stderr @@ -7,22 +7,6 @@ LL | type Output; LL | let x = &10 as &dyn Add; | ^^^ help: specify the associated type: `Add<Output = Type>` -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/issue-21950.rs:10:25 - | -LL | trait Add<Rhs=Self> { - | ------------------- type parameter `Rhs` must be specified for this -... -LL | let x = &10 as &dyn Add; - | ^^^ - | - = note: because of the default `Self` reference, type parameters must be specified on object types -help: set the type parameter to the desired type - | -LL | let x = &10 as &dyn Add<Rhs>; - | +++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0191, E0393. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-28344.rs b/tests/ui/issues/issue-28344.rs index 1a6a7f46b27..951ea5d69e9 100644 --- a/tests/ui/issues/issue-28344.rs +++ b/tests/ui/issues/issue-28344.rs @@ -3,13 +3,11 @@ use std::ops::BitXor; fn main() { let x: u8 = BitXor::bitor(0 as u8, 0 as u8); //~^ ERROR must be specified - //~| no function or associated item named //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let g = BitXor::bitor; //~^ ERROR must be specified - //~| no function or associated item named //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition } diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index 261f8b67b52..d8febe71652 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -18,17 +18,8 @@ error[E0191]: the value of the associated type `Output` in `BitXor` must be spec LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>` -error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:4:25 - | -LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^ function or associated item not found in `dyn BitXor<_>` - | -help: there is a method `bitxor` with a similar name, but with different arguments - --> $SRC_DIR/core/src/ops/bit.rs:LL:COL - warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-28344.rs:10:13 + --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; | ^^^^^^ @@ -41,21 +32,11 @@ LL | let g = <dyn BitXor>::bitor; | ++++ + error[E0191]: the value of the associated type `Output` in `BitXor` must be specified - --> $DIR/issue-28344.rs:10:13 + --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; | ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>` -error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:10:21 - | -LL | let g = BitXor::bitor; - | ^^^^^ function or associated item not found in `dyn BitXor<_>` - | -help: there is a method `bitxor` with a similar name - --> $SRC_DIR/core/src/ops/bit.rs:LL:COL - -error: aborting due to 4 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0191, E0599. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-50582.rs b/tests/ui/issues/issue-50582.rs index 2d5c9358752..1358e0bde4c 100644 --- a/tests/ui/issues/issue-50582.rs +++ b/tests/ui/issues/issue-50582.rs @@ -1,5 +1,4 @@ fn main() { Vec::<[(); 1 + for x in 0..1 {}]>::new(); //~^ ERROR cannot add - //~| ERROR `for` is not allowed in a `const` } diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr index af7a36f62fb..168f5894fb0 100644 --- a/tests/ui/issues/issue-50582.stderr +++ b/tests/ui/issues/issue-50582.stderr @@ -1,13 +1,3 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-50582.rs:2:20 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0277]: cannot add `()` to `{integer}` --> $DIR/issue-50582.rs:2:18 | @@ -26,7 +16,6 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); `&f64` implements `Add` and 56 others -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-50585.rs b/tests/ui/issues/issue-50585.rs index a2f11c98d5a..ca2ece8d53b 100644 --- a/tests/ui/issues/issue-50585.rs +++ b/tests/ui/issues/issue-50585.rs @@ -1,5 +1,4 @@ fn main() { |y: Vec<[(); for x in 0..2 {}]>| {}; //~^ ERROR mismatched types - //~| ERROR `for` is not allowed in a `const` } diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr index e7f13e63475..7e83ea35fbb 100644 --- a/tests/ui/issues/issue-50585.stderr +++ b/tests/ui/issues/issue-50585.stderr @@ -1,13 +1,3 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-50585.rs:2:18 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/issue-50585.rs:2:18 | @@ -20,7 +10,6 @@ help: consider returning a value here LL | |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {}; | +++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr index 455bd2cbf8b..ee7f5162552 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr @@ -25,6 +25,12 @@ LL | const C: S = unsafe { std::mem::transmute(()) }; = note: source type: `()` (0 bits) = note: target type: `S` (size can vary because of [u8]) +note: erroneous constant encountered + --> $DIR/base-layout-is-sized-ice-123078.rs:13:5 + | +LL | C; + | ^ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0512. diff --git a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs index 35ef6fc019d..4e4b7f61f1e 100644 --- a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs +++ b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - //#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/lifetimes/issue-91763.rs b/tests/ui/lifetimes/issue-91763.rs index 5df69cff3be..6abb64db5fe 100644 --- a/tests/ui/lifetimes/issue-91763.rs +++ b/tests/ui/lifetimes/issue-91763.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-91763-aux.rs +//@ proc-macro: issue-91763-aux.rs #![deny(elided_lifetimes_in_paths)] diff --git a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr index 232453df8ef..0f184853ece 100644 --- a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr +++ b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr @@ -1,5 +1,5 @@ error: lifetimes cannot use keyword names - --> $DIR/gen-lt.rs:11:11 + --> $DIR/gen-lt.rs:10:11 | LL | fn gen_lt<'gen>() {} | ^^^^ diff --git a/tests/ui/lifetimes/raw/gen-lt.rs b/tests/ui/lifetimes/raw/gen-lt.rs index 4f3ede5b4a2..3c33dc285f0 100644 --- a/tests/ui/lifetimes/raw/gen-lt.rs +++ b/tests/ui/lifetimes/raw/gen-lt.rs @@ -2,7 +2,6 @@ //@[e2021] edition:2021 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2021] check-pass diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr index 1caeec84b22..e600cc37fc4 100644 --- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr @@ -1,5 +1,5 @@ error: character literal may only contain one codepoint - --> $DIR/immediately-followed-by-lt.rs:11:4 + --> $DIR/immediately-followed-by-lt.rs:15:4 | LL | w!('r#long'id); | ^^^^^^^^ diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs index fe2b6de7bb3..eb161f9c855 100644 --- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs @@ -1,4 +1,8 @@ -//@ edition: 2021 +//@ revisions: e2015 e2021 + +//@[e2021] edition: 2021 +//@[e2015] edition: 2015 +//@[e2015] check-pass // Make sure we reject the case where a raw lifetime is immediately followed by another // lifetime. This reserves a modest amount of space for changing lexing to, for example, @@ -9,6 +13,6 @@ macro_rules! w { } w!('r#long'id); -//~^ ERROR character literal may only contain one codepoint +//[e2021]~^ ERROR character literal may only contain one codepoint fn main() {} diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr index 157a1c5e09b..6d7000a1370 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr +++ b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `cell` does not live long enough - --> $DIR/refcell-in-tail-expr.rs:10:27 + --> $DIR/refcell-in-tail-expr.rs:9:27 | LL | let cell = std::cell::RefCell::new(0u8); | ---- binding `cell` declared here diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.rs b/tests/ui/lifetimes/refcell-in-tail-expr.rs index 595e951f373..2cca7acbf5a 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.rs +++ b/tests/ui/lifetimes/refcell-in-tail-expr.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] check-pass fn main() { diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr index 3c074c5c3a2..ac23c67a8e1 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/shorter-tail-expr-lifetime.rs:8:5 + --> $DIR/shorter-tail-expr-lifetime.rs:7:5 | LL | let c = std::cell::RefCell::new(".."); | - binding `c` declared here diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs index 4195a8b6c32..25c530d4391 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs @@ -1,5 +1,4 @@ //@ revisions: edition2021 edition2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ [edition2024] run-pass diff --git a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs index ec74596a08d..6af6655149b 100644 --- a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs +++ b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs @@ -1,6 +1,5 @@ //@ revisions: edition2021 edition2024 //@ ignore-wasm no panic or subprocess support -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ run-pass //@ needs-unwind diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs index d03027cf4a3..86c478af317 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -15,7 +15,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Z unstable-options fn temp() -> (String, i32) { (String::from("Hello"), 1) diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 0a5f17be804..51c4837f458 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -11,23 +11,6 @@ note: inside `main` LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/issue-55878.rs:7:26 - | -LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) - -note: erroneous constant encountered - --> $DIR/issue-55878.rs:7:26 - | -LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs index a1fdd5a014c..e5de08a7a28 100644 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs @@ -2,6 +2,7 @@ //@ failure-status: 101 //@ known-bug: #109681 //@ ignore-wasm32 this appears to SIGABRT on wasm, not fail cleanly +//@ compile-flags: -Z verify-llvm-ir // This test verifies that we continue to hit the LLVM error for common linkage with non-zero // initializers, since it generates invalid LLVM IR. diff --git a/tests/ui/lint/auxiliary/add-impl.rs b/tests/ui/lint/auxiliary/add-impl.rs index 7ee4a4e4fde..d0f2baf94bf 100644 --- a/tests/ui/lint/auxiliary/add-impl.rs +++ b/tests/ui/lint/auxiliary/add-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr index ed1242eacfc..07773ee4ddf 100644 --- a/tests/ui/lint/group-forbid-always-trumps-cli.stderr +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr @@ -1,5 +1,5 @@ error: unused variable: `x` - --> $DIR/group-forbid-always-trumps-cli.rs:4:9 + --> $DIR/forbid-always-trumps-cli.rs:15:9 | LL | let x = 1; | ^ help: if this is intentional, prefix it with an underscore: `_x` diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr new file mode 100644 index 00000000000..cf357ef8ca8 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr new file mode 100644 index 00000000000..07773ee4ddf --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr new file mode 100644 index 00000000000..cf357ef8ca8 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr new file mode 100644 index 00000000000..07773ee4ddf --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr new file mode 100644 index 00000000000..cf357ef8ca8 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr new file mode 100644 index 00000000000..07773ee4ddf --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr new file mode 100644 index 00000000000..cf357ef8ca8 --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.rs b/tests/ui/lint/forbid-always-trumps-cli.rs new file mode 100644 index 00000000000..d94cc2e8efe --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.rs @@ -0,0 +1,17 @@ +//! Ensure that "forbid" always trumps" allow" in CLI arguments, no matter the order +//! and no matter whether it is used with a lint group vs an individual lint. +// ignore-tidy-linelength +//@ revisions: forbid-first-group allow-first-group forbid-first-lint allow-first-lint forbid-first-mix1 allow-first-mix1 forbid-first-mix2 allow-first-mix2 +//@[forbid-first-group] compile-flags: -F unused -A unused +//@[allow-first-group] compile-flags: -A unused -F unused +//@[forbid-first-lint] compile-flags: -F unused_variables -A unused_variables +//@[allow-first-lint] compile-flags: -A unused_variables -F unused_variables +//@[forbid-first-mix1] compile-flags: -F unused -A unused_variables +//@[allow-first-mix1] compile-flags: -A unused_variables -F unused +//@[forbid-first-mix2] compile-flags: -F unused_variables -A unused +//@[allow-first-mix2] compile-flags: -A unused -F unused_variables + +fn main() { + let x = 1; + //~^ ERROR unused variable: `x` +} diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr index 80e2f566eb8..b075a521cc9 100644 --- a/tests/ui/lint/forbid-group-group-2.stderr +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -43,3 +43,57 @@ LL | #[allow(nonstandard_style)] error: aborting due to 3 previous errors +Future incompatibility report: Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr index 8794591bd31..2e0147693f3 100644 --- a/tests/ui/lint/forbid-group-member.stderr +++ b/tests/ui/lint/forbid-group-member.stderr @@ -13,3 +13,17 @@ LL | #[allow(unused_variables)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + = note: `#[warn(forbidden_lint_groups)]` on by default + diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.rs b/tests/ui/lint/group-forbid-always-trumps-cli.rs deleted file mode 100644 index 4b63452bf5d..00000000000 --- a/tests/ui/lint/group-forbid-always-trumps-cli.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ compile-flags: -F unused -A unused - -fn main() { - let x = 1; - //~^ ERROR unused variable: `x` -} diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index 407eaf1c60a..77c8d1eab58 100644 --- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -17,3 +17,399 @@ LL | #![forbid(forbidden_lint_groups)] error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr index a47877980a0..64a1077462a 100644 --- a/tests/ui/lint/outer-forbid.stderr +++ b/tests/ui/lint/outer-forbid.stderr @@ -39,3 +39,417 @@ LL | #[allow(nonstandard_style)] error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0453`. +Future incompatibility report: Future breakage diagnostic: +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs index 2a58af0fedc..72303f12b7e 100644 --- a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs +++ b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type="proc-macro"] #![crate_name="redundant_semi_proc_macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs index 33c7e26ba47..3469614aab0 100644 --- a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:redundant-semi-proc-macro-def.rs +//@ proc-macro: redundant-semi-proc-macro-def.rs #![deny(redundant_semicolons)] extern crate redundant_semi_proc_macro; diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index d42aa1d613f..1ec440b4e45 100644 --- a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(199..201) }, Ident { ident: "span_preservation", span: #0 bytes(202..219) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(219..221) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(229..232) }, Ident { ident: "tst", span: #0 bytes(233..236) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(237..238) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(239..242) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(242..243) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(243..244) }, Ident { ident: "match", span: #0 bytes(290..295) }, Ident { ident: "tst", span: #0 bytes(296..299) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(484..487) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(488..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(489..490) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(491..493) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(493..494) }, Ident { ident: "_", span: #0 bytes(503..504) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(505..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(506..507) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(508..510) }], span: #0 bytes(300..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(517..518) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(518..519) }], span: #0 bytes(223..563) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(201..203) }, Ident { ident: "span_preservation", span: #0 bytes(204..221) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(221..223) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(231..234) }, Ident { ident: "tst", span: #0 bytes(235..238) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(239..240) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(241..244) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(244..245) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(245..246) }, Ident { ident: "match", span: #0 bytes(292..297) }, Ident { ident: "tst", span: #0 bytes(298..301) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(486..489) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(490..491) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(491..492) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(493..495) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(495..496) }, Ident { ident: "_", span: #0 bytes(505..506) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(507..508) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(508..509) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(510..512) }], span: #0 bytes(302..518) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(518..519) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(519..520) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(520..521) }], span: #0 bytes(225..565) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 26af60b6bc5..4205d406b51 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -103,7 +103,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:45:16 | LL | let deferred = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ | @@ -113,7 +113,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:48:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; - | ---------------------------------------------------------------------------- casting happend here + | ---------------------------------------------------------------------------- casting happened here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ | @@ -123,7 +123,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:51:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; - | ---------------------------------------------------------------------------- casting happend here + | ---------------------------------------------------------------------------- casting happened here ... LL | let _num = &mut *deferred_rebind; | ^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:62:16 | LL | let num = NUM as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | let _num = &mut *num; | ^^^^^^^^^ @@ -279,7 +279,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:115:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -289,7 +289,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:119:5 | LL | let value = value as *mut i32; - | ----------------- casting happend here + | ----------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -299,7 +299,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:122:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -309,7 +309,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:125:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | *value_rebind = 1; | ^^^^^^^^^^^^^^^^^ @@ -336,7 +336,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:131:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -347,7 +347,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:133:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write_unaligned(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:135:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write_volatile(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -496,7 +496,7 @@ LL | let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _; | -------------------------------- | | | | | backing allocation comes from here - | casting happend here + | casting happened here LL | let w: *mut [u16] = unsafe {&mut *w}; | ^^^^^^^ | diff --git a/tests/ui/lint/static-mut-refs.e2021.stderr b/tests/ui/lint/static-mut-refs.e2021.stderr index 09f560652e7..5a4e712b3c0 100644 --- a/tests/ui/lint/static-mut-refs.e2021.stderr +++ b/tests/ui/lint/static-mut-refs.e2021.stderr @@ -1,5 +1,5 @@ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:39:18 + --> $DIR/static-mut-refs.rs:38:18 | LL | let _y = &X; | ^^ shared reference to mutable static @@ -13,7 +13,7 @@ LL | let _y = &raw const X; | ~~~~~~~~~~ warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:43:18 + --> $DIR/static-mut-refs.rs:42:18 | LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static @@ -26,7 +26,7 @@ LL | let _y = &raw mut X; | ~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:51:22 + --> $DIR/static-mut-refs.rs:50:22 | LL | let ref _a = X; | ^ shared reference to mutable static @@ -35,7 +35,7 @@ LL | let ref _a = X; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:25 + --> $DIR/static-mut-refs.rs:54:25 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -48,7 +48,7 @@ LL | let (_b, _c) = (&raw const X, &Y); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:29 + --> $DIR/static-mut-refs.rs:54:29 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -61,7 +61,7 @@ LL | let (_b, _c) = (&X, &raw const Y); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:61:13 + --> $DIR/static-mut-refs.rs:60:13 | LL | foo(&X); | ^^ shared reference to mutable static @@ -74,7 +74,7 @@ LL | foo(&raw const X); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:67:17 + --> $DIR/static-mut-refs.rs:66:17 | LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static @@ -83,7 +83,7 @@ LL | let _ = Z.len(); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:73:33 + --> $DIR/static-mut-refs.rs:72:33 | LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static @@ -92,7 +92,7 @@ LL | let _ = format!("{:?}", Z); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:77:18 + --> $DIR/static-mut-refs.rs:76:18 | LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static @@ -105,7 +105,7 @@ LL | let _v = &raw const A.value; | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:81:18 + --> $DIR/static-mut-refs.rs:80:18 | LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static @@ -118,7 +118,7 @@ LL | let _s = &raw const A.s.value; | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:85:22 + --> $DIR/static-mut-refs.rs:84:22 | LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static @@ -127,7 +127,7 @@ LL | let ref _v = A.value; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:15:14 + --> $DIR/static-mut-refs.rs:14:14 | LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static diff --git a/tests/ui/lint/static-mut-refs.e2024.stderr b/tests/ui/lint/static-mut-refs.e2024.stderr index 2d2a4f7afe0..1b549272bd5 100644 --- a/tests/ui/lint/static-mut-refs.e2024.stderr +++ b/tests/ui/lint/static-mut-refs.e2024.stderr @@ -1,5 +1,5 @@ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:39:18 + --> $DIR/static-mut-refs.rs:38:18 | LL | let _y = &X; | ^^ shared reference to mutable static @@ -13,7 +13,7 @@ LL | let _y = &raw const X; | ~~~~~~~~~~ error: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:43:18 + --> $DIR/static-mut-refs.rs:42:18 | LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static @@ -26,7 +26,7 @@ LL | let _y = &raw mut X; | ~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:51:22 + --> $DIR/static-mut-refs.rs:50:22 | LL | let ref _a = X; | ^ shared reference to mutable static @@ -35,7 +35,7 @@ LL | let ref _a = X; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:25 + --> $DIR/static-mut-refs.rs:54:25 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -48,7 +48,7 @@ LL | let (_b, _c) = (&raw const X, &Y); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:29 + --> $DIR/static-mut-refs.rs:54:29 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -61,7 +61,7 @@ LL | let (_b, _c) = (&X, &raw const Y); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:61:13 + --> $DIR/static-mut-refs.rs:60:13 | LL | foo(&X); | ^^ shared reference to mutable static @@ -74,7 +74,7 @@ LL | foo(&raw const X); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:67:17 + --> $DIR/static-mut-refs.rs:66:17 | LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static @@ -83,7 +83,7 @@ LL | let _ = Z.len(); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:73:33 + --> $DIR/static-mut-refs.rs:72:33 | LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static @@ -92,7 +92,7 @@ LL | let _ = format!("{:?}", Z); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:77:18 + --> $DIR/static-mut-refs.rs:76:18 | LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static @@ -105,7 +105,7 @@ LL | let _v = &raw const A.value; | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:81:18 + --> $DIR/static-mut-refs.rs:80:18 | LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static @@ -118,7 +118,7 @@ LL | let _s = &raw const A.s.value; | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:85:22 + --> $DIR/static-mut-refs.rs:84:22 | LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static @@ -127,7 +127,7 @@ LL | let ref _v = A.value; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:15:14 + --> $DIR/static-mut-refs.rs:14:14 | LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static diff --git a/tests/ui/lint/static-mut-refs.rs b/tests/ui/lint/static-mut-refs.rs index 3d84d7dbf40..1040dfcae7a 100644 --- a/tests/ui/lint/static-mut-refs.rs +++ b/tests/ui/lint/static-mut-refs.rs @@ -6,7 +6,6 @@ //@ [e2021] run-pass //@ [e2024] edition:2024 -//@ [e2024] compile-flags: -Zunstable-options static mut FOO: (u32, u32) = (1, 2); diff --git a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs index 6849e9170c1..b00f5838749 100644 --- a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs +++ b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; diff --git a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs index 6392849f915..93b2b60647d 100644 --- a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs +++ b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:forge_unsafe_block.rs +//@ proc-macro: forge_unsafe_block.rs #[macro_use] extern crate forge_unsafe_block; diff --git a/tests/ui/lint/unused-qualification-in-derive-expansion.rs b/tests/ui/lint/unused-qualification-in-derive-expansion.rs index 5cea9086d12..b2067e22c44 100644 --- a/tests/ui/lint/unused-qualification-in-derive-expansion.rs +++ b/tests/ui/lint/unused-qualification-in-derive-expansion.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:add-impl.rs +//@ proc-macro: add-impl.rs #![forbid(unused_qualifications)] diff --git a/tests/ui/macros/auxiliary/hello_macro.rs b/tests/ui/macros/auxiliary/hello_macro.rs index 10f474bd1b3..79125a1f86e 100644 --- a/tests/ui/macros/auxiliary/hello_macro.rs +++ b/tests/ui/macros/auxiliary/hello_macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/issue-100199.rs b/tests/ui/macros/auxiliary/issue-100199.rs index 9ee9a2f5039..f05c4f0722c 100644 --- a/tests/ui/macros/auxiliary/issue-100199.rs +++ b/tests/ui/macros/auxiliary/issue-100199.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/proc_macro_def.rs b/tests/ui/macros/auxiliary/proc_macro_def.rs index 6574bf184fb..38a1f6fa3c1 100644 --- a/tests/ui/macros/auxiliary/proc_macro_def.rs +++ b/tests/ui/macros/auxiliary/proc_macro_def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/proc_macro_sequence.rs b/tests/ui/macros/auxiliary/proc_macro_sequence.rs index de2efdfecf1..0f543540171 100644 --- a/tests/ui/macros/auxiliary/proc_macro_sequence.rs +++ b/tests/ui/macros/auxiliary/proc_macro_sequence.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_span, proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/issue-100199.rs b/tests/ui/macros/issue-100199.rs index b1bcc535d74..78a6ff149e2 100644 --- a/tests/ui/macros/issue-100199.rs +++ b/tests/ui/macros/issue-100199.rs @@ -5,7 +5,7 @@ struct Foo {} // an unexpected dummy span (lo == 0 == hi) while attempting to print a // suggestion. -//@ aux-build: issue-100199.rs +//@ proc-macro: issue-100199.rs extern crate issue_100199; diff --git a/tests/ui/macros/macro-missing-fragment.e2015.stderr b/tests/ui/macros/macro-missing-fragment.e2015.stderr index a068dc5c054..3d32f203d4a 100644 --- a/tests/ui/macros/macro-missing-fragment.e2015.stderr +++ b/tests/ui/macros/macro-missing-fragment.e2015.stderr @@ -1,11 +1,11 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -28,7 +28,7 @@ LL | ( $name ) => {}; = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -40,7 +40,7 @@ error: aborting due to 1 previous error; 3 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -48,14 +48,14 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -63,14 +63,14 @@ LL | ( $name ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -78,7 +78,7 @@ LL | ( $name ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-missing-fragment.e2024.stderr b/tests/ui/macros/macro-missing-fragment.e2024.stderr index 0dc48e0c7b2..a9195063a5b 100644 --- a/tests/ui/macros/macro-missing-fragment.e2024.stderr +++ b/tests/ui/macros/macro-missing-fragment.e2024.stderr @@ -1,5 +1,5 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -25,7 +25,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -38,7 +38,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index b7da87ae610..42387e8dbbf 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -1,7 +1,6 @@ //@ revisions: e2015 e2024 //@[e2015] edition:2015 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options #![warn(missing_fragment_specifier)] diff --git a/tests/ui/macros/macro-quote-test.rs b/tests/ui/macros/macro-quote-test.rs index dd7b10f6322..a4b667b4af6 100644 --- a/tests/ui/macros/macro-quote-test.rs +++ b/tests/ui/macros/macro-quote-test.rs @@ -1,7 +1,7 @@ // Test that a macro can emit delimiters with nothing inside - `()`, `{}` //@ run-pass -//@ aux-build:hello_macro.rs +//@ proc-macro: hello_macro.rs extern crate hello_macro; diff --git a/tests/ui/macros/proc_macro.rs b/tests/ui/macros/proc_macro.rs index 8fea4ca282c..b73f3112536 100644 --- a/tests/ui/macros/proc_macro.rs +++ b/tests/ui/macros/proc_macro.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:proc_macro_def.rs +//@ proc-macro: proc_macro_def.rs extern crate proc_macro_def; diff --git a/tests/ui/macros/same-sequence-span.rs b/tests/ui/macros/same-sequence-span.rs index 67f6b6ad1cd..dfaf669a769 100644 --- a/tests/ui/macros/same-sequence-span.rs +++ b/tests/ui/macros/same-sequence-span.rs @@ -1,4 +1,4 @@ -//@ aux-build:proc_macro_sequence.rs +//@ proc-macro: proc_macro_sequence.rs // Regression test for issue #62831: Check that multiple sequences with the same span in the // left-hand side of a macro definition behave as if they had unique spans, and in particular that diff --git a/tests/ui/macros/same-sequence-span.stderr b/tests/ui/macros/same-sequence-span.stderr index 3242a32e2f4..ff32ef94386 100644 --- a/tests/ui/macros/same-sequence-span.stderr +++ b/tests/ui/macros/same-sequence-span.stderr @@ -17,9 +17,9 @@ LL | $(= $z:tt)* error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments --> $DIR/same-sequence-span.rs:19:1 | -LL | | } +LL | | macro_rules! manual_foo { | |_________________________________^ not allowed after `expr` fragments -LL | +... LL | proc_macro_sequence::make_foo!(); | ^------------------------------- | | diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 92199625207..8991c6db7b9 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -2,7 +2,6 @@ //@ needs-unwind //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] edition: 2024 // See `mir_drop_order.rs` for more information diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs index dcda2b9536a..b112842030e 100644 --- a/tests/ui/never_type/issue-52443.rs +++ b/tests/ui/never_type/issue-52443.rs @@ -7,7 +7,6 @@ fn main() { //~^ WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR cannot convert - //~| ERROR cannot call + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` } diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index 2207ceb5033..1c5a0d65142 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -6,16 +6,6 @@ LL | [(); {while true {break}; 0}]; | = note: `#[warn(while_true)]` on by default -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-52443.rs:9:12 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/issue-52443.rs:2:10 | @@ -41,25 +31,24 @@ help: give the `break` a value of the expected type LL | [(); loop { break 42 }]; | ++ -error[E0015]: cannot convert `RangeFrom<usize>` into an iterator in constants +error[E0015]: cannot use `for` loop on `RangeFrom<usize>` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<RangeFrom<usize> as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `RangeFrom<usize>` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0015, E0308, E0658. +Some errors have detailed explanations: E0015, E0308. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed new file mode 100644 index 00000000000..f9f2b59a8c2 --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] +#![deny(dependency_on_unit_never_type_fallback)] + +fn foo<T: Default>() -> Result<T, ()> { + Err(()) +} + +fn test() -> Result<(), ()> { + //~^ ERROR this function depends on never type fallback being `()` + //~| WARN this was previously accepted by the compiler but is being phased out + _ = foo::<()>()?; + Ok(()) +} + +fn main() {} diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs new file mode 100644 index 00000000000..8a2f3d311ab --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] +#![deny(dependency_on_unit_never_type_fallback)] + +fn foo<T: Default>() -> Result<T, ()> { + Err(()) +} + +fn test() -> Result<(), ()> { + //~^ ERROR this function depends on never type fallback being `()` + //~| WARN this was previously accepted by the compiler but is being phased out + _ = foo()?; + Ok(()) +} + +fn main() {} diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr new file mode 100644 index 00000000000..dc4ffa0d6f4 --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr @@ -0,0 +1,26 @@ +error: this function depends on never type fallback being `()` + --> $DIR/lint-breaking-2024-assign-underscore.rs:10:1 + | +LL | fn test() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/lint-breaking-2024-assign-underscore.rs:13:9 + | +LL | _ = foo()?; + | ^^^^^ +note: the lint level is defined here + --> $DIR/lint-breaking-2024-assign-underscore.rs:4:9 + | +LL | #![deny(dependency_on_unit_never_type_fallback)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | _ = foo::<()>()?; + | ++++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr index 03bb0ca5f3a..ec1483b0aae 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr @@ -1,5 +1,5 @@ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | unsafe { mem::zeroed::<()>() } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ warning: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | unsafe { Union { a: () }.b } = help: specify the type explicitly warning: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | unsafe { internally_create::<()>(x) } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -80,7 +80,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let f = internally_create::<()>; | ++++++ warning: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | S(marker::PhantomData).create_out_of_thin_air() = help: specify the type explicitly warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr index cf12d699f2e..790facee09e 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr @@ -1,5 +1,5 @@ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | unsafe { mem::zeroed::<()>() } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ error: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | unsafe { Union { a: () }.b } = help: specify the type explicitly error: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | unsafe { internally_create::<()>(x) } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -80,7 +80,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let f = internally_create::<()>; | ++++++ error: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | S(marker::PhantomData).create_out_of_thin_air() = help: specify the type explicitly error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | match send_message::<() /* ?0 */>() { | ~~ warning: the type `!` does not permit zero-initialization - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ this code causes undefined behavior when executed diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs index 19b51eea2f5..97e7a2f56bd 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs @@ -2,7 +2,6 @@ //@[e2015] check-pass //@[e2024] check-fail //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options use std::{marker, mem, ptr}; diff --git a/tests/ui/nll/issue-54556-niconii.edition2021.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr index abee09ed950..8bd559034b0 100644 --- a/tests/ui/nll/issue-54556-niconii.edition2021.stderr +++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:28:20 + --> $DIR/issue-54556-niconii.rs:27:20 | LL | let counter = Mutex; | ------- binding `counter` declared here diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index f01e0523cbf..9d37adede6a 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -9,7 +9,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] check-pass struct Mutex; diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs index 97d2e22574a..0d216fdd653 100644 --- a/tests/ui/panics/issue-47429-short-backtraces.rs +++ b/tests/ui/panics/issue-47429-short-backtraces.rs @@ -6,6 +6,12 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=1 +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" + //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename @@ -14,11 +20,6 @@ //@ ignore-sgx no subprocess support //@ ignore-fuchsia Backtraces not symbolized -// NOTE(eddyb) output differs between symbol mangling schemes -//@ revisions: legacy v0 -//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy -//@ [v0] compile-flags: -Csymbol-mangling-version=v0 - fn main() { panic!() } diff --git a/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.run.stderr index dce91ce59e3..1078a2fbc90 100644 --- a/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr +++ b/tests/ui/panics/issue-47429-short-backtraces.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5: +thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:24:5: explicit panic stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr deleted file mode 100644 index f458c7acb39..00000000000 --- a/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr +++ /dev/null @@ -1,6 +0,0 @@ -thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5: -explicit panic -stack backtrace: - 0: std::panicking::begin_panic::<&str> - 1: issue_47429_short_backtraces::main -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr index 3417d4bf1a3..e7def11b0e9 100644 --- a/tests/ui/panics/panic-in-cleanup.run.stderr +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -4,6 +4,6 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at $DIR/panic-in-cleanup.rs:16:9: BOOM stack backtrace: -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a destructor during cleanup thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index 58f5187f0da..fe8c2b04b91 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -2,7 +2,7 @@ thread 'main' panicked at $DIR/panic-in-ffi.rs:21:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Noisy Drop -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs index a4ef0dcd8a2..10dce250909 100644 --- a/tests/ui/panics/runtime-switch.rs +++ b/tests/ui/panics/runtime-switch.rs @@ -6,6 +6,12 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=0 +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" + //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename @@ -14,11 +20,6 @@ //@ ignore-sgx no subprocess support //@ ignore-fuchsia Backtrace not symbolized -// NOTE(eddyb) output differs between symbol mangling schemes -//@ revisions: legacy v0 -//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy -//@ [v0] compile-flags: -Csymbol-mangling-version=v0 - #![feature(panic_backtrace_config)] fn main() { diff --git a/tests/ui/panics/runtime-switch.legacy.run.stderr b/tests/ui/panics/runtime-switch.run.stderr index bd05b6cc00f..abbb91eba60 100644 --- a/tests/ui/panics/runtime-switch.legacy.run.stderr +++ b/tests/ui/panics/runtime-switch.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/runtime-switch.rs:26:5: +thread 'main' panicked at $DIR/runtime-switch.rs:27:5: explicit panic stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/runtime-switch.v0.run.stderr b/tests/ui/panics/runtime-switch.v0.run.stderr deleted file mode 100644 index 2078c356d5c..00000000000 --- a/tests/ui/panics/runtime-switch.v0.run.stderr +++ /dev/null @@ -1,6 +0,0 @@ -thread 'main' panicked at $DIR/runtime-switch.rs:26:5: -explicit panic -stack backtrace: - 0: std::panicking::begin_panic::<&str> - 1: runtime_switch::main -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs index 6caad2212d4..c2f04cd122c 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs @@ -9,6 +9,11 @@ //@ ignore-sgx Backtraces not symbolized //@ ignore-fuchsia Backtraces not symbolized //@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable. +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" /// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace` diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr index 2b648a0cad2..67577f3568e 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:61:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs index 5f275d13cc4..c035e7e69bc 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames.rs @@ -10,6 +10,11 @@ //@ ignore-fuchsia Backtraces not symbolized //@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable. +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" #[inline(never)] fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T { diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr index 5b372684096..63fa466ab24 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:57:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/parser/assoc/assoc-oddities-1.rs b/tests/ui/parser/assoc/assoc-oddities-1.rs index 246546ac034..c1b305a4eeb 100644 --- a/tests/ui/parser/assoc/assoc-oddities-1.rs +++ b/tests/ui/parser/assoc/assoc-oddities-1.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn main() { // following lines below parse and must not fail diff --git a/tests/ui/parser/assoc/assoc-oddities-2.rs b/tests/ui/parser/assoc/assoc-oddities-2.rs index aee2af41d62..82cf7d79c0d 100644 --- a/tests/ui/parser/assoc/assoc-oddities-2.rs +++ b/tests/ui/parser/assoc/assoc-oddities-2.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn main() { // see assoc-oddities-1 for explanation diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs index 15c0b377c8a..964d32c55bc 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.rs +++ b/tests/ui/parser/bad-recover-kw-after-impl.rs @@ -12,6 +12,6 @@ macro_rules! impl_primitive { impl_primitive!(impl async); //~^ ERROR expected identifier, found `<eof>` -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/parser/bad-recover-kw-after-impl.stderr b/tests/ui/parser/bad-recover-kw-after-impl.stderr index f617cf65498..7a8979db165 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.stderr +++ b/tests/ui/parser/bad-recover-kw-after-impl.stderr @@ -7,16 +7,16 @@ LL | ($ty:ty) => { LL | impl_primitive!(impl async); | ^^^^^ expected identifier -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bad-recover-kw-after-impl.rs:13:22 | LL | impl_primitive!(impl async); | ^^^^^ | = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index 7cee6def32f..ec0e83c314e 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ edition: 2021 struct S< diff --git a/tests/ui/parser/impl-qpath.rs b/tests/ui/parser/impl-qpath.rs index d7c4989b6e4..fed026792c9 100644 --- a/tests/ui/parser/impl-qpath.rs +++ b/tests/ui/parser/impl-qpath.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only impl <*const u8>::AssocTy {} // OK impl <Type as Trait>::AssocTy {} // OK diff --git a/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs index 44697afcfed..2df0b3a17dc 100644 --- a/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs +++ b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/parser/issues/issue-17904.rs b/tests/ui/parser/issues/issue-17904.rs index 6f77d4bb086..99a3b139898 100644 --- a/tests/ui/parser/issues/issue-17904.rs +++ b/tests/ui/parser/issues/issue-17904.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zparse-only +//@ compile-flags: -Zparse-crate-root-only struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well. diff --git a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs index 51bb04dba19..461890e63e3 100644 --- a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs +++ b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs +//@ proc-macro: issue-89971-outer-attr-following-inner-attr-ice.rs #[macro_use] extern crate issue_89971_outer_attr_following_inner_attr_ice; diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs index b8610c4e190..45968a516e3 100644 --- a/tests/ui/parser/mut-patterns.rs +++ b/tests/ui/parser/mut-patterns.rs @@ -15,6 +15,10 @@ pub fn main() { //~^ ERROR `mut` on a binding may not be repeated //~| remove the additional `mut`s + let mut mut mut mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + struct Foo { x: isize } let mut Foo { x: x } = Foo { x: 3 }; //~^ ERROR `mut` must be attached to each individual binding diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index f4f11b88d36..ad19a60af34 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -45,11 +45,23 @@ LL | let mut mut x = 0; help: remove the additional `mut`s | LL - let mut mut x = 0; -LL + let mut x = 0; +LL + let mut x = 0; + | + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:18:13 + | +LL | let mut mut mut mut mut x = 0; + | ^^^^^^^^^^^^^^^ + | +help: remove the additional `mut`s + | +LL - let mut mut mut mut mut x = 0; +LL + let mut x = 0; | error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:19:9 + --> $DIR/mut-patterns.rs:23:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; | ^^^^^^^^^^^^^^^^ @@ -61,7 +73,7 @@ LL | let Foo { x: mut x } = Foo { x: 3 }; | ~~~~~~~~~~~~~~~~ error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:23:9 + --> $DIR/mut-patterns.rs:27:9 | LL | let mut Foo { x } = Foo { x: 3 }; | ^^^^^^^^^^^^^ @@ -73,7 +85,7 @@ LL | let Foo { mut x } = Foo { x: 3 }; | ~~~~~~~~~~~~~ error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:28:13 + --> $DIR/mut-patterns.rs:32:13 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^ @@ -81,11 +93,11 @@ LL | let mut mut yield(become, await) = r#yield(0, 0); help: remove the additional `mut`s | LL - let mut mut yield(become, await) = r#yield(0, 0); -LL + let mut yield(become, await) = r#yield(0, 0); +LL + let mut yield(become, await) = r#yield(0, 0); | error: expected identifier, found reserved keyword `yield` - --> $DIR/mut-patterns.rs:28:17 + --> $DIR/mut-patterns.rs:32:17 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -96,7 +108,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0); | ++ error: expected identifier, found reserved keyword `become` - --> $DIR/mut-patterns.rs:28:23 + --> $DIR/mut-patterns.rs:32:23 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^ expected identifier, found reserved keyword @@ -107,7 +119,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ++ error: expected identifier, found keyword `await` - --> $DIR/mut-patterns.rs:28:31 + --> $DIR/mut-patterns.rs:32:31 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found keyword @@ -118,7 +130,7 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ++ error: `mut` must be followed by a named binding - --> $DIR/mut-patterns.rs:28:9 + --> $DIR/mut-patterns.rs:32:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^^^ @@ -131,7 +143,7 @@ LL + let yield(become, await) = r#yield(0, 0); | error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:37:9 + --> $DIR/mut-patterns.rs:41:9 | LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +155,7 @@ LL | let W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f })))) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: expected identifier, found `x` - --> $DIR/mut-patterns.rs:44:21 + --> $DIR/mut-patterns.rs:48:21 | LL | let mut $p = 0; | ^^ expected identifier @@ -153,5 +165,5 @@ LL | foo!(x); | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/print-request/macos-target.rs b/tests/ui/print-request/macos-target.rs index 197edd02474..af74babbed4 100644 --- a/tests/ui/print-request/macos-target.rs +++ b/tests/ui/print-request/macos-target.rs @@ -1,5 +1,6 @@ //@ only-apple //@ compile-flags: --print deployment-target +//@ normalize-stdout-test: "\w*_DEPLOYMENT_TARGET" -> "$$OS_DEPLOYMENT_TARGET" //@ normalize-stdout-test: "\d+\." -> "$$CURRENT_MAJOR_VERSION." //@ normalize-stdout-test: "\d+" -> "$$CURRENT_MINOR_VERSION" //@ check-pass diff --git a/tests/ui/print-request/macos-target.stdout b/tests/ui/print-request/macos-target.stdout index f55ef568ed6..34ade570969 100644 --- a/tests/ui/print-request/macos-target.stdout +++ b/tests/ui/print-request/macos-target.stdout @@ -1 +1 @@ -deployment_target=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION +$OS_DEPLOYMENT_TARGET=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION diff --git a/tests/ui/proc-macro/add-impl.rs b/tests/ui/proc-macro/add-impl.rs index 7780c39f0c1..2299f05c2e7 100644 --- a/tests/ui/proc-macro/add-impl.rs +++ b/tests/ui/proc-macro/add-impl.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:add-impl.rs +//@ proc-macro: add-impl.rs #[macro_use] extern crate add_impl; diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.rs b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs index c5e3ffa1672..10c2d3f9d13 100644 --- a/tests/ui/proc-macro/allowed-attr-stmt-expr.rs +++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs @@ -1,5 +1,5 @@ -//@ aux-build:attr-stmt-expr.rs -//@ aux-build:test-macros.rs +//@ proc-macro: attr-stmt-expr.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs index 3f191cba745..8ee2223822a 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs @@ -1,4 +1,4 @@ -//@ aux-build:builtin-attrs.rs +//@ proc-macro: builtin-attrs.rs //@ compile-flags:--test #![feature(decl_macro, test)] diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs index c82663541a7..edc7748eff3 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs.rs +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -1,5 +1,5 @@ //@ edition:2018 -//@ aux-build:builtin-attrs.rs +//@ proc-macro: builtin-attrs.rs #![feature(decl_macro)] //~ ERROR `feature` is ambiguous extern crate builtin_attrs; diff --git a/tests/ui/proc-macro/amputate-span.fixed b/tests/ui/proc-macro/amputate-span.fixed index 0fdaf01357c..9742f585d49 100644 --- a/tests/ui/proc-macro/amputate-span.fixed +++ b/tests/ui/proc-macro/amputate-span.fixed @@ -1,4 +1,4 @@ -//@ aux-build:amputate-span.rs +//@ proc-macro: amputate-span.rs //@ run-rustfix //@ edition:2018 //@ compile-flags: --extern amputate_span diff --git a/tests/ui/proc-macro/amputate-span.rs b/tests/ui/proc-macro/amputate-span.rs index 7081660bc29..6cdde46962e 100644 --- a/tests/ui/proc-macro/amputate-span.rs +++ b/tests/ui/proc-macro/amputate-span.rs @@ -1,4 +1,4 @@ -//@ aux-build:amputate-span.rs +//@ proc-macro: amputate-span.rs //@ run-rustfix //@ edition:2018 //@ compile-flags: --extern amputate_span diff --git a/tests/ui/proc-macro/append-impl.rs b/tests/ui/proc-macro/append-impl.rs index f5163e965a0..c0f208460b2 100644 --- a/tests/ui/proc-macro/append-impl.rs +++ b/tests/ui/proc-macro/append-impl.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:append-impl.rs +//@ proc-macro: append-impl.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/attr-args.rs b/tests/ui/proc-macro/attr-args.rs index ed7e96bcc89..1d3e0f725d2 100644 --- a/tests/ui/proc-macro/attr-args.rs +++ b/tests/ui/proc-macro/attr-args.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-args.rs +//@ proc-macro: attr-args.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/attr-cfg.rs b/tests/ui/proc-macro/attr-cfg.rs index 4679807ad79..af0c6e1b541 100644 --- a/tests/ui/proc-macro/attr-cfg.rs +++ b/tests/ui/proc-macro/attr-cfg.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-cfg.rs +//@ proc-macro: attr-cfg.rs //@ revisions: foo bar extern crate attr_cfg; diff --git a/tests/ui/proc-macro/attr-complex-fn.rs b/tests/ui/proc-macro/attr-complex-fn.rs index 7baf469d7d0..bf100401a65 100644 --- a/tests/ui/proc-macro/attr-complex-fn.rs +++ b/tests/ui/proc-macro/attr-complex-fn.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/attr-invalid-exprs.rs b/tests/ui/proc-macro/attr-invalid-exprs.rs index ec0b79469a4..f476858a32b 100644 --- a/tests/ui/proc-macro/attr-invalid-exprs.rs +++ b/tests/ui/proc-macro/attr-invalid-exprs.rs @@ -1,6 +1,6 @@ //! Attributes producing expressions in invalid locations -//@ aux-build:attr-stmt-expr.rs +//@ proc-macro: attr-stmt-expr.rs #![feature(proc_macro_hygiene)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/attr-on-trait.rs b/tests/ui/proc-macro/attr-on-trait.rs index 659b461f759..e95760a837c 100644 --- a/tests/ui/proc-macro/attr-on-trait.rs +++ b/tests/ui/proc-macro/attr-on-trait.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-on-trait.rs +//@ proc-macro: attr-on-trait.rs extern crate attr_on_trait; diff --git a/tests/ui/proc-macro/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs index 18e477f0129..c4188bde309 100644 --- a/tests/ui/proc-macro/attr-stmt-expr-rpass.rs +++ b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-stmt-expr-rpass.rs +//@ proc-macro: attr-stmt-expr-rpass.rs #![feature(stmt_expr_attributes, proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/attr-stmt-expr.rs b/tests/ui/proc-macro/attr-stmt-expr.rs index f33c686f284..1ed2bd048e6 100644 --- a/tests/ui/proc-macro/attr-stmt-expr.rs +++ b/tests/ui/proc-macro/attr-stmt-expr.rs @@ -1,5 +1,5 @@ -//@ aux-build:attr-stmt-expr.rs -//@ aux-build:test-macros.rs +//@ proc-macro: attr-stmt-expr.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/attribute-after-derive.rs b/tests/ui/proc-macro/attribute-after-derive.rs index 3120b23e97e..f2e2eb12a19 100644 --- a/tests/ui/proc-macro/attribute-after-derive.rs +++ b/tests/ui/proc-macro/attribute-after-derive.rs @@ -3,7 +3,7 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build: test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/attribute-spans-preserved.rs b/tests/ui/proc-macro/attribute-spans-preserved.rs index 946b16a0c80..4d5b93797e6 100644 --- a/tests/ui/proc-macro/attribute-spans-preserved.rs +++ b/tests/ui/proc-macro/attribute-spans-preserved.rs @@ -1,4 +1,4 @@ -//@ aux-build:attribute-spans-preserved.rs +//@ proc-macro: attribute-spans-preserved.rs extern crate attribute_spans_preserved as foo; diff --git a/tests/ui/proc-macro/attribute-with-error.rs b/tests/ui/proc-macro/attribute-with-error.rs index 5e81a9c7011..d44d558badd 100644 --- a/tests/ui/proc-macro/attribute-with-error.rs +++ b/tests/ui/proc-macro/attribute-with-error.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/attributes-included.rs b/tests/ui/proc-macro/attributes-included.rs index 47fd21fdd24..73d1c1a8f05 100644 --- a/tests/ui/proc-macro/attributes-included.rs +++ b/tests/ui/proc-macro/attributes-included.rs @@ -1,4 +1,4 @@ -//@ aux-build:attributes-included.rs +//@ proc-macro: attributes-included.rs //@ check-pass #![warn(unused)] diff --git a/tests/ui/proc-macro/attributes-on-definitions.rs b/tests/ui/proc-macro/attributes-on-definitions.rs index 187d1be2364..d9700434b51 100644 --- a/tests/ui/proc-macro/attributes-on-definitions.rs +++ b/tests/ui/proc-macro/attributes-on-definitions.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:attributes-on-definitions.rs +//@ proc-macro: attributes-on-definitions.rs #![forbid(unsafe_code)] diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.rs b/tests/ui/proc-macro/attributes-on-modules-fail.rs index 9b2eb703eac..80300b47c5f 100644 --- a/tests/ui/proc-macro/attributes-on-modules-fail.rs +++ b/tests/ui/proc-macro/attributes-on-modules-fail.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/attributes-on-modules.rs b/tests/ui/proc-macro/attributes-on-modules.rs index 26c8d8e113b..f1be7e44a47 100644 --- a/tests/ui/proc-macro/attributes-on-modules.rs +++ b/tests/ui/proc-macro/attributes-on-modules.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/auxiliary/add-impl.rs b/tests/ui/proc-macro/auxiliary/add-impl.rs index 23a86e76ef9..327e6065ef2 100644 --- a/tests/ui/proc-macro/auxiliary/add-impl.rs +++ b/tests/ui/proc-macro/auxiliary/add-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/amputate-span.rs b/tests/ui/proc-macro/auxiliary/amputate-span.rs index c1ab0477ba2..969176eaa67 100644 --- a/tests/ui/proc-macro/auxiliary/amputate-span.rs +++ b/tests/ui/proc-macro/auxiliary/amputate-span.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs index e0a381cb6c1..abd667d8ce1 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic //@ edition: 2021 -#![crate_type = "proc-macro"] -#![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] #![deny(dead_code)] // catch if a test function is never called diff --git a/tests/ui/proc-macro/auxiliary/append-impl.rs b/tests/ui/proc-macro/auxiliary/append-impl.rs index 30657d2738e..e286f01a971 100644 --- a/tests/ui/proc-macro/auxiliary/append-impl.rs +++ b/tests/ui/proc-macro/auxiliary/append-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs index 8935ce2bc0a..6459d2169a9 100644 --- a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs +++ b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_diagnostic, proc_macro_span)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/attr-args.rs b/tests/ui/proc-macro/auxiliary/attr-args.rs index 1fac41c3721..6a1041603f1 100644 --- a/tests/ui/proc-macro/auxiliary/attr-args.rs +++ b/tests/ui/proc-macro/auxiliary/attr-args.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-cfg.rs b/tests/ui/proc-macro/auxiliary/attr-cfg.rs index 3645128b509..0e625932512 100644 --- a/tests/ui/proc-macro/auxiliary/attr-cfg.rs +++ b/tests/ui/proc-macro/auxiliary/attr-cfg.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs index c4581359da1..012243febce 100644 --- a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs +++ b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs index c8b7aa412b5..022f10e5615 100644 --- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs index 888aab848d4..7efeda16b9c 100644 --- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs index d06903c2708..76cf959279c 100644 --- a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs +++ b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/attributes-included.rs b/tests/ui/proc-macro/auxiliary/attributes-included.rs index cc29818380b..3a129c8185e 100644 --- a/tests/ui/proc-macro/auxiliary/attributes-included.rs +++ b/tests/ui/proc-macro/auxiliary/attributes-included.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group}; diff --git a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs index c7e6e681da3..ef981ba8500 100644 --- a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs +++ b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -1,11 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/bang-macro.rs b/tests/ui/proc-macro/auxiliary/bang-macro.rs index 361643aa8e5..3ac30ab8e32 100644 --- a/tests/ui/proc-macro/auxiliary/bang-macro.rs +++ b/tests/ui/proc-macro/auxiliary/bang-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs index 3df2676ddab..7a094c2d477 100644 --- a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs +++ b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs index bd634b4f41c..9743ec78c96 100644 --- a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs +++ b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/call-deprecated.rs b/tests/ui/proc-macro/auxiliary/call-deprecated.rs index 8864de17ed3..28919ab29ec 100644 --- a/tests/ui/proc-macro/auxiliary/call-deprecated.rs +++ b/tests/ui/proc-macro/auxiliary/call-deprecated.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/call-site.rs b/tests/ui/proc-macro/auxiliary/call-site.rs index ce0fc70c1a6..8201ec5c48f 100644 --- a/tests/ui/proc-macro/auxiliary/call-site.rs +++ b/tests/ui/proc-macro/auxiliary/call-site.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/cond_plugin.rs b/tests/ui/proc-macro/auxiliary/cond_plugin.rs index c6cdc8ce8ba..9858be230c9 100644 --- a/tests/ui/proc-macro/auxiliary/cond_plugin.rs +++ b/tests/ui/proc-macro/auxiliary/cond_plugin.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs index 86c27f2d818..c5a1c561976 100644 --- a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs +++ b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs index eab7d903e91..0f50aedcd9e 100644 --- a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs +++ b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/custom-quote.rs b/tests/ui/proc-macro/auxiliary/custom-quote.rs index 88800596ce5..bccbed8a6b4 100644 --- a/tests/ui/proc-macro/auxiliary/custom-quote.rs +++ b/tests/ui/proc-macro/auxiliary/custom-quote.rs @@ -1,9 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic // ignore-tidy-linelength #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use std::iter::FromIterator; diff --git a/tests/ui/proc-macro/auxiliary/derive-a.rs b/tests/ui/proc-macro/auxiliary/derive-a.rs index 50e963a0a41..89d0263c9e2 100644 --- a/tests/ui/proc-macro/auxiliary/derive-a.rs +++ b/tests/ui/proc-macro/auxiliary/derive-a.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-atob.rs b/tests/ui/proc-macro/auxiliary/derive-atob.rs index 8a1f81450fa..0ed62565771 100644 --- a/tests/ui/proc-macro/auxiliary/derive-atob.rs +++ b/tests/ui/proc-macro/auxiliary/derive-atob.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs index b9c0b5e6f77..cb60c182a43 100644 --- a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs +++ b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs index 82f0b4f19ed..de2935eb9c1 100644 --- a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-b.rs b/tests/ui/proc-macro/auxiliary/derive-b.rs index 0b2cf31b059..efdb785c23b 100644 --- a/tests/ui/proc-macro/auxiliary/derive-b.rs +++ b/tests/ui/proc-macro/auxiliary/derive-b.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-bad.rs b/tests/ui/proc-macro/auxiliary/derive-bad.rs index 3fd2bfc4b63..bd25478fb1d 100644 --- a/tests/ui/proc-macro/auxiliary/derive-bad.rs +++ b/tests/ui/proc-macro/auxiliary/derive-bad.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-clona.rs b/tests/ui/proc-macro/auxiliary/derive-clona.rs index 83bcc5b08be..b38bf31dbcc 100644 --- a/tests/ui/proc-macro/auxiliary/derive-clona.rs +++ b/tests/ui/proc-macro/auxiliary/derive-clona.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-ctod.rs b/tests/ui/proc-macro/auxiliary/derive-ctod.rs index 78b1b8615b0..1e08ec61262 100644 --- a/tests/ui/proc-macro/auxiliary/derive-ctod.rs +++ b/tests/ui/proc-macro/auxiliary/derive-ctod.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-foo.rs b/tests/ui/proc-macro/auxiliary/derive-foo.rs index 5c63c3937e4..22fbc4bc54f 100644 --- a/tests/ui/proc-macro/auxiliary/derive-foo.rs +++ b/tests/ui/proc-macro/auxiliary/derive-foo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs index d09ff6cadc5..da474cf5614 100644 --- a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs index d1f5b67cf85..32136f79ff2 100644 --- a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-nothing.rs b/tests/ui/proc-macro/auxiliary/derive-nothing.rs index adf9b4e83fd..eefa2c40ac3 100644 --- a/tests/ui/proc-macro/auxiliary/derive-nothing.rs +++ b/tests/ui/proc-macro/auxiliary/derive-nothing.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs index bfdd71e9a15..8e7bcb6aaba 100644 --- a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs +++ b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs index 24a88dceb4b..532c72dacff 100644 --- a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs +++ b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-union.rs b/tests/ui/proc-macro/auxiliary/derive-union.rs index 8bf7041ebad..da4132604a7 100644 --- a/tests/ui/proc-macro/auxiliary/derive-union.rs +++ b/tests/ui/proc-macro/auxiliary/derive-union.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs index f80a2cfdd99..4bc56efecdb 100644 --- a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs +++ b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable.rs b/tests/ui/proc-macro/auxiliary/derive-unstable.rs index c92df49191b..8ba3a06e354 100644 --- a/tests/ui/proc-macro/auxiliary/derive-unstable.rs +++ b/tests/ui/proc-macro/auxiliary/derive-unstable.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/double.rs b/tests/ui/proc-macro/auxiliary/double.rs index ffde0bce245..b6d952437ea 100644 --- a/tests/ui/proc-macro/auxiliary/double.rs +++ b/tests/ui/proc-macro/auxiliary/double.rs @@ -1,10 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/duplicate.rs b/tests/ui/proc-macro/auxiliary/duplicate.rs index bcbb1c7474c..0474aed2266 100644 --- a/tests/ui/proc-macro/auxiliary/duplicate.rs +++ b/tests/ui/proc-macro/auxiliary/duplicate.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![deny(unused)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs index da6584e31e5..9347a2e975b 100644 --- a/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs +++ b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs @@ -1,12 +1,7 @@ -//@ force-host -//@ no-prefer-dynamic - // Proc macro helper for issue #89699, used by tests/ui/proc-macro/edition-gated-async-move- // syntax-issue89699.rs, emitting an `async move` closure. This syntax is only available in // editions 2018 and up, but is used in edition 2015 in the test. -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs index c33736a74a7..6d584f4e6ab 100644 --- a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs +++ b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs @@ -1,8 +1,4 @@ //@ edition:2015 -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/empty-crate.rs b/tests/ui/proc-macro/auxiliary/empty-crate.rs index c502cd921cc..5e15112a9cb 100644 --- a/tests/ui/proc-macro/auxiliary/empty-crate.rs +++ b/tests/ui/proc-macro/auxiliary/empty-crate.rs @@ -1,5 +1 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(unused_variables)] diff --git a/tests/ui/proc-macro/auxiliary/env.rs b/tests/ui/proc-macro/auxiliary/env.rs index da9aaa5cb56..d01e3b42d4c 100644 --- a/tests/ui/proc-macro/auxiliary/env.rs +++ b/tests/ui/proc-macro/auxiliary/env.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_tracked_env)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs index 68d0843be5a..78c9fa75d9f 100644 --- a/tests/ui/proc-macro/auxiliary/expand-expr.rs +++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(warnings)] #![feature(proc_macro_expand, proc_macro_span)] diff --git a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs index 9096fd71397..c6281a42d2a 100644 --- a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs +++ b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(warnings)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/first-second.rs b/tests/ui/proc-macro/auxiliary/first-second.rs index c8c1defa9f1..110d054add7 100644 --- a/tests/ui/proc-macro/auxiliary/first-second.rs +++ b/tests/ui/proc-macro/auxiliary/first-second.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Group, Delimiter}; diff --git a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs index fb05c97833c..b0728b8a0b8 100644 --- a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs +++ b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs index 9d6767dc11f..40ecf4ef704 100644 --- a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs index d2f82c52c58..855cb1d7095 100644 --- a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs index 855084be84d..28d35c82148 100644 --- a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs +++ b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/generate-mod.rs b/tests/ui/proc-macro/auxiliary/generate-mod.rs index 2ef1faffaa6..62710bd1e2d 100644 --- a/tests/ui/proc-macro/auxiliary/generate-mod.rs +++ b/tests/ui/proc-macro/auxiliary/generate-mod.rs @@ -1,10 +1,6 @@ //@ run-pass -//@ force-host -//@ no-prefer-dynamic //@ ignore-pass -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/helper-attr.rs b/tests/ui/proc-macro/auxiliary/helper-attr.rs index 79ccefd9844..ee2968688f9 100644 --- a/tests/ui/proc-macro/auxiliary/helper-attr.rs +++ b/tests/ui/proc-macro/auxiliary/helper-attr.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; // Doesn't do anything, but has a helper attribute. diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example.rs b/tests/ui/proc-macro/auxiliary/hygiene_example.rs index f7e7e0b5751..b690dbfaae7 100644 --- a/tests/ui/proc-macro/auxiliary/hygiene_example.rs +++ b/tests/ui/proc-macro/auxiliary/hygiene_example.rs @@ -1,3 +1,5 @@ +//@ proc-macro: hygiene_example_codegen.rs + extern crate hygiene_example_codegen; pub use hygiene_example_codegen::hello; diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs index e324e3f3129..dde997bf3ea 100644 --- a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs +++ b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` diff --git a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs index 19b3632dc3f..47d06086467 100644 --- a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs +++ b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_raw_ident)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/is-available.rs b/tests/ui/proc-macro/auxiliary/is-available.rs index f1d0e3c78f5..1eeffa50913 100644 --- a/tests/ui/proc-macro/auxiliary/is-available.rs +++ b/tests/ui/proc-macro/auxiliary/is-available.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Literal, TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/issue-104884.rs b/tests/ui/proc-macro/auxiliary/issue-104884.rs index 55d0d76ad18..64922d997b6 100644 --- a/tests/ui/proc-macro/auxiliary/issue-104884.rs +++ b/tests/ui/proc-macro/auxiliary/issue-104884.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-107113.rs b/tests/ui/proc-macro/auxiliary/issue-107113.rs index 5662277acce..f7c2c856435 100644 --- a/tests/ui/proc-macro/auxiliary/issue-107113.rs +++ b/tests/ui/proc-macro/auxiliary/issue-107113.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-118809.rs b/tests/ui/proc-macro/auxiliary/issue-118809.rs index f662f623b19..2751b16b6b5 100644 --- a/tests/ui/proc-macro/auxiliary/issue-118809.rs +++ b/tests/ui/proc-macro/auxiliary/issue-118809.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-38586.rs b/tests/ui/proc-macro/auxiliary/issue-38586.rs index e2bba3e13d1..7e30ba371d1 100644 --- a/tests/ui/proc-macro/auxiliary/issue-38586.rs +++ b/tests/ui/proc-macro/auxiliary/issue-38586.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; #[proc_macro_derive(A)] diff --git a/tests/ui/proc-macro/auxiliary/issue-39889.rs b/tests/ui/proc-macro/auxiliary/issue-39889.rs index b1659d6168e..e4975fddd4c 100644 --- a/tests/ui/proc-macro/auxiliary/issue-39889.rs +++ b/tests/ui/proc-macro/auxiliary/issue-39889.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-42708.rs b/tests/ui/proc-macro/auxiliary/issue-42708.rs index ed5ba530341..c055409ba06 100644 --- a/tests/ui/proc-macro/auxiliary/issue-42708.rs +++ b/tests/ui/proc-macro/auxiliary/issue-42708.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-50061.rs b/tests/ui/proc-macro/auxiliary/issue-50061.rs index 9ecbb383d4b..9137a78f530 100644 --- a/tests/ui/proc-macro/auxiliary/issue-50061.rs +++ b/tests/ui/proc-macro/auxiliary/issue-50061.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-50493.rs b/tests/ui/proc-macro/auxiliary/issue-50493.rs index e9ad8600533..22bf1428e56 100644 --- a/tests/ui/proc-macro/auxiliary/issue-50493.rs +++ b/tests/ui/proc-macro/auxiliary/issue-50493.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-59191.rs b/tests/ui/proc-macro/auxiliary/issue-59191.rs index 40ba0063e43..84b156d61e5 100644 --- a/tests/ui/proc-macro/auxiliary/issue-59191.rs +++ b/tests/ui/proc-macro/auxiliary/issue-59191.rs @@ -1,8 +1,4 @@ //@ edition:2018 -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-66286.rs b/tests/ui/proc-macro/auxiliary/issue-66286.rs index d224dcda590..a317e68a3d7 100644 --- a/tests/ui/proc-macro/auxiliary/issue-66286.rs +++ b/tests/ui/proc-macro/auxiliary/issue-66286.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-75801.rs b/tests/ui/proc-macro/auxiliary/issue-75801.rs index bd553b7ab84..f1554f0fe75 100644 --- a/tests/ui/proc-macro/auxiliary/issue-75801.rs +++ b/tests/ui/proc-macro/auxiliary/issue-75801.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-79242.rs b/tests/ui/proc-macro/auxiliary/issue-79242.rs index 7b24e5a2ef2..165318d67b0 100644 --- a/tests/ui/proc-macro/auxiliary/issue-79242.rs +++ b/tests/ui/proc-macro/auxiliary/issue-79242.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-79825.rs b/tests/ui/proc-macro/auxiliary/issue-79825.rs index 4326712458b..912a3c2147c 100644 --- a/tests/ui/proc-macro/auxiliary/issue-79825.rs +++ b/tests/ui/proc-macro/auxiliary/issue-79825.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-83510.rs b/tests/ui/proc-macro/auxiliary/issue-83510.rs index 6e8e2d1f780..50bdd36607d 100644 --- a/tests/ui/proc-macro/auxiliary/issue-83510.rs +++ b/tests/ui/proc-macro/auxiliary/issue-83510.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs index a638a33cf25..e6f91a52de5 100644 --- a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs +++ b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs index 4f605ed07b3..d487d8f989c 100644 --- a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/lifetimes.rs b/tests/ui/proc-macro/auxiliary/lifetimes.rs index 79885a92f68..5d7ebecf832 100644 --- a/tests/ui/proc-macro/auxiliary/lifetimes.rs +++ b/tests/ui/proc-macro/auxiliary/lifetimes.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs index 501a03985cb..4971de284b7 100644 --- a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs +++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - // These are tests for syntax that is accepted by the Rust parser but // unconditionally rejected semantically after macro expansion. Attribute macros // are permitted to accept such syntax as long as they replace it with something @@ -9,7 +6,6 @@ // We also inspect some of the spans to verify the syntax is not triggering the // lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081). -#![crate_type = "proc-macro"] #![feature(proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs b/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs index a4fd76b9c9d..fb244d09d9c 100644 --- a/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs +++ b/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/meta-macro.rs b/tests/ui/proc-macro/auxiliary/meta-macro.rs index cbe882c173f..3436b1944d0 100644 --- a/tests/ui/proc-macro/auxiliary/meta-macro.rs +++ b/tests/ui/proc-macro/auxiliary/meta-macro.rs @@ -1,9 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic //@ edition:2018 #![feature(proc_macro_def_site)] -#![crate_type = "proc-macro"] extern crate proc_macro; extern crate make_macro; diff --git a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs index c143e2d40f3..d837c88c955 100644 --- a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs +++ b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs @@ -1,10 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/modify-ast.rs b/tests/ui/proc-macro/auxiliary/modify-ast.rs index 174c588e8bf..389b0968814 100644 --- a/tests/ui/proc-macro/auxiliary/modify-ast.rs +++ b/tests/ui/proc-macro/auxiliary/modify-ast.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/multiple-derives.rs b/tests/ui/proc-macro/auxiliary/multiple-derives.rs index 84a826cf1f6..6f03f0a08f0 100644 --- a/tests/ui/proc-macro/auxiliary/multiple-derives.rs +++ b/tests/ui/proc-macro/auxiliary/multiple-derives.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/multispan.rs b/tests/ui/proc-macro/auxiliary/multispan.rs index b5f1ed9b56a..1eb379d3877 100644 --- a/tests/ui/proc-macro/auxiliary/multispan.rs +++ b/tests/ui/proc-macro/auxiliary/multispan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/negative-token.rs b/tests/ui/proc-macro/auxiliary/negative-token.rs index 43355bfd20b..d3731c1c8cc 100644 --- a/tests/ui/proc-macro/auxiliary/negative-token.rs +++ b/tests/ui/proc-macro/auxiliary/negative-token.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs index 48ae3600192..96aed8625aa 100644 --- a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs +++ b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/not-joint.rs b/tests/ui/proc-macro/auxiliary/not-joint.rs index 5f94805361a..bc15ced0566 100644 --- a/tests/ui/proc-macro/auxiliary/not-joint.rs +++ b/tests/ui/proc-macro/auxiliary/not-joint.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs index 3ec92d71332..257d1489ce2 100644 --- a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs +++ b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_diagnostic, proc_macro_span)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs index 07e135ee8eb..2b77b45565a 100644 --- a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs +++ b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/print-tokens.rs b/tests/ui/proc-macro/auxiliary/print-tokens.rs index 6d25f1f8471..171ff6e61fb 100644 --- a/tests/ui/proc-macro/auxiliary/print-tokens.rs +++ b/tests/ui/proc-macro/auxiliary/print-tokens.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs index cfd6464661e..8506c9f0de0 100644 --- a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs +++ b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, Ident, Span}; diff --git a/tests/ui/proc-macro/auxiliary/raw-ident.rs b/tests/ui/proc-macro/auxiliary/raw-ident.rs index 1fec6179756..7fd73dd97ba 100644 --- a/tests/ui/proc-macro/auxiliary/raw-ident.rs +++ b/tests/ui/proc-macro/auxiliary/raw-ident.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Ident, Punct, Spacing, Span}; diff --git a/tests/ui/proc-macro/auxiliary/re-export.rs b/tests/ui/proc-macro/auxiliary/re-export.rs index a886015a031..ae88e2f3e11 100644 --- a/tests/ui/proc-macro/auxiliary/re-export.rs +++ b/tests/ui/proc-macro/auxiliary/re-export.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/recollect.rs b/tests/ui/proc-macro/auxiliary/recollect.rs index 7db29035f71..439f37c8832 100644 --- a/tests/ui/proc-macro/auxiliary/recollect.rs +++ b/tests/ui/proc-macro/auxiliary/recollect.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs index 032d41688af..493956c00e9 100644 --- a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs +++ b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs @@ -1,10 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_def_site)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs index 16640a32098..99db66ed6a9 100644 --- a/tests/ui/proc-macro/auxiliary/span-api-tests.rs +++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs index fdcca29e177..16ca5e3f9e2 100644 --- a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs +++ b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] #![feature(proc_macro_internals)] // FIXME - this shouldn't be necessary -#![crate_type = "proc-macro"] extern crate proc_macro; extern crate custom_quote; diff --git a/tests/ui/proc-macro/auxiliary/subspan.rs b/tests/ui/proc-macro/auxiliary/subspan.rs index 69a9c8a9fa8..edfb053d6f1 100644 --- a/tests/ui/proc-macro/auxiliary/subspan.rs +++ b/tests/ui/proc-macro/auxiliary/subspan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/test-macros.rs b/tests/ui/proc-macro/auxiliary/test-macros.rs index 69a89e94cd6..8375767d6fb 100644 --- a/tests/ui/proc-macro/auxiliary/test-macros.rs +++ b/tests/ui/proc-macro/auxiliary/test-macros.rs @@ -1,11 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - // Proc macros commonly used by tests. // `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/three-equals.rs b/tests/ui/proc-macro/auxiliary/three-equals.rs index f0ff0437a8b..56cfd4a2828 100644 --- a/tests/ui/proc-macro/auxiliary/three-equals.rs +++ b/tests/ui/proc-macro/auxiliary/three-equals.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs index f401f7d55ba..c37eed360f0 100644 --- a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs +++ b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Group}; diff --git a/tests/ui/proc-macro/bang-macro.rs b/tests/ui/proc-macro/bang-macro.rs index 03d4174d652..2287e34c5dd 100644 --- a/tests/ui/proc-macro/bang-macro.rs +++ b/tests/ui/proc-macro/bang-macro.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:bang-macro.rs +//@ proc-macro: bang-macro.rs extern crate bang_macro; use bang_macro::rewrite; diff --git a/tests/ui/proc-macro/break-token-spans.rs b/tests/ui/proc-macro/break-token-spans.rs index ae90e04e081..efbd0c0d7e2 100644 --- a/tests/ui/proc-macro/break-token-spans.rs +++ b/tests/ui/proc-macro/break-token-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issues #68489 and #70987 // Tests that we properly break tokens in `probably_equal_for_proc_macro` // See #72306 diff --git a/tests/ui/proc-macro/call-deprecated.rs b/tests/ui/proc-macro/call-deprecated.rs index 1779e33f3b1..fc9354331cc 100644 --- a/tests/ui/proc-macro/call-deprecated.rs +++ b/tests/ui/proc-macro/call-deprecated.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:call-deprecated.rs +//@ proc-macro: call-deprecated.rs extern crate call_deprecated; diff --git a/tests/ui/proc-macro/call-site.rs b/tests/ui/proc-macro/call-site.rs index 31fa78902d5..9c285e1ed11 100644 --- a/tests/ui/proc-macro/call-site.rs +++ b/tests/ui/proc-macro/call-site.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:call-site.rs +//@ proc-macro: call-site.rs extern crate call_site; diff --git a/tests/ui/proc-macro/capture-macro-rules-invoke.rs b/tests/ui/proc-macro/capture-macro-rules-invoke.rs index 71a290c1fc0..101461854c4 100644 --- a/tests/ui/proc-macro/capture-macro-rules-invoke.rs +++ b/tests/ui/proc-macro/capture-macro-rules-invoke.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/capture-unglued-token.rs b/tests/ui/proc-macro/capture-unglued-token.rs index 32286ed084c..586fb934931 100644 --- a/tests/ui/proc-macro/capture-unglued-token.rs +++ b/tests/ui/proc-macro/capture-unglued-token.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/cfg-eval-inner.rs b/tests/ui/proc-macro/cfg-eval-inner.rs index d0a6c1afa23..7493f3ea523 100644 --- a/tests/ui/proc-macro/cfg-eval-inner.rs +++ b/tests/ui/proc-macro/cfg-eval-inner.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #![feature(cfg_eval)] diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs index bbf11949e7e..1d9b4f23ea5 100644 --- a/tests/ui/proc-macro/cfg-eval.rs +++ b/tests/ui/proc-macro/cfg-eval.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(cfg_eval)] #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/count_compound_ops.rs b/tests/ui/proc-macro/count_compound_ops.rs index e58c36e047d..20b0b87817e 100644 --- a/tests/ui/proc-macro/count_compound_ops.rs +++ b/tests/ui/proc-macro/count_compound_ops.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:count_compound_ops.rs +//@ proc-macro: count_compound_ops.rs extern crate count_compound_ops; use count_compound_ops::count_compound_ops; diff --git a/tests/ui/proc-macro/crate-attrs-multiple.rs b/tests/ui/proc-macro/crate-attrs-multiple.rs index 24f46b0a2fa..ebd14590a21 100644 --- a/tests/ui/proc-macro/crate-attrs-multiple.rs +++ b/tests/ui/proc-macro/crate-attrs-multiple.rs @@ -1,7 +1,7 @@ // Multiple custom crate-level attributes, both inert and active. //@ check-pass -//@ aux-crate:test_macros=test-macros.rs +//@ proc-macro: test-macros.rs #![feature(custom_inner_attributes)] #![feature(prelude_import)] diff --git a/tests/ui/proc-macro/crate-var.rs b/tests/ui/proc-macro/crate-var.rs index 7388ca68358..cea5d48e080 100644 --- a/tests/ui/proc-macro/crate-var.rs +++ b/tests/ui/proc-macro/crate-var.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:double.rs +//@ proc-macro: double.rs //@ aux-build:external-crate-var.rs #![allow(unused)] diff --git a/tests/ui/proc-macro/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/custom-attr-only-one-derive.rs index 2616c122a65..f0e82f36757 100644 --- a/tests/ui/proc-macro/custom-attr-only-one-derive.rs +++ b/tests/ui/proc-macro/custom-attr-only-one-derive.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:custom-attr-only-one-derive.rs +//@ proc-macro: custom-attr-only-one-derive.rs #[macro_use] extern crate custom_attr_only_one_derive; diff --git a/tests/ui/proc-macro/custom-attr-panic.rs b/tests/ui/proc-macro/custom-attr-panic.rs index 23bcb66319d..560af228c2a 100644 --- a/tests/ui/proc-macro/custom-attr-panic.rs +++ b/tests/ui/proc-macro/custom-attr-panic.rs @@ -1,4 +1,4 @@ -//@ aux-build: test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs index 2d7bff83681..1e261ea3213 100644 --- a/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs +++ b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![crate_name = "macro_dump_debug"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/debug/dump-debug-span-debug.rs b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs index d4d9199bf3b..618e13c0f15 100644 --- a/tests/ui/proc-macro/debug/dump-debug-span-debug.rs +++ b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-dump-debug.rs +//@ proc-macro: macro-dump-debug.rs //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/debug/dump-debug.rs b/tests/ui/proc-macro/debug/dump-debug.rs index 7a5cc979df9..b20cd2dc948 100644 --- a/tests/ui/proc-macro/debug/dump-debug.rs +++ b/tests/ui/proc-macro/debug/dump-debug.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-dump-debug.rs +//@ proc-macro: macro-dump-debug.rs extern crate macro_dump_debug; use macro_dump_debug::dump_debug; diff --git a/tests/ui/proc-macro/debug/dump-debug.stderr b/tests/ui/proc-macro/debug/dump-debug.stderr index 6aefacacd00..abcbfbfd5ec 100644 --- a/tests/ui/proc-macro/debug/dump-debug.stderr +++ b/tests/ui/proc-macro/debug/dump-debug.stderr @@ -1,166 +1,166 @@ -TokenStream [Ident { ident: "ident", span: #0 bytes(132..137) }, Ident { ident: "r#ident", span: #0 bytes(153..160) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(178..179) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(205..206) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(206..207) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(207..208) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(232..234) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(260..261) }], span: #0 bytes(259..262) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(317..318) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(323..326) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(331..334) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(339..343) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(348..352) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(357..365) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(370..376) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(381..391) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(396..399) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(404..408) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(439..441) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(446..450) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(455..459) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(464..469) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(474..479) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(484..493) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(498..505) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(510..521) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(526..530) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(535..540) }] +TokenStream [Ident { ident: "ident", span: #0 bytes(134..139) }, Ident { ident: "r#ident", span: #0 bytes(155..162) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(180..181) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(207..208) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(208..209) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(209..210) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(234..236) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(262..263) }], span: #0 bytes(261..264) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(319..320) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(325..328) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(333..336) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(341..345) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(350..354) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(359..367) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(372..378) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(383..393) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(398..401) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(406..410) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(441..443) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(448..452) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(457..461) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(466..471) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(476..481) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(486..495) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(500..507) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(512..523) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(528..532) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(537..542) }] TokenStream [ Ident { ident: "ident", - span: #0 bytes(132..137), + span: #0 bytes(134..139), }, Ident { ident: "r#ident", - span: #0 bytes(153..160), + span: #0 bytes(155..162), }, Punct { ch: ',', spacing: Alone, - span: #0 bytes(178..179), + span: #0 bytes(180..181), }, Punct { ch: '=', spacing: Joint, - span: #0 bytes(205..206), + span: #0 bytes(207..208), }, Punct { ch: '=', spacing: Joint, - span: #0 bytes(206..207), + span: #0 bytes(208..209), }, Punct { ch: '>', spacing: Alone, - span: #0 bytes(207..208), + span: #0 bytes(209..210), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: #0 bytes(232..234), + span: #0 bytes(234..236), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "_", - span: #0 bytes(260..261), + span: #0 bytes(262..263), }, ], - span: #0 bytes(259..262), + span: #0 bytes(261..264), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(317..318), + span: #0 bytes(319..320), }, Literal { kind: Float, symbol: "1.0", suffix: None, - span: #0 bytes(323..326), + span: #0 bytes(325..328), }, Literal { kind: Str, symbol: "S", suffix: None, - span: #0 bytes(331..334), + span: #0 bytes(333..336), }, Literal { kind: ByteStr, symbol: "B", suffix: None, - span: #0 bytes(339..343), + span: #0 bytes(341..345), }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, - span: #0 bytes(348..352), + span: #0 bytes(350..354), }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, - span: #0 bytes(357..365), + span: #0 bytes(359..367), }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, - span: #0 bytes(370..376), + span: #0 bytes(372..378), }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, - span: #0 bytes(381..391), + span: #0 bytes(383..393), }, Literal { kind: Char, symbol: "C", suffix: None, - span: #0 bytes(396..399), + span: #0 bytes(398..401), }, Literal { kind: Byte, symbol: "B", suffix: None, - span: #0 bytes(404..408), + span: #0 bytes(406..410), }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), - span: #0 bytes(439..441), + span: #0 bytes(441..443), }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), - span: #0 bytes(446..450), + span: #0 bytes(448..452), }, Literal { kind: Str, symbol: "S", suffix: Some("q"), - span: #0 bytes(455..459), + span: #0 bytes(457..461), }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), - span: #0 bytes(464..469), + span: #0 bytes(466..471), }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), - span: #0 bytes(474..479), + span: #0 bytes(476..481), }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), - span: #0 bytes(484..493), + span: #0 bytes(486..495), }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), - span: #0 bytes(498..505), + span: #0 bytes(500..507), }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), - span: #0 bytes(510..521), + span: #0 bytes(512..523), }, Literal { kind: Char, symbol: "C", suffix: Some("q"), - span: #0 bytes(526..530), + span: #0 bytes(528..532), }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), - span: #0 bytes(535..540), + span: #0 bytes(537..542), }, ] diff --git a/tests/ui/proc-macro/derive-attr-cfg.rs b/tests/ui/proc-macro/derive-attr-cfg.rs index 162be0754d9..2f3516cabae 100644 --- a/tests/ui/proc-macro/derive-attr-cfg.rs +++ b/tests/ui/proc-macro/derive-attr-cfg.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-attr-cfg.rs +//@ proc-macro: derive-attr-cfg.rs extern crate derive_attr_cfg; use derive_attr_cfg::Foo; diff --git a/tests/ui/proc-macro/derive-b.rs b/tests/ui/proc-macro/derive-b.rs index 6cbe1fd0a3f..68d341478f1 100644 --- a/tests/ui/proc-macro/derive-b.rs +++ b/tests/ui/proc-macro/derive-b.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:derive-b-rpass.rs +//@ proc-macro: derive-b-rpass.rs extern crate derive_b_rpass as derive_b; diff --git a/tests/ui/proc-macro/derive-bad.rs b/tests/ui/proc-macro/derive-bad.rs index c8f3a77ea4c..9b237c731db 100644 --- a/tests/ui/proc-macro/derive-bad.rs +++ b/tests/ui/proc-macro/derive-bad.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-bad.rs +//@ proc-macro: derive-bad.rs #[macro_use] extern crate derive_bad; diff --git a/tests/ui/proc-macro/derive-expand-order.rs b/tests/ui/proc-macro/derive-expand-order.rs index 75981f16a7f..076590bdb4c 100644 --- a/tests/ui/proc-macro/derive-expand-order.rs +++ b/tests/ui/proc-macro/derive-expand-order.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:multiple-derives.rs +//@ proc-macro: multiple-derives.rs extern crate multiple_derives; diff --git a/tests/ui/proc-macro/derive-helper-configured.rs b/tests/ui/proc-macro/derive-helper-configured.rs index 45e6e64d392..b753e29b8bf 100644 --- a/tests/ui/proc-macro/derive-helper-configured.rs +++ b/tests/ui/proc-macro/derive-helper-configured.rs @@ -1,7 +1,7 @@ // Derive helpers are resolved successfully inside `cfg_attr`. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.rs b/tests/ui/proc-macro/derive-helper-legacy-limits.rs index ff09095a60f..76b09f33ecc 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-limits.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.rs @@ -2,7 +2,7 @@ // (that's exactly the reason why they are deprecated). //@ edition:2018 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs index 2b5bb905e83..8e902f30419 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![dummy] //~ ERROR cannot find attribute `dummy` in this scope diff --git a/tests/ui/proc-macro/derive-helper-shadowed.rs b/tests/ui/proc-macro/derive-helper-shadowed.rs index 9b2a4ab6bc7..ea2c56b0b73 100644 --- a/tests/ui/proc-macro/derive-helper-shadowed.rs +++ b/tests/ui/proc-macro/derive-helper-shadowed.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:derive-helper-shadowed-2.rs #[macro_use] diff --git a/tests/ui/proc-macro/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/derive-helper-shadowing-2.rs index dc35dd05498..6aba061acf3 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing-2.rs +++ b/tests/ui/proc-macro/derive-helper-shadowing-2.rs @@ -2,7 +2,7 @@ // then make sure that it's usable without ambiguities. //@ check-pass -//@ aux-build:derive-helper-shadowing-2.rs +//@ proc-macro: derive-helper-shadowing-2.rs #[macro_use] extern crate derive_helper_shadowing_2; diff --git a/tests/ui/proc-macro/derive-helper-shadowing.rs b/tests/ui/proc-macro/derive-helper-shadowing.rs index 1c66a60b294..e774e464053 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.rs +++ b/tests/ui/proc-macro/derive-helper-shadowing.rs @@ -1,6 +1,6 @@ //@ edition:2018 -//@ aux-build:test-macros.rs -//@ aux-build:derive-helper-shadowing.rs +//@ proc-macro: test-macros.rs +//@ proc-macro: derive-helper-shadowing.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-vs-legacy.rs b/tests/ui/proc-macro/derive-helper-vs-legacy.rs index feae7adda68..83917a2fbf7 100644 --- a/tests/ui/proc-macro/derive-helper-vs-legacy.rs +++ b/tests/ui/proc-macro/derive-helper-vs-legacy.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-in-mod.rs b/tests/ui/proc-macro/derive-in-mod.rs index 3bd70f1090d..7ec7cf62fb4 100644 --- a/tests/ui/proc-macro/derive-in-mod.rs +++ b/tests/ui/proc-macro/derive-in-mod.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-same-struct.rs b/tests/ui/proc-macro/derive-same-struct.rs index 432476d1ebb..f7669ba1480 100644 --- a/tests/ui/proc-macro/derive-same-struct.rs +++ b/tests/ui/proc-macro/derive-same-struct.rs @@ -2,7 +2,7 @@ #![allow(path_statements)] #![allow(dead_code)] -//@ aux-build:derive-same-struct.rs +//@ proc-macro: derive-same-struct.rs #[macro_use] extern crate derive_same_struct; diff --git a/tests/ui/proc-macro/derive-still-gated.rs b/tests/ui/proc-macro/derive-still-gated.rs index bce7badeffe..518ed9d51be 100644 --- a/tests/ui/proc-macro/derive-still-gated.rs +++ b/tests/ui/proc-macro/derive-still-gated.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-two-attrs.rs b/tests/ui/proc-macro/derive-two-attrs.rs index 91116097665..33a8fef2ac7 100644 --- a/tests/ui/proc-macro/derive-two-attrs.rs +++ b/tests/ui/proc-macro/derive-two-attrs.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-two-attrs.rs +//@ proc-macro: derive-two-attrs.rs extern crate derive_two_attrs as foo; diff --git a/tests/ui/proc-macro/derive-union.rs b/tests/ui/proc-macro/derive-union.rs index d1e65bf4595..e0fe9dee85c 100644 --- a/tests/ui/proc-macro/derive-union.rs +++ b/tests/ui/proc-macro/derive-union.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_variables)] -//@ aux-build:derive-union.rs +//@ proc-macro: derive-union.rs #[macro_use] extern crate derive_union; diff --git a/tests/ui/proc-macro/disappearing-resolution.rs b/tests/ui/proc-macro/disappearing-resolution.rs index b8bc2953576..8e7fa85eba1 100644 --- a/tests/ui/proc-macro/disappearing-resolution.rs +++ b/tests/ui/proc-macro/disappearing-resolution.rs @@ -1,6 +1,6 @@ // Regression test for issue #64803 (initial attribute resolution can disappear later). -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/disappearing-resolution.stderr b/tests/ui/proc-macro/disappearing-resolution.stderr index e6d0868687e..e66f721444f 100644 --- a/tests/ui/proc-macro/disappearing-resolution.stderr +++ b/tests/ui/proc-macro/disappearing-resolution.stderr @@ -16,7 +16,7 @@ note: the derive macro import `Empty` is defined here... LL | use test_macros::Empty; | ^^^^^^^^^^^^^^^^^^ note: ...and refers to the derive macro `Empty` which is defined here - --> $DIR/auxiliary/test-macros.rs:25:1 + --> $DIR/auxiliary/test-macros.rs:20:1 | LL | pub fn empty_derive(_: TokenStream) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly diff --git a/tests/ui/proc-macro/doc-comment-preserved.rs b/tests/ui/proc-macro/doc-comment-preserved.rs index f0891e7d6a7..a4bfd105d36 100644 --- a/tests/ui/proc-macro/doc-comment-preserved.rs +++ b/tests/ui/proc-macro/doc-comment-preserved.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-101211.rs b/tests/ui/proc-macro/dollar-crate-issue-101211.rs index fd5768dc7d1..ca871d57a69 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-101211.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-101211.rs @@ -1,6 +1,6 @@ //@ check-pass //@ edition:2021 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.rs b/tests/ui/proc-macro/dollar-crate-issue-57089.rs index d4540643e02..52f41b78375 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-57089.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-57089.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.rs b/tests/ui/proc-macro/dollar-crate-issue-62325.rs index ee2e0c3973d..716bf6790fe 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-62325.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-62325.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:dollar-crate-external.rs diff --git a/tests/ui/proc-macro/dollar-crate.rs b/tests/ui/proc-macro/dollar-crate.rs index a487e77a833..0d13bbd8967 100644 --- a/tests/ui/proc-macro/dollar-crate.rs +++ b/tests/ui/proc-macro/dollar-crate.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:dollar-crate-external.rs #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs index 0f302708537..e4878a93af1 100644 --- a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs +++ b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs @@ -1,4 +1,4 @@ -//@ aux-build:edition-gated-async-move-syntax.rs +//@ proc-macro: edition-gated-async-move-syntax.rs //@ edition: 2015 // Non-regression test for issue #89699, where a proc-macro emitting syntax only available in diff --git a/tests/ui/proc-macro/edition-imports-2018.rs b/tests/ui/proc-macro/edition-imports-2018.rs index de05868ebf9..a3808d9dce8 100644 --- a/tests/ui/proc-macro/edition-imports-2018.rs +++ b/tests/ui/proc-macro/edition-imports-2018.rs @@ -1,6 +1,6 @@ //@ check-pass //@ edition:2018 -//@ aux-build:edition-imports-2015.rs +//@ proc-macro: edition-imports-2015.rs #[macro_use] extern crate edition_imports_2015; diff --git a/tests/ui/proc-macro/empty-crate.rs b/tests/ui/proc-macro/empty-crate.rs index ba4de590e63..f82660ac4fd 100644 --- a/tests/ui/proc-macro/empty-crate.rs +++ b/tests/ui/proc-macro/empty-crate.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_imports)] -//@ aux-build:empty-crate.rs +//@ proc-macro: empty-crate.rs #[macro_use] extern crate empty_crate; diff --git a/tests/ui/proc-macro/empty-where-clause.rs b/tests/ui/proc-macro/empty-where-clause.rs index 4e432934e3c..770b44515f9 100644 --- a/tests/ui/proc-macro/empty-where-clause.rs +++ b/tests/ui/proc-macro/empty-where-clause.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; use test_macros::recollect_attr; diff --git a/tests/ui/proc-macro/env.rs b/tests/ui/proc-macro/env.rs index 85bcf4521fe..94e3b09e526 100644 --- a/tests/ui/proc-macro/env.rs +++ b/tests/ui/proc-macro/env.rs @@ -1,4 +1,4 @@ -//@ aux-build:env.rs +//@ proc-macro: env.rs //@ run-pass //@ rustc-env: THE_CONST=1 //@ compile-flags: -Zunstable-options --env-set THE_CONST=12 --env-set ANOTHER=4 diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs index e06ddc51a29..8a4ed9768d5 100644 --- a/tests/ui/proc-macro/expand-expr.rs +++ b/tests/ui/proc-macro/expand-expr.rs @@ -1,4 +1,4 @@ -//@ aux-build:expand-expr.rs +//@ proc-macro: expand-expr.rs // no-remap-src-base: check_expand_expr_file!() fails when enabled. #![feature(concat_bytes)] diff --git a/tests/ui/proc-macro/expand-to-derive.rs b/tests/ui/proc-macro/expand-to-derive.rs index 0b603cd4bcc..0e38e471980 100644 --- a/tests/ui/proc-macro/expand-to-derive.rs +++ b/tests/ui/proc-macro/expand-to-derive.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/expand-to-unstable.rs b/tests/ui/proc-macro/expand-to-unstable.rs index c4eaba6bba2..8968471ebd8 100644 --- a/tests/ui/proc-macro/expand-to-unstable.rs +++ b/tests/ui/proc-macro/expand-to-unstable.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-unstable.rs +//@ proc-macro: derive-unstable.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/expand-with-a-macro.rs b/tests/ui/proc-macro/expand-with-a-macro.rs index fcaafbbc149..e5baf3601db 100644 --- a/tests/ui/proc-macro/expand-with-a-macro.rs +++ b/tests/ui/proc-macro/expand-with-a-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ aux-build:expand-with-a-macro.rs +//@ proc-macro: expand-with-a-macro.rs #![deny(warnings)] diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs index 0b34b07edbe..6f31c07ff89 100644 --- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(decl_macro)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout index 0168689b605..7555ef8f632 100644 --- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout @@ -2,39 +2,39 @@ PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0; 0 }, PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #3 bytes(301..305), + span: #3 bytes(303..307), }, Ident { ident: "E", - span: #3 bytes(306..307), + span: #3 bytes(308..309), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #3 bytes(322..323), + span: #3 bytes(324..325), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(324..325), + span: #3 bytes(326..327), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #3 bytes(328..331), + span: #3 bytes(330..333), }, Ident { ident: "_", - span: #3 bytes(332..333), + span: #3 bytes(334..335), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(334..335), + span: #3 bytes(336..337), }, Group { delimiter: None, @@ -42,97 +42,97 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: #0 bytes(543..544), + span: #0 bytes(545..546), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: #0 bytes(545..550), + span: #0 bytes(547..552), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: #0 bytes(551..559), + span: #0 bytes(553..561), }, ], - span: #0 bytes(550..560), + span: #0 bytes(552..562), }, ], - span: #0 bytes(544..561), + span: #0 bytes(546..563), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(562..563), + span: #0 bytes(564..565), }, ], - span: #3 bytes(336..341), + span: #3 bytes(338..343), }, Punct { ch: ';', spacing: Alone, - span: #3 bytes(341..342), + span: #3 bytes(343..344), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #3 bytes(343..344), + span: #3 bytes(345..346), }, ], - span: #3 bytes(326..346), + span: #3 bytes(328..348), }, Punct { ch: ',', spacing: Alone, - span: #3 bytes(346..347), + span: #3 bytes(348..349), }, ], - span: #3 bytes(308..357), + span: #3 bytes(310..359), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #7 bytes(425..429), + span: #7 bytes(427..431), }, Ident { ident: "E", - span: #7 bytes(430..431), + span: #7 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #7 bytes(446..447), + span: #7 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #7 bytes(448..449), + span: #7 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #7 bytes(452..455), + span: #7 bytes(454..457), }, Ident { ident: "_", - span: #7 bytes(456..457), + span: #7 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #7 bytes(458..459), + span: #7 bytes(460..461), }, Group { delimiter: Brace, @@ -144,74 +144,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(580..581), + span: #0 bytes(582..583), }, ], - span: #7 bytes(462..467), + span: #7 bytes(464..469), }, ], - span: #7 bytes(460..469), + span: #7 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #7 bytes(469..470), + span: #7 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #7 bytes(471..472), + span: #7 bytes(473..474), }, ], - span: #7 bytes(450..474), + span: #7 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #7 bytes(474..475), + span: #7 bytes(476..477), }, ], - span: #7 bytes(432..485), + span: #7 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #11 bytes(425..429), + span: #11 bytes(427..431), }, Ident { ident: "E", - span: #11 bytes(430..431), + span: #11 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #11 bytes(446..447), + span: #11 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #11 bytes(448..449), + span: #11 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #11 bytes(452..455), + span: #11 bytes(454..457), }, Ident { ident: "_", - span: #11 bytes(456..457), + span: #11 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #11 bytes(458..459), + span: #11 bytes(460..461), }, Group { delimiter: Brace, @@ -222,74 +222,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Group { delimiter: Brace, stream: TokenStream [], - span: #0 bytes(598..600), + span: #0 bytes(600..602), }, ], - span: #11 bytes(462..467), + span: #11 bytes(464..469), }, ], - span: #11 bytes(460..469), + span: #11 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #11 bytes(469..470), + span: #11 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #11 bytes(471..472), + span: #11 bytes(473..474), }, ], - span: #11 bytes(450..474), + span: #11 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #11 bytes(474..475), + span: #11 bytes(476..477), }, ], - span: #11 bytes(432..485), + span: #11 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #15 bytes(425..429), + span: #15 bytes(427..431), }, Ident { ident: "E", - span: #15 bytes(430..431), + span: #15 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #15 bytes(446..447), + span: #15 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #15 bytes(448..449), + span: #15 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #15 bytes(452..455), + span: #15 bytes(454..457), }, Ident { ident: "_", - span: #15 bytes(456..457), + span: #15 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #15 bytes(458..459), + span: #15 bytes(460..461), }, Group { delimiter: Brace, @@ -299,74 +299,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "PATH", - span: #0 bytes(617..621), + span: #0 bytes(619..623), }, ], - span: #15 bytes(462..467), + span: #15 bytes(464..469), }, ], - span: #15 bytes(460..469), + span: #15 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #15 bytes(469..470), + span: #15 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #15 bytes(471..472), + span: #15 bytes(473..474), }, ], - span: #15 bytes(450..474), + span: #15 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #15 bytes(474..475), + span: #15 bytes(476..477), }, ], - span: #15 bytes(432..485), + span: #15 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #19 bytes(425..429), + span: #19 bytes(427..431), }, Ident { ident: "E", - span: #19 bytes(430..431), + span: #19 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #19 bytes(446..447), + span: #19 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #19 bytes(448..449), + span: #19 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #19 bytes(452..455), + span: #19 bytes(454..457), }, Ident { ident: "_", - span: #19 bytes(456..457), + span: #19 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #19 bytes(458..459), + span: #19 bytes(460..461), }, Group { delimiter: Brace, @@ -378,85 +378,85 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(638..639), + span: #0 bytes(640..641), }, Punct { ch: '+', spacing: Alone, - span: #0 bytes(640..641), + span: #0 bytes(642..643), }, Literal { kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(642..643), + span: #0 bytes(644..645), }, ], - span: #19 bytes(462..467), + span: #19 bytes(464..469), }, ], - span: #19 bytes(460..469), + span: #19 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #19 bytes(469..470), + span: #19 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #19 bytes(471..472), + span: #19 bytes(473..474), }, ], - span: #19 bytes(450..474), + span: #19 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #19 bytes(474..475), + span: #19 bytes(476..477), }, ], - span: #19 bytes(432..485), + span: #19 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #23 bytes(425..429), + span: #23 bytes(427..431), }, Ident { ident: "E", - span: #23 bytes(430..431), + span: #23 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #23 bytes(446..447), + span: #23 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #23 bytes(448..449), + span: #23 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #23 bytes(452..455), + span: #23 bytes(454..457), }, Ident { ident: "_", - span: #23 bytes(456..457), + span: #23 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #23 bytes(458..459), + span: #23 bytes(460..461), }, Group { delimiter: Brace, @@ -466,45 +466,45 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "PATH", - span: #0 bytes(660..664), + span: #0 bytes(662..666), }, Punct { ch: '+', spacing: Alone, - span: #0 bytes(665..666), + span: #0 bytes(667..668), }, Literal { kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(667..668), + span: #0 bytes(669..670), }, ], - span: #23 bytes(462..467), + span: #23 bytes(464..469), }, ], - span: #23 bytes(460..469), + span: #23 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #23 bytes(469..470), + span: #23 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #23 bytes(471..472), + span: #23 bytes(473..474), }, ], - span: #23 bytes(450..474), + span: #23 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #23 bytes(474..475), + span: #23 bytes(476..477), }, ], - span: #23 bytes(432..485), + span: #23 bytes(434..487), }, ] diff --git a/tests/ui/proc-macro/gen-lifetime-token.rs b/tests/ui/proc-macro/gen-lifetime-token.rs index d65efb5c464..4296d58df0d 100644 --- a/tests/ui/proc-macro/gen-lifetime-token.rs +++ b/tests/ui/proc-macro/gen-lifetime-token.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:gen-lifetime-token.rs +//@ proc-macro: gen-lifetime-token.rs extern crate gen_lifetime_token as bar; diff --git a/tests/ui/proc-macro/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs index 2bfbf9dccca..3deec94fa34 100644 --- a/tests/ui/proc-macro/gen-macro-rules-hygiene.rs +++ b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs @@ -2,7 +2,7 @@ // Local variables and labels are hygienic, items are not hygienic. // `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. -//@ aux-build:gen-macro-rules-hygiene.rs +//@ proc-macro: gen-macro-rules-hygiene.rs #[macro_use] extern crate gen_macro_rules_hygiene; diff --git a/tests/ui/proc-macro/gen-macro-rules.rs b/tests/ui/proc-macro/gen-macro-rules.rs index 5f2cfc70d8e..121d029e2e3 100644 --- a/tests/ui/proc-macro/gen-macro-rules.rs +++ b/tests/ui/proc-macro/gen-macro-rules.rs @@ -1,7 +1,7 @@ // Derive macros can generate `macro_rules` items, regression test for issue #63651. //@ check-pass -//@ aux-build:gen-macro-rules.rs +//@ proc-macro: gen-macro-rules.rs extern crate gen_macro_rules as repro; diff --git a/tests/ui/proc-macro/generate-dollar-ident.rs b/tests/ui/proc-macro/generate-dollar-ident.rs index c087a206566..54e872fefb6 100644 --- a/tests/ui/proc-macro/generate-dollar-ident.rs +++ b/tests/ui/proc-macro/generate-dollar-ident.rs @@ -2,7 +2,7 @@ // without it being recognized as an unknown macro variable. //@ check-pass -//@ aux-build:generate-dollar-ident.rs +//@ proc-macro: generate-dollar-ident.rs extern crate generate_dollar_ident; use generate_dollar_ident::*; diff --git a/tests/ui/proc-macro/generate-mod.rs b/tests/ui/proc-macro/generate-mod.rs index ab93666f28a..729bfc1db66 100644 --- a/tests/ui/proc-macro/generate-mod.rs +++ b/tests/ui/proc-macro/generate-mod.rs @@ -1,6 +1,6 @@ // Modules generated by transparent proc macros still acts as barriers for names (issue #50504). -//@ aux-build:generate-mod.rs +//@ proc-macro: generate-mod.rs extern crate generate_mod; diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs index 03bb04b7786..1197dd7f3bf 100644 --- a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use(Empty)] extern crate test_macros; diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs index 03c30783411..53c079fd19c 100644 --- a/tests/ui/proc-macro/helper-attr-blocked-by-import.rs +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use(Empty)] extern crate test_macros; diff --git a/tests/ui/proc-macro/helper-attr-builtin-derive.rs b/tests/ui/proc-macro/helper-attr-builtin-derive.rs index eb7292e093c..7d36e055c14 100644 --- a/tests/ui/proc-macro/helper-attr-builtin-derive.rs +++ b/tests/ui/proc-macro/helper-attr-builtin-derive.rs @@ -2,7 +2,7 @@ // other built-in derive macros. // issue: rust-lang/rust#132561 //@ check-pass -//@ aux-build:helper-attr.rs +//@ proc-macro: helper-attr.rs //@ edition:2021 #[macro_use] diff --git a/tests/ui/proc-macro/hygiene_example.rs b/tests/ui/proc-macro/hygiene_example.rs index 6c3e1067436..84b5e345608 100644 --- a/tests/ui/proc-macro/hygiene_example.rs +++ b/tests/ui/proc-macro/hygiene_example.rs @@ -1,5 +1,4 @@ //@ check-pass -//@ aux-build:hygiene_example_codegen.rs //@ aux-build:hygiene_example.rs extern crate hygiene_example; diff --git a/tests/ui/proc-macro/import.rs b/tests/ui/proc-macro/import.rs index 53dc0f4cbed..44a37dad5c5 100644 --- a/tests/ui/proc-macro/import.rs +++ b/tests/ui/proc-macro/import.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/inert-attribute-order.rs b/tests/ui/proc-macro/inert-attribute-order.rs index bca4df96040..5a4eae03594 100644 --- a/tests/ui/proc-macro/inert-attribute-order.rs +++ b/tests/ui/proc-macro/inert-attribute-order.rs @@ -2,7 +2,7 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs index df006a4d7a9..714463b6225 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs @@ -2,7 +2,7 @@ //@ error-pattern:custom inner attributes are unstable //@ error-pattern:inner macro attributes are unstable //@ error-pattern:this was previously accepted -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/inner-attrs.rs b/tests/ui/proc-macro/inner-attrs.rs index 45bb4d3c5bf..34c37ddfac3 100644 --- a/tests/ui/proc-macro/inner-attrs.rs +++ b/tests/ui/proc-macro/inner-attrs.rs @@ -1,7 +1,7 @@ // gate-test-custom_inner_attributes //@ compile-flags: -Z span-debug --error-format human //@ error-pattern:expected non-macro inner attribute -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ edition:2018 #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/input-interpolated.rs b/tests/ui/proc-macro/input-interpolated.rs index d84572a6afe..a20fe72c6d5 100644 --- a/tests/ui/proc-macro/input-interpolated.rs +++ b/tests/ui/proc-macro/input-interpolated.rs @@ -2,7 +2,7 @@ //@ check-pass //@ edition:2018 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/input-interpolated.stdout b/tests/ui/proc-macro/input-interpolated.stdout index 1bccd8806be..b567292ea9a 100644 --- a/tests/ui/proc-macro/input-interpolated.stdout +++ b/tests/ui/proc-macro/input-interpolated.stdout @@ -2,58 +2,58 @@ PRINT-BANG INPUT (DISPLAY): A PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, ] PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "const", - span: #3 bytes(419..424), + span: #3 bytes(421..426), }, Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, Punct { ch: ':', spacing: Alone, - span: #3 bytes(427..428), + span: #3 bytes(429..430), }, Ident { ident: "u8", - span: #3 bytes(429..431), + span: #3 bytes(431..433), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(432..433), + span: #3 bytes(434..435), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #3 bytes(434..435), + span: #3 bytes(436..437), }, Punct { ch: ';', spacing: Alone, - span: #3 bytes(435..436), + span: #3 bytes(437..438), }, ] PRINT-DERIVE INPUT (DISPLAY): struct A {} PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #3 bytes(471..477), + span: #3 bytes(473..479), }, Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, Group { delimiter: Brace, stream: TokenStream [], - span: #3 bytes(481..483), + span: #3 bytes(483..485), }, ] diff --git a/tests/ui/proc-macro/invalid-punct-ident-1.rs b/tests/ui/proc-macro/invalid-punct-ident-1.rs index b0f163adc02..e7306a7e8ba 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-1.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-1.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-2.rs b/tests/ui/proc-macro/invalid-punct-ident-2.rs index b1f7f570d3f..14656652e1d 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-2.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-2.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-3.rs b/tests/ui/proc-macro/invalid-punct-ident-3.rs index 7698d2c4b39..266e8d3d925 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-3.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-3.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-4.rs b/tests/ui/proc-macro/invalid-punct-ident-4.rs index 042fe6c600d..dbffddd1585 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-4.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-4.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/is-available.rs b/tests/ui/proc-macro/is-available.rs index 36fd44b266f..faee560d7a9 100644 --- a/tests/ui/proc-macro/is-available.rs +++ b/tests/ui/proc-macro/is-available.rs @@ -2,7 +2,7 @@ extern crate proc_macro; -//@ aux-build:is-available.rs +//@ proc-macro: is-available.rs extern crate is_available; fn main() { diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index 29793e9f734..abdd6bf136d 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-104884.rs +//@ proc-macro: issue-104884.rs use std::collections::BinaryHeap; diff --git a/tests/ui/proc-macro/issue-107113-wrap.rs b/tests/ui/proc-macro/issue-107113-wrap.rs index 01bf3615acf..2799e79bb1c 100644 --- a/tests/ui/proc-macro/issue-107113-wrap.rs +++ b/tests/ui/proc-macro/issue-107113-wrap.rs @@ -1,5 +1,5 @@ //@ edition:2021 -//@ aux-build:issue-107113.rs +//@ proc-macro: issue-107113.rs #[macro_use] extern crate issue_107113; diff --git a/tests/ui/proc-macro/issue-118809.rs b/tests/ui/proc-macro/issue-118809.rs index 770b19e8172..a6a3956981a 100644 --- a/tests/ui/proc-macro/issue-118809.rs +++ b/tests/ui/proc-macro/issue-118809.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-118809.rs +//@ proc-macro: issue-118809.rs #[macro_use] extern crate issue_118809; diff --git a/tests/ui/proc-macro/issue-36935.rs b/tests/ui/proc-macro/issue-36935.rs index eb019d1e174..51d85c7dfa9 100644 --- a/tests/ui/proc-macro/issue-36935.rs +++ b/tests/ui/proc-macro/issue-36935.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/issue-37788.rs b/tests/ui/proc-macro/issue-37788.rs index c32ab6b8116..b44525b3b20 100644 --- a/tests/ui/proc-macro/issue-37788.rs +++ b/tests/ui/proc-macro/issue-37788.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-38586.rs b/tests/ui/proc-macro/issue-38586.rs index 54d5d1038a6..88dbb8037be 100644 --- a/tests/ui/proc-macro/issue-38586.rs +++ b/tests/ui/proc-macro/issue-38586.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-38586.rs +//@ proc-macro: issue-38586.rs #[macro_use] extern crate issue_38586; diff --git a/tests/ui/proc-macro/issue-39889.rs b/tests/ui/proc-macro/issue-39889.rs index 687aefbc068..a10fa02e14a 100644 --- a/tests/ui/proc-macro/issue-39889.rs +++ b/tests/ui/proc-macro/issue-39889.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code, unused_macros)] -//@ aux-build:issue-39889.rs +//@ proc-macro: issue-39889.rs extern crate issue_39889; use issue_39889::Issue39889; diff --git a/tests/ui/proc-macro/issue-42708.rs b/tests/ui/proc-macro/issue-42708.rs index 27cb2f73d56..9eb616008de 100644 --- a/tests/ui/proc-macro/issue-42708.rs +++ b/tests/ui/proc-macro/issue-42708.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:issue-42708.rs +//@ proc-macro: issue-42708.rs #![feature(decl_macro)] #![allow(unused)] diff --git a/tests/ui/proc-macro/issue-50061.rs b/tests/ui/proc-macro/issue-50061.rs index 34999bb5070..8a660c2f350 100644 --- a/tests/ui/proc-macro/issue-50061.rs +++ b/tests/ui/proc-macro/issue-50061.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(path_statements)] -//@ aux-build:issue-50061.rs +//@ proc-macro: issue-50061.rs #![feature(decl_macro)] diff --git a/tests/ui/proc-macro/issue-50493.rs b/tests/ui/proc-macro/issue-50493.rs index 5456eddb78d..e23f1f7c7d8 100644 --- a/tests/ui/proc-macro/issue-50493.rs +++ b/tests/ui/proc-macro/issue-50493.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-50493.rs +//@ proc-macro: issue-50493.rs #[macro_use] extern crate issue_50493; diff --git a/tests/ui/proc-macro/issue-53481.rs b/tests/ui/proc-macro/issue-53481.rs index 636b8e0c0ae..11e11e2e6b6 100644 --- a/tests/ui/proc-macro/issue-53481.rs +++ b/tests/ui/proc-macro/issue-53481.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index 24e3be0ed2e..c1b55fd99df 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -2,7 +2,7 @@ // `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`. //@ edition:2018 -//@ aux-crate:issue_59191=issue-59191.rs +//@ proc-macro: issue-59191.rs //@ error-pattern: requires `sized` lang_item #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/issue-66286.rs b/tests/ui/proc-macro/issue-66286.rs index 3ca064768b2..57d1af26e93 100644 --- a/tests/ui/proc-macro/issue-66286.rs +++ b/tests/ui/proc-macro/issue-66286.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-66286.rs +//@ proc-macro: issue-66286.rs // Regression test for #66286. diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs index 8f07cd34cc9..3421d13f4d9 100644 --- a/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #[macro_use] diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout index 5e39c01ab5e..83a3f580958 100644 --- a/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -2,20 +2,20 @@ PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #0 bytes(102..106), + span: #0 bytes(104..108), }, Ident { ident: "ProceduralMasqueradeDummyType", - span: #0 bytes(107..136), + span: #0 bytes(109..138), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Input", - span: #0 bytes(143..148), + span: #0 bytes(145..150), }, ], - span: #0 bytes(137..150), + span: #0 bytes(139..152), }, ] diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.rs b/tests/ui/proc-macro/issue-75734-pp-paren.rs index ab0f4f72e62..d084c4a2873 100644 --- a/tests/ui/proc-macro/issue-75734-pp-paren.rs +++ b/tests/ui/proc-macro/issue-75734-pp-paren.rs @@ -3,7 +3,7 @@ // normally insert extra parentheses. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/issue-75801.rs b/tests/ui/proc-macro/issue-75801.rs index f0a1940cb5c..feda5e60b0d 100644 --- a/tests/ui/proc-macro/issue-75801.rs +++ b/tests/ui/proc-macro/issue-75801.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-75801.rs +//@ proc-macro: issue-75801.rs // Regression test for #75801. diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.rs b/tests/ui/proc-macro/issue-75930-derive-cfg.rs index f480de24e3e..376a8ea4278 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.rs +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issue #75930 // Tests that we cfg-strip all targets before invoking diff --git a/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs index dc40a1715a6..218debf3e7c 100644 --- a/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs +++ b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug // // Regression test for issue #76182 diff --git a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs index 001a09fc552..2a003c30bf9 100644 --- a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs +++ b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:proc-macro-panic.rs +//@ proc-macro: proc-macro-panic.rs //@ edition:2018 //@ needs-unwind proc macro panics to report errors diff --git a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs index d3716b22729..63e8af31027 100644 --- a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs +++ b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/issue-79148.rs b/tests/ui/proc-macro/issue-79148.rs index 96ee5e033e1..b2248759b5f 100644 --- a/tests/ui/proc-macro/issue-79148.rs +++ b/tests/ui/proc-macro/issue-79148.rs @@ -1,4 +1,4 @@ -//@ aux-build:re-export.rs +//@ proc-macro: re-export.rs //@ edition:2018 extern crate re_export; diff --git a/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs index d0c14d8b5d0..3306bc21e3a 100644 --- a/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs +++ b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-79242.rs +//@ proc-macro: issue-79242.rs // Regression test for issue #79242 // Tests that compilation time doesn't blow up for a proc-macro diff --git a/tests/ui/proc-macro/issue-79825.rs b/tests/ui/proc-macro/issue-79825.rs index f846bb40486..67b79172bb3 100644 --- a/tests/ui/proc-macro/issue-79825.rs +++ b/tests/ui/proc-macro/issue-79825.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-79825.rs +//@ proc-macro: issue-79825.rs #![feature(trait_alias)] extern crate issue_79825; diff --git a/tests/ui/proc-macro/issue-80760-empty-stmt.rs b/tests/ui/proc-macro/issue-80760-empty-stmt.rs index 59244e12eb8..b940da6778a 100644 --- a/tests/ui/proc-macro/issue-80760-empty-stmt.rs +++ b/tests/ui/proc-macro/issue-80760-empty-stmt.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/issue-81007-item-attrs.rs b/tests/ui/proc-macro/issue-81007-item-attrs.rs index ab47c9df081..f3b8aa8c7c5 100644 --- a/tests/ui/proc-macro/issue-81007-item-attrs.rs +++ b/tests/ui/proc-macro/issue-81007-item-attrs.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/issue-81543-item-parse-err.rs b/tests/ui/proc-macro/issue-81543-item-parse-err.rs index f3c307318a0..6cd8c0d6c40 100644 --- a/tests/ui/proc-macro/issue-81543-item-parse-err.rs +++ b/tests/ui/proc-macro/issue-81543-item-parse-err.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issue #81543 // Tests that we emit a properly spanned error diff --git a/tests/ui/proc-macro/issue-81555.rs b/tests/ui/proc-macro/issue-81555.rs index 7a61a31952f..bbc7542cb24 100644 --- a/tests/ui/proc-macro/issue-81555.rs +++ b/tests/ui/proc-macro/issue-81555.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes, proc_macro_hygiene)] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-83510.rs b/tests/ui/proc-macro/issue-83510.rs index ea8a334f57c..67469511fc3 100644 --- a/tests/ui/proc-macro/issue-83510.rs +++ b/tests/ui/proc-macro/issue-83510.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-83510.rs +//@ proc-macro: issue-83510.rs extern crate issue_83510; diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed index 367ad66a1a6..b8b3e6f3f7e 100644 --- a/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ run-rustfix #[macro_use] diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs index c49619ef2ac..ce1a0da6cad 100644 --- a/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ run-rustfix #[macro_use] diff --git a/tests/ui/proc-macro/issue-91800.rs b/tests/ui/proc-macro/issue-91800.rs index b69fce4cf77..bc78bcacfd0 100644 --- a/tests/ui/proc-macro/issue-91800.rs +++ b/tests/ui/proc-macro/issue-91800.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-91800-macro.rs +//@ proc-macro: issue-91800-macro.rs #[macro_use] extern crate issue_91800_macro; diff --git a/tests/ui/proc-macro/item-error.rs b/tests/ui/proc-macro/item-error.rs index f3e3eafcd8d..5f798faf436 100644 --- a/tests/ui/proc-macro/item-error.rs +++ b/tests/ui/proc-macro/item-error.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-b.rs +//@ proc-macro: derive-b.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/keep-expr-tokens.rs b/tests/ui/proc-macro/keep-expr-tokens.rs index ced7fad47b9..2bd66da90e2 100644 --- a/tests/ui/proc-macro/keep-expr-tokens.rs +++ b/tests/ui/proc-macro/keep-expr-tokens.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/lifetimes-rpass.rs b/tests/ui/proc-macro/lifetimes-rpass.rs index a6b1f46a5d1..c462b27722f 100644 --- a/tests/ui/proc-macro/lifetimes-rpass.rs +++ b/tests/ui/proc-macro/lifetimes-rpass.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_variables)] -//@ aux-build:lifetimes-rpass.rs +//@ proc-macro: lifetimes-rpass.rs extern crate lifetimes_rpass as lifetimes; use lifetimes::*; diff --git a/tests/ui/proc-macro/lifetimes.rs b/tests/ui/proc-macro/lifetimes.rs index 0c5d3e2f72f..cfff3cb1785 100644 --- a/tests/ui/proc-macro/lifetimes.rs +++ b/tests/ui/proc-macro/lifetimes.rs @@ -1,4 +1,4 @@ -//@ aux-build:lifetimes.rs +//@ proc-macro: lifetimes.rs extern crate lifetimes; diff --git a/tests/ui/proc-macro/lints_in_proc_macros.rs b/tests/ui/proc-macro/lints_in_proc_macros.rs index 13ae7239a14..6714b8b6e1d 100644 --- a/tests/ui/proc-macro/lints_in_proc_macros.rs +++ b/tests/ui/proc-macro/lints_in_proc_macros.rs @@ -1,4 +1,4 @@ -//@ aux-build:bang_proc_macro2.rs +//@ proc-macro: bang_proc_macro2.rs extern crate bang_proc_macro2; diff --git a/tests/ui/proc-macro/literal-to-string.rs b/tests/ui/proc-macro/literal-to-string.rs index e87315fe144..7a56e08109c 100644 --- a/tests/ui/proc-macro/literal-to-string.rs +++ b/tests/ui/proc-macro/literal-to-string.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition: 2021 -//@ aux-build: print-tokens.rs +//@ proc-macro: print-tokens.rs extern crate print_tokens; fn main() { diff --git a/tests/ui/proc-macro/literal-to-string.stdout b/tests/ui/proc-macro/literal-to-string.stdout index c3114265e0a..18c0c20dde4 100644 --- a/tests/ui/proc-macro/literal-to-string.stdout +++ b/tests/ui/proc-macro/literal-to-string.stdout @@ -3,91 +3,91 @@ TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(147..148), + span: #0 bytes(148..149), }, Literal { kind: Integer, symbol: "17", suffix: Some("u8"), - span: #0 bytes(157..161), + span: #0 bytes(158..162), }, Literal { kind: Float, symbol: "42.", suffix: None, - span: #0 bytes(170..173), + span: #0 bytes(171..174), }, Literal { kind: Float, symbol: "3.14", suffix: Some("f32"), - span: #0 bytes(182..189), + span: #0 bytes(183..190), }, Literal { kind: Byte, symbol: "a", suffix: None, - span: #0 bytes(198..202), + span: #0 bytes(199..203), }, Literal { kind: Byte, symbol: "\xFF", suffix: None, - span: #0 bytes(211..218), + span: #0 bytes(212..219), }, Literal { kind: Char, symbol: "c", suffix: None, - span: #0 bytes(227..230), + span: #0 bytes(228..231), }, Literal { kind: Char, symbol: "\x32", suffix: None, - span: #0 bytes(239..245), + span: #0 bytes(240..246), }, Literal { kind: Str, symbol: "\\"str\\"", suffix: None, - span: #0 bytes(254..263), + span: #0 bytes(255..264), }, Literal { kind: StrRaw(1), symbol: "\"raw\" str", suffix: None, - span: #0 bytes(272..286), + span: #0 bytes(273..287), }, Literal { kind: StrRaw(3), symbol: "very ##\"raw\"## str", suffix: None, - span: #0 bytes(295..322), + span: #0 bytes(296..323), }, Literal { kind: ByteStr, symbol: "\\"byte\\" str", suffix: None, - span: #0 bytes(331..346), + span: #0 bytes(332..347), }, Literal { kind: ByteStrRaw(1), symbol: "\"raw\" \"byte\" str", suffix: None, - span: #0 bytes(355..377), + span: #0 bytes(356..378), }, Literal { kind: CStr, symbol: "\\"c\\" str", suffix: None, - span: #0 bytes(386..398), + span: #0 bytes(387..399), }, Literal { kind: CStrRaw(1), symbol: "\"raw\" \"c\" str", suffix: None, - span: #0 bytes(407..426), + span: #0 bytes(408..427), }, ] 1 diff --git a/tests/ui/proc-macro/load-panic-backtrace.rs b/tests/ui/proc-macro/load-panic-backtrace.rs index 15badedef97..302bcaea75e 100644 --- a/tests/ui/proc-macro/load-panic-backtrace.rs +++ b/tests/ui/proc-macro/load-panic-backtrace.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z proc-macro-backtrace //@ rustc-env:RUST_BACKTRACE=0 //@ normalize-stderr-test: "thread '.*' panicked " -> "" diff --git a/tests/ui/proc-macro/load-panic-backtrace.stderr b/tests/ui/proc-macro/load-panic-backtrace.stderr index 18f51358672..0f3db6c831e 100644 --- a/tests/ui/proc-macro/load-panic-backtrace.stderr +++ b/tests/ui/proc-macro/load-panic-backtrace.stderr @@ -1,4 +1,4 @@ -at $DIR/auxiliary/test-macros.rs:43:5: +at $DIR/auxiliary/test-macros.rs:38:5: panic-derive error: proc-macro derive panicked --> $DIR/load-panic-backtrace.rs:11:10 diff --git a/tests/ui/proc-macro/load-panic.rs b/tests/ui/proc-macro/load-panic.rs index 50475a34226..18bfb71050b 100644 --- a/tests/ui/proc-macro/load-panic.rs +++ b/tests/ui/proc-macro/load-panic.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/load-two.rs b/tests/ui/proc-macro/load-two.rs index 44fcdb056dd..608379949e6 100644 --- a/tests/ui/proc-macro/load-two.rs +++ b/tests/ui/proc-macro/load-two.rs @@ -2,8 +2,8 @@ #![allow(path_statements)] #![allow(dead_code)] -//@ aux-build:derive-atob.rs -//@ aux-build:derive-ctod.rs +//@ proc-macro: derive-atob.rs +//@ proc-macro: derive-ctod.rs #[macro_use] extern crate derive_atob; diff --git a/tests/ui/proc-macro/macro-brackets.rs b/tests/ui/proc-macro/macro-brackets.rs index 91bd652d37b..70686eed0bd 100644 --- a/tests/ui/proc-macro/macro-brackets.rs +++ b/tests/ui/proc-macro/macro-brackets.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro-crate-multi-decorator.rs b/tests/ui/proc-macro/macro-crate-multi-decorator.rs index 26a2d1592ab..c4f02e7adfc 100644 --- a/tests/ui/proc-macro/macro-crate-multi-decorator.rs +++ b/tests/ui/proc-macro/macro-crate-multi-decorator.rs @@ -1,7 +1,7 @@ // The duplicate macro will create a copy of the item with the given identifier. //@ check-pass -//@ aux-build:duplicate.rs +//@ proc-macro: duplicate.rs #[macro_use] extern crate duplicate; diff --git a/tests/ui/proc-macro/macro-quote-cond.rs b/tests/ui/proc-macro/macro-quote-cond.rs index 3658e2a28f2..062511eec9b 100644 --- a/tests/ui/proc-macro/macro-quote-cond.rs +++ b/tests/ui/proc-macro/macro-quote-cond.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:cond_plugin.rs +//@ proc-macro: cond_plugin.rs #![allow(unused_parens)] diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.rs b/tests/ui/proc-macro/macro-rules-derive-cfg.rs index c34f1695761..ab504bc63a2 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.rs +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/macro-rules-derive.rs b/tests/ui/proc-macro/macro-rules-derive.rs index 4023a9a044a..c4e906fb5ed 100644 --- a/tests/ui/proc-macro/macro-rules-derive.rs +++ b/tests/ui/proc-macro/macro-rules-derive.rs @@ -1,4 +1,4 @@ -//@ aux-build:first-second.rs +//@ proc-macro: first-second.rs extern crate first_second; use first_second::*; diff --git a/tests/ui/proc-macro/macro-use-attr.rs b/tests/ui/proc-macro/macro-use-attr.rs index fe071b26383..b2d4b9e6ffa 100644 --- a/tests/ui/proc-macro/macro-use-attr.rs +++ b/tests/ui/proc-macro/macro-use-attr.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro-use-bang.rs b/tests/ui/proc-macro/macro-use-bang.rs index f8ccba6b094..9397baff1d6 100644 --- a/tests/ui/proc-macro/macro-use-bang.rs +++ b/tests/ui/proc-macro/macro-use-bang.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs index 3ba80f5177a..8fc7d909749 100644 --- a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs +++ b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs @@ -2,11 +2,10 @@ // proc-macro. // See https://github.com/rust-lang/rust/issues/132906 -//@ aux-crate: macro_rules_edition_pm=macro_rules_edition_pm.rs +//@ proc-macro: macro_rules_edition_pm.rs //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass // This checks how the expr fragment specifier works. diff --git a/tests/ui/proc-macro/macros-in-extern.rs b/tests/ui/proc-macro/macros-in-extern.rs index da384d1b141..f39322d126e 100644 --- a/tests/ui/proc-macro/macros-in-extern.rs +++ b/tests/ui/proc-macro/macros-in-extern.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macros-in-type.rs b/tests/ui/proc-macro/macros-in-type.rs index 4db7cf273f7..1874bb80db3 100644 --- a/tests/ui/proc-macro/macros-in-type.rs +++ b/tests/ui/proc-macro/macros-in-type.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/meta-macro-hygiene.rs b/tests/ui/proc-macro/meta-macro-hygiene.rs index 98496d5a4c6..9fbe9763b44 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.rs +++ b/tests/ui/proc-macro/meta-macro-hygiene.rs @@ -1,5 +1,5 @@ //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no //@ check-pass diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 3c6ec6fbdd4..ae02b24e1d0 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -3,7 +3,7 @@ Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:26 Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }] #![feature /* 0#0 */(prelude_import)] //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no //@ check-pass diff --git a/tests/ui/proc-macro/meta-macro.rs b/tests/ui/proc-macro/meta-macro.rs index abe63c60fb8..02ef45c0c21 100644 --- a/tests/ui/proc-macro/meta-macro.rs +++ b/tests/ui/proc-macro/meta-macro.rs @@ -1,5 +1,5 @@ //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug //@ run-pass diff --git a/tests/ui/proc-macro/mixed-site-span.rs b/tests/ui/proc-macro/mixed-site-span.rs index bab76a8c433..2b5d9757043 100644 --- a/tests/ui/proc-macro/mixed-site-span.rs +++ b/tests/ui/proc-macro/mixed-site-span.rs @@ -1,6 +1,6 @@ // Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene. -//@ aux-build:mixed-site-span.rs +//@ proc-macro: mixed-site-span.rs #[macro_use] extern crate mixed_site_span; diff --git a/tests/ui/proc-macro/modify-ast.rs b/tests/ui/proc-macro/modify-ast.rs index 4c125c1c6e8..9e890f3ebaa 100644 --- a/tests/ui/proc-macro/modify-ast.rs +++ b/tests/ui/proc-macro/modify-ast.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:modify-ast.rs +//@ proc-macro: modify-ast.rs extern crate modify_ast; diff --git a/tests/ui/proc-macro/multispan.rs b/tests/ui/proc-macro/multispan.rs index 60f67c8c67c..e06aa9f7c5a 100644 --- a/tests/ui/proc-macro/multispan.rs +++ b/tests/ui/proc-macro/multispan.rs @@ -1,4 +1,4 @@ -//@ aux-build:multispan.rs +//@ proc-macro: multispan.rs extern crate multispan; diff --git a/tests/ui/proc-macro/negative-token.rs b/tests/ui/proc-macro/negative-token.rs index 32408e0d936..8c6fa9ca689 100644 --- a/tests/ui/proc-macro/negative-token.rs +++ b/tests/ui/proc-macro/negative-token.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:negative-token.rs +//@ proc-macro: negative-token.rs extern crate negative_token; diff --git a/tests/ui/proc-macro/nested-derive-cfg.rs b/tests/ui/proc-macro/nested-derive-cfg.rs index 696a5024ec2..bd8f231ac2c 100644 --- a/tests/ui/proc-macro/nested-derive-cfg.rs +++ b/tests/ui/proc-macro/nested-derive-cfg.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/nested-item-spans.rs b/tests/ui/proc-macro/nested-item-spans.rs index c19af0f9796..f7e2365586d 100644 --- a/tests/ui/proc-macro/nested-item-spans.rs +++ b/tests/ui/proc-macro/nested-item-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs index 2f0d85c4bbf..95a38e4c1b6 100644 --- a/tests/ui/proc-macro/nested-macro-rules.rs +++ b/tests/ui/proc-macro/nested-macro-rules.rs @@ -1,6 +1,6 @@ //@ run-pass //@ aux-build:nested-macro-rules.rs -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug -Z macro-backtrace //@ edition:2018 diff --git a/tests/ui/proc-macro/nested-nonterminal-tokens.rs b/tests/ui/proc-macro/nested-nonterminal-tokens.rs index 6e28cabd2fe..630e33dbd83 100644 --- a/tests/ui/proc-macro/nested-nonterminal-tokens.rs +++ b/tests/ui/proc-macro/nested-nonterminal-tokens.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Tests that we properly pass tokens to proc-macro when nested // nonterminals are involved. diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs index ae507a31ba7..d44f51bfd8d 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.rs +++ b/tests/ui/proc-macro/no-macro-use-attr.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] #![warn(unused_extern_crates)] diff --git a/tests/ui/proc-macro/nodelim-groups.rs b/tests/ui/proc-macro/nodelim-groups.rs index f13d97aaff5..9acdc7023c0 100644 --- a/tests/ui/proc-macro/nodelim-groups.rs +++ b/tests/ui/proc-macro/nodelim-groups.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ edition:2018 // diff --git a/tests/ui/proc-macro/nonterminal-expansion.rs b/tests/ui/proc-macro/nonterminal-expansion.rs index 96ea4aef85b..99a68996c30 100644 --- a/tests/ui/proc-macro/nonterminal-expansion.rs +++ b/tests/ui/proc-macro/nonterminal-expansion.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/nonterminal-recollect-attr.rs index 7d922bafdcd..3f3348b18c1 100644 --- a/tests/ui/proc-macro/nonterminal-recollect-attr.rs +++ b/tests/ui/proc-macro/nonterminal-recollect-attr.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:nonterminal-recollect-attr.rs +//@ proc-macro: nonterminal-recollect-attr.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs index 6a4406b053d..76c71441c80 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.rs +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs @@ -7,7 +7,7 @@ //@ normalize-stdout-test: "\d+#" -> "0#" //@ normalize-stdout-test: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout-test: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(decl_macro)] #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index de3265e9281..1ad14059028 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -31,7 +31,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ //@ normalize-stdout-test: "\d+#" -> "0#" //@ normalize-stdout-test: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout-test: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature /* 0#0 */(decl_macro)] #![no_std /* 0#0 */] diff --git a/tests/ui/proc-macro/not-joint.rs b/tests/ui/proc-macro/not-joint.rs index 16b89bc6e81..c585e7e33dc 100644 --- a/tests/ui/proc-macro/not-joint.rs +++ b/tests/ui/proc-macro/not-joint.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:not-joint.rs +//@ proc-macro: not-joint.rs extern crate not_joint as bar; use bar::{tokens, nothing}; diff --git a/tests/ui/proc-macro/out-of-line-mod.rs b/tests/ui/proc-macro/out-of-line-mod.rs index 2a4fb16a09a..efe9588bef6 100644 --- a/tests/ui/proc-macro/out-of-line-mod.rs +++ b/tests/ui/proc-macro/out-of-line-mod.rs @@ -1,7 +1,7 @@ // Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818). //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/parent-source-spans.rs b/tests/ui/proc-macro/parent-source-spans.rs index 12a1ab1a43d..cc3ac795f7f 100644 --- a/tests/ui/proc-macro/parent-source-spans.rs +++ b/tests/ui/proc-macro/parent-source-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:parent-source-spans.rs +//@ proc-macro: parent-source-spans.rs #![feature(decl_macro)] diff --git a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs index 3d5af5fee21..2dc32202465 100644 --- a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs +++ b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs @@ -1,4 +1,4 @@ -//@ aux-build:parse-invis-delim-issue-128895.rs +//@ proc-macro: parse-invis-delim-issue-128895.rs //@ check-pass #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/pretty-print-hack-hide.rs b/tests/ui/proc-macro/pretty-print-hack-hide.rs index 26db43341ab..fd98f16a780 100644 --- a/tests/ui/proc-macro/pretty-print-hack-hide.rs +++ b/tests/ui/proc-macro/pretty-print-hack-hide.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs index 1b6794ae698..de6453c6a82 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.rs +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ revisions: local remapped // [local] no-remap-src-base: The hack should work regardless of remapping. diff --git a/tests/ui/proc-macro/pretty-print-tts.rs b/tests/ui/proc-macro/pretty-print-tts.rs index e3240e27c2a..b1b4f278e2a 100644 --- a/tests/ui/proc-macro/pretty-print-tts.rs +++ b/tests/ui/proc-macro/pretty-print-tts.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/proc-macro-attributes.rs b/tests/ui/proc-macro/proc-macro-attributes.rs index 6d5e7b67c78..455fcc56e58 100644 --- a/tests/ui/proc-macro/proc-macro-attributes.rs +++ b/tests/ui/proc-macro/proc-macro-attributes.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-b.rs +//@ proc-macro: derive-b.rs #[macro_use] extern crate derive_b; diff --git a/tests/ui/proc-macro/proc-macro-gates.rs b/tests/ui/proc-macro/proc-macro-gates.rs index 585d9a3c9be..bf384bc479b 100644 --- a/tests/ui/proc-macro/proc-macro-gates.rs +++ b/tests/ui/proc-macro/proc-macro-gates.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // gate-test-proc_macro_hygiene #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/proc-macro-gates2.rs b/tests/ui/proc-macro/proc-macro-gates2.rs index 76d8036d8a4..450f64982b0 100644 --- a/tests/ui/proc-macro/proc-macro-gates2.rs +++ b/tests/ui/proc-macro/proc-macro-gates2.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/raw-ident.rs b/tests/ui/proc-macro/raw-ident.rs index 2ea2d3079dc..95ada295f5c 100644 --- a/tests/ui/proc-macro/raw-ident.rs +++ b/tests/ui/proc-macro/raw-ident.rs @@ -1,4 +1,4 @@ -//@ aux-build:raw-ident.rs +//@ proc-macro: raw-ident.rs #[macro_use] extern crate raw_ident; diff --git a/tests/ui/proc-macro/resolve-error.rs b/tests/ui/proc-macro/resolve-error.rs index 2670d8884ae..0ca250194f0 100644 --- a/tests/ui/proc-macro/resolve-error.rs +++ b/tests/ui/proc-macro/resolve-error.rs @@ -1,6 +1,6 @@ -//@ aux-build:derive-foo.rs -//@ aux-build:derive-clona.rs -//@ aux-build:test-macros.rs +//@ proc-macro: derive-foo.rs +//@ proc-macro: derive-clona.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate derive_foo; diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr index e7639f474c7..963298311ef 100644 --- a/tests/ui/proc-macro/resolve-error.stderr +++ b/tests/ui/proc-macro/resolve-error.stderr @@ -4,7 +4,7 @@ error: cannot find macro `bang_proc_macrp` in this scope LL | bang_proc_macrp!(); | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` | - ::: $DIR/auxiliary/test-macros.rs:15:1 + ::: $DIR/auxiliary/test-macros.rs:10:1 | LL | pub fn empty(_: TokenStream) -> TokenStream { | ------------------------------------------- similarly named macro `bang_proc_macro` defined here @@ -53,7 +53,7 @@ error: cannot find derive macro `Dlona` in this scope LL | #[derive(Dlona)] | ^^^^^ help: a derive macro with a similar name exists: `Clona` | - ::: $DIR/auxiliary/derive-clona.rs:11:1 + ::: $DIR/auxiliary/derive-clona.rs:6:1 | LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { | ------------------------------------------------------- similarly named derive macro `Clona` defined here @@ -64,7 +64,7 @@ error: cannot find derive macro `Dlona` in this scope LL | #[derive(Dlona)] | ^^^^^ help: a derive macro with a similar name exists: `Clona` | - ::: $DIR/auxiliary/derive-clona.rs:11:1 + ::: $DIR/auxiliary/derive-clona.rs:6:1 | LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { | ------------------------------------------------------- similarly named derive macro `Clona` defined here @@ -103,7 +103,7 @@ error: cannot find attribute `attr_proc_macra` in this scope LL | #[attr_proc_macra] | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` | - ::: $DIR/auxiliary/test-macros.rs:20:1 + ::: $DIR/auxiliary/test-macros.rs:15:1 | LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here @@ -114,7 +114,7 @@ error: cannot find derive macro `FooWithLongNan` in this scope LL | #[derive(FooWithLongNan)] | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` | - ::: $DIR/auxiliary/derive-foo.rs:11:1 + ::: $DIR/auxiliary/derive-foo.rs:6:1 | LL | pub fn derive_foo(input: TokenStream) -> TokenStream { | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here @@ -125,7 +125,7 @@ error: cannot find derive macro `FooWithLongNan` in this scope LL | #[derive(FooWithLongNan)] | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` | - ::: $DIR/auxiliary/derive-foo.rs:11:1 + ::: $DIR/auxiliary/derive-foo.rs:6:1 | LL | pub fn derive_foo(input: TokenStream) -> TokenStream { | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here diff --git a/tests/ui/proc-macro/resolved-located-at.rs b/tests/ui/proc-macro/resolved-located-at.rs index 2f906d91e6b..c932c401896 100644 --- a/tests/ui/proc-macro/resolved-located-at.rs +++ b/tests/ui/proc-macro/resolved-located-at.rs @@ -1,4 +1,4 @@ -//@ aux-build:resolved-located-at.rs +//@ proc-macro: resolved-located-at.rs #[macro_use] extern crate resolved_located_at; diff --git a/tests/ui/proc-macro/shadow.rs b/tests/ui/proc-macro/shadow.rs index 22aecb7c05f..bcb38f97dbf 100644 --- a/tests/ui/proc-macro/shadow.rs +++ b/tests/ui/proc-macro/shadow.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/smoke.rs b/tests/ui/proc-macro/smoke.rs index dc32adb2e27..667112837c1 100644 --- a/tests/ui/proc-macro/smoke.rs +++ b/tests/ui/proc-macro/smoke.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(path_statements)] -//@ aux-build:derive-a.rs +//@ proc-macro: derive-a.rs #[macro_use] extern crate derive_a; diff --git a/tests/ui/proc-macro/span-absolute-posititions.rs b/tests/ui/proc-macro/span-absolute-posititions.rs index ddbc5902d6b..fc9f06a9e9f 100644 --- a/tests/ui/proc-macro/span-absolute-posititions.rs +++ b/tests/ui/proc-macro/span-absolute-posititions.rs @@ -1,4 +1,4 @@ -//@ aux-build:assert-span-pos.rs +//@ proc-macro: assert-span-pos.rs // ignore-tidy-tab extern crate assert_span_pos; diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs index 1e00f3ad7ac..ac42a7ea611 100644 --- a/tests/ui/proc-macro/span-api-tests.rs +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:span-api-tests.rs +//@ proc-macro: span-api-tests.rs //@ aux-build:span-test-macros.rs //@ compile-flags: -Ztranslate-remapped-path-to-local-path=yes diff --git a/tests/ui/proc-macro/span-from-proc-macro.rs b/tests/ui/proc-macro/span-from-proc-macro.rs index 9d851d62d12..4e12a695a5c 100644 --- a/tests/ui/proc-macro/span-from-proc-macro.rs +++ b/tests/ui/proc-macro/span-from-proc-macro.rs @@ -1,5 +1,5 @@ -//@ aux-build:custom-quote.rs -//@ aux-build:span-from-proc-macro.rs +//@ proc-macro: custom-quote.rs +//@ proc-macro: span-from-proc-macro.rs //@ compile-flags: -Z macro-backtrace #[macro_use] diff --git a/tests/ui/proc-macro/span-from-proc-macro.stderr b/tests/ui/proc-macro/span-from-proc-macro.stderr index 7beed505a7e..452c04df877 100644 --- a/tests/ui/proc-macro/span-from-proc-macro.stderr +++ b/tests/ui/proc-macro/span-from-proc-macro.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `MissingType` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 + --> $DIR/auxiliary/span-from-proc-macro.rs:33:20 | LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]` @@ -13,7 +13,7 @@ LL | #[error_from_attribute] | ----------------------- in this procedural macro expansion error[E0412]: cannot find type `OtherMissingType` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:46:21 + --> $DIR/auxiliary/span-from-proc-macro.rs:42:21 | LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream { | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]` @@ -27,7 +27,7 @@ LL | #[derive(ErrorFromDerive)] | --------------- in this derive macro expansion error[E0425]: cannot find value `my_ident` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:29:9 + --> $DIR/auxiliary/span-from-proc-macro.rs:25:9 | LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!` @@ -41,7 +41,7 @@ LL | other_error_from_bang!(); | ------------------------ in this macro invocation error[E0308]: mismatched types - --> $DIR/auxiliary/span-from-proc-macro.rs:16:36 + --> $DIR/auxiliary/span-from-proc-macro.rs:12:36 | LL | let bang_error: bool = 25; | ---- ^^ expected `bool`, found integer diff --git a/tests/ui/proc-macro/span-preservation.rs b/tests/ui/proc-macro/span-preservation.rs index 25a44505c77..fc914865678 100644 --- a/tests/ui/proc-macro/span-preservation.rs +++ b/tests/ui/proc-macro/span-preservation.rs @@ -1,7 +1,7 @@ // For each of these, we should get the appropriate type mismatch error message, // and the function should be echoed. -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/struct-field-macro.rs b/tests/ui/proc-macro/struct-field-macro.rs index b2c3dd49de9..9b1ddcaf274 100644 --- a/tests/ui/proc-macro/struct-field-macro.rs +++ b/tests/ui/proc-macro/struct-field-macro.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-nothing.rs +//@ proc-macro: derive-nothing.rs #[macro_use] extern crate derive_nothing; diff --git a/tests/ui/proc-macro/subspan.rs b/tests/ui/proc-macro/subspan.rs index 78804cba342..a87b11f3288 100644 --- a/tests/ui/proc-macro/subspan.rs +++ b/tests/ui/proc-macro/subspan.rs @@ -1,4 +1,4 @@ -//@ aux-build:subspan.rs +//@ proc-macro: subspan.rs extern crate subspan; diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs index 9e76deab9ce..b36910a414b 100644 --- a/tests/ui/proc-macro/test.rs +++ b/tests/ui/proc-macro/test.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:api/mod.rs +//@ proc-macro: api/proc_macro_api_tests.rs //@ edition: 2021 //! This is for everything that *would* be a #[test] inside of libproc_macro, diff --git a/tests/ui/proc-macro/three-equals.rs b/tests/ui/proc-macro/three-equals.rs index d16fc55656c..ad528e144b0 100644 --- a/tests/ui/proc-macro/three-equals.rs +++ b/tests/ui/proc-macro/three-equals.rs @@ -1,4 +1,4 @@ -//@ aux-build:three-equals.rs +//@ proc-macro: three-equals.rs extern crate three_equals; diff --git a/tests/ui/proc-macro/trailing-plus.rs b/tests/ui/proc-macro/trailing-plus.rs index 875225c15ca..a69ec510bed 100644 --- a/tests/ui/proc-macro/trailing-plus.rs +++ b/tests/ui/proc-macro/trailing-plus.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/trait-fn-args-2015.rs b/tests/ui/proc-macro/trait-fn-args-2015.rs index 389bb5b6a92..c25bd768efe 100644 --- a/tests/ui/proc-macro/trait-fn-args-2015.rs +++ b/tests/ui/proc-macro/trait-fn-args-2015.rs @@ -1,7 +1,7 @@ // Unnamed arguments in trait functions can be passed through proc macros on 2015 edition. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![allow(anonymous_parameters)] diff --git a/tests/ui/proc-macro/unsafe-foreign-mod.rs b/tests/ui/proc-macro/unsafe-foreign-mod.rs index b863b0fc114..e1e4ce96f1f 100644 --- a/tests/ui/proc-macro/unsafe-foreign-mod.rs +++ b/tests/ui/proc-macro/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-only-syntax.rs +//@ proc-macro: macro-only-syntax.rs extern crate macro_only_syntax; diff --git a/tests/ui/proc-macro/unsafe-mod.rs b/tests/ui/proc-macro/unsafe-mod.rs index 00ea388af93..f8453c2f62c 100644 --- a/tests/ui/proc-macro/unsafe-mod.rs +++ b/tests/ui/proc-macro/unsafe-mod.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-only-syntax.rs +//@ proc-macro: macro-only-syntax.rs #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/weird-braces.rs b/tests/ui/proc-macro/weird-braces.rs index b17b90742b5..1197156f6b0 100644 --- a/tests/ui/proc-macro/weird-braces.rs +++ b/tests/ui/proc-macro/weird-braces.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/weird-hygiene.rs b/tests/ui/proc-macro/weird-hygiene.rs index 8b35898a4d2..de55484109a 100644 --- a/tests/ui/proc-macro/weird-hygiene.rs +++ b/tests/ui/proc-macro/weird-hygiene.rs @@ -1,4 +1,4 @@ -//@ aux-build:weird-hygiene.rs +//@ proc-macro: weird-hygiene.rs #![feature(stmt_expr_attributes)] #![feature(proc_macro_hygiene)] diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs index 314ccaea015..a4a71c94020 100644 --- a/tests/ui/process/env-funky-keys.rs +++ b/tests/ui/process/env-funky-keys.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ edition: 2021 // Ignore this test on Android, because it segfaults there. //@ ignore-android @@ -32,10 +33,9 @@ fn main() { .unwrap() .as_os_str() .as_bytes()).unwrap(); - let new_env_var = CString::new("FOOBAR").unwrap(); let filename: *const c_char = current_exe.as_ptr(); let argv: &[*const c_char] = &[filename, filename, ptr::null()]; - let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()]; + let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()]; unsafe { execve(filename, &argv[0], &envp[0]); } diff --git a/tests/ui/process/println-with-broken-pipe.run.stderr b/tests/ui/process/println-with-broken-pipe.run.stderr index f9d138a0424..a334c0ad204 100644 --- a/tests/ui/process/println-with-broken-pipe.run.stderr +++ b/tests/ui/process/println-with-broken-pipe.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at std/src/io/stdio.rs:LL:CC: +thread 'main' panicked at library/std/src/io/stdio.rs:LL:CC: failed printing to stdout: Broken pipe (os error 32) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/resolve/auxiliary/issue-112831-aux.rs b/tests/ui/resolve/auxiliary/issue-112831-aux.rs index e5c1486d8ae..7d258299c18 100644 --- a/tests/ui/resolve/auxiliary/issue-112831-aux.rs +++ b/tests/ui/resolve/auxiliary/issue-112831-aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; struct Zeroable; diff --git a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs index c0b24706dcb..9a9e0eb3ff7 100644 --- a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs +++ b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -//@ compile-flags: --crate-type proc-macro - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/resolve/derive-macro-1.rs b/tests/ui/resolve/derive-macro-1.rs index f4fbb1d2c7c..d39eeba2e6c 100644 --- a/tests/ui/resolve/derive-macro-1.rs +++ b/tests/ui/resolve/derive-macro-1.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-112831-aux.rs +//@ proc-macro: issue-112831-aux.rs mod z { pub trait Zeroable {} diff --git a/tests/ui/resolve/derive-macro-2.rs b/tests/ui/resolve/derive-macro-2.rs index 126f5ae107f..71d791eaef8 100644 --- a/tests/ui/resolve/derive-macro-2.rs +++ b/tests/ui/resolve/derive-macro-2.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-112831-aux.rs +//@ proc-macro: issue-112831-aux.rs extern crate issue_112831_aux; use issue_112831_aux::Zeroable; diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index fbb9ede8aa1..c7e9df10d41 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -29,6 +29,20 @@ LL | const _: u32 = T::C; | = note: a `const` is a separate item from the item that contains it +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 60aa94038c3..64c436d3ceb 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -35,6 +35,20 @@ LL | const _: u32 = T::C; | = note: a `const` is a separate item from the item that contains it +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr index 24fb3d580b8..427dc9f2049 100644 --- a/tests/ui/resolve/issue-50599.stderr +++ b/tests/ui/resolve/issue-50599.stderr @@ -20,6 +20,12 @@ LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; LL + const M: usize = (f64::from(N) * LOG10_2) as usize; | +note: erroneous constant encountered + --> $DIR/issue-50599.rs:4:29 + | +LL | let mut digits = [0u32; M]; + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/proc_macro_generated_packed.rs b/tests/ui/resolve/proc_macro_generated_packed.rs index e8d04f808d0..8459fb79f1e 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.rs +++ b/tests/ui/resolve/proc_macro_generated_packed.rs @@ -1,7 +1,7 @@ //! This test ICEs because the `repr(packed)` attribute //! was generated by a proc macro, so `#[derive]` didn't see it. -//@aux-build: proc_macro_generate_packed.rs +//@proc-macro: proc_macro_generate_packed.rs //@known-bug: #120873 //@ failure-status: 101 //@ normalize-stderr-test: "note: .*\n\n" -> "" diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr index 606f808f093..eab2604d4c0 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr @@ -6,5 +6,11 @@ LL | !let y = 42; | = note: only supported directly in conditions of `if` and `while` expressions +note: erroneous constant encountered + --> $DIR/avoid-invalid-mir.rs:11:13 + | +LL | x: [(); N] + | ^ + error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs index 93c2901fe66..176ba837043 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs index c427cf7af6d..9a813666c33 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs index 17b59009bb8..cd97587bf03 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs @@ -1,4 +1,4 @@ -//@ aux-build:param-attrs.rs +//@ proc-macro: param-attrs.rs //@ check-pass diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs index 6ed2d4fad0e..89864348eda 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs @@ -1,4 +1,4 @@ -//@ aux-build:param-attrs.rs +//@ proc-macro: param-attrs.rs //@ check-pass diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs index c1e6a92e317..049c5b32cb3 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -1,4 +1,4 @@ -//@ aux-build:ident-mac.rs +//@ proc-macro: ident-mac.rs #![feature(c_variadic)] #![allow(anonymous_parameters)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs index e7c560a2c35..aebf8d1e0fc 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs @@ -1,7 +1,4 @@ -//@ force-host //@ edition: 2018 -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs index 57c1ba05560..414d5518e1f 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs @@ -6,7 +6,7 @@ //@ edition: 2021 //@ check-pass -//@ aux-build: count.rs +//@ proc-macro: count.rs extern crate count; const _: () = { diff --git a/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs index d8e5eb884cf..bccde8e8de7 100644 --- a/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs +++ b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed index f94bf2d66d3..e3070ba150b 100644 --- a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed @@ -1,4 +1,4 @@ -//@ aux-build:suggestions-not-always-applicable.rs +//@ proc-macro: suggestions-not-always-applicable.rs //@ edition:2015 //@ run-rustfix //@ rustfix-only-machine-applicable diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/suggestions-not-always-applicable.rs index f94bf2d66d3..e3070ba150b 100644 --- a/tests/ui/rust-2018/suggestions-not-always-applicable.rs +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.rs @@ -1,4 +1,4 @@ -//@ aux-build:suggestions-not-always-applicable.rs +//@ proc-macro: suggestions-not-always-applicable.rs //@ edition:2015 //@ run-rustfix //@ rustfix-only-machine-applicable diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs index 1273969c4af..469c2e7f8d9 100644 --- a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2018 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs index b68701a5165..cfc39d5208b 100644 --- a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2021 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs index b64761b55e9..6c0c7b38c01 100644 --- a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs @@ -1,6 +1,6 @@ //@ edition:2018 -//@ aux-build:reserved-prefixes-macro-2018.rs -//@ aux-build:reserved-prefixes-macro-2021.rs +//@ proc-macro: reserved-prefixes-macro-2018.rs +//@ proc-macro: reserved-prefixes-macro-2021.rs extern crate reserved_prefixes_macro_2018 as m2018; extern crate reserved_prefixes_macro_2021 as m2021; diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs index 85f894d7f79..eec1b859c20 100644 --- a/tests/ui/rust-2021/reserved-prefixes-via-macro.rs +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ edition:2021 -//@ aux-build:reserved-prefixes-macro-2018.rs +//@ proc-macro: reserved-prefixes-macro-2018.rs extern crate reserved_prefixes_macro_2018 as m2018; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs index 81080fcdce3..ab23e63c0da 100644 --- a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2021 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs index aa655942150..0fa908411f5 100644 --- a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2024 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs index 7bf5118c340..0f0120b721f 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed index 44850c8c45b..ff8c4beca6b 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr index 496b3197c34..15a3fa11414 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `poll` will become ambiguous in Rust 2024 - --> $DIR/future-poll-async-block.rs:14:5 + --> $DIR/future-poll-async-block.rs:13:5 | LL | core::pin::pin!(async {}).poll(&mut context()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())` @@ -7,7 +7,7 @@ LL | core::pin::pin!(async {}).poll(&mut context()); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html> note: the lint level is defined here - --> $DIR/future-poll-async-block.rs:8:9 + --> $DIR/future-poll-async-block.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs index 614e4c786c5..60b0b2689c2 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed index c96d1dcecc2..f68729e483a 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr index 020a00ccdec..633731c2a5a 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `poll` will become ambiguous in Rust 2024 - --> $DIR/future-poll-not-future-pinned.rs:18:5 + --> $DIR/future-poll-not-future-pinned.rs:17:5 | LL | core::pin::pin!(()).poll(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(()))` @@ -7,7 +7,7 @@ LL | core::pin::pin!(()).poll(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html> note: the lint level is defined here - --> $DIR/future-poll-not-future-pinned.rs:8:9 + --> $DIR/future-poll-not-future-pinned.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs index 21b170a5f1d..4845ef779e0 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs index 899b69ebfc2..36578e28b80 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed index 0b0873eb238..03bf4ab19c1 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr index b74e80e2a4a..e67f07b4e46 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `into_future` will become ambiguous in Rust 2024 - --> $DIR/into-future-adt.rs:26:5 + --> $DIR/into-future-adt.rs:25:5 | LL | Cat.into_future(); | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` @@ -7,7 +7,7 @@ LL | Cat.into_future(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html> note: the lint level is defined here - --> $DIR/into-future-adt.rs:8:9 + --> $DIR/into-future-adt.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs index 0db70930bc7..65edc88baab 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs index 6bc2ea31705..16ac89759f3 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed index a798014d93d..4e082883395 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr index 6ea4580ca72..0588f5bf3f5 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `into_future` will become ambiguous in Rust 2024 - --> $DIR/into-future-not-into-future.rs:20:5 + --> $DIR/into-future-not-into-future.rs:19:5 | LL | Cat.into_future(); | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` @@ -7,7 +7,7 @@ LL | Cat.into_future(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html> note: the lint level is defined here - --> $DIR/into-future-not-into-future.rs:8:9 + --> $DIR/into-future-not-into-future.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs index 23e81cfe6b4..f640d9b50bb 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs index 83e0dcbb4be..43413f7470e 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs @@ -26,24 +26,24 @@ macro_rules! demo7 { fn main() { demo3!(## "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(### "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(## "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo7!(### "foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo5!(###"foo"#); @@ -56,14 +56,14 @@ fn main() { demo5!(#"foo"###); //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 // Non-ascii identifiers diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr index e2e1ac42f05..4d54a08617b 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr @@ -28,7 +28,7 @@ error: identifiers cannot contain emoji: `🙃` LL | demo3!(🙃#""); | ^^ -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:28:12 | LL | demo3!(## "foo"); @@ -41,12 +41,12 @@ note: the lint level is defined here | LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo3!(# # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:31:12 | LL | demo4!(### "foo"); @@ -54,12 +54,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# ## "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:31:13 | LL | demo4!(### "foo"); @@ -67,12 +67,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(## # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:36:12 | LL | demo4!(## "foo"#); @@ -80,12 +80,12 @@ LL | demo4!(## "foo"#); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# # "foo"#); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:12 | LL | demo7!(### "foo"###); @@ -93,12 +93,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(# ## "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:13 | LL | demo7!(### "foo"###); @@ -106,12 +106,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(## # "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:21 | LL | demo7!(### "foo"###); @@ -119,12 +119,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(### "foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:22 | LL | demo7!(### "foo"###); @@ -132,7 +132,7 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(### "foo"## #); | + @@ -189,7 +189,7 @@ help: insert whitespace here to avoid this being parsed as a guarded string in R LL | demo5!(# "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:56:18 | LL | demo5!(#"foo"###); @@ -197,12 +197,12 @@ LL | demo5!(#"foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(#"foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:56:19 | LL | demo5!(#"foo"###); @@ -210,12 +210,12 @@ LL | demo5!(#"foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(#"foo"## #); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:63:17 | LL | demo4!("foo"###); @@ -223,12 +223,12 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:63:18 | LL | demo4!("foo"###); @@ -236,7 +236,7 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"## #); | + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed index d92df7b5375..ef00ed3f610 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed @@ -38,28 +38,28 @@ fn main() { demo2!("foo"#); demo3!(# # "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(# # # "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(# # "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo6!(# # # "foo"# #); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"# # #); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo2!(# ""); @@ -94,6 +94,6 @@ fn main() { //~| WARNING hard error in Rust 2024 //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 } diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs index 5905f2abe32..cf2d8716ad2 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs @@ -38,28 +38,28 @@ fn main() { demo2!("foo"#); demo3!(## "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(### "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(## "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo6!(### "foo"##); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo2!(#""); @@ -94,6 +94,6 @@ fn main() { //~| WARNING hard error in Rust 2024 //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 } diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr index d7f8e5c9b4b..b17ae941ef4 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr @@ -1,4 +1,4 @@ -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:40:12 | LL | demo3!(## "foo"); @@ -11,12 +11,12 @@ note: the lint level is defined here | LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo3!(# # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:43:12 | LL | demo4!(### "foo"); @@ -24,12 +24,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# ## "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:43:13 | LL | demo4!(### "foo"); @@ -37,12 +37,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(## # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:48:12 | LL | demo4!(## "foo"#); @@ -50,12 +50,12 @@ LL | demo4!(## "foo"#); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# # "foo"#); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:12 | LL | demo6!(### "foo"##); @@ -63,12 +63,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(# ## "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:13 | LL | demo6!(### "foo"##); @@ -76,12 +76,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(## # "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:21 | LL | demo6!(### "foo"##); @@ -89,12 +89,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(### "foo"# #); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:59:17 | LL | demo4!("foo"###); @@ -102,12 +102,12 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:59:18 | LL | demo4!("foo"###); @@ -115,7 +115,7 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"## #); | + @@ -276,7 +276,7 @@ help: insert whitespace here to avoid this being parsed as a guarded string in R LL | demo5!(## "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:92:19 | LL | demo5!(##"foo"##); @@ -284,7 +284,7 @@ LL | demo5!(##"foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735> -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(##"foo"# #); | + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs index 3f9f373ba22..6b0103d4a50 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs @@ -1,6 +1,6 @@ //@ edition:2021 -//@ aux-build:reserved-guarded-strings-macro-2021.rs -//@ aux-build:reserved-guarded-strings-macro-2024.rs +//@ proc-macro: reserved-guarded-strings-macro-2021.rs +//@ proc-macro: reserved-guarded-strings-macro-2024.rs extern crate reserved_guarded_strings_macro_2021 as m2021; extern crate reserved_guarded_strings_macro_2024 as m2024; diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs index 882f52c48a6..ead2ab40b77 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ edition:2024 -//@ aux-build:reserved-guarded-strings-macro-2021.rs +//@ proc-macro: reserved-guarded-strings-macro-2021.rs extern crate reserved_guarded_strings_macro_2021 as m2021; diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs index 878881c1d24..ae68d34cb86 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings.rs @@ -46,13 +46,13 @@ fn main() { //~^ ERROR prefix `blah` is unknown //~| ERROR invalid string literal - demo2!(## "foo"); //~ ERROR invalid string literal - demo3!("foo"###); //~ ERROR invalid string literal - demo3!(### "foo"); //~ ERROR invalid string literal - demo3!(## "foo"#); //~ ERROR invalid string literal + demo2!(## "foo"); //~ reserved multi-hash token is forbidden + demo3!("foo"###); //~ reserved multi-hash token is forbidden + demo3!(### "foo"); //~ reserved multi-hash token is forbidden + demo3!(## "foo"#); //~ reserved multi-hash token is forbidden demo5!(### "foo"###); - //~^ ERROR invalid string literal - //~| ERROR invalid string literal + //~^ reserved multi-hash token is forbidden + //~| reserved multi-hash token is forbidden demo1!(#""); //~ ERROR invalid string literal demo1!(#""#); //~ ERROR invalid string literal @@ -65,7 +65,7 @@ fn main() { demo1!(###"foo"###); //~ ERROR invalid string literal demo2!(#"foo"###); //~^ ERROR invalid string literal - //~| ERROR invalid string literal + //~| ERROR reserved multi-hash token is forbidden // More than 255 hashes demon!(####################################################################################################################################################################################################################################################################"foo"); diff --git a/tests/ui/rust-2024/reserved-guarded-strings.stderr b/tests/ui/rust-2024/reserved-guarded-strings.stderr index c8f8557b0f4..0f3b06147c4 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings.stderr @@ -34,73 +34,73 @@ help: consider inserting whitespace here LL | demo2!(blah# "xx"#); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:49:12 | LL | demo2!(## "foo"); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo2!(# # "foo"); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:50:17 | LL | demo3!("foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!("foo"# ##); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:51:12 | LL | demo3!(### "foo"); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!(# ## "foo"); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:52:12 | LL | demo3!(## "foo"#); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!(# # "foo"#); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:53:12 | LL | demo5!(### "foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo5!(# ## "foo"###); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:53:21 | LL | demo5!(### "foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo5!(### "foo"# ##); @@ -226,13 +226,13 @@ help: consider inserting whitespace here LL | demo2!(# "foo"###); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:66:19 | LL | demo2!(#"foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo2!(#"foo"## #); diff --git a/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs index 557731d82d3..cab6af57cb1 100644 --- a/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs +++ b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs @@ -1,7 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] +//@ edition: 2018 extern crate proc_macro; diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs index 7c919fed976..79fba46c77f 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs index 782a3942236..e2c504e708c 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs @@ -5,8 +5,7 @@ //@ check-pass //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options -//@ aux-crate: unsafe_attributes_pm=unsafe-attributes-pm.rs +//@ proc-macro: unsafe-attributes-pm.rs unsafe_attributes_pm::missing_unsafe!(); diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr index fb697e14ef1..5c3927a0928 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes.rs:8:3 + --> $DIR/unsafe-attributes.rs:7:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs index f6f2994bb6d..4b161bc34ea 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs @@ -2,7 +2,6 @@ //@[edition2021] edition:2021 //@[edition2021] check-pass //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options #[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe diff --git a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr index 2798ccdefd0..10d0e8b830c 100644 --- a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `before_exec` is unsafe and requires unsafe block - --> $DIR/unsafe-before_exec.rs:14:5 + --> $DIR/unsafe-before_exec.rs:13:5 | LL | cmd.before_exec(|| Ok(())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/rust-2024/unsafe-before_exec.rs b/tests/ui/rust-2024/unsafe-before_exec.rs index 540394da80e..44a955e229d 100644 --- a/tests/ui/rust-2024/unsafe-before_exec.rs +++ b/tests/ui/rust-2024/unsafe-before_exec.rs @@ -3,7 +3,6 @@ //@[e2021] edition: 2021 //@[e2021] check-pass //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options use std::process::Command; use std::os::unix::process::CommandExt; diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr index 90c1df192aa..6f9618eb14b 100644 --- a/tests/ui/rust-2024/unsafe-env.e2021.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:15:9 + --> $DIR/unsafe-env.rs:14:9 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -7,18 +7,18 @@ LL | unsafe_fn(); = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668> = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/unsafe-env.rs:9:1 + --> $DIR/unsafe-env.rs:8:1 | LL | unsafe fn unsafe_fn() { | ^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/unsafe-env.rs:8:8 + --> $DIR/unsafe-env.rs:7:8 | LL | #[deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block - --> $DIR/unsafe-env.rs:33:5 + --> $DIR/unsafe-env.rs:32:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -26,13 +26,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:36:5 + --> $DIR/unsafe-env.rs:35:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:21:8 + --> $DIR/unsafe-env.rs:20:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr index 5ecdf3cd7a7..04a35933c79 100644 --- a/tests/ui/rust-2024/unsafe-env.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `std::env::set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:10:5 + --> $DIR/unsafe-env.rs:9:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,18 +7,18 @@ LL | env::set_var("FOO", "BAR"); = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668> = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/unsafe-env.rs:9:1 + --> $DIR/unsafe-env.rs:8:1 | LL | unsafe fn unsafe_fn() { | ^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/unsafe-env.rs:8:8 + --> $DIR/unsafe-env.rs:7:8 | LL | #[deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error[E0133]: call to unsafe function `std::env::remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:12:5 + --> $DIR/unsafe-env.rs:11:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -27,7 +27,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:15:9 + --> $DIR/unsafe-env.rs:14:9 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -36,7 +36,7 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:23:5 + --> $DIR/unsafe-env.rs:22:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -44,7 +44,7 @@ LL | env::set_var("FOO", "BAR"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:25:5 + --> $DIR/unsafe-env.rs:24:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -52,7 +52,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:33:5 + --> $DIR/unsafe-env.rs:32:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -60,13 +60,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:36:5 + --> $DIR/unsafe-env.rs:35:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:21:8 + --> $DIR/unsafe-env.rs:20:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs index 601f44e1d3e..4a7c646323a 100644 --- a/tests/ui/rust-2024/unsafe-env.rs +++ b/tests/ui/rust-2024/unsafe-env.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options use std::env; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index 77554da10e6..50201140cda 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:11:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:11:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index 33b752782d5..fa79d76546a 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:11:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:11:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index 721e07acca5..7bb4f666924 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index 8ef7c2caf21..17b49d8ed5c 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/extern-items.rs:7:1 + --> $DIR/extern-items.rs:6:1 | LL | / extern "C" { LL | | diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index 08805c36347..8c0b8bc8899 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -2,7 +2,6 @@ //@[edition2021] edition:2021 //@[edition2021] check-pass //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index b0b8a8b012a..2b2d58c3eb3 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass unsafe extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index ddc5477116f..07d934da24b 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,5 +1,5 @@ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:7:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | unsafe extern "C" { | ++++++ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:9:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index ae7b4cd47c0..cceb3bddef4 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:5:1 | LL | / extern "C" { LL | | @@ -11,7 +11,7 @@ LL | | } | |_^ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:7:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | unsafe extern "C" { | ++++++ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:9:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 89415a69f08..a5a6ccdffa0 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index e3626bb497e..9433dd1f2e5 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:17:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:17:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 89bc501b7b5..af86b4c5805 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:17:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:17:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index dc2bae892a9..50c97b51768 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { unsafe static TEST1: i32; diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr index cf4c219215e..e4991823d28 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -17,6 +17,12 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 { LL | } | - value is dropped here +note: erroneous constant encountered + --> $DIR/arbitrary-self-from-method-substs-ice.rs:24:5 + | +LL | FOO; + | ^^^ + error[E0801]: invalid generic `self` parameter type: `R` --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49 | diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index 9b14d410acb..24b9941133e 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -23,6 +23,7 @@ extern "rust-intrinsic" { fn simd_fexp<T>(x: T) -> T; fn simd_fexp2<T>(x: T) -> T; fn simd_fma<T>(x: T, y: T, z: T) -> T; + fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T; fn simd_flog<T>(x: T) -> T; fn simd_flog10<T>(x: T) -> T; fn simd_flog2<T>(x: T) -> T; @@ -77,6 +78,9 @@ fn main() { let r = simd_fma(x, h, h); assert_approx_eq!(x, r); + let r = simd_relaxed_fma(x, h, h); + assert_approx_eq!(x, r); + let r = simd_fsqrt(x); assert_approx_eq!(x, r); diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs index 1961f10bd0a..a8fadcc1d1e 100644 --- a/tests/ui/structs-enums/type-sizes.rs +++ b/tests/ui/structs-enums/type-sizes.rs @@ -5,6 +5,7 @@ #![allow(dead_code)] #![feature(never_type)] #![feature(pointer_is_aligned_to)] +#![feature(rustc_attrs)] use std::mem::size_of; use std::num::NonZero; @@ -237,6 +238,10 @@ struct VecDummy { len: usize, } +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_layout_scalar_valid_range_end(100)] +struct PointerWithRange(#[allow(dead_code)] *const u8); + pub fn main() { assert_eq!(size_of::<u8>(), 1 as usize); assert_eq!(size_of::<u32>(), 4 as usize); @@ -354,4 +359,6 @@ pub fn main() { assert!(ptr::from_ref(&v.a).addr() > ptr::from_ref(&v.b).addr()); + assert_eq!(size_of::<Option<PointerWithRange>>(), size_of::<PointerWithRange>()); + assert_eq!(size_of::<Option<Option<PointerWithRange>>>(), size_of::<PointerWithRange>()); } diff --git a/tests/ui/suggestions/auxiliary/issue-61963-1.rs b/tests/ui/suggestions/auxiliary/issue-61963-1.rs index 33e5f9db2c3..2e7b0dbef19 100644 --- a/tests/ui/suggestions/auxiliary/issue-61963-1.rs +++ b/tests/ui/suggestions/auxiliary/issue-61963-1.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Group, TokenStream, TokenTree}; diff --git a/tests/ui/suggestions/auxiliary/issue-61963.rs b/tests/ui/suggestions/auxiliary/issue-61963.rs index bfea8061c4b..07e6f319585 100644 --- a/tests/ui/suggestions/auxiliary/issue-61963.rs +++ b/tests/ui/suggestions/auxiliary/issue-61963.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; diff --git a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs index aebc5a6aaa9..2930b87d1bb 100644 --- a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs +++ b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs index de82700d7e4..2fafe629db9 100644 --- a/tests/ui/suggestions/issue-61963.rs +++ b/tests/ui/suggestions/issue-61963.rs @@ -1,5 +1,5 @@ -//@ aux-build:issue-61963.rs -//@ aux-build:issue-61963-1.rs +//@ proc-macro: issue-61963.rs +//@ proc-macro: issue-61963-1.rs #![deny(bare_trait_objects)] #[macro_use] diff --git a/tests/ui/suggestions/suggest-ref-macro.rs b/tests/ui/suggestions/suggest-ref-macro.rs index e5084e54115..2f31af33782 100644 --- a/tests/ui/suggestions/suggest-ref-macro.rs +++ b/tests/ui/suggestions/suggest-ref-macro.rs @@ -1,5 +1,5 @@ // run-check -//@ aux-build:proc-macro-type-error.rs +//@ proc-macro: proc-macro-type-error.rs extern crate proc_macro_type_error; diff --git a/tests/ui/suggestions/trait-hidden-method.rs b/tests/ui/suggestions/trait-hidden-method.rs index ae7ef47e1d4..1efc1cc6fae 100644 --- a/tests/ui/suggestions/trait-hidden-method.rs +++ b/tests/ui/suggestions/trait-hidden-method.rs @@ -1,8 +1,6 @@ // #107983 - testing that `__iterator_get_unchecked` isn't suggested // HELP included so that compiletest errors on the bad suggestion pub fn i_can_has_iterator() -> impl Iterator<Item = u32> { - //~^ ERROR expected `Box<dyn Iterator>` - //~| HELP consider constraining the associated type Box::new(1..=10) as Box<dyn Iterator> //~^ ERROR the value of the associated type `Item` //~| HELP specify the associated type diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr index 729523cde55..87753e57846 100644 --- a/tests/ui/suggestions/trait-hidden-method.stderr +++ b/tests/ui/suggestions/trait-hidden-method.stderr @@ -1,24 +1,9 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/trait-hidden-method.rs:6:33 + --> $DIR/trait-hidden-method.rs:4:33 | LL | Box::new(1..=10) as Box<dyn Iterator> | ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>` -error[E0271]: expected `Box<dyn Iterator>` to be an iterator that yields `u32`, but it yields `<dyn Iterator as Iterator>::Item` - --> $DIR/trait-hidden-method.rs:3:32 - | -LL | pub fn i_can_has_iterator() -> impl Iterator<Item = u32> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type -... -LL | Box::new(1..=10) as Box<dyn Iterator> - | ------------------------------------- return type was inferred to be `Box<dyn Iterator>` here - | - = note: expected type `u32` - found associated type `<dyn Iterator as Iterator>::Item` - = help: consider constraining the associated type `<dyn Iterator as Iterator>::Item` to `u32` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0191, E0271. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr index 86bd07a5f59..c7af0a220ca 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not sati --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::<U>::func(); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | <T as Trait>::Assoc::<U>::func(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr index 145fe2c41dd..99fc924ad06 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | <T as Trait>::Assoc::func(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/call-const-closure.stderr b/tests/ui/traits/const-traits/call-const-closure.stderr index 3fed67f5d08..fe7c115aaab 100644 --- a/tests/ui/traits/const-traits/call-const-closure.stderr +++ b/tests/ui/traits/const-traits/call-const-closure.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): ~const Bar` is not satisfied - --> $DIR/call-const-closure.rs:17:15 + --> $DIR/call-const-closure.rs:17:18 | LL | (const || ().foo())(); - | ^^^^^^^^ + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr index e56968b9097..b9dabceb5de 100644 --- a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr +++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: const Foo` is not satisfied --> $DIR/call-const-in-tilde-const.rs:9:13 | LL | const { T::foo() } - | ^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr index b461fd9e39e..64850335c2a 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied --> $DIR/call-const-trait-method-fail.rs:26:5 | LL | a.plus(b) - | ^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr index d881bd5f4de..74a22186a16 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `S: const Foo` is not satisfied - --> $DIR/call-generic-method-nonconst.rs:24:22 + --> $DIR/call-generic-method-nonconst.rs:24:34 | LL | pub const EQ: bool = equals_self(&S); - | ^^^^^^^^^^^^^^^ + | ----------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:17:25 + | +LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool { + | ^^^^^^ required by this bound in `equals_self` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr index 5879330f158..903f7d37f9d 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.stderr +++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied - --> $DIR/const-default-method-bodies.rs:25:5 + --> $DIR/const-default-method-bodies.rs:25:18 | LL | NonConstImpl.a(); - | ^^^^^^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr index 60718cc84c1..78ba0279566 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.stderr +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `Foo<E>: ~const Destruct` is not satisfied - --> $DIR/const-drop-bound.rs:23:5 + --> $DIR/const-drop-bound.rs:23:9 | LL | foo(res) - | ^^^^^^^^ + | --- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/const-drop-bound.rs:9:61 + | +LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct { + | ^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr index bb9966c7ec3..7b2cafb6124 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:15 + --> $DIR/const-drop-fail-2.rs:31:23 | -LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( - | _______________^ -LL | | -LL | | ConstDropImplWithBounds(PhantomData) -LL | | ); - | |_^ +LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail-2.rs:21:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr index bb9966c7ec3..7b2cafb6124 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:15 + --> $DIR/const-drop-fail-2.rs:31:23 | -LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( - | _______________^ -LL | | -LL | | ConstDropImplWithBounds(PhantomData) -LL | | ); - | |_^ +LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail-2.rs:21:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr index 67e774fbd05..8b3e777a0b0 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr @@ -1,31 +1,32 @@ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:32:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ | - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:34:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs index 08435266e1f..5e05b9db474 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.rs +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -25,14 +25,14 @@ const fn check<T: ~const Destruct>(_: T) {} macro_rules! check_all { ($($exp:expr),*$(,)?) => {$( const _: () = check($exp); - //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied - //~| ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied )*}; } check_all! { NonTrivialDrop, + //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied } fn main() {} diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr index 67e774fbd05..8b3e777a0b0 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr @@ -1,31 +1,32 @@ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:32:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ | - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:34:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr index e43a6b603fd..1278e125746 100644 --- a/tests/ui/traits/const-traits/const-opaque.no.stderr +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -1,14 +1,22 @@ error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:31:18 + --> $DIR/const-opaque.rs:31:22 | LL | let opaque = bar(()); - | ^^^^^^^ + | --- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/const-opaque.rs:26:17 + | +LL | const fn bar<T: ~const Foo>(t: T) -> impl ~const Foo { + | ^^^^^^ required by this bound in `bar` error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:33:5 + --> $DIR/const-opaque.rs:33:12 | LL | opaque.method(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr index b6f2434140d..4d5abf643a8 100644 --- a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:19:5 + --> $DIR/cross-crate.rs:19:14 | LL | NonConst.func(); - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr index 0534f3eb8d2..8c284bde67e 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr @@ -1,8 +1,14 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-body-checking.rs:12:9 + --> $DIR/default-method-body-is-const-body-checking.rs:12:15 | LL | foo::<()>(); - | ^^^^^^^^^^^ + | ^^ + | +note: required by a bound in `foo` + --> $DIR/default-method-body-is-const-body-checking.rs:7:28 + | +LL | const fn foo<T>() where T: ~const Tr {} + | ^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr index d987cad6f14..2bd71c940e7 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:9 + --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12 | LL | ().a() - | ^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr b/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr index cf158643b34..fa8be631a26 100644 --- a/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr +++ b/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `(): ~const Foo` is not satisfied - --> $DIR/minicore-fn-fail.rs:19:5 + --> $DIR/minicore-fn-fail.rs:19:19 | LL | call_indirect(&foo::<()>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------- ^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `call_indirect` + --> $DIR/minicore-fn-fail.rs:11:27 + | +LL | const fn call_indirect<T: ~const Fn()>(t: &T) { t() } + | ^^^^^^ required by this bound in `call_indirect` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr index 0b8e4696c46..9bd2c2cb8da 100644 --- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr @@ -27,10 +27,10 @@ LL | trait Bar { | ^^^ error[E0277]: the trait bound `(): const Bar` is not satisfied - --> $DIR/no-explicit-const-params.rs:24:5 + --> $DIR/no-explicit-const-params.rs:24:6 | LL | <() as Bar<false>>::bar(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params.rs:15:5 diff --git a/tests/crashes/112623.rs b/tests/ui/traits/const-traits/eval-bad-signature.rs index 592ad742e5f..97c573ea652 100644 --- a/tests/crashes/112623.rs +++ b/tests/ui/traits/const-traits/eval-bad-signature.rs @@ -1,4 +1,4 @@ -//@ known-bug: #112623 +// Make sure we don't ICE when evaluating a trait whose impl has a bad signature. #![feature(const_trait_impl)] @@ -15,6 +15,7 @@ struct FortyTwo; impl const Value for FortyTwo { fn value() -> i64 { + //~^ ERROR method `value` has an incompatible type for trait 42 } } diff --git a/tests/ui/traits/const-traits/eval-bad-signature.stderr b/tests/ui/traits/const-traits/eval-bad-signature.stderr new file mode 100644 index 00000000000..a64cf631743 --- /dev/null +++ b/tests/ui/traits/const-traits/eval-bad-signature.stderr @@ -0,0 +1,21 @@ +error[E0053]: method `value` has an incompatible type for trait + --> $DIR/eval-bad-signature.rs:17:19 + | +LL | fn value() -> i64 { + | ^^^ expected `u32`, found `i64` + | +note: type in trait + --> $DIR/eval-bad-signature.rs:7:19 + | +LL | fn value() -> u32; + | ^^^ + = note: expected signature `fn() -> u32` + found signature `fn() -> i64` +help: change the output type to match the trait + | +LL | fn value() -> u32 { + | ~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs index ea1783b7c2c..c485fb12184 100644 --- a/tests/ui/traits/const-traits/hir-const-check.rs +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -11,9 +11,9 @@ pub trait MyTrait { impl const MyTrait for () { fn method(&self) -> Option<()> { - Some(())?; //~ ERROR `?` is not allowed in a `const fn` - //~^ ERROR `?` cannot determine the branch of `Option<()>` in constant functions - //~| ERROR `?` cannot convert from residual of `Option<()>` in constant functions + Some(())?; + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on None } } diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr index ef5dba0dc0e..d66a7ea3144 100644 --- a/tests/ui/traits/const-traits/hir-const-check.stderr +++ b/tests/ui/traits/const-traits/hir-const-check.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/hir-const-check.rs:14:9 | LL | Some(())?; | ^^^^^^^^^ | - = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions - --> $DIR/hir-const-check.rs:14:9 - | -LL | Some(())?; - | ^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/hir-const-check.rs:14:9 | LL | Some(())?; | ^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs index 9ce81031b27..3473be565c1 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -18,8 +18,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; - //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions - //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on TryMe } diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr index db047bfd94d..9bd493e5fdb 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr @@ -33,7 +33,7 @@ LL | impl const Try for TryMe { = help: implement the missing item: `fn from_output(_: <Self as Try>::Output) -> Self { todo!() }` = help: implement the missing item: `fn branch(self) -> ControlFlow<<Self as Try>::Residual, <Self as Try>::Output> { todo!() }` -error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/ice-126148-failed-to-normalize.rs:20:5 | LL | TryMe?; @@ -41,7 +41,7 @@ LL | TryMe?; | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/ice-126148-failed-to-normalize.rs:20:5 | LL | TryMe?; diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr new file mode 100644 index 00000000000..bd822970ad1 --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` + --> $DIR/overlap-const-with-nonconst.rs:23:1 + | +LL | / impl<T> const Foo for T +LL | | where +LL | | T: ~const Bar, + | |__________________- first implementation here +... +LL | impl<T> Foo for (T,) { + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs new file mode 100644 index 00000000000..eb66d03faa6 --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs @@ -0,0 +1,38 @@ +//@ revisions: spec min_spec + +#![feature(const_trait_impl)] +#![cfg_attr(spec, feature(specialization))] +//[spec]~^ WARN the feature `specialization` is incomplete +#![cfg_attr(min_spec, feature(min_specialization))] + +#[const_trait] +trait Bar {} +impl<T> const Bar for T {} + +#[const_trait] +trait Foo { + fn method(&self); +} +impl<T> const Foo for T +where + T: ~const Bar, +{ + default fn method(&self) {} +} +// specializing impl: +impl<T> Foo for (T,) { +//~^ ERROR conflicting implementations + fn method(&self) { + println!("hi"); + } +} + +const fn dispatch<T: ~const Bar + Copy>(t: T) { + t.method(); +} + +fn main() { + const { + dispatch(((),)); + } +} diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr new file mode 100644 index 00000000000..cbdcb45f6be --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-const-with-nonconst.rs:4:27 + | +LL | #![cfg_attr(spec, feature(specialization))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` + --> $DIR/overlap-const-with-nonconst.rs:23:1 + | +LL | / impl<T> const Foo for T +LL | | where +LL | | T: ~const Bar, + | |__________________- first implementation here +... +LL | impl<T> Foo for (T,) { + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr index bffc60c65fc..9166b8ca5d2 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -1,11 +1,31 @@ -error: cannot specialize on const impl with non-const impl +error[E0119]: conflicting implementations of trait `Bar` --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1 | +LL | / impl<T> const Bar for T +LL | | where +LL | | T: ~const Foo, + | |__________________- first implementation here +... LL | / impl<T> Bar for T LL | | where LL | | T: Foo, //FIXME ~ ERROR missing `~const` qualifier LL | | T: Specialize, - | |__________________^ + | |__________________^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Baz` + --> $DIR/const-default-bound-non-const-specialized-bound.rs:48:1 + | +LL | / impl<T> const Baz for T +LL | | where +LL | | T: ~const Foo, + | |__________________- first implementation here +... +LL | / impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz` +LL | | where +LL | | T: Foo, +LL | | T: Specialize, + | |__________________^ conflicting implementation -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr new file mode 100644 index 00000000000..38fc5ddfbef --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` + --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + | +LL | impl<T> const Value for T { + | ------------------------- first implementation here +... +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs index a3bb9b3f93e..acf0a967a88 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs @@ -1,7 +1,10 @@ // Tests that specializing trait impls must be at least as const as the default impl. +//@ revisions: spec min_spec #![feature(const_trait_impl)] -#![feature(min_specialization)] +#![cfg_attr(spec, feature(specialization))] +//[spec]~^ WARN the feature `specialization` is incomplete +#![cfg_attr(min_spec, feature(min_specialization))] #[const_trait] trait Value { @@ -16,7 +19,8 @@ impl<T> const Value for T { struct FortyTwo; -impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl +impl Value for FortyTwo { + //~^ ERROR conflicting implementations fn value() -> u32 { println!("You can't do that (constly)"); 42 diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr new file mode 100644 index 00000000000..b59c42f5189 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-impl-non-const-specialized-impl.rs:5:27 + | +LL | #![cfg_attr(spec, feature(specialization))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` + --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + | +LL | impl<T> const Value for T { + | ------------------------- first implementation here +... +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr deleted file mode 100644 index e356621ba47..00000000000 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot specialize on const impl with non-const impl - --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 - | -LL | impl Value for FortyTwo { - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/const-traits/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr index 4ad5e3157d4..edba836aac3 100644 --- a/tests/ui/traits/const-traits/specializing-constness-2.stderr +++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: ~const A` is not satisfied - --> $DIR/specializing-constness-2.rs:27:5 + --> $DIR/specializing-constness-2.rs:27:6 | LL | <T as A>::a(); - | ^^^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs index 632121924a6..94b6da7124d 100644 --- a/tests/ui/traits/const-traits/specializing-constness.rs +++ b/tests/ui/traits/const-traits/specializing-constness.rs @@ -21,8 +21,7 @@ impl<T: ~const Spec> const A for T { } impl<T: Spec + Sup> A for T { -//~^ ERROR: cannot specialize -//FIXME(const_trait_impl) ~| ERROR: missing `~const` qualifier + //~^ ERROR conflicting implementations of trait `A` fn a() -> u32 { 3 } diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr index 21e21c2cb71..2ca70b53e4e 100644 --- a/tests/ui/traits/const-traits/specializing-constness.stderr +++ b/tests/ui/traits/const-traits/specializing-constness.stderr @@ -1,8 +1,12 @@ -error: cannot specialize on const impl with non-const impl +error[E0119]: conflicting implementations of trait `A` --> $DIR/specializing-constness.rs:23:1 | +LL | impl<T: ~const Spec> const A for T { + | ---------------------------------- first implementation here +... LL | impl<T: Spec + Sup> A for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index 01ae209016a..ee49810bace 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -11,10 +11,10 @@ LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:5 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr index ae4c65e4aee..a213273c1c7 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:5 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr index 8fcada1bfd1..ecee348222d 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr @@ -25,10 +25,10 @@ LL | const fn foo<T: ~const Bar>(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-3.rs:24:5 + --> $DIR/super-traits-fail-3.rs:24:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/syntax.rs b/tests/ui/traits/const-traits/syntax.rs index 1064713ac59..cfac6e0a93e 100644 --- a/tests/ui/traits/const-traits/syntax.rs +++ b/tests/ui/traits/const-traits/syntax.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ check-pass #![feature(const_trait_bound_opt_out)] diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr index 78bf85e9c6d..f77d63db054 100644 --- a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr +++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr @@ -26,13 +26,13 @@ error[E0277]: the trait bound `A: const Add42` is not satisfied --> $DIR/tilde-const-and-const-params.rs:27:61 | LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `A: const Add42` is not satisfied --> $DIR/tilde-const-and-const-params.rs:9:44 | LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/tilde-const-syntax.rs b/tests/ui/traits/const-traits/tilde-const-syntax.rs index d65ecae3d06..f9944c426cc 100644 --- a/tests/ui/traits/const-traits/tilde-const-syntax.rs +++ b/tests/ui/traits/const-traits/tilde-const-syntax.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/tilde-twice.rs b/tests/ui/traits/const-traits/tilde-twice.rs index c3f9f8e6764..d341513b8a8 100644 --- a/tests/ui/traits/const-traits/tilde-twice.rs +++ b/tests/ui/traits/const-traits/tilde-twice.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr index 5806b6d6fd2..b471cb81c3b 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -16,7 +16,7 @@ LL | impl const FromResidual for T { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0015]: `?` cannot determine the branch of `T` in constant functions +error[E0015]: `?` is not allowed on `T` in constant functions --> $DIR/trait-default-body-stability.rs:45:9 | LL | T? @@ -24,7 +24,7 @@ LL | T? | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `T` in constant functions +error[E0015]: `?` is not allowed on `T` in constant functions --> $DIR/trait-default-body-stability.rs:45:9 | LL | T? diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index d7735ef282f..4100ae1c6bf 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -2,13 +2,25 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^^^ + | ^ + | +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause-const.rs:15:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^ required by this bound in `Foo::b` error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:5 + --> $DIR/trait-where-clause-const.rs:23:12 | LL | T::c::<T>(); - | ^^^^^^^^^^^ + | ^ + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause-const.rs:16:13 + | +LL | fn c<T: ~const Bar>(); + | ^^^^^^ required by this bound in `Foo::c` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index d04143fc464..bda6a029cc2 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -10,19 +10,19 @@ error[E0277]: the trait bound `T: const Trait` is not satisfied --> $DIR/unsatisfied-const-trait-bound.rs:29:37 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `T: const Trait` is not satisfied --> $DIR/unsatisfied-const-trait-bound.rs:33:50 | LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `Ty: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:22:5 + --> $DIR/unsatisfied-const-trait-bound.rs:22:15 | LL | require::<Ty>(); - | ^^^^^^^^^^^^^^^ + | ^^ | note: required by a bound in `require` --> $DIR/unsatisfied-const-trait-bound.rs:8:15 diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index 03a4017b3d7..38e692521ca 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -23,29 +23,29 @@ LL | struct Struct {} | ---------------- not a trait error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 | LL | #[rustc_must_implement_one_of(a, b)] - | ^ - -error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args - --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 - | -LL | #[rustc_must_implement_one_of(a)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 | LL | #[rustc_must_implement_one_of(a, b)] - | ^ + | ^ error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 | LL | #[rustc_must_implement_one_of(a, b)] | ^ +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 | diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index e1bd234a275..8fe53d6773b 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -18,6 +18,6 @@ impl<T> Overlap<T> for T {} impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} //~^ ERROR cannot find type `Missing` in this scope -//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied +//~| ERROR the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index f6545c6ebf9..09162970d33 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,17 +26,16 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } -error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied - --> $DIR/issue-118950-root-region.rs:19:17 +error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied + --> $DIR/issue-118950-root-region.rs:19:47 | LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T` + | ^ the trait `Overlap<for<'a> fn(Assoc<'a, T>)>` is not implemented for `T` | -help: this trait has no implementations, consider adding one - --> $DIR/issue-118950-root-region.rs:8:1 +help: consider further restricting type parameter `T` | -LL | trait ToUnit<'a> { - | ^^^^^^^^^^^^^^^^ +LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {} + | ++++++++++++++++++++++++++++++++++++++ error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/traits/next-solver/non-wf-ret.rs b/tests/ui/traits/next-solver/non-wf-ret.rs new file mode 100644 index 00000000000..c54d61c895d --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-ret.rs @@ -0,0 +1,47 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +use std::ops::Deref; + +pub struct List<T> { + skel: [T], +} + +impl<'a, T: Copy> IntoIterator for &'a List<T> { + type Item = T; + type IntoIter = std::iter::Copied<<&'a [T] as IntoIterator>::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} + +impl<T> Deref for List<T> { + type Target = [T]; + + fn deref(&self) -> &[T] { + todo!() + } +} + +impl<T> List<T> { + fn iter(&self) -> <&Self as IntoIterator>::IntoIter + where + T: Copy, + { + todo!() + } +} + +fn test<Q>(t: &List<Q>) { + // Checking that `<&List<Q> as IntoIterator>::IntoIter` is WF + // will disqualify the inherent method, since normalizing it + // requires `Q: Copy` which does not hold. and allow us to fall + // through to the deref'd `<[Q]>::iter` method which works. + // + // In the old solver, the same behavior is achieved by just + // eagerly normalizing the return type. + t.iter(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs new file mode 100644 index 00000000000..1dca19d28e9 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs @@ -0,0 +1,46 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Minimized example from `rustc_type_ir` that demonstrates a missing deep normalization +// in the new solver when computing the implies outlives bounds of an impl. + +use std::marker::PhantomData; +use std::ops::Deref; + +pub struct SearchGraph<D: Delegate, X = <D as Delegate>::Cx> { + d: PhantomData<D>, + x: PhantomData<X>, +} + +pub trait Delegate { + type Cx; +} + +struct SearchGraphDelegate<D: SolverDelegate> { + _marker: PhantomData<D>, +} + +impl<D> Delegate for SearchGraphDelegate<D> +where + D: SolverDelegate, +{ + type Cx = D::Interner; +} + +pub trait SolverDelegate { + type Interner; +} + +struct EvalCtxt<'a, D, I> +where + D: SolverDelegate<Interner = I>, +{ + search_graph: &'a SearchGraph<SearchGraphDelegate<D>>, +} + +impl<'a, D, I> EvalCtxt<'a, D, <D as SolverDelegate>::Interner> +where + D: SolverDelegate<Interner = I> +{} + +fn main() {} diff --git a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs index 904bc179495..904bc179495 100644 --- a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs +++ b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr index 158fefd1538..158fefd1538 100644 --- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr +++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr index 158fefd1538..158fefd1538 100644 --- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr +++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs index 10b746cc989..10b746cc989 100644 --- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs +++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr new file mode 100644 index 00000000000..9a28dc093c1 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr @@ -0,0 +1,34 @@ +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:19:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:27:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:36:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:47:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs new file mode 100644 index 00000000000..dd6df097da1 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs @@ -0,0 +1,66 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +// Regression test for trait-system-refactor-initiative#106. We previously +// tried to define other opaques while checking that opaques are well-formed. +// +// This resulted in undesirable ambiguity + +#![feature(type_alias_impl_trait)] + +mod ex0 { + fn foo() -> (impl Sized, impl Sized) { + ((), ()) + } +} +mod ex1 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + fn foo(x: Tait1) -> impl Sized { + let () = x; + } +} + +mod ex2 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + type Tait2 = impl Sized; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +mod ex3 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + trait Something<T> {} + impl<T, U> Something<U> for T {} + type Tait2 = impl Something<Tait1>; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +mod ex4 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + trait Trait<U> { + type Assoc; + } + + impl<T, U> Trait<U> for T { + type Assoc = T; + } + + // ambiguity when checking that `Tait2` is wf + // + // ambiguity proving `(): Trait<Tait1>`. + type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs b/tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs index fd40ef1f872..fd40ef1f872 100644 --- a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs +++ b/tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs diff --git a/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs new file mode 100644 index 00000000000..d2d68128fde --- /dev/null +++ b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs @@ -0,0 +1,32 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Interner: Sized { + type Value; +} + +enum Kind<I: Interner> { + Value(I::Value), +} + +struct Intern; + +impl Interner for Intern { + type Value = Wrap<u32>; +} + +struct Wrap<T>(T); + +type KindAlias = Kind<Intern>; + +trait PrettyPrinter: Sized { + fn hello(c: KindAlias) { + match c { + KindAlias::Value(Wrap(v)) => { + println!("{v:?}"); + } + } + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs new file mode 100644 index 00000000000..23915808279 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} +impl<T> Mirror for T { + type Assoc = T; +} + +type Foo<T> = <Option<T> as Mirror>::Assoc; + +fn main() { + let x = Foo::<i32>::None; +} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs new file mode 100644 index 00000000000..87f9c241e40 --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -0,0 +1,20 @@ +// Need a different module so we try to build the mir for `test` +// before analyzing `mod foo`. + +mod foo { + pub trait Callable { + fn call(); + } + + impl<V: ?Sized> Callable for () { + //~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates + fn call() {} + } +} +use foo::*; + +fn test() -> impl Sized { + <() as Callable>::call() +} + +fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr new file mode 100644 index 00000000000..e8e569ba625 --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates + --> $DIR/resolve-impl-before-constrain-check.rs:9:10 + | +LL | impl<V: ?Sized> Callable for () { + | ^ unconstrained type parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs b/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs new file mode 100644 index 00000000000..f953eb1c0f7 --- /dev/null +++ b/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs @@ -0,0 +1,19 @@ +// Regression test for #107481 + +//@ check-pass + +use std::{borrow::Cow, collections::HashMap}; + +#[derive(Clone)] +struct Foo<'a>(Cow<'a, [Self]>); + +#[derive(Clone)] +struct Bar<'a>(Cow<'a, HashMap<String, Self>>); + +#[derive(Clone)] +struct Baz<'a>(Cow<'a, Vec<Self>>); + +#[derive(Clone)] +struct Qux<'a>(Cow<'a, Box<Self>>); + +fn main() {} diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs index 74f7a1a2e89..274104ffb39 100644 --- a/tests/ui/transmutability/uninhabited.rs +++ b/tests/ui/transmutability/uninhabited.rs @@ -91,3 +91,19 @@ fn distant_void() { assert::is_maybe_transmutable::<DistantVoid, &'static Void>(); assert::is_maybe_transmutable::<u128, DistantVoid>(); //~ ERROR: cannot be safely transmuted } + +fn issue_126267() { + pub enum ApiError {} + pub struct TokioError { + b: bool, + } + pub enum Error { + Api { source: ApiError }, // this variant is uninhabited + Ethereum, + Tokio { source: TokioError }, + } + + struct Src; + type Dst = Error; + assert::is_maybe_transmutable::<Src, Dst>(); //~ERROR: cannot be safely transmuted +} diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 3fa02f0867c..f112d2fbe44 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -110,7 +110,29 @@ LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` -error: aborting due to 7 previous errors +error[E0277]: `Src` cannot be safely transmuted into `issue_126267::Error` + --> $DIR/uninhabited.rs:108:42 + | +LL | assert::is_maybe_transmutable::<Src, Dst>(); + | ^^^ the size of `Src` is smaller than the size of `issue_126267::Error` + | +note: required by a bound in `is_maybe_transmutable` + --> $DIR/uninhabited.rs:10:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom<Src, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0080, E0277. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr index cf372dc5968..4e55618e5cb 100644 --- a/tests/ui/type/type-dependent-def-issue-49241.stderr +++ b/tests/ui/type/type-dependent-def-issue-49241.stderr @@ -9,6 +9,12 @@ help: consider using `let` instead of `const` LL | let l: usize = v.count(); | ~~~ +note: erroneous constant encountered + --> $DIR/type-dependent-def-issue-49241.rs:4:18 + | +LL | let s: [u32; l] = v.into_iter().collect(); + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/underscore-imports/auxiliary/duplicate.rs b/tests/ui/underscore-imports/auxiliary/duplicate.rs index 61613d24b9e..b346522b721 100644 --- a/tests/ui/underscore-imports/auxiliary/duplicate.rs +++ b/tests/ui/underscore-imports/auxiliary/duplicate.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/underscore-imports/duplicate.rs b/tests/ui/underscore-imports/duplicate.rs index 4afad77ee4f..125ccdf52b0 100644 --- a/tests/ui/underscore-imports/duplicate.rs +++ b/tests/ui/underscore-imports/duplicate.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:duplicate.rs +//@ proc-macro: duplicate.rs extern crate duplicate; diff --git a/triagebot.toml b/triagebot.toml index 47b96824098..4d6806711fb 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -996,7 +996,6 @@ warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", - "oli-obk", ] [assign.adhoc_groups] |
