diff --git a/Cargo.lock b/Cargo.lock index 01300d56cff9..1bc531ba916c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,7 +630,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clippy" -version = "0.1.94" +version = "0.1.95" dependencies = [ "anstream", "askama", @@ -657,7 +657,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.94" +version = "0.1.95" dependencies = [ "clippy_utils", "itertools", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.94" +version = "0.1.95" dependencies = [ "arrayvec", "cargo_metadata 0.18.1", @@ -713,7 +713,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.94" +version = "0.1.95" dependencies = [ "arrayvec", "itertools", @@ -1117,7 +1117,7 @@ dependencies = [ [[package]] name = "declare_clippy_lint" -version = "0.1.94" +version = "0.1.95" [[package]] name = "derive-where" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b2b1f997ac54..591abdaa2683 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3626,6 +3626,7 @@ impl Item { pub fn opt_generics(&self) -> Option<&Generics> { match &self.kind { ItemKind::ExternCrate(..) + | ItemKind::ConstBlock(_) | ItemKind::Use(_) | ItemKind::Mod(..) | ItemKind::ForeignMod(_) @@ -3895,6 +3896,17 @@ impl ConstItemRhs { } } +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub struct ConstBlockItem { + pub id: NodeId, + pub span: Span, + pub block: Box, +} + +impl ConstBlockItem { + pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP }; +} + // Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum ItemKind { @@ -3914,6 +3926,11 @@ pub enum ItemKind { /// /// E.g., `const FOO: i32 = 42;`. Const(Box), + /// A module-level const block. + /// Equivalent to `const _: () = const { ... };`. + /// + /// E.g., `const { assert!(true) }`. + ConstBlock(ConstBlockItem), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. @@ -3990,6 +4007,8 @@ impl ItemKind { | ItemKind::MacroDef(ident, _) | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), + ItemKind::ConstBlock(_) => Some(ConstBlockItem::IDENT), + ItemKind::Use(_) | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) @@ -4003,9 +4022,9 @@ impl ItemKind { pub fn article(&self) -> &'static str { use ItemKind::*; match self { - Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) - | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) - | Delegation(..) | DelegationMac(..) => "a", + Use(..) | Static(..) | Const(..) | ConstBlock(..) | Fn(..) | Mod(..) + | GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) + | MacroDef(..) | Delegation(..) | DelegationMac(..) => "a", ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an", } } @@ -4016,6 +4035,7 @@ impl ItemKind { ItemKind::Use(..) => "`use` import", ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", + ItemKind::ConstBlock(..) => "const block", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", ItemKind::ForeignMod(..) => "extern block", @@ -4045,7 +4065,18 @@ impl ItemKind { | Self::Trait(box Trait { generics, .. }) | Self::TraitAlias(box TraitAlias { generics, .. }) | Self::Impl(Impl { generics, .. }) => Some(generics), - _ => None, + + Self::ExternCrate(..) + | Self::Use(..) + | Self::Static(..) + | Self::ConstBlock(..) + | Self::Mod(..) + | Self::ForeignMod(..) + | Self::GlobalAsm(..) + | Self::MacCall(..) + | Self::MacroDef(..) + | Self::Delegation(..) + | Self::DelegationMac(..) => None, } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f7b8b9da3241..51614460d3c4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -425,6 +425,7 @@ macro_rules! common_visitor_and_walkers { ByRef, Closure, Const, + ConstBlockItem, ConstItem, ConstItemRhs, Defaultness, @@ -825,6 +826,8 @@ macro_rules! common_visitor_and_walkers { visit_visitable!($($mut)? vis, use_tree), ItemKind::Static(item) => visit_visitable!($($mut)? vis, item), + ItemKind::ConstBlock(item) => + visit_visitable!($($mut)? vis, item), ItemKind::Const(item) => visit_visitable!($($mut)? vis, item), ItemKind::Mod(safety, ident, mod_kind) => diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c8ebfb96b558..b497c6beeb98 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -205,6 +205,7 @@ impl<'hir> LoweringContext<'_, 'hir> { | ItemKind::Use(..) | ItemKind::Static(..) | ItemKind::Const(..) + | ItemKind::ConstBlock(..) | ItemKind::Mod(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) @@ -282,8 +283,13 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_define_opaque(hir_id, define_opaque); hir::ItemKind::Static(*m, ident, ty, body_id) } - ItemKind::Const(box ast::ConstItem { - ident, generics, ty, rhs, define_opaque, .. + ItemKind::Const(box ConstItem { + defaultness: _, + ident, + generics, + ty, + rhs, + define_opaque, }) => { let ident = self.lower_ident(*ident); let (generics, (ty, rhs)) = self.lower_generics( @@ -302,6 +308,19 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_define_opaque(hir_id, &define_opaque); hir::ItemKind::Const(ident, generics, ty, rhs) } + ItemKind::ConstBlock(ConstBlockItem { span, id, block }) => hir::ItemKind::Const( + self.lower_ident(ConstBlockItem::IDENT), + hir::Generics::empty(), + self.arena.alloc(self.ty_tup(DUMMY_SP, &[])), + hir::ConstItemRhs::Body({ + let body = hir::Expr { + hir_id: self.lower_node_id(*id), + kind: hir::ExprKind::Block(self.lower_block(block, false), None), + span: self.lower_span(*span), + }; + self.record_body(&[], body) + }), + ), ItemKind::Fn(box Fn { sig: FnSig { decl, header, span: fn_sig_span }, ident, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index dd0e27948bec..6376cab364db 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -537,6 +537,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(super_let, "`super let` is experimental"); gate_all!(frontmatter, "frontmatters are experimental"); gate_all!(coroutines, "coroutine syntax is experimental"); + gate_all!(const_block_items, "const block items are experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3233d8c2c251..68054b06e39f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -205,6 +205,17 @@ impl<'a> State<'a> { define_opaque.as_deref(), ); } + ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => { + let ib = self.ibox(INDENT_UNIT); + self.word("const"); + self.nbsp(); + { + let cb = self.cbox(0); + let ib = self.ibox(0); + self.print_block_with_attrs(block, &[], cb, ib); + } + self.end(ib); + } ast::ItemKind::Const(box ast::ConstItem { defaultness, ident, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index a9b2a4c96c33..3a540d80998d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -360,7 +360,8 @@ fn parse_cfg_attr_internal<'a>( ) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> { // Parse cfg predicate let pred_start = parser.token.span; - let meta = MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints)?; + let meta = + MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?; let pred_span = pred_start.with_hi(parser.token.span.hi()); let cfg_predicate = AttributeParser::parse_single_args( @@ -375,7 +376,7 @@ fn parse_cfg_attr_internal<'a>( CRATE_NODE_ID, Target::Crate, features, - ShouldEmit::ErrorsAndLints, + ShouldEmit::ErrorsAndLints { recover: true }, &meta, parse_cfg_entry, &CFG_ATTR_TEMPLATE, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index e80084021a84..ca844758daaa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -78,8 +78,9 @@ pub fn parse_cfg_select( } } } else { - let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints) - .map_err(|diag| diag.emit())?; + let meta = + MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true }) + .map_err(|diag| diag.emit())?; let cfg_span = meta.span(); let cfg = AttributeParser::parse_single_args( sess, @@ -94,7 +95,7 @@ pub fn parse_cfg_select( // Doesn't matter what the target actually is here. Target::Crate, features, - ShouldEmit::ErrorsAndLints, + ShouldEmit::ErrorsAndLints { recover: true }, &meta, parse_cfg_entry, &AttributeTemplate::default(), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index e500be68e241..20bdfa45a013 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -381,7 +381,7 @@ impl Stage for Late { } fn should_emit(&self) -> ShouldEmit { - ShouldEmit::ErrorsAndLints + ShouldEmit::ErrorsAndLints { recover: true } } } @@ -438,7 +438,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { pub(crate) fn emit_lint(&mut self, lint: &'static Lint, kind: AttributeLintKind, span: Span) { if !matches!( self.stage.should_emit(), - ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true } + ShouldEmit::ErrorsAndLints { .. } | ShouldEmit::EarlyFatal { also_emit_lints: true } ) { return; } @@ -765,9 +765,18 @@ pub enum ShouldEmit { EarlyFatal { also_emit_lints: bool }, /// The operation will emit errors and lints. /// This is usually what you need. - ErrorsAndLints, - /// The operation will emit *not* errors and lints. - /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`. + ErrorsAndLints { + /// Whether [`ArgParser`] will attempt to recover from errors. + /// + /// If true, it will attempt to recover from bad input (like an invalid literal). Setting + /// this to false will instead return early, and not raise errors except at the top level + /// (in [`ArgParser::from_attr_args`]). + recover: bool, + }, + /// The operation will *not* emit errors and lints. + /// + /// The parser can still call `delay_bug`, so you *must* ensure that this operation will also be + /// called with `ShouldEmit::ErrorsAndLints`. Nothing, } @@ -776,7 +785,7 @@ impl ShouldEmit { match self { ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(), ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(), - ShouldEmit::ErrorsAndLints => diag.emit(), + ShouldEmit::ErrorsAndLints { .. } => diag.emit(), ShouldEmit::Nothing => diag.delay_as_bug(), } } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 99e36a78d6ae..7f3c6d28005f 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -16,7 +16,7 @@ use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; -use rustc_session::errors::{create_lit_error, report_lit_error}; +use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::ThinVec; @@ -113,16 +113,29 @@ impl ArgParser { Some(match value { AttrArgs::Empty => Self::NoArgs, AttrArgs::Delimited(args) => { - // The arguments of rustc_dummy and diagnostic::do_not_recommend are not validated - // if the arguments are delimited. - // See https://doc.rust-lang.org/reference/attributes/diagnostics.html#r-attributes.diagnostic.namespace.unknown-invalid-syntax - if parts == &[sym::rustc_dummy] - || parts == &[sym::diagnostic, sym::do_not_recommend] - { - return Some(ArgParser::List(MetaItemListParser { - sub_parsers: ThinVec::new(), - span: args.dspan.entire(), - })); + // Diagnostic attributes can't error if they encounter non meta item syntax. + // However, the current syntax for diagnostic attributes is meta item syntax. + // Therefore we can substitute with a dummy value on invalid syntax. + if matches!(parts, [sym::rustc_dummy] | [sym::diagnostic, ..]) { + match MetaItemListParser::new( + &args.tokens, + args.dspan.entire(), + psess, + ShouldEmit::ErrorsAndLints { recover: false }, + ) { + Ok(p) => return Some(ArgParser::List(p)), + Err(e) => { + // We can just dispose of the diagnostic and not bother with a lint, + // because this will look like `#[diagnostic::attr()]` was used. This + // is invalid for all diagnostic attrs, so a lint explaining the proper + // form will be issued later. + e.cancel(); + return Some(ArgParser::List(MetaItemListParser { + sub_parsers: ThinVec::new(), + span: args.dspan.entire(), + })); + } + } } if args.delim != Delimiter::Parenthesis { @@ -141,7 +154,9 @@ impl ArgParser { } AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser { eq_span: *eq_span, - value: expr_to_lit(psess, &expr, expr.span, should_emit)?, + value: expr_to_lit(psess, &expr, expr.span, should_emit) + .map_err(|e| should_emit.emit_err(e)) + .ok()??, value_span: expr.span, }), }) @@ -336,58 +351,53 @@ impl NameValueParser { } } -fn expr_to_lit( - psess: &ParseSess, +fn expr_to_lit<'sess>( + psess: &'sess ParseSess, expr: &Expr, span: Span, should_emit: ShouldEmit, -) -> Option { +) -> PResult<'sess, Option> { if let ExprKind::Lit(token_lit) = expr.kind { let res = MetaItemLit::from_token_lit(token_lit, expr.span); match res { Ok(lit) => { if token_lit.suffix.is_some() { - should_emit.emit_err( - psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }), - ); - None + Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span })) } else { - if !lit.kind.is_unsuffixed() { - // Emit error and continue, we can still parse the attribute as if the suffix isn't there - should_emit.emit_err( - psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }), - ); + if lit.kind.is_unsuffixed() { + Ok(Some(lit)) + } else { + Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span })) } - - Some(lit) } } Err(err) => { - let guar = report_lit_error(psess, err, token_lit, expr.span); - let lit = MetaItemLit { - symbol: token_lit.symbol, - suffix: token_lit.suffix, - kind: LitKind::Err(guar), - span: expr.span, - }; - Some(lit) + let err = create_lit_error(psess, err, token_lit, expr.span); + if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + Err(err) + } else { + let lit = MetaItemLit { + symbol: token_lit.symbol, + suffix: token_lit.suffix, + kind: LitKind::Err(err.emit()), + span: expr.span, + }; + Ok(Some(lit)) + } } } } else { if matches!(should_emit, ShouldEmit::Nothing) { - return None; + return Ok(None); } // Example cases: // - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`. // - `#[foo = include_str!("nonexistent-file.rs")]`: - // results in `ast::ExprKind::Err`. In that case we delay - // the error because an earlier error will have already - // been reported. + // results in `ast::ExprKind::Err`. let msg = "attribute value must be a literal"; let err = psess.dcx().struct_span_err(span, msg); - should_emit.emit_err(err); - None + Err(err) } } @@ -420,9 +430,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if !lit.kind.is_unsuffixed() { // Emit error and continue, we can still parse the attribute as if the suffix isn't there - self.should_emit.emit_err( - self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }), - ); + let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }); + if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + return Err(err); + } else { + self.should_emit.emit_err(err) + }; } Ok(lit) diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs index e4e52962bf7f..cfe9376fb502 100644 --- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs @@ -45,7 +45,6 @@ pub(super) fn convert_typeck_constraints<'tcx>( { localize_statement_constraint( tcx, - body, stmt, &outlives_constraint, point, @@ -74,7 +73,6 @@ pub(super) fn convert_typeck_constraints<'tcx>( /// needed CFG `from`-`to` intra-block nodes. fn localize_statement_constraint<'tcx>( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, stmt: &Statement<'tcx>, outlives_constraint: &OutlivesConstraint<'tcx>, current_point: PointIndex, @@ -114,28 +112,22 @@ fn localize_statement_constraint<'tcx>( }, "there should be no common regions between the LHS and RHS of an assignment" ); - - let lhs_ty = body.local_decls[lhs.local].ty; - let successor_point = current_point; - compute_constraint_direction( - tcx, - outlives_constraint, - &lhs_ty, - current_point, - successor_point, - universal_regions, - ) } _ => { - // For the other cases, we localize an outlives constraint to where it arises. - LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from: current_point, - target: outlives_constraint.sub, - to: current_point, - } + // Assignments should be the only statement that can both generate constraints that + // apply on entry (specific to the RHS place) *and* others that only apply on exit (the + // subset of RHS regions that actually flow into the LHS): i.e., where midpoints would + // be used to ensure the former happen before the latter, within the same MIR Location. } } + + // We generally localize an outlives constraint to where it arises. + LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from: current_point, + target: outlives_constraint.sub, + to: current_point, + } } /// For a given outlives constraint arising from a MIR terminator, localize the constraint with the @@ -150,14 +142,12 @@ fn localize_terminator_constraint<'tcx>( universal_regions: &UniversalRegions<'tcx>, ) -> LocalizedOutlivesConstraint { // FIXME: check if other terminators need the same handling as `Call`s, in particular - // Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some - // coroutine tests, and that may be why. + // Assert/Yield/Drop. match &terminator.kind { // FIXME: also handle diverging calls. TerminatorKind::Call { destination, target: Some(target), .. } => { - // Calls are similar to assignments, and thus follow the same pattern. If there is a - // target for the call we also relate what flows into the destination here to entry to - // that successor. + // If there is a target for the call we also relate what flows into the destination here + // to entry to that successor. let destination_ty = destination.ty(&body.local_decls, tcx); let successor_location = Location { block: *target, statement_index: 0 }; let successor_point = liveness.point_from_location(successor_location); diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index be1ce5a06d5e..8e925cfe09a2 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -40,8 +40,11 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result, span: Span, tts: TokenStream) -> Result { let res: PResult<'_, Annotatable> = try { match annotatable { Annotatable::Item(_) => { - let item = parser.parse_item(ForceCollect::Yes)?.unwrap(); + let item = + parser.parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)?.unwrap(); Annotatable::Item(self.flat_map_item(item).pop().unwrap()) } Annotatable::AssocItem(_, ctxt) => { diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 0f31de60a8a4..f53574601441 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -13,7 +13,7 @@ use rustc_expand::base::{ }; use rustc_expand::module::DirOwnership; use rustc_parse::lexer::StripTokens; -use rustc_parse::parser::ForceCollect; +use rustc_parse::parser::{AllowConstBlockItems, ForceCollect}; use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_session::parse::ParseSess; @@ -168,7 +168,7 @@ pub(crate) fn expand_include<'cx>( )); let mut ret = SmallVec::new(); loop { - match p.parse_item(ForceCollect::No) { + match p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) { Err(err) => { err.emit(); break; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index bef9c6747457..200cedf0f6ae 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -348,6 +348,31 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret.write_cvalue(fx, ret_lane); } + sym::simd_splat => { + intrinsic_args!(fx, args => (value); intrinsic); + + if !ret.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, ret.layout().ty); + return; + } + let (lane_count, lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + + if value.layout().ty != lane_ty { + fx.tcx.dcx().span_fatal( + span, + format!( + "[simd_splat] expected element type {lane_ty:?}, got {got:?}", + got = value.layout().ty + ), + ); + } + + for i in 0..lane_count { + let ret_lane = ret.place_lane(fx, i.into()); + ret_lane.write_cvalue(fx, value); + } + } + sym::simd_neg | sym::simd_bswap | sym::simd_bitreverse diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 39b4bb3ebefa..eab067a02b7b 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -121,6 +121,42 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate())); } + #[cfg(feature = "master")] + if name == sym::simd_splat { + let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn); + + require!( + args[0].layout.ty == out_ty, + InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: out_ty, + vector_type: ret_ty, + } + ); + + let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type"); + let elem_ty = vec_ty.get_element_type(); + + // Cast pointer type to usize (GCC does not support pointer SIMD vectors). + let value = args[0]; + let scalar = if value.layout.ty.is_numeric() { + value.immediate() + } else if value.layout.ty.is_raw_ptr() { + bx.ptrtoint(value.immediate(), elem_ty) + } else { + return_error!(InvalidMonomorphization::UnsupportedOperation { + span, + name, + in_ty: ret_ty, + in_elem: value.layout.ty + }); + }; + + let elements = vec![scalar; out_len as usize]; + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements)); + } + // every intrinsic below takes a SIMD vector as its first argument require_simd!( args[0].layout.ty, diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index f88932d43d2a..65cf4cad24bd 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -39,6 +39,7 @@ impl OwnedTargetMachine { debug_info_compression: llvm::CompressionKind, use_emulated_tls: bool, use_wasm_eh: bool, + large_data_threshold: u64, ) -> Result> { // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data let tm_ptr = unsafe { @@ -65,6 +66,7 @@ impl OwnedTargetMachine { debug_info_compression, use_emulated_tls, use_wasm_eh, + large_data_threshold, ) }; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index e66a4ab6b37b..fb07794e1bba 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -275,6 +275,8 @@ pub(crate) fn target_machine_factory( let use_wasm_eh = wants_wasm_eh(sess); + let large_data_threshold = sess.opts.unstable_opts.large_data_threshold.unwrap_or(0); + let prof = SelfProfilerRef::clone(&sess.prof); Arc::new(move |config: TargetMachineFactoryConfig| { // Self-profile timer for invoking a factory to create a target machine. @@ -316,6 +318,7 @@ pub(crate) fn target_machine_factory( debuginfo_compression, use_emulated_tls, use_wasm_eh, + large_data_threshold, ) }) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e11ed796887a..1c674f0e8a85 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -665,8 +665,8 @@ impl MsvcBasicName for ty::UintTy { impl MsvcBasicName for ty::FloatTy { fn msvc_basic_name(self) -> &'static str { - // FIXME(f16_f128): `f16` and `f128` have no MSVC representation. We could improve the - // debuginfo. See: + // FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo. + // See: match self { ty::FloatTy::F16 => { bug!("`f16` should have been handled in `build_basic_type_di_node`") diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a712b7b4138c..50e627cf6bdf 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1581,6 +1581,31 @@ fn generic_simd_intrinsic<'ll, 'tcx>( return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } + if name == sym::simd_splat { + let (_out_len, out_ty) = require_simd!(ret_ty, SimdReturn); + + require!( + args[0].layout.ty == out_ty, + InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: out_ty, + vector_type: ret_ty, + } + ); + + // `insertelement poison, elem %x, i32 0` + let poison_vec = bx.const_poison(llret_ty); + let idx0 = bx.const_i32(0); + let v0 = bx.insert_element(poison_vec, args[0].immediate(), idx0); + + // `shufflevector v0, poison, zeroinitializer` + // The masks is all zeros, so this splats lane 0 (which has our element in it). + let splat = bx.shuffle_vector(v0, poison_vec, bx.const_null(llret_ty)); + + return Ok(splat); + } + // every intrinsic below takes a SIMD vector as its first argument let (in_len, in_elem) = require_simd!(args[0].layout.ty, SimdInput); let in_ty = args[0].layout.ty; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index a3d4e9f9d32a..454d5c4ffb24 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2347,6 +2347,7 @@ unsafe extern "C" { DebugInfoCompression: CompressionKind, UseEmulatedTls: bool, UseWasmEH: bool, + LargeDataThreshold: u64, ) -> *mut TargetMachine; pub(crate) fn LLVMRustAddLibraryInfo<'a>( diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 241c8d6bfd18..1b75db51140b 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1827,9 +1827,9 @@ fn exported_symbols_for_non_proc_macro( // Mark allocator shim symbols as exported only if they were generated. if export_threshold == SymbolExportLevel::Rust && needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type) - && tcx.allocator_kind(()).is_some() + && let Some(kind) = tcx.allocator_kind(()) { - symbols.extend(allocator_shim_symbols(tcx)); + symbols.extend(allocator_shim_symbols(tcx, kind)); } symbols diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index 677268e367c2..e3cf28acfa53 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -118,8 +118,10 @@ pub(super) fn exported_symbols_for_lto( } // Mark allocator shim symbols as exported only if they were generated. - if export_threshold == SymbolExportLevel::Rust && allocator_kind_for_codegen(tcx).is_some() { - symbols_below_threshold.extend(allocator_shim_symbols(tcx).map(|(name, _kind)| name)); + if export_threshold == SymbolExportLevel::Rust + && let Some(kind) = allocator_kind_for_codegen(tcx) + { + symbols_below_threshold.extend(allocator_shim_symbols(tcx, kind).map(|(name, _kind)| name)); } symbols_below_threshold diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9b26a653fbd7..c6e945691921 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,9 +1,7 @@ use std::collections::hash_map::Entry::*; use rustc_abi::{CanonAbi, X86Call}; -use rustc_ast::expand::allocator::{ - ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name, -}; +use rustc_ast::expand::allocator::{AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId}; @@ -21,6 +19,7 @@ use rustc_target::spec::{Arch, Os, TlsModel}; use tracing::debug; use crate::back::symbol_export; +use crate::base::allocator_shim_contents; fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(tcx.crate_types()) @@ -490,14 +489,12 @@ pub(crate) fn provide(providers: &mut Providers) { pub(crate) fn allocator_shim_symbols( tcx: TyCtxt<'_>, + kind: AllocatorKind, ) -> impl Iterator { - ALLOCATOR_METHODS - .iter() + allocator_shim_contents(tcx, kind) + .into_iter() .map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str())) - .chain([ - mangle_internal_symbol(tcx, global_fn_name(ALLOC_ERROR_HANDLER).as_str()), - mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), - ]) + .chain([mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)]) .map(move |symbol_name| { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 78dfecdd1818..50ca676b5d05 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -1074,8 +1074,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if constant_ty.is_simd() { // However, some SIMD types do not actually use the vector ABI // (in particular, packed SIMD types do not). Ensure we exclude those. + // + // We also have to exclude vectors of pointers because `immediate_const_vector` + // does not work for those. let layout = bx.layout_of(constant_ty); - if let BackendRepr::SimdVector { .. } = layout.backend_repr { + let (_, element_ty) = constant_ty.simd_size_and_type(bx.tcx()); + if let BackendRepr::SimdVector { .. } = layout.backend_repr + && element_ty.is_numeric() + { let (llval, ty) = self.immediate_const_vector(bx, constant); return OperandRef { val: OperandValue::Immediate(llval), diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index f61baa006b63..303183fd924d 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -61,6 +61,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } self.copy_op(&self.project_index(&input, index)?, &dest)?; } + sym::simd_splat => { + let elem = &args[0]; + let (dest, dest_len) = self.project_to_simd(&dest)?; + + for i in 0..dest_len { + let place = self.project_index(&dest, i)?; + self.copy_op(elem, &place)?; + } + } sym::simd_neg | sym::simd_fabs | sym::simd_ceil diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e2d62bdc5453..6a3c9697a939 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -22,7 +22,7 @@ use rustc_hir::limit::Limit; use rustc_hir::{Stability, find_attr}; use rustc_lint_defs::RegisteredTools; use rustc_parse::MACRO_ARGUMENTS; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser}; use rustc_session::Session; use rustc_session::parse::ParseSess; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -1472,7 +1472,7 @@ pub(crate) fn stream_pretty_printing_compatibility_hack( let mut parser = Parser::new(psess, stream.clone(), None); // No need to collect tokens for this simple check. parser - .parse_item(ForceCollect::No) + .parse_item(ForceCollect::No, AllowConstBlockItems::No) .expect("failed to reparse item") .expect("an actual item") } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 53392f100e14..4887bfa44588 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -393,9 +393,10 @@ impl<'a> StripUnconfigured<'a> { /// Determines if a node with the given attributes should be included in this configuration. fn in_cfg(&self, attrs: &[Attribute]) -> bool { - attrs - .iter() - .all(|attr| !is_cfg(attr) || self.cfg_true(attr, ShouldEmit::ErrorsAndLints).as_bool()) + attrs.iter().all(|attr| { + !is_cfg(attr) + || self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool() + }) } pub(crate) fn cfg_true(&self, attr: &Attribute, emit_errors: ShouldEmit) -> EvalConfigResult { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 20cdffac2d67..cfa7725c7400 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -25,8 +25,8 @@ use rustc_hir::Target; use rustc_hir::def::MacroKinds; use rustc_hir::limit::Limit; use rustc_parse::parser::{ - AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma, - token_descr, + AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, + RecoverColon, RecoverComma, token_descr, }; use rustc_session::Session; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; @@ -1099,7 +1099,7 @@ pub fn parse_ast_fragment<'a>( Ok(match kind { AstFragmentKind::Items => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_item(ForceCollect::No)? { + while let Some(item) = this.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? { items.push(item); } AstFragment::Items(items) @@ -2170,7 +2170,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { call.span(), self.cx.current_expansion.lint_node_id, Some(self.cx.ecfg.features), - ShouldEmit::ErrorsAndLints, + ShouldEmit::ErrorsAndLints { recover: true }, ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; @@ -2220,7 +2220,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Target doesn't matter for `cfg` parsing. Target::Crate, self.cfg().features, - ShouldEmit::ErrorsAndLints, + ShouldEmit::ErrorsAndLints { recover: true }, parse_cfg, &CFG_TEMPLATE, ) else { diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 5e7a272bcba4..ea63ff7bfc46 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -1,7 +1,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_errors::ErrorGuaranteed; use rustc_middle::ty::{self, TyCtxt}; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser}; use rustc_session::Session; use rustc_session::config::ProcMacroExecutionStrategy; use rustc_span::profiling::SpannedEventArgRecorder; @@ -160,7 +160,10 @@ impl MultiItemModifier for DeriveProcMacro { let mut items = vec![]; loop { - match parser.parse_item(ForceCollect::No) { + match parser.parse_item( + ForceCollect::No, + if is_stmt { AllowConstBlockItems::No } else { AllowConstBlockItems::Yes }, + ) { Ok(None) => break, Ok(Some(item)) => { if is_stmt { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 105eb573967d..22db43b7ee64 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -414,6 +414,8 @@ declare_features! ( (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)), /// Allows `async {}` expressions in const contexts. (unstable, const_async_blocks, "1.53.0", Some(85368)), + /// Allows `const { ... }` as a shorthand for `const _: () = const { ... };` for module items. + (unstable, const_block_items, "CURRENT_RUSTC_VERSION", Some(149226)), /// Allows `const || {}` closures in const contexts. (incomplete, const_closures, "1.68.0", Some(106003)), /// Allows using `[const] Destruct` bounds and calling drop impls in const contexts. diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 87953321af3f..b76c48fbe8ac 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -171,6 +171,7 @@ impl Target { ast::ItemKind::Use(..) => Target::Use, ast::ItemKind::Static { .. } => Target::Static, ast::ItemKind::Const(..) => Target::Const, + ast::ItemKind::ConstBlock(..) => Target::Const, ast::ItemKind::Fn { .. } => Target::Fn, ast::ItemKind::Mod(..) => Target::Mod, ast::ItemKind::ForeignMod { .. } => Target::ForeignMod, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 98f9548058f4..22ee490b81a7 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -746,6 +746,7 @@ pub(crate) fn check_intrinsic_type( sym::simd_extract | sym::simd_extract_dyn => { (2, 0, vec![param(0), tcx.types.u32], param(1)) } + sym::simd_splat => (2, 0, vec![param(1)], param(0)), sym::simd_cast | sym::simd_as | sym::simd_cast_ptr diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 733f5fd0df0a..97f95ac01e86 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -305,7 +305,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, const char *SplitDwarfFile, const char *OutputObjFile, LLVMRustCompressionKind DebugInfoCompression, bool UseEmulatedTls, - bool UseWasmEH) { + bool UseWasmEH, uint64_t LargeDataThreshold) { auto OptLevel = fromRust(RustOptLevel); auto RM = fromRust(RustReloc); @@ -381,6 +381,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( TargetMachine *TM = TheTarget->createTargetMachine( Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel); #endif + + if (LargeDataThreshold != 0) { + TM->setLargeDataThreshold(LargeDataThreshold); + } + return wrap(TM); } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 16121c38d1a9..17330f4e14be 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -4,10 +4,9 @@ use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; -use rustc_query_system::HandleCycleError; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; pub(crate) use rustc_query_system::query::QueryJobId; -use rustc_query_system::query::*; +use rustc_query_system::query::{CycleError, CycleErrorHandling, HashResult, QueryCache}; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -23,7 +22,8 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { pub name: &'static str, pub eval_always: bool, pub dep_kind: DepKind, - pub handle_cycle_error: HandleCycleError, + /// How this query deals with query cycle errors. + pub cycle_error_handling: CycleErrorHandling, // Offset of this query's state field in the QueryStates struct pub query_state: usize, // Offset of this query's cache field in the QueryCaches struct diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index dcbed92d350b..5e8031403565 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -807,12 +807,22 @@ pub enum PatKind<'tcx> { subpatterns: Vec>, }, - /// `box P`, `&P`, `&mut P`, etc. + /// Explicit or implicit `&P` or `&mut P`, for some subpattern `P`. + /// + /// Implicit `&`/`&mut` patterns can be inserted by match-ergonomics. + /// + /// With `feature(pin_ergonomics)`, this can also be `&pin const P` or + /// `&pin mut P`, as indicated by the `pin` field. Deref { + #[type_visitable(ignore)] + pin: hir::Pinnedness, subpattern: Box>, }, - /// Deref pattern, written `box P` for now. + /// Explicit or implicit `deref!(..)` pattern, under `feature(deref_patterns)`. + /// Represents a call to `Deref` or `DerefMut`, or a deref-move of `Box`. + /// + /// `box P` patterns also lower to this, under `feature(box_patterns)`. DerefPattern { subpattern: Box>, /// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c06d5c5f0ebb..8e0e3aa294b8 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -268,7 +268,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( | PatKind::Error(_) => {} PatKind::Binding { subpattern: Some(subpattern), .. } - | PatKind::Deref { subpattern } + | PatKind::Deref { subpattern, .. } | PatKind::DerefPattern { subpattern, .. } => callback(subpattern), PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => { diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index e80e29415e6f..a3662b2768cd 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use rustc_abi::FieldIdx; use rustc_middle::mir::*; +use rustc_middle::span_bug; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -314,23 +315,24 @@ impl<'tcx> MatchPairTree<'tcx> { None } - // FIXME: Pin-patterns should probably have their own pattern kind, - // instead of overloading `PatKind::Deref` via the pattern type. - PatKind::Deref { ref subpattern } - if let Some(ref_ty) = pattern.ty.pinned_ty() - && ref_ty.is_ref() => - { + PatKind::Deref { pin: Pinnedness::Pinned, ref subpattern } => { + let pinned_ref_ty = match pattern.ty.pinned_ty() { + Some(p_ty) if p_ty.is_ref() => p_ty, + _ => span_bug!(pattern.span, "bad type for pinned deref: {:?}", pattern.ty), + }; MatchPairTree::for_pattern( - place_builder.field(FieldIdx::ZERO, ref_ty).deref(), + // Project into the `Pin(_)` struct, then deref the inner `&` or `&mut`. + place_builder.field(FieldIdx::ZERO, pinned_ref_ty).deref(), subpattern, cx, &mut subpairs, extra_data, ); + None } - PatKind::Deref { ref subpattern } + PatKind::Deref { pin: Pinnedness::Not, ref subpattern } | PatKind::DerefPattern { ref subpattern, borrow: DerefPatBorrowMode::Box } => { MatchPairTree::for_pattern( place_builder.deref(), diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 2f9486c2d552..d04322c320b4 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -10,7 +10,7 @@ use std::mem; use std::sync::Arc; use itertools::{Itertools, Position}; -use rustc_abi::{FIRST_VARIANT, VariantIdx}; +use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_data_structures::debug_assert_matches; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -909,7 +909,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Never | PatKind::Error(_) => {} - PatKind::Deref { ref subpattern } => { + PatKind::Deref { pin: Pinnedness::Pinned, ref subpattern } => { + // Project into the `Pin(_)` struct, then deref the inner `&` or `&mut`. + visit_subpat(self, subpattern, &user_tys.leaf(FieldIdx::ZERO).deref(), f); + } + PatKind::Deref { pin: Pinnedness::Not, ref subpattern } => { visit_subpat(self, subpattern, &user_tys.deref(), f); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7fbf8cd11466..0a0e0d06061e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -294,8 +294,12 @@ impl<'tcx> ConstToPat<'tcx> { || pointee_ty.is_slice() || pointee_ty.is_sized(tcx, self.typing_env) { - // References have the same valtree representation as their pointee. PatKind::Deref { + // This node has type `ty::Ref`, so it's not a pin-deref. + pin: hir::Pinnedness::Not, + // Lower the valtree to a pattern as the pointee type. + // This works because references have the same valtree + // representation as their pointee. subpattern: self.valtree_to_pat(ty::Value { ty: *pointee_ty, valtree }), } } else { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d0abb6396145..3641561567bc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -132,12 +132,16 @@ impl<'tcx> PatCtxt<'tcx> { debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust); let span = thir_pat.span; let kind = match adjust.kind { - PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat }, + PatAdjust::BuiltinDeref => { + PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat } + } PatAdjust::OverloadedDeref => { let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat); PatKind::DerefPattern { subpattern: thir_pat, borrow } } - PatAdjust::PinDeref => PatKind::Deref { subpattern: thir_pat }, + PatAdjust::PinDeref => { + PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat } + } }; Box::new(Pat { span, ty: adjust.source, kind, extra: None }) }); @@ -334,7 +338,7 @@ impl<'tcx> PatCtxt<'tcx> { let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern); PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow } } - hir::PatKind::Ref(subpattern, _, _) => { + hir::PatKind::Ref(subpattern, pin, _) => { // Track the default binding mode for the Rust 2024 migration suggestion. let opt_old_mode_span = self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref()); @@ -342,7 +346,7 @@ impl<'tcx> PatCtxt<'tcx> { if let Some(s) = &mut self.rust_2024_migration { s.leave_ref(opt_old_mode_span); } - PatKind::Deref { subpattern } + PatKind::Deref { pin, subpattern } } hir::PatKind::Box(subpattern) => PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index a87257fa79bf..db8b2518981d 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -774,8 +774,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "]", depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } - PatKind::Deref { subpattern } => { + PatKind::Deref { pin, subpattern } => { print_indented!(self, "Deref { ", depth_lvl + 1); + print_indented!(self, format_args!("pin: {pin:?}"), depth_lvl + 2); print_indented!(self, "subpattern:", depth_lvl + 2); self.print_pat(subpattern, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 1cb9a1b65d65..fe8c1deedff7 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -9,7 +9,8 @@ use thin_vec::ThinVec; use tracing::debug; use super::{ - AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos, + AllowConstBlockItems, AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, + Trailing, UsePreAttrPos, }; use crate::parser::FnContext; use crate::{errors, exp, fluent_generated as fluent}; @@ -203,6 +204,7 @@ impl<'a> Parser<'a> { false, FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true }, ForceCollect::No, + AllowConstBlockItems::Yes, ) { Ok(Some(item)) => { // FIXME(#100717) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c7d09b834540..6b61504f2327 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -22,8 +22,8 @@ use tracing::debug; use super::diagnostics::{ConsumeClosingDelim, dummy_arg}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ - AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, Parser, PathStyle, - Recovered, Trailing, UsePreAttrPos, + AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, + Parser, PathStyle, Recovered, Trailing, UsePreAttrPos, }; use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField}; use crate::{exp, fluent_generated as fluent}; @@ -69,7 +69,7 @@ impl<'a> Parser<'a> { // `parse_item` consumes the appropriate semicolons so any leftover is an error. loop { while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons - let Some(item) = self.parse_item(ForceCollect::No)? else { + let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else { break; }; items.push(item); @@ -123,21 +123,34 @@ enum ReuseKind { } impl<'a> Parser<'a> { - pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { + pub fn parse_item( + &mut self, + force_collect: ForceCollect, + allow_const_block_items: AllowConstBlockItems, + ) -> PResult<'a, Option>> { let fn_parse_mode = FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true }; - self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new)) + self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items) + .map(|i| i.map(Box::new)) } fn parse_item_( &mut self, fn_parse_mode: FnParseMode, force_collect: ForceCollect, + const_block_items_allowed: AllowConstBlockItems, ) -> PResult<'a, Option> { self.recover_vcs_conflict_marker(); let attrs = self.parse_outer_attributes()?; self.recover_vcs_conflict_marker(); - self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) + self.parse_item_common( + attrs, + true, + false, + fn_parse_mode, + force_collect, + const_block_items_allowed, + ) } pub(super) fn parse_item_common( @@ -147,10 +160,11 @@ impl<'a> Parser<'a> { attrs_allowed: bool, fn_parse_mode: FnParseMode, force_collect: ForceCollect, + allow_const_block_items: AllowConstBlockItems, ) -> PResult<'a, Option> { - if let Some(item) = - self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes)) - { + if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| { + this.parse_item(ForceCollect::Yes, allow_const_block_items) + }) { let mut item = item.expect("an actual item"); attrs.prepend_to_nt_inner(&mut item.attrs); return Ok(Some(*item)); @@ -163,6 +177,7 @@ impl<'a> Parser<'a> { let kind = this.parse_item_kind( &mut attrs, mac_allowed, + allow_const_block_items, lo, &vis, &mut def, @@ -209,6 +224,7 @@ impl<'a> Parser<'a> { &mut self, attrs: &mut AttrVec, macros_allowed: bool, + allow_const_block_items: AllowConstBlockItems, lo: Span, vis: &Visibility, def: &mut Defaultness, @@ -257,6 +273,15 @@ impl<'a> Parser<'a> { } else if self.check_impl_frontmatter(0) { // IMPL ITEM self.parse_item_impl(attrs, def_(), false)? + } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter = + allow_const_block_items + && self.check_inline_const(0) + { + // CONST BLOCK ITEM + if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items { + debug!("Parsing a const block item that does not matter: {:?}", self.token.span); + }; + ItemKind::ConstBlock(self.parse_const_block_item()?) } else if let Const::Yes(const_span) = self.parse_constness(case) { // CONST ITEM self.recover_const_mut(const_span); @@ -316,6 +341,7 @@ impl<'a> Parser<'a> { return self.parse_item_kind( attrs, macros_allowed, + allow_const_block_items, lo, vis, def, @@ -1068,8 +1094,13 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, kind, tokens }| { + Ok(self + .parse_item_( + fn_parse_mode, + force_collect, + AllowConstBlockItems::DoesNotMatter, // due to `AssocItemKind::try_from` below + )? + .map(|Item { attrs, id, span, vis, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { @@ -1096,8 +1127,7 @@ impl<'a> Parser<'a> { }, }; Some(Box::new(Item { attrs, id, span, vis, kind, tokens })) - }, - )) + })) } /// Parses a `type` alias with the following grammar: @@ -1320,8 +1350,13 @@ impl<'a> Parser<'a> { context: FnContext::Free, req_body: false, }; - Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, kind, tokens }| { + Ok(self + .parse_item_( + fn_parse_mode, + force_collect, + AllowConstBlockItems::DoesNotMatter, // due to `ForeignItemKind::try_from` below + )? + .map(|Item { attrs, id, span, vis, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { @@ -1348,8 +1383,7 @@ impl<'a> Parser<'a> { }, }; Some(Box::new(Item { attrs, id, span, vis, kind, tokens })) - }, - )) + })) } fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option { @@ -1437,6 +1471,14 @@ impl<'a> Parser<'a> { } } + fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> { + self.expect_keyword(exp!(Const))?; + let const_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::const_block_items, const_span); + let block = self.parse_block()?; + Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block }) + } + /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in /// `mutability`. /// @@ -2394,7 +2436,10 @@ impl<'a> Parser<'a> { { let kw_token = self.token; let kw_str = pprust::token_to_string(&kw_token); - let item = self.parse_item(ForceCollect::No)?; + let item = self.parse_item( + ForceCollect::No, + AllowConstBlockItems::DoesNotMatter, // self.token != kw::Const + )?; let mut item = item.unwrap().span; if self.token == token::Comma { item = item.to(self.token.span); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2b711b2f43ef..3ef73a55d47d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -145,6 +145,14 @@ pub enum ForceCollect { No, } +/// Whether to accept `const { ... }` as a shorthand for `const _: () = const { ... }`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AllowConstBlockItems { + Yes, + No, + DoesNotMatter, +} + /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. #[macro_export] macro_rules! maybe_recover_from_interpolated_ty_qpath { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index ea2b896f5fb9..706b454835fa 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -6,7 +6,9 @@ use rustc_span::{Ident, kw}; use crate::errors::UnexpectedNonterminal; use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle}; +use crate::parser::{ + AllowConstBlockItems, FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle, +}; impl<'a> Parser<'a> { /// Checks whether a non-terminal may begin with a particular token. @@ -118,7 +120,9 @@ impl<'a> Parser<'a> { match kind { // Note that TT is treated differently to all the others. NonterminalKind::TT => Ok(ParseNtResult::Tt(self.parse_token_tree())), - NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { + NonterminalKind::Item => match self + .parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)? + { Some(item) => Ok(ParseNtResult::Item(item)), None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))), }, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 26393bf61a32..3c6629572ae5 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -20,8 +20,8 @@ use super::diagnostics::AttemptLocalParseRecovery; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ - AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions, - SemiColonMode, Trailing, UsePreAttrPos, + AllowConstBlockItems, AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, + Restrictions, SemiColonMode, Trailing, UsePreAttrPos, }; use crate::errors::{self, MalformedLoopLabel}; use crate::exp; @@ -156,6 +156,7 @@ impl<'a> Parser<'a> { true, FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true }, force_collect, + AllowConstBlockItems::No, )? { self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item))) } else if self.eat(exp!(Semi)) { diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 3cc0aa67a5bc..61b498431b04 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -22,7 +22,7 @@ use rustc_span::{ }; use crate::lexer::StripTokens; -use crate::parser::{ForceCollect, Parser}; +use crate::parser::{AllowConstBlockItems, ForceCollect, Parser}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; fn psess() -> ParseSess { @@ -2233,7 +2233,7 @@ fn parse_item_from_source_str( psess: &ParseSess, ) -> PResult<'_, Option>> { unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing)) - .parse_item(ForceCollect::No) + .parse_item(ForceCollect::No, AllowConstBlockItems::Yes) } // Produces a `rustc_span::span`. @@ -2248,7 +2248,9 @@ fn string_to_expr(source_str: String) -> Box { /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option> { - with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No)) + with_error_checking_parse(source_str, &psess(), |p| { + p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) + }) } #[test] diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 35101624bd68..23fbb9ab3a2b 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -572,6 +572,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Use, Static, Const, + ConstBlock, Fn, Mod, ForeignMod, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 141a60a8ec3f..b9417af13b11 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -276,7 +276,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { ast::ItemKind::ExternCrate(..) => Target::ExternCrate, ast::ItemKind::Use(_) => Target::Use, ast::ItemKind::Static(_) => Target::Static, - ast::ItemKind::Const(_) => Target::Const, + ast::ItemKind::Const(_) | ast::ItemKind::ConstBlock(_) => Target::Const, ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn, ast::ItemKind::Mod(..) => Target::Mod, ast::ItemKind::ForeignMod(_) => Target::ForeignFn, diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 364ffc7bace0..265284086377 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -4,6 +4,7 @@ // tidy-alphabetical-start #![allow(unused_crate_dependencies)] +#![cfg_attr(feature = "rustc", feature(if_let_guard))] // tidy-alphabetical-end pub(crate) mod checks; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 5e75192ff309..3e97842b7f39 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -4,8 +4,8 @@ use std::iter::once; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; -use rustc_hir::HirId; use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, HirId}; use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; @@ -468,12 +468,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { fields = vec![]; arity = 0; } - PatKind::Deref { subpattern } => { + PatKind::Deref { pin, subpattern } => { fields = vec![self.lower_pat(subpattern).at_index(0)]; arity = 1; - ctor = match ty.pinned_ref() { - None if ty.is_ref() => Ref, - Some((inner_ty, _)) => { + ctor = match pin { + hir::Pinnedness::Not if ty.is_ref() => Ref, + hir::Pinnedness::Pinned if let Some((inner_ty, _)) = ty.pinned_ref() => { self.internal_state.has_lowered_deref_pat.set(true); DerefPattern(RevealedTy(inner_ty)) } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index f763b707aa23..c9abc4bdcdfc 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -18,13 +18,13 @@ use rustc_middle::query::{ queries, }; use rustc_middle::ty::TyCtxt; +use rustc_query_system::Value; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState, - get_query_incr, get_query_non_incr, + CycleError, CycleErrorHandling, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, + QueryState, get_query_incr, get_query_non_incr, }; -use rustc_query_system::{HandleCycleError, Value}; use rustc_span::{ErrorGuaranteed, Span}; use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green}; @@ -181,8 +181,8 @@ where } #[inline(always)] - fn handle_cycle_error(self) -> HandleCycleError { - self.dynamic.handle_cycle_error + fn cycle_error_handling(self) -> CycleErrorHandling { + self.dynamic.cycle_error_handling } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d6d1dc781f3e..7479a992e297 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -199,21 +199,21 @@ pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { } } -macro_rules! handle_cycle_error { +macro_rules! cycle_error_handling { ([]) => {{ - rustc_query_system::HandleCycleError::Error + rustc_query_system::query::CycleErrorHandling::Error }}; ([(cycle_fatal) $($rest:tt)*]) => {{ - rustc_query_system::HandleCycleError::Fatal + rustc_query_system::query::CycleErrorHandling::Fatal }}; ([(cycle_stash) $($rest:tt)*]) => {{ - rustc_query_system::HandleCycleError::Stash + rustc_query_system::query::CycleErrorHandling::Stash }}; ([(cycle_delay_bug) $($rest:tt)*]) => {{ - rustc_query_system::HandleCycleError::DelayBug + rustc_query_system::query::CycleErrorHandling::DelayBug }}; ([$other:tt $($modifiers:tt)*]) => { - handle_cycle_error!([$($modifiers)*]) + cycle_error_handling!([$($modifiers)*]) }; } @@ -618,7 +618,7 @@ macro_rules! define_queries { name: stringify!($name), eval_always: is_eval_always!([$($modifiers)*]), dep_kind: dep_graph::dep_kinds::$name, - handle_cycle_error: handle_cycle_error!([$($modifiers)*]), + cycle_error_handling: cycle_error_handling!([$($modifiers)*]), query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 96998c798689..4b1effe2b33d 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -11,14 +11,6 @@ pub(crate) struct CycleStack { pub desc: String, } -#[derive(Copy, Clone)] -pub enum HandleCycleError { - Error, - Fatal, - DelayBug, - Stash, -} - #[derive(Subdiagnostic)] pub(crate) enum StackCount { #[note(query_system_cycle_stack_single)] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 7fa643d91aa3..cdfe3454061c 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -12,7 +12,7 @@ pub mod ich; pub mod query; mod values; -pub use error::{HandleCycleError, QueryOverflow, QueryOverflowNote}; +pub use error::{QueryOverflow, QueryOverflowNote}; pub use values::Value; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 371b896400a5..739e8e3a8f26 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -7,10 +7,9 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_span::ErrorGuaranteed; use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; -use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; -use crate::query::{CycleError, DepNodeIndex, QueryContext, QueryState}; +use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState}; pub type HashResult = Option, &V) -> Fingerprint>; @@ -67,7 +66,7 @@ pub trait QueryConfig: Copy { fn feedable(self) -> bool; fn dep_kind(self) -> DepKind; - fn handle_cycle_error(self) -> HandleCycleError; + fn cycle_error_handling(self) -> CycleErrorHandling; fn hash_result(self) -> HashResult; // Just here for convenience and checking that the key matches the kind, don't override this. diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index b524756d81b6..796f41d41efa 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -20,6 +20,18 @@ mod config; mod job; mod plumbing; +/// How a particular query deals with query cycle errors. +/// +/// Inspected by the code that actually handles cycle errors, to decide what +/// approach to use. +#[derive(Copy, Clone)] +pub enum CycleErrorHandling { + Error, + Fatal, + DelayBug, + Stash, +} + /// Description of a frame in the query stack. /// /// This is mostly used in case of cycles for error reporting. diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index fa5a94d65188..150ad238dad9 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -19,12 +19,13 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::instrument; use super::QueryConfig; -use crate::HandleCycleError; use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; -use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex}; +use crate::query::{ + CycleErrorHandling, QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex, +}; #[inline] fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { @@ -142,22 +143,21 @@ where Q: QueryConfig, Qcx: QueryContext, { - use HandleCycleError::*; - match query.handle_cycle_error() { - Error => { + match query.cycle_error_handling() { + CycleErrorHandling::Error => { let guar = error.emit(); query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) } - Fatal => { + CycleErrorHandling::Fatal => { error.emit(); qcx.dep_context().sess().dcx().abort_if_errors(); unreachable!() } - DelayBug => { + CycleErrorHandling::DelayBug => { let guar = error.delay_as_bug(); query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) } - Stash => { + CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() && let Some(span) = root.query.span { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 736648c125b6..aa458024b89e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -959,7 +959,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items do not add names to modules. - ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} + ItemKind::Impl { .. } + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) + | ItemKind::ConstBlock(..) => {} ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { unreachable!() diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 8f1a43c090b1..e2fea9146c79 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -131,7 +131,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { mutability: s.mutability, nested: false, }, - ItemKind::Const(..) => DefKind::Const, + ItemKind::Const(..) | ItemKind::ConstBlock(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(ident, def) => { let edition = i.span.edition(); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index ebdb0060e1b9..295635a60547 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -275,6 +275,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> | ast::ItemKind::Use(..) | ast::ItemKind::Static(..) | ast::ItemKind::Const(..) + | ast::ItemKind::ConstBlock(..) | ast::ItemKind::GlobalAsm(..) | ast::ItemKind::TyAlias(..) | ast::ItemKind::TraitAlias(..) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 963bee369f6b..7a7261cf7b95 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2727,8 +2727,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); let def_kind = self.r.local_def_kind(item.id); - match item.kind { - ItemKind::TyAlias(box TyAlias { ref generics, .. }) => { + match &item.kind { + ItemKind::TyAlias(box TyAlias { generics, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -2739,7 +2739,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => { + ItemKind::Fn(box Fn { generics, define_opaque, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -2751,19 +2751,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - ItemKind::Enum(_, ref generics, _) - | ItemKind::Struct(_, ref generics, _) - | ItemKind::Union(_, ref generics, _) => { + ItemKind::Enum(_, generics, _) + | ItemKind::Struct(_, generics, _) + | ItemKind::Union(_, generics, _) => { self.resolve_adt(item, generics); } - ItemKind::Impl(Impl { - ref generics, - ref of_trait, - ref self_ty, - items: ref impl_items, - .. - }) => { + ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, .. }) => { self.diag_metadata.current_impl_items = Some(impl_items); self.resolve_implementation( &item.attrs, @@ -2776,7 +2770,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.diag_metadata.current_impl_items = None; } - ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { + ItemKind::Trait(box Trait { generics, bounds, items, .. }) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -2795,7 +2789,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::TraitAlias(box TraitAlias { ref generics, ref bounds, .. }) => { + ItemKind::TraitAlias(box TraitAlias { generics, bounds, .. }) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -2835,13 +2829,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.parent_scope.module = orig_module; } - ItemKind::Static(box ast::StaticItem { - ident, - ref ty, - ref expr, - ref define_opaque, - .. - }) => { + ItemKind::Static(box ast::StaticItem { ident, ty, expr, define_opaque, .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); @@ -2849,7 +2837,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. - this.resolve_static_body(expr, Some((ident, ConstantItemKind::Static))); + this.resolve_static_body(expr, Some((*ident, ConstantItemKind::Static))); } }); self.resolve_define_opaques(define_opaque); @@ -2857,11 +2845,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ItemKind::Const(box ast::ConstItem { ident, - ref generics, - ref ty, - ref rhs, - ref define_opaque, - .. + generics, + ty, + rhs, + define_opaque, + defaultness: _, }) => { let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( @@ -2903,15 +2891,36 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(rhs) = rhs { this.resolve_const_item_rhs( rhs, - Some((ident, ConstantItemKind::Const)), + Some((*ident, ConstantItemKind::Const)), ); } }, ); self.resolve_define_opaques(define_opaque); } + ItemKind::ConstBlock(ConstBlockItem { id: _, span: _, block }) => self + .with_generic_param_rib( + &[], + RibKind::Item(HasGenericParams::No, def_kind), + item.id, + LifetimeBinderKind::ConstItem, + DUMMY_SP, + |this| { + this.with_lifetime_rib( + LifetimeRibKind::Elided(LifetimeRes::Infer), + |this| { + this.with_constant_rib( + IsRepeatExpr::No, + ConstantHasGenerics::Yes, + Some((ConstBlockItem::IDENT, ConstantItemKind::Const)), + |this| this.resolve_labeled_block(None, block.id, block), + ) + }, + ); + }, + ), - ItemKind::Use(ref use_tree) => { + ItemKind::Use(use_tree) => { let maybe_exported = match use_tree.kind { UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id), UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis), @@ -2921,7 +2930,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.future_proof_import(use_tree); } - ItemKind::MacroDef(_, ref macro_def) => { + ItemKind::MacroDef(_, macro_def) => { // Maintain macro_rules scopes in the same way as during early resolution // for diagnostics and doc links. if macro_def.macro_rules { @@ -2945,7 +2954,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { visit::walk_item(self, item); } - ItemKind::Delegation(ref delegation) => { + ItemKind::Delegation(delegation) => { let span = delegation.path.segments.last().unwrap().ident.span; self.with_generic_param_rib( &[], @@ -5477,6 +5486,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { ItemKind::Mod(..) | ItemKind::Static(..) + | ItemKind::ConstBlock(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8d3deb0f25e1..9219b5a7e8ac 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2426,6 +2426,9 @@ options! { `=skip-entry` `=skip-exit` Multiple options can be combined with commas."), + large_data_threshold: Option = (None, parse_opt_number, [TRACKED], + "set the threshold for objects to be stored in a \"large data\" section \ + (only effective with -Ccode-model=medium, default: 65536)"), layout_seed: Option = (None, parse_opt_number, [TRACKED], "seed layout randomization"), link_directives: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5767444025ec..96e883a2d9ce 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -731,6 +731,7 @@ symbols! { console, const_allocate, const_async_blocks, + const_block_items, const_closures, const_compare_raw_pointers, const_constructor, @@ -2140,6 +2141,7 @@ symbols! { simd_shr, simd_shuffle, simd_shuffle_const_generic, + simd_splat, simd_sub, simd_trunc, simd_with_exposed_provenance, diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index d6b305253798..97eb93335818 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -47,7 +47,7 @@ impl RiscVInlineAsmRegClass { types! { _: I8, I16, I32, F16, F32; } } } - // FIXME(f16_f128): Add `q: F128;` once LLVM support the `Q` extension. + // FIXME(f128): Add `q: F128;` once LLVM support the `Q` extension. Self::freg => types! { f: F16, F32; d: F64; }, Self::vreg => &[], } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ef475630d494..fe4b91c53f63 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1596,8 +1596,11 @@ supported_targets! { ("armebv7r-none-eabi", armebv7r_none_eabi), ("armebv7r-none-eabihf", armebv7r_none_eabihf), ("armv7r-none-eabi", armv7r_none_eabi), + ("thumbv7r-none-eabi", thumbv7r_none_eabi), ("armv7r-none-eabihf", armv7r_none_eabihf), + ("thumbv7r-none-eabihf", thumbv7r_none_eabihf), ("armv8r-none-eabihf", armv8r_none_eabihf), + ("thumbv8r-none-eabihf", thumbv8r_none_eabihf), ("armv7-rtems-eabihf", armv7_rtems_eabihf), @@ -1649,7 +1652,9 @@ supported_targets! { ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf), ("armv7a-none-eabi", armv7a_none_eabi), + ("thumbv7a-none-eabi", thumbv7a_none_eabi), ("armv7a-none-eabihf", armv7a_none_eabihf), + ("thumbv7a-none-eabihf", thumbv7a_none_eabihf), ("armv7a-nuttx-eabi", armv7a_nuttx_eabi), ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf), ("armv7a-vex-v5", armv7a_vex_v5), @@ -1741,10 +1746,14 @@ supported_targets! { ("mipsel-unknown-none", mipsel_unknown_none), ("mips-mti-none-elf", mips_mti_none_elf), ("mipsel-mti-none-elf", mipsel_mti_none_elf), - ("thumbv4t-none-eabi", thumbv4t_none_eabi), + ("armv4t-none-eabi", armv4t_none_eabi), - ("thumbv5te-none-eabi", thumbv5te_none_eabi), ("armv5te-none-eabi", armv5te_none_eabi), + ("armv6-none-eabi", armv6_none_eabi), + ("armv6-none-eabihf", armv6_none_eabihf), + ("thumbv4t-none-eabi", thumbv4t_none_eabi), + ("thumbv5te-none-eabi", thumbv5te_none_eabi), + ("thumbv6-none-eabi", thumbv6_none_eabi), ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu), ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32), diff --git a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs index fc66a2fa8f9e..c917531932f6 100644 --- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs @@ -1,4 +1,4 @@ -//! Targets the ARMv4T, with code as `a32` code by default. +//! Targets the ARMv4T architecture, with `a32` code by default. //! //! Primarily of use for the GBA, but usable with other devices too. //! diff --git a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs index 8089e9a7a064..b8ae881f3dae 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs @@ -1,4 +1,4 @@ -//! Targets the ARMv5TE, with code as `a32` code by default. +//! Targets the ARMv5TE architecture, with `a32` code by default. use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs}; diff --git a/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs new file mode 100644 index 000000000000..48a196b231b0 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs @@ -0,0 +1,29 @@ +//! Targets the ARMv6K architecture, with `a32` code by default. + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "armv6-none-eabi".into(), + metadata: TargetMetadata { + description: Some("Bare ARMv6 soft-float".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: Arch::Arm, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + options: TargetOptions { + abi: Abi::Eabi, + llvm_floatabi: Some(FloatAbi::Soft), + asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",], + features: "+soft-float,+strict-align,+v6k".into(), + atomic_cas: true, + has_thumb_interworking: true, + // LDREXD/STREXD available as of ARMv6K + max_atomic_width: Some(64), + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs new file mode 100644 index 000000000000..8bc6b06ecee3 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs @@ -0,0 +1,29 @@ +//! Targets the ARMv6K architecture, with `a32` code by default, and hard-float ABI + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "armv6-none-eabihf".into(), + metadata: TargetMetadata { + description: Some("Bare ARMv6 hard-float".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: Arch::Arm, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + options: TargetOptions { + abi: Abi::EabiHf, + llvm_floatabi: Some(FloatAbi::Hard), + asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",], + features: "+strict-align,+v6k,+vfp2,-d32".into(), + atomic_cas: true, + has_thumb_interworking: true, + // LDREXD/STREXD available as of ARMv6K + max_atomic_width: Some(64), + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs index 6b7707a47390..e8c5c16d8eb5 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs @@ -1,40 +1,8 @@ -// Generic ARMv7-A target for bare-metal code - floating point disabled -// -// This is basically the `armv7-unknown-linux-gnueabi` target with some changes -// (listed below) to bring it closer to the bare-metal `thumb` & `aarch64` -// targets: -// -// - `TargetOptions.features`: added `+strict-align`. rationale: unaligned -// memory access is disabled on boot on these cores -// - linker changed to LLD. rationale: C is not strictly needed to build -// bare-metal binaries (the `gcc` linker has the advantage that it knows where C -// libraries and crt*.o are but it's not much of an advantage here); LLD is also -// faster -// - `panic_strategy` set to `abort`. rationale: matches `thumb` targets -// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic -// linking. rationale: matches `thumb` targets +// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A) -use crate::spec::{ - Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, -}; +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { - let opts = TargetOptions { - abi: Abi::Eabi, - llvm_floatabi: Some(FloatAbi::Soft), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), - linker: Some("rust-lld".into()), - features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(), - relocation_model: RelocModel::Static, - disable_redzone: true, - max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, - emit_debug_gdb_scripts: false, - c_enum_min_bits: Some(8), - has_thumb_interworking: true, - ..Default::default() - }; Target { llvm_target: "armv7a-none-eabi".into(), metadata: TargetMetadata { @@ -46,6 +14,13 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: Arch::Arm, - options: opts, + options: TargetOptions { + abi: Abi::Eabi, + llvm_floatabi: Some(FloatAbi::Soft), + features: "+soft-float,-neon,+strict-align".into(), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs index 993390543b96..32a79e346adc 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs @@ -1,32 +1,8 @@ -// Generic ARMv7-A target for bare-metal code - floating point enabled (assumes -// FPU is present and emits FPU instructions) -// -// This is basically the `armv7-unknown-linux-gnueabihf` target with some -// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal -// `thumb` & `aarch64` targets. +// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A) -use crate::spec::{ - Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, -}; +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { - let opts = TargetOptions { - abi: Abi::EabiHf, - llvm_floatabi: Some(FloatAbi::Hard), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), - linker: Some("rust-lld".into()), - features: "+v7,+vfp3d16,+thumb2,-neon,+strict-align".into(), - relocation_model: RelocModel::Static, - disable_redzone: true, - max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, - emit_debug_gdb_scripts: false, - // GCC defaults to 8 for arm-none here. - c_enum_min_bits: Some(8), - has_thumb_interworking: true, - ..Default::default() - }; Target { llvm_target: "armv7a-none-eabihf".into(), metadata: TargetMetadata { @@ -38,6 +14,13 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: Arch::Arm, - options: opts, + options: TargetOptions { + abi: Abi::EabiHf, + llvm_floatabi: Some(FloatAbi::Hard), + features: "+vfp3d16,-neon,+strict-align".into(), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs index 551cbf4a589f..114b079f360b 100644 --- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs @@ -1,15 +1,12 @@ // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R) -use crate::spec::{ - Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, -}; +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { llvm_target: "armv7r-none-eabi".into(), metadata: TargetMetadata { - description: Some("Armv7-R".into()), + description: Some("Bare Armv7-R".into()), tier: Some(2), host_tools: Some(false), std: Some(false), @@ -17,20 +14,12 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: Arch::Arm, - options: TargetOptions { abi: Abi::Eabi, llvm_floatabi: Some(FloatAbi::Soft), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), - linker: Some("rust-lld".into()), - relocation_model: RelocModel::Static, - panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(64), - emit_debug_gdb_scripts: false, - // GCC defaults to 8 for arm-none here. - c_enum_min_bits: Some(8), has_thumb_interworking: true, - ..Default::default() + ..base::arm_none::opts() }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs index 97c911ec8090..1c6114f9fc83 100644 --- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs @@ -1,15 +1,12 @@ // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R) -use crate::spec::{ - Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, -}; +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { llvm_target: "armv7r-none-eabihf".into(), metadata: TargetMetadata { - description: Some("Armv7-R, hardfloat".into()), + description: Some("Bare Armv7-R, hardfloat".into()), tier: Some(2), host_tools: Some(false), std: Some(false), @@ -17,21 +14,13 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: Arch::Arm, - options: TargetOptions { abi: Abi::EabiHf, llvm_floatabi: Some(FloatAbi::Hard), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), - linker: Some("rust-lld".into()), - relocation_model: RelocModel::Static, - panic_strategy: PanicStrategy::Abort, features: "+vfp3d16".into(), max_atomic_width: Some(64), - emit_debug_gdb_scripts: false, - // GCC defaults to 8 for arm-none here. - c_enum_min_bits: Some(8), has_thumb_interworking: true, - ..Default::default() + ..base::arm_none::opts() }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs index e36240b9c223..16006e4c52cf 100644 --- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -1,9 +1,6 @@ // Targets the Little-endian Cortex-R52 processor (ARMv8-R) -use crate::spec::{ - Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, -}; +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -21,10 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { abi: Abi::EabiHf, llvm_floatabi: Some(FloatAbi::Hard), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), - linker: Some("rust-lld".into()), - relocation_model: RelocModel::Static, - panic_strategy: PanicStrategy::Abort, // Armv8-R requires a minimum set of floating-point features equivalent to: // fp-armv8, SP-only, with 16 DP (32 SP) registers // LLVM defines Armv8-R to include these features automatically. @@ -36,11 +29,8 @@ pub(crate) fn target() -> Target { // Arm Cortex-R52 Processor Technical Reference Manual // - Chapter 15 Advanced SIMD and floating-point support max_atomic_width: Some(64), - emit_debug_gdb_scripts: false, - // GCC defaults to 8 for arm-none here. - c_enum_min_bits: Some(8), has_thumb_interworking: true, - ..Default::default() + ..base::arm_none::opts() }, } } diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index b663ddf962ea..130bcacfc8cc 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -17,8 +17,8 @@ pub(crate) fn target() -> Target { llvm_target: "powerpc64-unknown-linux-musl".into(), metadata: TargetMetadata { description: Some("64-bit PowerPC Linux with musl 1.2.5".into()), - tier: Some(3), - host_tools: Some(false), + tier: Some(2), + host_tools: Some(true), std: Some(true), }, pointer_width: 64, diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs index 50eccbed3ac1..dfb8ccb06bc2 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs @@ -1,4 +1,4 @@ -//! Targets the ARMv4T, with code as `t32` code by default. +//! Targets the ARMv4T architecture, with `t32` code by default. //! //! Primarily of use for the GBA, but usable with other devices too. //! diff --git a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs index 6acb03e3b296..3b41208b69f4 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs @@ -1,4 +1,4 @@ -//! Targets the ARMv5TE, with code as `t32` code by default. +//! Targets the ARMv5TE architecture, with `t32` code by default. use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs}; diff --git a/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs new file mode 100644 index 000000000000..077f02818085 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs @@ -0,0 +1,30 @@ +//! Targets the ARMv6K architecture, with `t32` code by default. + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv6-none-eabi".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare ARMv6 soft-float".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: Arch::Arm, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + options: TargetOptions { + abi: Abi::Eabi, + llvm_floatabi: Some(FloatAbi::Soft), + asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",], + features: "+soft-float,+strict-align,+v6k".into(), + // CAS atomics are implemented in LLVM on this target using __sync* functions, + // which were added to compiler-builtins in https://github.com/rust-lang/compiler-builtins/pull/1050 + atomic_cas: true, + has_thumb_interworking: true, + max_atomic_width: Some(32), + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs new file mode 100644 index 000000000000..ce11e3f0875c --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs @@ -0,0 +1,26 @@ +// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A) + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7a-none-eabi".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare Armv7-A".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: Arch::Arm, + options: TargetOptions { + abi: Abi::Eabi, + llvm_floatabi: Some(FloatAbi::Soft), + features: "+soft-float,-neon,+strict-align".into(), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs new file mode 100644 index 000000000000..12210e9c2b01 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs @@ -0,0 +1,26 @@ +// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A) + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7a-none-eabihf".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: Arch::Arm, + options: TargetOptions { + abi: Abi::EabiHf, + llvm_floatabi: Some(FloatAbi::Hard), + features: "+vfp3d16,-neon,+strict-align".into(), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs new file mode 100644 index 000000000000..bf71d31a06ec --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs @@ -0,0 +1,25 @@ +// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R) + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7r-none-eabi".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare Armv7-R".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: Arch::Arm, + options: TargetOptions { + abi: Abi::Eabi, + llvm_floatabi: Some(FloatAbi::Soft), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs new file mode 100644 index 000000000000..88b5e6764403 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs @@ -0,0 +1,26 @@ +// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R) + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7r-none-eabihf".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: Arch::Arm, + options: TargetOptions { + abi: Abi::EabiHf, + llvm_floatabi: Some(FloatAbi::Hard), + features: "+vfp3d16".into(), + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs new file mode 100644 index 000000000000..87434cd7353c --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs @@ -0,0 +1,36 @@ +// Targets the Little-endian Cortex-R52 processor (ARMv8-R) + +use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv8r-none-eabihf".into(), + metadata: TargetMetadata { + description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: Arch::Arm, + + options: TargetOptions { + abi: Abi::EabiHf, + llvm_floatabi: Some(FloatAbi::Hard), + // Armv8-R requires a minimum set of floating-point features equivalent to: + // fp-armv8, SP-only, with 16 DP (32 SP) registers + // LLVM defines Armv8-R to include these features automatically. + // + // The Cortex-R52 supports these default features and optionally includes: + // neon-fp-armv8, SP+DP, with 32 DP registers + // + // Reference: + // Arm Cortex-R52 Processor Technical Reference Manual + // - Chapter 15 Advanced SIMD and floating-point support + max_atomic_width: Some(64), + has_thumb_interworking: true, + ..base::arm_none::opts() + }, + } +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 4eba426dda59..fde7dfcabb70 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -492,7 +492,22 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("hvx", Unstable(sym::hexagon_target_feature), &[]), + ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]), ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]), + ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]), + ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]), + ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]), + ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]), + ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]), + ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]), + ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]), + ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]), + ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]), + ("zreg", Unstable(sym::hexagon_target_feature), &[]), // tidy-alphabetical-end ]; @@ -949,7 +964,7 @@ const SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'stat &[/*(64, "vis")*/]; const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = - &[/*(512, "hvx-length64b"),*/ (1024, "hvx-length128b")]; + &[(512, "hvx-length64b"), (1024, "hvx-length128b")]; const MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")]; const CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 1e76710d3536..ff996ba93cd7 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -865,9 +865,13 @@ const fn handle_error(e: TryReserveError) -> ! { #[inline] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const fn layout_array(cap: usize, elem_layout: Layout) -> Result { + // This is only used with `elem_layout`s which are those of real rust types, + // which lets us use the much-simpler `repeat_packed`. + debug_assert!(elem_layout.size() == elem_layout.pad_to_align().size()); + // FIXME(const-hack) return to using `map` and `map_err` once `const_closures` is implemented - match elem_layout.repeat(cap) { - Ok((layout, _pad)) => Ok(layout), + match elem_layout.repeat_packed(cap) { + Ok(layout) => Ok(layout), Err(_) => Err(CapacityOverflow.into()), } } diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 6447fde0cd8a..9b80e3b70fa2 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -118,12 +118,12 @@ use crate::{cmp, ptr}; /// /// # Re-entrance /// -/// When implementing a global allocator one has to be careful not to create an infinitely recursive +/// When implementing a global allocator, one has to be careful not to create an infinitely recursive /// implementation by accident, as many constructs in the Rust standard library may allocate in -/// their implementation. For example, on some platforms [`std::sync::Mutex`] may allocate, so using +/// their implementation. For example, on some platforms, [`std::sync::Mutex`] may allocate, so using /// it is highly problematic in a global allocator. /// -/// Generally speaking for this reason one should stick to library features available through +/// For this reason, one should generally stick to library features available through /// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are /// guaranteed to not use `#[global_allocator]` to allocate: /// diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 99268d6182f6..9b9d2f02550b 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -1,5 +1,7 @@ //! impl bool {} +use crate::marker::Destruct; + impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. @@ -29,8 +31,9 @@ impl bool { /// assert_eq!(a, 2); /// ``` #[stable(feature = "bool_to_option", since = "1.62.0")] + #[rustc_const_unstable(feature = "const_bool", issue = "151531")] #[inline] - pub fn then_some(self, t: T) -> Option { + pub const fn then_some(self, t: T) -> Option { if self { Some(t) } else { None } } @@ -57,8 +60,9 @@ impl bool { #[doc(alias = "then_with")] #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[rustc_diagnostic_item = "bool_then"] + #[rustc_const_unstable(feature = "const_bool", issue = "151531")] #[inline] - pub fn then T>(self, f: F) -> Option { + pub const fn then T + [const] Destruct>(self, f: F) -> Option { if self { Some(f()) } else { None } } @@ -94,8 +98,9 @@ impl bool { /// assert_eq!(a, 2); /// ``` #[unstable(feature = "bool_to_result", issue = "142748")] + #[rustc_const_unstable(feature = "const_bool", issue = "151531")] #[inline] - pub fn ok_or(self, err: E) -> Result<(), E> { + pub const fn ok_or(self, err: E) -> Result<(), E> { if self { Ok(()) } else { Err(err) } } @@ -124,8 +129,12 @@ impl bool { /// assert_eq!(a, 1); /// ``` #[unstable(feature = "bool_to_result", issue = "142748")] + #[rustc_const_unstable(feature = "const_bool", issue = "151531")] #[inline] - pub fn ok_or_else E>(self, f: F) -> Result<(), E> { + pub const fn ok_or_else E + [const] Destruct>( + self, + f: F, + ) -> Result<(), E> { if self { Ok(()) } else { Err(f()) } } } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 6ae588a4e044..c69026c5c9f3 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -154,7 +154,7 @@ impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.2 // * 53 bits in f64 // * 113 bits in f128 // Lossy float conversions are not implemented at this time. -// FIXME(f16_f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference +// FIXME(f16,f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference // `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none // of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable). @@ -168,7 +168,7 @@ impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); -// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised. +// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised. // impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // unsigned integer -> float @@ -181,11 +181,11 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); -// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised. +// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised. // impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // float -> float -// FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See +// FIXME(f16,f128): adding additional `From<{float}>` impls to `f32` breaks inference. See // impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 556db239f249..380dbd25e104 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -236,7 +236,7 @@ floating! { f32 f64 } #[cfg(target_has_reliable_f16)] floating! { f16 } -// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order +// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order // to avoid ICEs. #[cfg(not(target_has_reliable_f16))] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 4c050b49bf7e..b7f78288b2b6 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -292,9 +292,18 @@ pub fn spin_loop() { // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) } } - all(target_arch = "arm", target_feature = "v6") => { - // SAFETY: the `cfg` attr ensures that we only execute this on arm targets - // with support for the v6 feature. + all( + target_arch = "arm", + any( + all(target_feature = "v6k", not(target_feature = "thumb-mode")), + target_feature = "v6t2", + all(target_feature = "v6", target_feature = "mclass"), + ) + ) => { + // SAFETY: the `cfg` attr ensures that we only execute this on arm + // targets with support for the this feature. On ARMv6 in Thumb + // mode, T2 is required (see Arm DDI0406C Section A8.8.427), + // otherwise ARMv6-M or ARMv6K is enough unsafe { crate::arch::arm::__yield() } } target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(), diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 9d5dfb172586..f70262c38ae5 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -52,6 +52,13 @@ pub const unsafe fn simd_insert_dyn(x: T, idx: u32, val: U) -> T; #[rustc_intrinsic] pub const unsafe fn simd_extract_dyn(x: T, idx: u32) -> U; +/// Creates a vector where every lane has the provided value. +/// +/// `T` must be a vector with element type `U`. +#[rustc_nounwind] +#[rustc_intrinsic] +pub const unsafe fn simd_splat(value: U) -> T; + /// Adds two simd vectors elementwise. /// /// `T` must be a vector of integers or floats. diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index eee8adf4f755..66e30e1c5f7f 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -179,7 +179,7 @@ from_str_float_impl!(f16); from_str_float_impl!(f32); from_str_float_impl!(f64); -// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order +// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order // to avoid ICEs. #[cfg(not(target_has_reliable_f16))] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 65afdd2969b8..cc142fab8e82 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -137,10 +137,8 @@ pub mod consts { pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128; } +#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))] impl f128 { - // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const - // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. - /// The radix or base of the internal representation of `f128`. #[unstable(feature = "f128", issue = "116909")] pub const RADIX: u32 = 2; @@ -277,8 +275,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `unordtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let nan = f128::NAN; /// let f = 7.0_f128; @@ -300,8 +297,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let f = 7.0f128; /// let inf = f128::INFINITY; @@ -326,8 +322,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `lttf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let f = 7.0f128; /// let inf: f128 = f128::INFINITY; @@ -355,8 +350,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128 /// let max = f128::MAX; @@ -386,8 +380,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128 /// let max = f128::MAX; @@ -419,8 +412,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// use std::num::FpCategory; /// @@ -514,8 +506,7 @@ impl f128 { /// /// ```rust /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// // f128::EPSILON is the difference between 1.0 and the next number up. /// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON); @@ -569,8 +560,7 @@ impl f128 { /// /// ```rust /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let x = 1.0f128; /// // Clamp value into range [0, 1). @@ -613,8 +603,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let x = 2.0_f128; /// let abs_difference = (x.recip() - (1.0 / x)).abs(); @@ -640,8 +629,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let angle = std::f128::consts::PI; /// @@ -671,8 +659,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let angle = 180.0f128; /// @@ -706,8 +693,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // Using aarch64 because `reliable_f128_math` is needed - /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let y = 2.0f128; @@ -738,8 +724,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // Using aarch64 because `reliable_f128_math` is needed - /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let y = 2.0f128; @@ -771,8 +756,7 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_minimum_maximum)] - /// # // Using aarch64 because `reliable_f128_math` is needed - /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let y = 2.0f128; @@ -804,8 +788,7 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_minimum_maximum)] - /// # // Using aarch64 because `reliable_f128_math` is needed - /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let y = 2.0f128; @@ -831,8 +814,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // Using aarch64 because `reliable_f128_math` is needed - /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// assert_eq!(1f128.midpoint(4.0), 2.5); /// assert_eq!((-5.5f128).midpoint(8.0), 1.25); @@ -862,8 +844,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `float*itf` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let value = 4.6_f128; /// let rounded = unsafe { value.to_int_unchecked::() }; @@ -906,10 +887,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] + /// # #[cfg(target_has_reliable_f128)] { /// - /// # // FIXME(f16_f128): enable this once const casting works - /// # // assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting! + /// assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting! /// assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + /// # } /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] @@ -952,8 +934,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let v = f128::from_bits(0x40029000000000000000000000000000); /// assert_eq!(v, 12.5); @@ -1064,8 +1045,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let value = f128::from_be_bytes( /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1090,8 +1070,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let value = f128::from_le_bytes( /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1123,8 +1102,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `eqtf2` is available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1257,8 +1235,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0); /// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0); @@ -1333,7 +1310,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let x = 3.5_f128; /// let y = -3.5_f128; @@ -1349,9 +1326,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn abs(self) -> Self { - // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available - // We don't do this now because LLVM has lowering bugs for f128 math. - Self::from_bits(self.to_bits() & !(1 << 127)) + intrinsics::fabsf128(self) } /// Returns a number that represents the sign of `self`. @@ -1364,7 +1339,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let f = 3.5_f128; /// @@ -1400,7 +1375,7 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// # #[cfg(target_has_reliable_f128)] { /// /// let f = 3.5_f128; /// @@ -1477,8 +1452,6 @@ impl f128 { } // Functions in this module fall into `core_float_math` -// FIXME(f16_f128): all doctests must be gated to platforms that have `long double` === `_Float128` -// due to https://github.com/llvm/llvm-project/issues/44744. aarch64 linux matches this. // #[unstable(feature = "core_float_math", issue = "137578")] #[cfg(not(test))] #[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 344f58da277b..e97a44e991f6 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -134,9 +134,6 @@ pub mod consts { #[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))] impl f16 { - // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const - // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. - /// The radix or base of the internal representation of `f16`. #[unstable(feature = "f16", issue = "116909")] pub const RADIX: u32 = 2; @@ -887,8 +884,7 @@ impl f16 { /// #![feature(f16)] /// # #[cfg(target_has_reliable_f16)] { /// - /// # // FIXME(f16_f128): enable this once const casting works - /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! + /// assert_ne!((1f16).to_bits(), 1f16 as u16); // to_bits() is not casting! /// assert_eq!((12.5f16).to_bits(), 0x4a40); /// # } /// ``` diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 3e8c553f9f15..459c826f4064 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -3,10 +3,7 @@ use core::ascii::EscapeDefault; use crate::fmt::{self, Write}; -#[cfg(not(any( - all(target_arch = "x86_64", target_feature = "sse2"), - all(target_arch = "loongarch64", target_feature = "lsx") -)))] +#[cfg(not(all(target_arch = "loongarch64", target_feature = "lsx")))] use crate::intrinsics::const_eval_select; use crate::{ascii, iter, ops}; @@ -463,19 +460,101 @@ const fn is_ascii(s: &[u8]) -> bool { ) } -/// ASCII test optimized to use the `pmovmskb` instruction on `x86-64` and the -/// `vmskltz.b` instruction on `loongarch64`. +/// Chunk size for vectorized ASCII checking (two 16-byte SSE registers). +#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] +const CHUNK_SIZE: usize = 32; + +/// SSE2 implementation using `_mm_movemask_epi8` (compiles to `pmovmskb`) to +/// avoid LLVM's broken AVX-512 auto-vectorization of counting loops. +/// +/// FIXME(llvm#176906): Remove this workaround once LLVM generates efficient code. +#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] +fn is_ascii_sse2(bytes: &[u8]) -> bool { + use crate::arch::x86_64::{__m128i, _mm_loadu_si128, _mm_movemask_epi8, _mm_or_si128}; + + let mut i = 0; + + while i + CHUNK_SIZE <= bytes.len() { + // SAFETY: We have verified that `i + CHUNK_SIZE <= bytes.len()`. + let ptr = unsafe { bytes.as_ptr().add(i) }; + + // Load two 16-byte chunks and combine them. + // SAFETY: We verified `i + 32 <= len`, so ptr is valid for 32 bytes. + // `_mm_loadu_si128` allows unaligned loads. + let chunk1 = unsafe { _mm_loadu_si128(ptr as *const __m128i) }; + // SAFETY: Same as above - ptr.add(16) is within the valid 32-byte range. + let chunk2 = unsafe { _mm_loadu_si128(ptr.add(16) as *const __m128i) }; + + // OR them together - if any byte has the high bit set, the result will too. + // SAFETY: SSE2 is guaranteed by the cfg predicate. + let combined = unsafe { _mm_or_si128(chunk1, chunk2) }; + + // Create a mask from the MSBs of each byte. + // If any byte is >= 128, its MSB is 1, so the mask will be non-zero. + // SAFETY: SSE2 is guaranteed by the cfg predicate. + let mask = unsafe { _mm_movemask_epi8(combined) }; + + if mask != 0 { + return false; + } + + i += CHUNK_SIZE; + } + + // Handle remaining bytes with simple loop + while i < bytes.len() { + if !bytes[i].is_ascii() { + return false; + } + i += 1; + } + + true +} + +/// ASCII test optimized to use the `pmovmskb` instruction on `x86-64`. +/// +/// Uses explicit SSE2 intrinsics to prevent LLVM from auto-vectorizing with +/// broken AVX-512 code that extracts mask bits one-by-one. +#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +const fn is_ascii(bytes: &[u8]) -> bool { + const USIZE_SIZE: usize = size_of::(); + const NONASCII_MASK: usize = usize::MAX / 255 * 0x80; + + const_eval_select!( + @capture { bytes: &[u8] } -> bool: + if const { + is_ascii_simple(bytes) + } else { + // For small inputs, use usize-at-a-time processing to avoid SSE2 call overhead. + if bytes.len() < CHUNK_SIZE { + let chunks = bytes.chunks_exact(USIZE_SIZE); + let remainder = chunks.remainder(); + for chunk in chunks { + let word = usize::from_ne_bytes(chunk.try_into().unwrap()); + if (word & NONASCII_MASK) != 0 { + return false; + } + } + return remainder.iter().all(|b| b.is_ascii()); + } + + is_ascii_sse2(bytes) + } + ) +} + +/// ASCII test optimized to use the `vmskltz.b` instruction on `loongarch64`. /// /// Other platforms are not likely to benefit from this code structure, so they /// use SWAR techniques to test for ASCII in `usize`-sized chunks. -#[cfg(any( - all(target_arch = "x86_64", target_feature = "sse2"), - all(target_arch = "loongarch64", target_feature = "lsx") -))] +#[cfg(all(target_arch = "loongarch64", target_feature = "lsx"))] #[inline] const fn is_ascii(bytes: &[u8]) -> bool { // Process chunks of 32 bytes at a time in the fast path to enable - // auto-vectorization and use of `pmovmskb`. Two 128-bit vector registers + // auto-vectorization and use of `vmskltz.b`. Two 128-bit vector registers // can be OR'd together and then the resulting vector can be tested for // non-ASCII bytes. const CHUNK_SIZE: usize = 32; @@ -485,7 +564,7 @@ const fn is_ascii(bytes: &[u8]) -> bool { while i + CHUNK_SIZE <= bytes.len() { let chunk_end = i + CHUNK_SIZE; - // Get LLVM to produce a `pmovmskb` instruction on x86-64 which + // Get LLVM to produce a `vmskltz.b` instruction on loongarch64 which // creates a mask from the most significant bit of each byte. // ASCII bytes are less than 128 (0x80), so their most significant // bit is unset. diff --git a/library/coretests/tests/bool.rs b/library/coretests/tests/bool.rs index eb5f0f50663e..802e43045b6e 100644 --- a/library/coretests/tests/bool.rs +++ b/library/coretests/tests/bool.rs @@ -82,6 +82,10 @@ pub fn test_bool_not() { } } +const fn zero() -> i32 { + 0 +} + #[test] fn test_bool_to_option() { assert_eq!(false.then_some(0), None); @@ -89,11 +93,6 @@ fn test_bool_to_option() { assert_eq!(false.then(|| 0), None); assert_eq!(true.then(|| 0), Some(0)); - /* FIXME(#110395) - const fn zero() -> i32 { - 0 - } - const A: Option = false.then_some(0); const B: Option = true.then_some(0); const C: Option = false.then(zero); @@ -103,7 +102,6 @@ fn test_bool_to_option() { assert_eq!(B, Some(0)); assert_eq!(C, None); assert_eq!(D, Some(0)); - */ } #[test] @@ -112,4 +110,14 @@ fn test_bool_to_result() { assert_eq!(true.ok_or(0), Ok(())); assert_eq!(false.ok_or_else(|| 0), Err(0)); assert_eq!(true.ok_or_else(|| 0), Ok(())); + + const A: Result<(), i32> = false.ok_or(0); + const B: Result<(), i32> = true.ok_or(0); + const C: Result<(), i32> = false.ok_or_else(zero); + const D: Result<(), i32> = true.ok_or_else(zero); + + assert_eq!(A, Err(0)); + assert_eq!(B, Ok(())); + assert_eq!(C, Err(0)); + assert_eq!(D, Ok(())); } diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 87e21b21f310..06fc3c96eafc 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -391,7 +391,7 @@ float_test! { } } -// FIXME(f16_f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on +// FIXME(f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on // all platforms. float_test! { name: num_rem, @@ -1357,15 +1357,11 @@ float_test! { } } -// FIXME(f16): Tests involving sNaN are disabled because without optimizations, `total_cmp` is -// getting incorrectly lowered to code that includes a `extend`/`trunc` round trip, which quiets -// sNaNs. See: https://github.com/llvm/llvm-project/issues/104915 - float_test! { name: total_cmp_s_nan, attrs: { const: #[cfg(false)], - f16: #[cfg(miri)], + f16: #[cfg(any(miri, target_has_reliable_f16_math))], f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { @@ -1636,7 +1632,7 @@ float_test! { } } -// FIXME(f16_f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added. +// FIXME(f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added. // float_test! { // name: from_u64_i64, // attrs: { diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 8c91567fc94a..8cca714b7393 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -17,6 +17,7 @@ #![feature(clamp_magnitude)] #![feature(clone_to_uninit)] #![feature(const_array)] +#![feature(const_bool)] #![feature(const_cell_traits)] #![feature(const_clone)] #![feature(const_cmp)] diff --git a/library/coretests/tests/num/dec2flt/decimal.rs b/library/coretests/tests/num/dec2flt/decimal.rs index f759e1dbde6c..f5ecc604a99a 100644 --- a/library/coretests/tests/num/dec2flt/decimal.rs +++ b/library/coretests/tests/num/dec2flt/decimal.rs @@ -7,7 +7,6 @@ const FPATHS_F32: &[FPath] = const FPATHS_F64: &[FPath] = &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))]; -// FIXME(f16_f128): enable on all targets once possible. #[test] #[cfg(target_has_reliable_f16)] fn check_fast_path_f16() { diff --git a/library/coretests/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs index 8bf4094ced72..734cb7e4f7db 100644 --- a/library/coretests/tests/num/dec2flt/float.rs +++ b/library/coretests/tests/num/dec2flt/float.rs @@ -2,7 +2,6 @@ use core::num::dec2flt::float::RawFloat; use crate::num::{ldexp_f32, ldexp_f64}; -// FIXME(f16_f128): enable on all targets once possible. #[test] #[cfg(target_has_reliable_f16)] fn test_f16_integer_decode() { @@ -54,7 +53,6 @@ fn test_f64_integer_decode() { /* Sanity checks of computed magic numbers */ -// FIXME(f16_f128): enable on all targets once possible. #[test] #[cfg(target_has_reliable_f16)] fn test_f16_consts() { diff --git a/library/coretests/tests/num/dec2flt/lemire.rs b/library/coretests/tests/num/dec2flt/lemire.rs index 6d49d85170e2..ba359a0495fe 100644 --- a/library/coretests/tests/num/dec2flt/lemire.rs +++ b/library/coretests/tests/num/dec2flt/lemire.rs @@ -17,7 +17,6 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) { (fp.p_biased, fp.m) } -// FIXME(f16_f128): enable on all targets once possible. #[test] #[cfg(target_has_reliable_f16)] fn compute_float_f16_rounding() { diff --git a/library/coretests/tests/num/dec2flt/mod.rs b/library/coretests/tests/num/dec2flt/mod.rs index b8ca220847cf..37136e62c6f4 100644 --- a/library/coretests/tests/num/dec2flt/mod.rs +++ b/library/coretests/tests/num/dec2flt/mod.rs @@ -92,8 +92,6 @@ fn fast_path_correct() { test_literal!(1.448997445238699); } -// FIXME(f16_f128): remove gates once tests work on all targets - #[test] fn lonely_dot() { #[cfg(target_has_reliable_f16)] diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs index 4e73bd1f12ee..be1bc6ac460b 100644 --- a/library/coretests/tests/num/flt2dec/mod.rs +++ b/library/coretests/tests/num/flt2dec/mod.rs @@ -287,7 +287,7 @@ where check_exact!(f(f16::MIN_POSITIVE) => b"6103515625 ", -4); check_exact!(f(minf16) => b"59604644775390625", -7); - // FIXME(f16_f128): these should gain the check_exact_one tests like `f32` and `f64` have, + // FIXME(f16): these should gain the check_exact_one tests like `f32` and `f64` have, // but these values are not easy to generate. The algorithm from the Paxon paper [1] needs // to be adapted to binary16. } diff --git a/library/std/src/net/hostname.rs b/library/std/src/net/hostname.rs index b1010cec6005..4042496d534f 100644 --- a/library/std/src/net/hostname.rs +++ b/library/std/src/net/hostname.rs @@ -8,10 +8,10 @@ use crate::ffi::OsString; /// /// # Underlying system calls /// -/// | Platform | System call | -/// |----------|---------------------------------------------------------------------------------------------------------| -/// | UNIX | [`gethostname`](https://www.man7.org/linux/man-pages/man2/gethostname.2.html) | -/// | Windows | [`GetHostNameW`](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostnamew) | +/// | Platform | System call | +/// |--------------|---------------------------------------------------------------------------------------------------------| +/// | UNIX | [`gethostname`](https://www.man7.org/linux/man-pages/man2/gethostname.2.html) | +/// | Windows (8+) | [`GetHostNameW`](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostnamew) | /// /// Note that platform-specific behavior [may change in the future][changes]. /// diff --git a/library/std/src/sys/net/hostname/mod.rs b/library/std/src/sys/net/hostname/mod.rs index 8ffe4894d718..65fcd6bfb00d 100644 --- a/library/std/src/sys/net/hostname/mod.rs +++ b/library/std/src/sys/net/hostname/mod.rs @@ -3,7 +3,8 @@ cfg_select! { mod unix; pub use unix::hostname; } - target_os = "windows" => { + // `GetHostNameW` is only available starting with Windows 8. + all(target_os = "windows", not(target_vendor = "win7")) => { mod windows; pub use windows::hostname; } diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index df3344e2df34..9f16ef07a4bd 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,14 +1,14 @@ //! These tests are not run automatically right now. Please run these tests manually by copying them //! to a separate project when modifying any related code. -use super::alloc::*; use super::time::system_time_internal::{from_uefi, to_uefi}; use crate::io::{IoSlice, IoSliceMut}; +use crate::ops::{Deref, DerefMut}; use crate::time::Duration; const SECS_IN_MINUTE: u64 = 60; -const MAX_UEFI_TIME: Duration = from_uefi(r_efi::efi::Time { +const MAX_UEFI_TIME: Duration = from_uefi(&r_efi::efi::Time { year: 9999, month: 12, day: 31, @@ -20,27 +20,8 @@ const MAX_UEFI_TIME: Duration = from_uefi(r_efi::efi::Time { daylight: 0, pad1: 0, pad2: 0, -}); - -#[test] -fn align() { - // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be - // statically verified. - assert_eq!(POOL_ALIGNMENT, 8); - - // Loop over allocation-request sizes from 0-256 and alignments from 1-128, and verify - // that in case of overalignment there is at least space for one additional pointer to - // store in the allocation. - for i in 0..256 { - for j in &[1, 2, 4, 8, 16, 32, 64, 128] { - if *j <= 8 { - assert_eq!(align_size(i, *j), i); - } else { - assert!(align_size(i, *j) > i + size_of::<*mut ()>()); - } - } - } -} +}) +.unwrap(); // UEFI Time cannot implement Eq due to uninitilaized pad1 and pad2 fn uefi_time_cmp(t1: r_efi::efi::Time, t2: r_efi::efi::Time) -> bool { @@ -70,9 +51,9 @@ fn systemtime_start() { daylight: 0, pad2: 0, }; - assert_eq!(from_uefi(&t), Duration::new(0, 0)); - assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t), -1440, 0).unwrap())); - assert!(to_uefi(&from_uefi(&t), 0, 0).is_err()); + assert_eq!(from_uefi(&t).unwrap(), Duration::new(0, 0)); + assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t).unwrap(), -1440, 0).unwrap())); + assert!(to_uefi(&from_uefi(&t).unwrap(), 0, 0).is_err()); } #[test] @@ -90,9 +71,9 @@ fn systemtime_utc_start() { daylight: 0, pad2: 0, }; - assert_eq!(from_uefi(&t), Duration::new(1440 * SECS_IN_MINUTE, 0)); - assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t), 0, 0).unwrap())); - assert!(to_uefi(&from_uefi(&t), -1440, 0).is_ok()); + assert_eq!(from_uefi(&t).unwrap(), Duration::new(1440 * SECS_IN_MINUTE, 0)); + assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t).unwrap(), 0, 0).unwrap())); + assert!(to_uefi(&from_uefi(&t).unwrap(), -1440, 0).is_ok()); } #[test] @@ -110,8 +91,8 @@ fn systemtime_end() { daylight: 0, pad2: 0, }; - assert!(to_uefi(&from_uefi(&t), 1440, 0).is_ok()); - assert!(to_uefi(&from_uefi(&t), 1439, 0).is_err()); + assert!(to_uefi(&from_uefi(&t).unwrap(), 1440, 0).is_ok()); + assert!(to_uefi(&from_uefi(&t).unwrap(), 1439, 0).is_err()); } #[test] @@ -139,17 +120,17 @@ fn min_time() { #[test] fn max_time() { - let inp = MAX_UEFI_TIME.0; + let inp = MAX_UEFI_TIME; let new_tz = to_uefi(&inp, -1440, 0).err().unwrap(); assert_eq!(new_tz, 1440); assert!(to_uefi(&inp, new_tz, 0).is_ok()); - let inp = MAX_UEFI_TIME.0 - Duration::from_secs(1440 * SECS_IN_MINUTE); + let inp = MAX_UEFI_TIME - Duration::from_secs(1440 * SECS_IN_MINUTE); let new_tz = to_uefi(&inp, -1440, 0).err().unwrap(); assert_eq!(new_tz, 0); assert!(to_uefi(&inp, new_tz, 0).is_ok()); - let inp = MAX_UEFI_TIME.0 - Duration::from_secs(1440 * SECS_IN_MINUTE + 10); + let inp = MAX_UEFI_TIME - Duration::from_secs(1440 * SECS_IN_MINUTE + 10); let new_tz = to_uefi(&inp, -1440, 0).err().unwrap(); assert_eq!(new_tz, 0); assert!(to_uefi(&inp, new_tz, 0).is_ok()); @@ -266,8 +247,8 @@ fn io_slice_mut_basic() { let mut data_clone = [0, 1, 2, 3, 4]; let mut io_slice_mut = IoSliceMut::new(&mut data_clone); - assert_eq!(data, io_slice_mut.as_slice()); - assert_eq!(data, io_slice_mut.as_mut_slice()); + assert_eq!(data, io_slice_mut.deref()); + assert_eq!(data, io_slice_mut.deref_mut()); io_slice_mut.advance(2); assert_eq!(&data[2..], io_slice_mut.into_slice()); diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 25c1a82cc426..0f54f80d72ee 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -237,3 +237,7 @@ cfg_select! { } _ => {} } + +// Only available starting with Windows 8. +#[cfg(not(target_vendor = "win7"))] +windows_targets::link!("ws2_32.dll" "system" fn GetHostNameW(name : PWSTR, namelen : i32) -> i32); diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 9009aa09f48e..12babcb84ccf 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2170,7 +2170,6 @@ GetFileType GETFINALPATHNAMEBYHANDLE_FLAGS GetFinalPathNameByHandleW GetFullPathNameW -GetHostNameW GetLastError GetModuleFileNameW GetModuleHandleA diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 98f277b33780..edc9d2d11f7c 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -49,7 +49,6 @@ windows_targets::link!("kernel32.dll" "system" fn GetFileSizeEx(hfile : HANDLE, windows_targets::link!("kernel32.dll" "system" fn GetFileType(hfile : HANDLE) -> FILE_TYPE); windows_targets::link!("kernel32.dll" "system" fn GetFinalPathNameByHandleW(hfile : HANDLE, lpszfilepath : PWSTR, cchfilepath : u32, dwflags : GETFINALPATHNAMEBYHANDLE_FLAGS) -> u32); windows_targets::link!("kernel32.dll" "system" fn GetFullPathNameW(lpfilename : PCWSTR, nbufferlength : u32, lpbuffer : PWSTR, lpfilepart : *mut PWSTR) -> u32); -windows_targets::link!("ws2_32.dll" "system" fn GetHostNameW(name : PWSTR, namelen : i32) -> i32); windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> WIN32_ERROR); windows_targets::link!("kernel32.dll" "system" fn GetModuleFileNameW(hmodule : HMODULE, lpfilename : PWSTR, nsize : u32) -> u32); windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename : PCSTR) -> HMODULE); diff --git a/library/std/src/sys/thread/mod.rs b/library/std/src/sys/thread/mod.rs index 3460270b15fc..5010774dafde 100644 --- a/library/std/src/sys/thread/mod.rs +++ b/library/std/src/sys/thread/mod.rs @@ -91,7 +91,7 @@ cfg_select! { } target_os = "vexos" => { mod vexos; - pub use vexos::{sleep, yield_now}; + pub use vexos::{sleep, sleep_until, yield_now}; #[expect(dead_code)] mod unsupported; pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE}; @@ -135,13 +135,22 @@ cfg_select! { target_os = "vxworks", target_os = "wasi", target_vendor = "apple", + target_os = "motor", + target_os = "vexos" )))] pub fn sleep_until(deadline: crate::time::Instant) { use crate::time::Instant; - let now = Instant::now(); - - if let Some(delay) = deadline.checked_duration_since(now) { + // The clock source used for `sleep` might not be the same used for `Instant`. + // Since this function *must not* return before the deadline, we recheck the + // time after every call to `sleep`. See #149935 for an example of this + // occurring on older Windows systems. + while let Some(delay) = deadline.checked_duration_since(Instant::now()) { + // Sleep for the estimated time remaining until the deadline. + // + // If your system has a better way of estimating the delay time or + // provides a way to sleep until an absolute time, specialize this + // function for your system. sleep(delay); } } diff --git a/library/std/src/sys/thread/motor.rs b/library/std/src/sys/thread/motor.rs index 3c6df936b0ae..c6a7b5ac356b 100644 --- a/library/std/src/sys/thread/motor.rs +++ b/library/std/src/sys/thread/motor.rs @@ -3,7 +3,7 @@ use crate::io; use crate::num::NonZeroUsize; use crate::sys::map_motor_error; use crate::thread::ThreadInit; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 256; @@ -62,3 +62,7 @@ pub fn yield_now() { pub fn sleep(dur: Duration) { moto_rt::thread::sleep_until(moto_rt::time::Instant::now() + dur) } + +pub fn sleep_until(deadline: Instant) { + moto_rt::thread::sleep_until(deadline.into_inner()) +} diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b1f27c32fedd..e708c9a3f1ba 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -528,8 +528,51 @@ pub fn set_name(name: &CStr) { debug_assert_eq!(res, libc::OK); } -#[cfg(not(any(target_os = "espidf", target_os = "wasi")))] +#[cfg(not(target_os = "espidf"))] pub fn sleep(dur: Duration) { + cfg_select! { + // Any unix that has clock_nanosleep + // If this list changes update the MIRI chock_nanosleep shim + any( + target_os = "freebsd", + target_os = "netbsd", + target_os = "linux", + target_os = "android", + target_os = "solaris", + target_os = "illumos", + target_os = "dragonfly", + target_os = "hurd", + target_os = "fuchsia", + target_os = "vxworks", + target_os = "wasi", + ) => { + // POSIX specifies that `nanosleep` uses CLOCK_REALTIME, but is not + // affected by clock adjustments. The timing of `sleep` however should + // be tied to `Instant` where possible. Thus, we use `clock_nanosleep` + // with a relative time interval instead, which allows explicitly + // specifying the clock. + // + // In practice, most systems (like e.g. Linux) actually use + // CLOCK_MONOTONIC for `nanosleep` anyway, but others like FreeBSD don't + // so it's better to be safe. + // + // wasi-libc prior to WebAssembly/wasi-libc#696 has a broken implementation + // of `nanosleep` which used `CLOCK_REALTIME` even though it is unsupported + // on WASIp2. Using `clock_nanosleep` directly bypasses the issue. + unsafe fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int { + unsafe { libc::clock_nanosleep(crate::sys::time::Instant::CLOCK_ID, 0, rqtp, rmtp) } + } + } + _ => { + unsafe fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int { + let r = unsafe { libc::nanosleep(rqtp, rmtp) }; + // `clock_nanosleep` returns the error number directly, so mimic + // that behaviour to make the shared code below simpler. + if r == 0 { 0 } else { sys::io::errno() } + } + } + } + let mut secs = dur.as_secs(); let mut nsecs = dur.subsec_nanos() as _; @@ -543,8 +586,9 @@ pub fn sleep(dur: Duration) { }; secs -= ts.tv_sec as u64; let ts_ptr = &raw mut ts; - if libc::nanosleep(ts_ptr, ts_ptr) == -1 { - assert_eq!(sys::io::errno(), libc::EINTR); + let r = nanosleep(ts_ptr, ts_ptr); + if r != 0 { + assert_eq!(r, libc::EINTR); secs += ts.tv_sec as u64; nsecs = ts.tv_nsec; } else { @@ -554,13 +598,7 @@ pub fn sleep(dur: Duration) { } } -#[cfg(any( - target_os = "espidf", - // wasi-libc prior to WebAssembly/wasi-libc#696 has a broken implementation - // of `nanosleep`, used above by most platforms, so use `usleep` until - // that fix propagates throughout the ecosystem. - target_os = "wasi", -))] +#[cfg(target_os = "espidf")] pub fn sleep(dur: Duration) { // ESP-IDF does not have `nanosleep`, so we use `usleep` instead. // As per the documentation of `usleep`, it is expected to support @@ -609,6 +647,56 @@ pub fn sleep(dur: Duration) { pub fn sleep_until(deadline: crate::time::Instant) { use crate::time::Instant; + #[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") + ))] + { + use crate::sys::pal::time::__timespec64; + use crate::sys::pal::weak::weak; + + // This got added in glibc 2.31, along with a 64-bit `clock_gettime` + // function. + weak! { + fn __clock_nanosleep_time64( + clock_id: libc::clockid_t, + flags: libc::c_int, + req: *const __timespec64, + rem: *mut __timespec64, + ) -> libc::c_int; + } + + if let Some(clock_nanosleep) = __clock_nanosleep_time64.get() { + let ts = deadline.into_inner().into_timespec().to_timespec64(); + loop { + let r = unsafe { + clock_nanosleep( + crate::sys::time::Instant::CLOCK_ID, + libc::TIMER_ABSTIME, + &ts, + core::ptr::null_mut(), + ) + }; + + match r { + 0 => return, + libc::EINTR => continue, + // If the underlying kernel doesn't support the 64-bit + // syscall, `__clock_nanosleep_time64` will fail. The + // error code nowadays is EOVERFLOW, but it used to be + // ENOSYS – so just don't rely on any particular value. + // The parameters are all valid, so the only reasons + // why the call might fail are EINTR and the call not + // being supported. Fall through to the clamping version + // in that case. + _ => break, + } + } + } + } + let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else { // The deadline is further in the future then can be passed to // clock_nanosleep. We have to use Self::sleep instead. This might diff --git a/library/std/src/sys/thread/vexos.rs b/library/std/src/sys/thread/vexos.rs index d917dde4d0bc..4311786720c4 100644 --- a/library/std/src/sys/thread/vexos.rs +++ b/library/std/src/sys/thread/vexos.rs @@ -10,8 +10,12 @@ pub fn sleep(dur: Duration) { let start = Instant::now(); while start.elapsed() < dur { - unsafe { - vex_sdk::vexTasksRun(); - } + yield_now(); + } +} + +pub fn sleep_until(deadline: Instant) { + while Instant::now() < deadline { + yield_now(); } } diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs index e7c90faa05c2..d20762023caf 100644 --- a/library/std/tests/floats/f128.rs +++ b/library/std/tests/floats/f128.rs @@ -1,4 +1,3 @@ -// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(target_has_reliable_f128)] use std::f128::consts; @@ -35,7 +34,7 @@ macro_rules! assert_f128_biteq { #[test] fn test_num_f128() { - // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128` + // FIXME(f128): replace with a `test_num` call once the required `fmodl`/`fmodf128` // function is available on all platforms. let ten = 10f128; let two = 2f128; diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs index 0f8b4138d226..cc0960765f41 100644 --- a/library/std/tests/floats/f16.rs +++ b/library/std/tests/floats/f16.rs @@ -1,4 +1,3 @@ -// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(target_has_reliable_f16)] use std::f16::consts; @@ -258,8 +257,6 @@ fn test_ln_gamma() { #[test] fn test_real_consts() { - // FIXME(f16_f128): add math tests when available - let pi: f16 = consts::PI; let frac_pi_2: f16 = consts::FRAC_PI_2; let frac_pi_3: f16 = consts::FRAC_PI_3; diff --git a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs index 54fd78270abd..8a25cc1163cc 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs @@ -83,8 +83,11 @@ pub unsafe fn __sevl() { /// improve overall system performance. // Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M // LLVM says "instruction requires: armv6k" +// On ARMv6 in Thumb mode, T2 is required (see Arm DDI0406C Section A8.8.427) #[cfg(any( - target_feature = "v6", + all(target_feature = "v6k", not(target_feature = "thumb-mode")), + target_feature = "v6t2", + all(target_feature = "v6", target_feature = "mclass"), target_arch = "aarch64", target_arch = "arm64ec", doc diff --git a/library/test/build.rs b/library/test/build.rs index a2bc8936b519..8e31adbf2ca7 100644 --- a/library/test/build.rs +++ b/library/test/build.rs @@ -1,4 +1,5 @@ fn main() { + println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-check-cfg=cfg(enable_unstable_features)"); let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index d8e8f65caa98..a918ae929d2e 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -75,7 +75,7 @@ book!( EditionGuide, "src/doc/edition-guide", "edition-guide", &[]; EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[]; Nomicon, "src/doc/nomicon", "nomicon", &[]; - RustByExample, "src/doc/rust-by-example", "rust-by-example", &["es", "ja", "zh"]; + RustByExample, "src/doc/rust-by-example", "rust-by-example", &["es", "ja", "zh", "ko"]; RustdocBook, "src/doc/rustdoc", "rustdoc", &[]; StyleGuide, "src/doc/style-guide", "style-guide", &[]; ); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 93b65dbec905..dbd4f1c81405 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -244,6 +244,7 @@ pub(crate) fn is_ci_llvm_available_for_target( ("loongarch64-unknown-linux-musl", false), ("powerpc-unknown-linux-gnu", false), ("powerpc64-unknown-linux-gnu", false), + ("powerpc64-unknown-linux-musl", false), ("powerpc64le-unknown-linux-gnu", false), ("powerpc64le-unknown-linux-musl", false), ("riscv64gc-unknown-linux-gnu", false), diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 074404b4cdf3..bf8d0cf4d534 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -460,6 +460,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo "loongarch64-unknown-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc64-unknown-linux-gnu", + "powerpc64-unknown-linux-musl", "powerpc64le-unknown-linux-gnu", "powerpc64le-unknown-linux-musl", "riscv64gc-unknown-linux-gnu", diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 607b9a384d19..a16a2b17be17 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -38,6 +38,14 @@ pub struct Finder { const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "x86_64-unknown-linux-gnuasan", + "thumbv7a-none-eabi", + "thumbv7a-none-eabihf", + "thumbv7r-none-eabi", + "thumbv7r-none-eabihf", + "thumbv8r-none-eabihf", + "armv6-none-eabi", + "armv6-none-eabihf", + "thumbv6-none-eabi", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 61b8b26dceaf..b264c961b659 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -148,7 +148,7 @@ impl CommandProfiler { }) .collect(); - entries.sort_by(|a, b| b.2.cmp(&a.2)); + entries.sort_by_key(|e| std::cmp::Reverse(e.2)); let total_bootstrap_duration = start_time.elapsed(); diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64-linux-gnu/Dockerfile similarity index 89% rename from src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile rename to src/ci/docker/host-x86_64/dist-powerpc64-linux-gnu/Dockerfile index 298282a76463..046406224c34 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux-gnu/Dockerfile @@ -11,7 +11,7 @@ RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig /tmp/crosstool.defconfig +COPY host-x86_64/dist-powerpc64-linux-gnu/powerpc64-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh COPY scripts/sccache.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64-linux-gnu/powerpc64-linux-gnu.defconfig similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig rename to src/ci/docker/host-x86_64/dist-powerpc64-linux-gnu/powerpc64-linux-gnu.defconfig diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/Dockerfile new file mode 100644 index 000000000000..7c8a1e657ac2 --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/Dockerfile @@ -0,0 +1,39 @@ +FROM ubuntu:22.04 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh + +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh + +WORKDIR /tmp + +COPY scripts/crosstool-ng-build.sh /scripts/ +COPY host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig /tmp/crosstool.defconfig +RUN /scripts/crosstool-ng-build.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-musl/bin + +ENV \ + AR_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-ar \ + CC_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-gcc \ + CXX_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-g++ + +ENV HOSTS=powerpc64-unknown-linux-musl + +ENV RUST_CONFIGURE_ARGS \ + --enable-extended \ + --enable-full-tools \ + --enable-profiler \ + --enable-sanitizers \ + --disable-docs \ + --set target.powerpc64-unknown-linux-musl.crt-static=false \ + --musl-root-powerpc64=/x-tools/powerpc64-unknown-linux-musl/powerpc64-unknown-linux-musl/sysroot/usr + +ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig new file mode 100644 index 000000000000..08132d3ab8ba --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig @@ -0,0 +1,15 @@ +CT_CONFIG_VERSION="4" +CT_EXPERIMENTAL=y +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" +CT_ARCH_POWERPC=y +CT_ARCH_64=y +CT_ARCH_ABI="elfv2" +# CT_DEMULTILIB is not set +CT_KERNEL_LINUX=y +CT_LINUX_V_4_19=y +CT_LIBC_MUSL=y +CT_MUSL_V_1_2_5=y +CT_CC_LANG_CXX=y +CT_GETTEXT_NEEDED=y diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7411b394b94a..6e07ffc43bc2 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -232,7 +232,10 @@ auto: - name: dist-powerpc-linux <<: *job-linux-4c - - name: dist-powerpc64-linux + - name: dist-powerpc64-linux-gnu + <<: *job-linux-4c + + - name: dist-powerpc64-linux-musl <<: *job-linux-4c - name: dist-powerpc64le-linux-gnu diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 7f22bc27600c..91a09db7009b 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -665,7 +665,9 @@ to link to the extern crate to make the crate be available as an extern prelude. That allows you to specify the additional syntax of the `--extern` flag, such as renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile `auxiliary/bar.rs` and make it available under then name `foo` within the test. -This is similar to how Cargo does dependency renaming. +This is similar to how Cargo does dependency renaming. It is also possible to +specify [`--extern` modifiers](https://github.com/rust-lang/rust/issues/98405). +For example, `//@ aux-crate:noprelude:foo=bar.rs`. `aux-bin` is similar to `aux-build` but will build a binary instead of a library. The binary will be available in `auxiliary/bin` relative to the working diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index ae341599f15a..81c421bc92c4 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -53,14 +53,14 @@ Directives can generally be found by browsing the See [Building auxiliary crates](compiletest.html#building-auxiliary-crates) -| Directive | Explanation | Supported test suites | Possible values | -|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|-----------------------------------------------| -| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file | -| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file | -| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `=` | -| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file | -| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file | -| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A | +| Directive | Explanation | Supported test suites | Possible values | +|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|--------------------------------------------------------------------| +| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file | +| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file | +| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `[:]=` | +| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file | +| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file | +| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A | [^pm]: please see the [Auxiliary proc-macro section](compiletest.html#auxiliary-proc-macro) in the compiletest chapter for specifics. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8ceeff2c9685..632b9e2fc431 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -56,15 +56,16 @@ - [arm-none-eabi](platform-support/arm-none-eabi.md) - [{arm,thumb}v4t-none-eabi](platform-support/armv4t-none-eabi.md) - [{arm,thumb}v5te-none-eabi](platform-support/armv5te-none-eabi.md) - - [armv7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md) - - [armv7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md) - - [armebv7r-none-eabi{,hf}](platform-support/armebv7r-none-eabi.md) - - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md) + - [{arm,thumb}v6-none-eabi{,hf}](platform-support/armv6-none-eabi.md) + - [{arm,thumb}v7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md) + - [{arm,thumb}v7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md) + - [{arm,thumb}v8r-none-eabihf](platform-support/armv8r-none-eabihf.md) - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md) - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md) - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md) - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) + - [armebv7r-none-eabi{,hf}](platform-support/armebv7r-none-eabi.md) - [arm\*-unknown-linux-\*](./platform-support/arm-linux.md) - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) - [armv5te-unknown-linux-gnueabi](platform-support/armv5te-unknown-linux-gnueabi.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 889f96f5fefa..dff8953347ff 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -100,6 +100,7 @@ target | notes [`i686-pc-windows-gnu`](platform-support/windows-gnu.md) | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment] `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2+, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2+, glibc 2.17) +[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | PPC64 Linux (kernel 4.19+, musl 1.2.5) [`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10+, glibc 2.17) [`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19+, musl 1.2.5) [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20+, glibc 2.29) @@ -292,6 +293,8 @@ target | std | host | notes `armv4t-unknown-linux-gnueabi` | ? | | Armv4T Linux [`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare Armv5TE `armv5te-unknown-linux-uclibceabi` | ? | | Armv5TE Linux with uClibc +[`armv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6 +[`armv6-none-eabihf`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6, hardfloat [`armv6-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | Armv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain) @@ -371,7 +374,6 @@ target | std | host | notes [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | [`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) [`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2) -[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | ✓ | ✓ | PPC64 Linux (kernel 4.19, musl 1.2.5) [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 [`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [`powerpc64le-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64LE FreeBSD @@ -410,18 +412,24 @@ target | std | host | notes [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 [`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE +[`thumbv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Thumb-mode Bare Armv6 [`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv6M with NuttX -`thumbv7a-pc-windows-msvc` | | | -[`thumbv7a-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | | | +[`thumbv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A +[`thumbv7a-none-eabihf`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A, hardfloat [`thumbv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX [`thumbv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat +`thumbv7a-pc-windows-msvc` | | | +[`thumbv7a-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | | | [`thumbv7em-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7EM with NuttX [`thumbv7em-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7EM with NuttX, hardfloat [`thumbv7m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7M with NuttX `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.5 +[`thumbv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | | Thumb-mode Bare Armv7-R +[`thumbv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | | Thumb-mode Bare Armv7-R, hardfloat [`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Baseline with NuttX [`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat +[`thumbv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Thumb-mode Bare Armv8-R, hardfloat [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) [`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | | WebAssembly with WASIp3 diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 81545db6c51f..cf1fe9ed59ed 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -37,6 +37,7 @@ their own document. - *Legacy* Arm Architectures - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md) - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md) + - [`armv6-none-eabi`, `armv6-none-eabihf`, `thumbv6-none-eabi`](armv6-none-eabi.md) ## Instruction Sets diff --git a/src/doc/rustc/src/platform-support/armv6-none-eabi.md b/src/doc/rustc/src/platform-support/armv6-none-eabi.md new file mode 100644 index 000000000000..ae88356e12ce --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv6-none-eabi.md @@ -0,0 +1,39 @@ +# `armv6-none-eabi*` and `thumbv6-none-eabi` + +* **Tier: 3** +* **Library Support:** core and alloc (bare-metal, `#![no_std]`) + +Bare-metal target for any cpu in the Armv6 architecture family, supporting +ARM/Thumb code interworking (aka `Arm`/`Thumb`), with `Arm` code as the default +code generation. The most common processor family using the Armv6 architecture +is the ARM11, which includes the ARM1176JZF-S used in the original Raspberry Pi +and in the Raspberry Pi Zero. + +This target assumes your processor has the Armv6K extensions, as basically all +Armv6 processors do[^1]. The Armv6K extension adds the `LDREXB` and `STREXB` +instructions required to efficiently implement CAS on the [`AtomicU8`] and +[`AtomicI8`] types. + +The `thumbv6-none-eabi` target is the same as this one, but the instruction set +defaults to `Thumb`. Note that this target only supports the old Thumb-1 +instruction set, not the later Thumb-2 instruction set that was added in the +Armv6T2 extension. Note that the Thumb-1 instruction set does not support +atomics. + +The `armv6-none-eabihf` target uses the EABIHF hard-float ABI, and requires an +FPU - it assumes a VFP2D16 FPU is present. The FPU is not available from Thumb +mode so there is no `thumbv6-none-eabihf` target. + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +[`AtomicU8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicU8.html +[`AtomicI8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicI8.html + +## Target Maintainers + +[@thejpster](https://github.com/thejpster) + +[^1]: The only ARMv6 processor without the Armv6k extensions is the first (r0) +revision of the ARM1136 - in the unlikely event you have a chip with one of +these processors, use the ARMv5TE target instead. diff --git a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md index 05afb4f4321b..555f69e81a02 100644 --- a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md @@ -1,10 +1,14 @@ -# `armv7a-none-eabi` and `armv7a-none-eabihf` +# `armv7a-none-eabi*` and `thumbv7a-none-eabi*` -* **Tier: 2** +* **Tier: 2** (`armv7a-none-eabi` and `armv7a-none-eabihf`) +* **Tier: 3** (`thumbv7a-none-eabi` and `thumbv7a-none-eabihf`) * **Library Support:** core and alloc (bare-metal, `#![no_std]`) -Bare-metal target for CPUs in the Armv7-A architecture family, supporting -dual ARM/Thumb mode, with ARM mode as the default. +Bare-metal target for CPUs in the Armv7-A architecture family, supporting dual +ARM/Thumb mode. The `armv7a-none-eabi*` targets use Arm mode by default and the +`thumbv7a-none-eabi` targets use Thumb mode by default. The `-eabi` targets use +a soft-float ABI and do not require an FPU, while the `-eabihf` targets use a +hard-float ABI and do require an FPU. Note, this is for processors running in AArch32 mode. For the AArch64 mode added in Armv8-A, see [`aarch64-unknown-none`](aarch64-unknown-none.md) instead. diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md index 7f22a29f2ee6..20fd55c6abd6 100644 --- a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md @@ -1,10 +1,14 @@ -# `armv7r-none-eabi` and `armv7r-none-eabihf` +# `armv7r-none-eabi*` and `thumbv7r-none-eabi*` -* **Tier: 2** +* **Tier: 2** (`armv7r-none-eabi` and `armv7r-none-eabihf`) +* **Tier: 3** (`thumbv7r-none-eabi` and `thumbv7r-none-eabihf`) * **Library Support:** core and alloc (bare-metal, `#![no_std]`) -Bare-metal target for CPUs in the Armv7-R architecture family, supporting -dual ARM/Thumb mode, with ARM mode as the default. +Bare-metal target for CPUs in the Armv7-R architecture family, supporting dual +ARM/Thumb mode. The `armv7r-none-eabi*` targets use Arm mode by default and the +`thumbv7r-none-eabi*` targets use Thumb mode by default. The `-eabi` targets use +a soft-float ABI and do not require an FPU, while the `-eabihf` targets use a +hard-float ABI and do require an FPU. Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r]. @@ -25,11 +29,11 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all ## Requirements -When using the hardfloat targets, the minimum floating-point features assumed -are those of the `vfpv3-d16`, which includes single- and double-precision, with -16 double-precision registers. This floating-point unit appears in Cortex-R4F -and Cortex-R5F processors. See [VFP in the Cortex-R processors][vfp] -for more details on the possible FPU variants. +When using the hardfloat (`-eabibf`) targets, the minimum floating-point +features assumed are those of the `vfpv3-d16`, which includes single- and +double-precision, with 16 double-precision registers. This floating-point unit +appears in Cortex-R4F and Cortex-R5F processors. See [VFP in the Cortex-R +processors][vfp] for more details on the possible FPU variants. If your processor supports a different set of floating-point features than the default expectations of `vfpv3-d16`, then these should also be enabled or diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md index 369e86dbfc7e..85abac3d7eb8 100644 --- a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -1,10 +1,13 @@ -# `armv8r-none-eabihf` +# `armv8r-none-eabihf` and `thumbv8r-none-eabihf` -* **Tier: 2** +* **Tier: 2**: `armv8r-none-eabihf` +* **Tier: 3**: `thumbv8r-none-eabihf` * **Library Support:** core and alloc (bare-metal, `#![no_std]`) -Bare-metal target for CPUs in the Armv8-R architecture family, supporting -dual ARM/Thumb mode, with ARM mode as the default. +Bare-metal target for CPUs in the Armv8-R architecture family, supporting dual +ARM/Thumb mode. The `armv8r-none-eabihf` target uses Arm mode by default and +the `thumbv8r-none-eabihf` target uses Thumb mode by default. Both targets +use a hard-float ABI and require an FPU. Processors in this family include the Arm [Cortex-R52][cortex-r52] and [Cortex-R52+][cortex-r52-plus]. diff --git a/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md index 7213e54d5a1a..23cb31af6a26 100644 --- a/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md @@ -1,10 +1,13 @@ # powerpc64-unknown-linux-musl -**Tier: 3** +**Tier: 2** Target for 64-bit big endian PowerPC Linux programs using musl libc. This target uses the ELF v2 ABI. +The baseline CPU required is a PowerPC 970, which means AltiVec is required and +the oldest IBM server CPU supported is therefore POWER6. + ## Target maintainers [@Gelbpunkt](https://github.com/Gelbpunkt) @@ -38,9 +41,8 @@ linker = "powerpc64-linux-musl-gcc" ## Building Rust programs -Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you will first need to build Rust with the target enabled (see -"Building the target" above). +This target is distributed through `rustup`, and otherwise requires no +special configuration. ## Cross-compilation diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 958a34a86928..eb74edda22de 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -20,7 +20,7 @@ focused on the Component Model-based definition of WASI. At this point the `wasm32-wasip1` Rust target is intended for historical compatibility with [WASIp1] set of syscalls. -[WASIp1]: https://github.com/WebAssembly/WASI/tree/main/legacy/preview1 +[WASIp1]: https://github.com/WebAssembly/WASI/tree/wasi-0.1/preview1 [Component Model]: https://github.com/webassembly/component-model Today the `wasm32-wasip1` target will generate core WebAssembly modules diff --git a/src/doc/unstable-book/src/compiler-flags/large-data-threshold.md b/src/doc/unstable-book/src/compiler-flags/large-data-threshold.md new file mode 100644 index 000000000000..27c86079a6c8 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/large-data-threshold.md @@ -0,0 +1,27 @@ +# `large-data-threshold` + +----------------------- + +This flag controls the threshold for static data to be placed in large data +sections when using the `medium` code model on x86-64. + +When using `-Ccode-model=medium`, static data smaller than this threshold will +use RIP-relative addressing (32-bit offsets), while larger data will use +absolute 64-bit addressing. This allows the compiler to generate more efficient +code for smaller data while still supporting data larger than 2GB. + +The default threshold is 65536 bytes (64KB) if not specified. + +## Example + +```sh +rustc -Ccode-model=medium -Zlarge-data-threshold=1024 main.rs +``` + +This sets the threshold to 1KB, meaning only data smaller than 1024 bytes will +use RIP-relative addressing. + +## Platform Support + +This flag is only effective on x86-64 targets when using `-Ccode-model=medium`. +On other architectures or with other code models, this flag has no effect. diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 53ba868ebeac..d30d869cd4c1 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -539,7 +539,10 @@ fn parse_source( let mut prev_span_hi = 0; let not_crate_attrs = &[sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; - let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No); + let parsed = parser.parse_item( + rustc_parse::parser::ForceCollect::No, + rustc_parse::parser::AllowConstBlockItems::No, + ); let result = match parsed { Ok(Some(ref item)) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 486ca9b22539..6c34d31cc918 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -210,6 +210,24 @@ body { color: var(--main-color); } +/* Skip navigation link for keyboard users (WCAG 2.4.1) */ +.skip-main-content { + position: absolute; + left: 0; + top: -100%; + z-index: 1000; + padding: 0.5rem 1rem; + background-color: var(--main-background-color); + color: var(--main-color); + text-decoration: none; + font-weight: 500; + border-bottom-right-radius: 4px; + outline: 2px solid var(--search-input-focused-border-color); +} +.skip-main-content:focus { + top: 0; +} + h1 { font-size: 1.5rem; /* 24px */ } @@ -1114,6 +1132,7 @@ pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers { #main-content { position: relative; + outline: none; } .docblock table { diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 1f8ec9f30c53..427e7b4071a1 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -66,6 +66,7 @@ {{ layout.external_html.in_header|safe }} {# #} {# #} + Skip to main content {# #} ``` -nightly-2026-01-08 +nightly-2026-01-22 ``` diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 32f6cb4fd5e9..56490cfc8b65 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -159,7 +159,10 @@ impl LimitStack { } pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) { let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| debug_assert_eq!(stack.pop(), Some(val))); + parse_attrs(sess, attrs, name, |val| { + let popped = stack.pop(); + debug_assert_eq!(popped, Some(val)); + }); } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c7bb3a064a09..b9f104a79a27 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -505,7 +505,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r), (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { + || swap_binop(self.inner.cx, l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, @@ -667,7 +667,7 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (ConstArgKind::Tup(l_t), ConstArgKind::Tup(r_t)) => { - l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(*l_c, *r_c)) + l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(l_c, r_c)) }, (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), @@ -689,9 +689,12 @@ impl HirEqInterExpr<'_, '_, '_> { (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() - && l_arr.elems.iter().zip(r_arr.elems.iter()) - .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) - } + && l_arr + .elems + .iter() + .zip(r_arr.elems.iter()) + .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) + }, // Use explicit match for now since ConstArg is undergoing flux. ( ConstArgKind::Path(..) @@ -955,26 +958,35 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' } fn swap_binop<'a>( + cx: &LateContext<'_>, binop: BinOpKind, lhs: &'a Expr<'a>, rhs: &'a Expr<'a>, ) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { match binop { - BinOpKind::Add | BinOpKind::Eq | BinOpKind::Ne | BinOpKind::BitAnd | BinOpKind::BitXor | BinOpKind::BitOr => { - Some((binop, rhs, lhs)) - }, + // `==` and `!=`, are commutative + BinOpKind::Eq | BinOpKind::Ne => Some((binop, rhs, lhs)), + // Comparisons can be reversed BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Mul // Not always commutative, e.g. with matrices. See issue #5698 - | BinOpKind::Shl - | BinOpKind::Shr - | BinOpKind::Rem - | BinOpKind::Sub - | BinOpKind::Div + // Non-commutative operators + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub | BinOpKind::Div => None, + // We know that those operators are commutative for primitive types, + // and we don't assume anything for other types + BinOpKind::Mul + | BinOpKind::Add | BinOpKind::And - | BinOpKind::Or => None, + | BinOpKind::Or + | BinOpKind::BitAnd + | BinOpKind::BitXor + | BinOpKind::BitOr => cx + .typeck_results() + .expr_ty_adjusted(lhs) + .peel_refs() + .is_primitive() + .then_some((binop, rhs, lhs)), } } @@ -1564,7 +1576,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Tup(tup) => { for arg in *tup { - self.hash_const_arg(*arg); + self.hash_const_arg(arg); } }, ConstArgKind::Path(path) => self.hash_qpath(path), diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 7e3b1ccd224e..6b10f4b51442 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -6,11 +6,7 @@ #![feature(assert_matches)] #![feature(unwrap_infallible)] #![recursion_limit = "512"] -#![allow( - clippy::missing_errors_doc, - clippy::missing_panics_doc, - clippy::must_use_candidate, -)] +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( trivial_casts, trivial_numeric_casts, @@ -2028,12 +2024,12 @@ pub fn is_expr_temporary_value(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { - if !is_no_std_crate(cx) { - Some("std") - } else if !is_no_core_crate(cx) { + if is_no_core_crate(cx) { + None + } else if is_no_std_crate(cx) { Some("core") } else { - None + Some("std") } } diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 4a7fa3472cae..18fab6035f28 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -23,6 +23,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,91,0 { DURATION_FROM_MINUTES_HOURS } 1,88,0 { LET_CHAINS } 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST } 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL } @@ -31,7 +32,7 @@ msrv_aliases! { 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS } 1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION, DURATION_ABS_DIFF } 1,80,0 { BOX_INTO_ITER, LAZY_CELL } - 1,79,0 { CONST_BLOCKS } + 1,79,0 { CONST_BLOCKS, CSTR_COUNT_BYTES } 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } @@ -61,7 +62,7 @@ msrv_aliases! { 1,45,0 { STR_STRIP_PREFIX } 1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS } 1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS } - 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } + 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR, RESULT_MAP_OR_ELSE } 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } 1,38,0 { POINTER_CAST, REM_EUCLID } 1,37,0 { TYPE_ALIAS_ENUM_VARIANTS } @@ -69,12 +70,12 @@ msrv_aliases! { 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,33,0 { UNDERSCORE_IMPORTS } - 1,32,0 { CONST_IS_POWER_OF_TWO } + 1,32,0 { CONST_IS_POWER_OF_TWO, CONST_DURATION_FROM_NANOS_MICROS_MILLIS_SECS } 1,31,0 { OPTION_REPLACE } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,29,0 { ITER_FLATTEN } 1,28,0 { FROM_BOOL, REPEAT_WITH, SLICE_FROM_REF } - 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND } + 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND, DURATION_FROM_NANOS_MICROS } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN, POINTER_ADD_SUB_METHODS } 1,24,0 { IS_ASCII_DIGIT, PTR_NULL } 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } @@ -82,6 +83,7 @@ msrv_aliases! { 1,16,0 { STR_REPEAT, RESULT_UNWRAP_OR_DEFAULT } 1,15,0 { MAYBE_BOUND_IN_WHERE } 1,13,0 { QUESTION_MARK_OPERATOR } + 1,3,0 { DURATION_FROM_MILLIS_SECS } } /// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index 94591a7ee30a..5d6f2241c7c0 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -139,6 +139,7 @@ generate! { disallowed_types, drain, dump, + duration_constructors, ends_with, enum_glob_use, enumerate, @@ -163,12 +164,20 @@ generate! { from_be_bytes, from_bytes_with_nul, from_bytes_with_nul_unchecked, + from_days, + from_hours, from_le_bytes, + from_micros, + from_millis, + from_mins, + from_nanos, from_ne_bytes, from_ptr, from_raw, from_raw_parts, + from_secs, from_str_radix, + from_weeks, fs, fuse, futures_util, @@ -179,6 +188,7 @@ generate! { get_unchecked, get_unchecked_mut, has_significant_drop, + help, hidden_glob_reexports, hygiene, ilog, @@ -271,6 +281,8 @@ generate! { powi, product, push, + push_back, + push_front, push_str, read, read_exact, @@ -325,7 +337,10 @@ generate! { sort, sort_by, sort_unstable_by, + span_help, span_lint_and_then, + span_note, + span_suggestion, split, split_at, split_at_checked, diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index dc5f7dc01dbb..2926a329ce16 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -441,6 +441,21 @@ pub fn peel_and_count_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize, Option, n: usize) -> (Ty<'_>, Option) { + let mut mutbl = None; + for _ in 0..n { + if let ty::Ref(_, dest_ty, m) = ty.kind() { + ty = *dest_ty; + mutbl.replace(mutbl.map_or(*m, |mutbl: Mutability| mutbl.min(*m))); + } else { + break; + } + } + (ty, mutbl) +} + /// Checks whether `a` and `b` are same types having same `Const` generic args, but ignores /// lifetimes. /// @@ -818,7 +833,7 @@ impl AdtVariantInfo { .enumerate() .map(|(i, f)| (i, approx_ty_size(cx, f.ty(cx.tcx, subst)))) .collect::>(); - fields_size.sort_by(|(_, a_size), (_, b_size)| a_size.cmp(b_size)); + fields_size.sort_by_key(|(_, a_size)| *a_size); Self { ind: i, @@ -827,7 +842,7 @@ impl AdtVariantInfo { } }) .collect::>(); - variants_size.sort_by(|a, b| b.size.cmp(&a.size)); + variants_size.sort_by_key(|b| std::cmp::Reverse(b.size)); variants_size } } diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index ee6d6cdbc34e..39831e2b52d6 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.94" +version = "0.1.95" edition = "2024" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs index 7dda2b7b25f8..ee3fcaa0a84a 100644 --- a/src/tools/clippy/lintcheck/src/input.rs +++ b/src/tools/clippy/lintcheck/src/input.rs @@ -281,8 +281,7 @@ impl CrateWithSource { CrateSource::Path { path } => { fn is_cache_dir(entry: &DirEntry) -> bool { fs::read(entry.path().join("CACHEDIR.TAG")) - .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) - .unwrap_or(false) + .is_ok_and(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) } // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file. diff --git a/src/tools/clippy/rust-toolchain.toml b/src/tools/clippy/rust-toolchain.toml index 0755e1d29c69..c26289c23725 100644 --- a/src/tools/clippy/rust-toolchain.toml +++ b/src/tools/clippy/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-01-08" +channel = "nightly-2026-01-22" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index c9ca6335de6e..7425da70df90 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -30,11 +30,10 @@ use rustc_span::symbol::Symbol; use std::env; use std::fs::read_to_string; +use std::io::Write as _; use std::path::Path; use std::process::exit; -use anstream::println; - /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. fn arg_value<'a>(args: &'a [String], find_arg: &str, pred: impl Fn(&str) -> bool) -> Option<&'a str> { @@ -184,7 +183,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } fn display_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; @@ -251,8 +252,10 @@ pub fn main() { if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); - exit(0); + match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => exit(rustc_driver::EXIT_SUCCESS), + Err(_) => exit(rustc_driver::EXIT_FAILURE), + } } // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index 688161c7bfcb..98b888444831 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -4,19 +4,24 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use std::env; -use std::path::PathBuf; -use std::process::{self, Command}; +extern crate rustc_driver; -use anstream::println; +use std::env; +use std::io::Write as _; +use std::path::PathBuf; +use std::process::{self, Command, exit}; fn show_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } fn show_version() { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); + if writeln!(&mut anstream::stdout().lock(), "{version_info}").is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } pub fn main() { diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed index 76f68686ee2a..2b646a38b534 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -50,6 +50,15 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}")); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}")); } } diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs index 214c8783a669..500552370053 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -65,6 +65,35 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_suggestion( + expr.span, + format!("try using {foo}"), + format!("{foo}.use"), + Applicability::MachineApplicable, + ); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_help(expr.span, format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.help(format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_note(expr.span, format!("required because of {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.note(format!("required because of {foo}")); + }); } } diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr index 9c83538947ca..76b453019270 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -49,5 +49,53 @@ LL | | db.note(note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` -error: aborting due to 5 previous errors +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:72:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_suggestion( +LL | | expr.span, +... | +LL | | ); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable)` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:81:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_help(expr.span, format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:85:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.help(format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:89:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_note(expr.span, format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:93:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.note(format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}"))` + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 61e5af81d827..bcc46adda8a0 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -289,13 +313,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -303,7 +327,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -311,7 +335,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -319,7 +343,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -343,136 +367,136 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:701:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:768:5 | LL | const UNIX_EPOCH_JULIAN_DAY: i32 = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:699:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:8 | LL | // SAFETY: fail ONLY if `accept-comment-above-attribute = false` | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:746:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:813:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:744:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:811:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:759:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:826:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:757:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:824:8 | LL | // SAFETY: ... | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:774:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:841:9 | LL | let x = 34; | ^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:772:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:839:12 | LL | // SAFETY: ... | ^^^^^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 50 previous errors +error: aborting due to 52 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index e252cffea916..0de8ed716bed 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:606:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +311,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -297,13 +321,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -311,7 +335,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -319,7 +343,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:635:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:640:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:578:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:645:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +367,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:652:5 | LL | unsafe {} | ^^^^^^^^^ @@ -351,7 +375,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:590:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:5 | LL | unsafe { | ^^^^^^^^ @@ -359,7 +383,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:598:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:665:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +391,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:604:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:671:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -375,7 +399,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:678:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -383,7 +407,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:617:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:684:5 | LL | unsafe {} | ^^^^^^^^^ @@ -391,7 +415,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -399,7 +423,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -407,7 +431,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -415,7 +439,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -423,7 +447,7 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:9 | LL | unsafe { here_is_another_variable_with_long_name }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -431,7 +455,7 @@ LL | unsafe { here_is_another_variable_with_long_name }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:702:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:769:9 | LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,19 +463,19 @@ LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:735:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:802:12 | LL | return unsafe { h() }; | ^^^^^^^^^^^^^^ @@ -459,31 +483,31 @@ LL | return unsafe { h() }; = help: consider adding a safety comment on the preceding line error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:833:9 | LL | unsafe {} | ^^^^^^^^^ @@ -491,52 +515,52 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 60 previous errors +error: aborting due to 62 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index db9e81cf10a1..8032c388ccfe 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -201,6 +201,66 @@ fn comment_macro_def() { t!(); } +fn comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = + // SAFETY: here be exactly one dragon + unsafe { 1 }; + }; + } + + t!(); +} + +#[rustfmt::skip] +fn comment_macro_def_with_let_same_line() { + macro_rules! t { + () => { + let _x =// SAFETY: same line comment + unsafe { 1 }; + }; + } + + t!(); +} + +fn inner_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { + // SAFETY: inside the block + 1 + }; + }; + } + + t!(); +} + +fn no_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + +fn prefixed_safety_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x =// not a SAFETY: comment, should lint + unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + fn non_ascii_comment() { // ॐ᧻໒ SaFeTy: ௵∰ unsafe {}; @@ -263,6 +323,13 @@ fn in_closure(x: *const u32) { let _ = || unsafe { *x }; } +fn inner_block_comment_block_style(x: *const u32) { + let _ = unsafe { + /* SAFETY: block comment inside */ + *x + }; +} + // Invalid comments #[rustfmt::skip] diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs index b7ed596d811e..87397a549bf4 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs @@ -174,7 +174,6 @@ pub fn hard_coded_allowed() { let _ = Saturating(0u32) + Saturating(0u32); let _ = String::new() + ""; let _ = String::new() + &String::new(); - //~^ arithmetic_side_effects let _ = Wrapping(0u32) + Wrapping(0u32); let saturating: Saturating = Saturating(0u32); diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr index 22742a82601a..2767a051786e 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr @@ -14,784 +14,778 @@ LL | let _ = 1f128 + 1f128; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:176:13 - | -LL | let _ = String::new() + &String::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:312:5 + --> tests/ui/arithmetic_side_effects.rs:311:5 | LL | _n += 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:314:5 + --> tests/ui/arithmetic_side_effects.rs:313:5 | LL | _n += &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:316:5 + --> tests/ui/arithmetic_side_effects.rs:315:5 | LL | _n -= 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:318:5 + --> tests/ui/arithmetic_side_effects.rs:317:5 | LL | _n -= &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:320:5 + --> tests/ui/arithmetic_side_effects.rs:319:5 | LL | _n /= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:322:5 + --> tests/ui/arithmetic_side_effects.rs:321:5 | LL | _n /= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:324:5 + --> tests/ui/arithmetic_side_effects.rs:323:5 | LL | _n %= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:326:5 + --> tests/ui/arithmetic_side_effects.rs:325:5 | LL | _n %= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:328:5 + --> tests/ui/arithmetic_side_effects.rs:327:5 | LL | _n *= 2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:330:5 + --> tests/ui/arithmetic_side_effects.rs:329:5 | LL | _n *= &2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:332:5 + --> tests/ui/arithmetic_side_effects.rs:331:5 | LL | _n += -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:334:5 + --> tests/ui/arithmetic_side_effects.rs:333:5 | LL | _n += &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:336:5 + --> tests/ui/arithmetic_side_effects.rs:335:5 | LL | _n -= -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:338:5 + --> tests/ui/arithmetic_side_effects.rs:337:5 | LL | _n -= &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:340:5 + --> tests/ui/arithmetic_side_effects.rs:339:5 | LL | _n /= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:342:5 + --> tests/ui/arithmetic_side_effects.rs:341:5 | LL | _n /= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:344:5 + --> tests/ui/arithmetic_side_effects.rs:343:5 | LL | _n %= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:346:5 + --> tests/ui/arithmetic_side_effects.rs:345:5 | LL | _n %= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:348:5 + --> tests/ui/arithmetic_side_effects.rs:347:5 | LL | _n *= -2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:350:5 + --> tests/ui/arithmetic_side_effects.rs:349:5 | LL | _n *= &-2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:352:5 + --> tests/ui/arithmetic_side_effects.rs:351:5 | LL | _custom += Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:354:5 + --> tests/ui/arithmetic_side_effects.rs:353:5 | LL | _custom += &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:356:5 + --> tests/ui/arithmetic_side_effects.rs:355:5 | LL | _custom -= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:358:5 + --> tests/ui/arithmetic_side_effects.rs:357:5 | LL | _custom -= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:360:5 + --> tests/ui/arithmetic_side_effects.rs:359:5 | LL | _custom /= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:362:5 + --> tests/ui/arithmetic_side_effects.rs:361:5 | LL | _custom /= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:364:5 + --> tests/ui/arithmetic_side_effects.rs:363:5 | LL | _custom %= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:366:5 + --> tests/ui/arithmetic_side_effects.rs:365:5 | LL | _custom %= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:368:5 + --> tests/ui/arithmetic_side_effects.rs:367:5 | LL | _custom *= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:370:5 + --> tests/ui/arithmetic_side_effects.rs:369:5 | LL | _custom *= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:372:5 + --> tests/ui/arithmetic_side_effects.rs:371:5 | LL | _custom >>= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:374:5 + --> tests/ui/arithmetic_side_effects.rs:373:5 | LL | _custom >>= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:376:5 + --> tests/ui/arithmetic_side_effects.rs:375:5 | LL | _custom <<= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:378:5 + --> tests/ui/arithmetic_side_effects.rs:377:5 | LL | _custom <<= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:380:5 + --> tests/ui/arithmetic_side_effects.rs:379:5 | LL | _custom += -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:382:5 + --> tests/ui/arithmetic_side_effects.rs:381:5 | LL | _custom += &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:384:5 + --> tests/ui/arithmetic_side_effects.rs:383:5 | LL | _custom -= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:386:5 + --> tests/ui/arithmetic_side_effects.rs:385:5 | LL | _custom -= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:388:5 + --> tests/ui/arithmetic_side_effects.rs:387:5 | LL | _custom /= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:390:5 + --> tests/ui/arithmetic_side_effects.rs:389:5 | LL | _custom /= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:392:5 + --> tests/ui/arithmetic_side_effects.rs:391:5 | LL | _custom %= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:394:5 + --> tests/ui/arithmetic_side_effects.rs:393:5 | LL | _custom %= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:396:5 + --> tests/ui/arithmetic_side_effects.rs:395:5 | LL | _custom *= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:398:5 + --> tests/ui/arithmetic_side_effects.rs:397:5 | LL | _custom *= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:400:5 + --> tests/ui/arithmetic_side_effects.rs:399:5 | LL | _custom >>= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:402:5 + --> tests/ui/arithmetic_side_effects.rs:401:5 | LL | _custom >>= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:404:5 + --> tests/ui/arithmetic_side_effects.rs:403:5 | LL | _custom <<= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:406:5 + --> tests/ui/arithmetic_side_effects.rs:405:5 | LL | _custom <<= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:410:10 + --> tests/ui/arithmetic_side_effects.rs:409:10 | LL | _n = _n + 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:412:10 + --> tests/ui/arithmetic_side_effects.rs:411:10 | LL | _n = _n + &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:414:10 + --> tests/ui/arithmetic_side_effects.rs:413:10 | LL | _n = 1 + _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:416:10 + --> tests/ui/arithmetic_side_effects.rs:415:10 | LL | _n = &1 + _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:418:10 + --> tests/ui/arithmetic_side_effects.rs:417:10 | LL | _n = _n - 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:420:10 + --> tests/ui/arithmetic_side_effects.rs:419:10 | LL | _n = _n - &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:422:10 + --> tests/ui/arithmetic_side_effects.rs:421:10 | LL | _n = 1 - _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:424:10 + --> tests/ui/arithmetic_side_effects.rs:423:10 | LL | _n = &1 - _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:426:10 + --> tests/ui/arithmetic_side_effects.rs:425:10 | LL | _n = _n / 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:428:10 + --> tests/ui/arithmetic_side_effects.rs:427:10 | LL | _n = _n / &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:430:10 + --> tests/ui/arithmetic_side_effects.rs:429:10 | LL | _n = _n % 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:432:10 + --> tests/ui/arithmetic_side_effects.rs:431:10 | LL | _n = _n % &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:434:10 + --> tests/ui/arithmetic_side_effects.rs:433:10 | LL | _n = _n * 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:436:10 + --> tests/ui/arithmetic_side_effects.rs:435:10 | LL | _n = _n * &2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:438:10 + --> tests/ui/arithmetic_side_effects.rs:437:10 | LL | _n = 2 * _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:440:10 + --> tests/ui/arithmetic_side_effects.rs:439:10 | LL | _n = &2 * _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:442:10 + --> tests/ui/arithmetic_side_effects.rs:441:10 | LL | _n = 23 + &85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:444:10 + --> tests/ui/arithmetic_side_effects.rs:443:10 | LL | _n = &23 + 85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:446:10 + --> tests/ui/arithmetic_side_effects.rs:445:10 | LL | _n = &23 + &85; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:448:15 + --> tests/ui/arithmetic_side_effects.rs:447:15 | LL | _custom = _custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:450:15 + --> tests/ui/arithmetic_side_effects.rs:449:15 | LL | _custom = _custom + &_custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:452:15 + --> tests/ui/arithmetic_side_effects.rs:451:15 | LL | _custom = Custom + _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:454:15 + --> tests/ui/arithmetic_side_effects.rs:453:15 | LL | _custom = &Custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:456:15 + --> tests/ui/arithmetic_side_effects.rs:455:15 | LL | _custom = _custom - Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:458:15 + --> tests/ui/arithmetic_side_effects.rs:457:15 | LL | _custom = _custom - &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:460:15 + --> tests/ui/arithmetic_side_effects.rs:459:15 | LL | _custom = Custom - _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:462:15 + --> tests/ui/arithmetic_side_effects.rs:461:15 | LL | _custom = &Custom - _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:464:15 + --> tests/ui/arithmetic_side_effects.rs:463:15 | LL | _custom = _custom / Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:466:15 + --> tests/ui/arithmetic_side_effects.rs:465:15 | LL | _custom = _custom / &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:468:15 + --> tests/ui/arithmetic_side_effects.rs:467:15 | LL | _custom = _custom % Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:470:15 + --> tests/ui/arithmetic_side_effects.rs:469:15 | LL | _custom = _custom % &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:472:15 + --> tests/ui/arithmetic_side_effects.rs:471:15 | LL | _custom = _custom * Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:474:15 + --> tests/ui/arithmetic_side_effects.rs:473:15 | LL | _custom = _custom * &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:476:15 + --> tests/ui/arithmetic_side_effects.rs:475:15 | LL | _custom = Custom * _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:478:15 + --> tests/ui/arithmetic_side_effects.rs:477:15 | LL | _custom = &Custom * _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:480:15 + --> tests/ui/arithmetic_side_effects.rs:479:15 | LL | _custom = Custom + &Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:482:15 + --> tests/ui/arithmetic_side_effects.rs:481:15 | LL | _custom = &Custom + Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:484:15 + --> tests/ui/arithmetic_side_effects.rs:483:15 | LL | _custom = &Custom + &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:486:15 + --> tests/ui/arithmetic_side_effects.rs:485:15 | LL | _custom = _custom >> _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:488:15 + --> tests/ui/arithmetic_side_effects.rs:487:15 | LL | _custom = _custom >> &_custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:490:15 + --> tests/ui/arithmetic_side_effects.rs:489:15 | LL | _custom = Custom << _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:492:15 + --> tests/ui/arithmetic_side_effects.rs:491:15 | LL | _custom = &Custom << _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:496:23 + --> tests/ui/arithmetic_side_effects.rs:495:23 | LL | _n.saturating_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:498:21 + --> tests/ui/arithmetic_side_effects.rs:497:21 | LL | _n.wrapping_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:500:21 + --> tests/ui/arithmetic_side_effects.rs:499:21 | LL | _n.wrapping_rem(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:502:28 + --> tests/ui/arithmetic_side_effects.rs:501:28 | LL | _n.wrapping_rem_euclid(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:505:23 + --> tests/ui/arithmetic_side_effects.rs:504:23 | LL | _n.saturating_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:507:21 + --> tests/ui/arithmetic_side_effects.rs:506:21 | LL | _n.wrapping_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:509:21 + --> tests/ui/arithmetic_side_effects.rs:508:21 | LL | _n.wrapping_rem(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:511:28 + --> tests/ui/arithmetic_side_effects.rs:510:28 | LL | _n.wrapping_rem_euclid(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:514:23 + --> tests/ui/arithmetic_side_effects.rs:513:23 | LL | _n.saturating_div(*Box::new(_n)); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:518:10 + --> tests/ui/arithmetic_side_effects.rs:517:10 | LL | _n = -_n; | ^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:520:10 + --> tests/ui/arithmetic_side_effects.rs:519:10 | LL | _n = -&_n; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:522:15 + --> tests/ui/arithmetic_side_effects.rs:521:15 | LL | _custom = -_custom; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:524:15 + --> tests/ui/arithmetic_side_effects.rs:523:15 | LL | _custom = -&_custom; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:526:9 + --> tests/ui/arithmetic_side_effects.rs:525:9 | LL | _ = -*Box::new(_n); | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:536:5 + --> tests/ui/arithmetic_side_effects.rs:535:5 | LL | 1 + i; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:538:5 + --> tests/ui/arithmetic_side_effects.rs:537:5 | LL | i * 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:540:5 + --> tests/ui/arithmetic_side_effects.rs:539:5 | LL | 1 % i / 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:542:5 + --> tests/ui/arithmetic_side_effects.rs:541:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:544:5 + --> tests/ui/arithmetic_side_effects.rs:543:5 | LL | -i; | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:556:5 + --> tests/ui/arithmetic_side_effects.rs:555:5 | LL | i += 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:558:5 + --> tests/ui/arithmetic_side_effects.rs:557:5 | LL | i -= 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:560:5 + --> tests/ui/arithmetic_side_effects.rs:559:5 | LL | i *= 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:563:5 + --> tests/ui/arithmetic_side_effects.rs:562:5 | LL | i /= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:566:5 + --> tests/ui/arithmetic_side_effects.rs:565:5 | LL | i /= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:568:5 + --> tests/ui/arithmetic_side_effects.rs:567:5 | LL | i /= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:571:5 + --> tests/ui/arithmetic_side_effects.rs:570:5 | LL | i %= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:574:5 + --> tests/ui/arithmetic_side_effects.rs:573:5 | LL | i %= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:576:5 + --> tests/ui/arithmetic_side_effects.rs:575:5 | LL | i %= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:587:5 + --> tests/ui/arithmetic_side_effects.rs:586:5 | LL | 10 / a | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:642:9 + --> tests/ui/arithmetic_side_effects.rs:641:9 | LL | x / maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:647:9 + --> tests/ui/arithmetic_side_effects.rs:646:9 | LL | x % maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:659:5 + --> tests/ui/arithmetic_side_effects.rs:658:5 | LL | one.add_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:664:5 + --> tests/ui/arithmetic_side_effects.rs:663:5 | LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:685:5 + --> tests/ui/arithmetic_side_effects.rs:684:5 | LL | one.add(&one); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:687:5 + --> tests/ui/arithmetic_side_effects.rs:686:5 | LL | Box::new(one).add(one); | ^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:696:13 + --> tests/ui/arithmetic_side_effects.rs:695:13 | LL | let _ = u128::MAX + u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:713:13 + --> tests/ui/arithmetic_side_effects.rs:712:13 | LL | let _ = u128::MAX * u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:736:33 + --> tests/ui/arithmetic_side_effects.rs:735:33 | LL | let _ = Duration::from_secs(86400 * Foo::from(1)); | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:742:33 + --> tests/ui/arithmetic_side_effects.rs:741:33 | LL | let _ = Duration::from_secs(86400 * shift(1)); | ^^^^^^^^^^^^^^^^ -error: aborting due to 132 previous errors +error: aborting due to 131 previous errors diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.rs b/src/tools/clippy/tests/ui/cognitive_complexity.rs index 8080c6775e0b..3945028f8271 100644 --- a/src/tools/clippy/tests/ui/cognitive_complexity.rs +++ b/src/tools/clippy/tests/ui/cognitive_complexity.rs @@ -472,3 +472,28 @@ mod issue14422 { return; } } + +#[clippy::cognitive_complexity = "1"] +mod attribute_stacking { + fn bad() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } + + #[clippy::cognitive_complexity = "2"] + fn ok() { + if true { + println!("a"); + } + } + + // should revert to cognitive_complexity = "1" + fn bad_again() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } +} diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.stderr b/src/tools/clippy/tests/ui/cognitive_complexity.stderr index 67ef4e5655bd..e5f54a37229d 100644 --- a/src/tools/clippy/tests/ui/cognitive_complexity.stderr +++ b/src/tools/clippy/tests/ui/cognitive_complexity.stderr @@ -176,5 +176,21 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions -error: aborting due to 22 previous errors +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:478:8 + | +LL | fn bad() { + | ^^^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:493:8 + | +LL | fn bad_again() { + | ^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs index 3ded902e36b1..84147d8e9c16 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,12 +1,11 @@ -//@check-pass //@ignore-target: apple - #![feature(rustc_attrs)] - #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] #[rustc_main] fn a() { - println!("Hello, World!"); a(); + //~^ main_recursion } + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr new file mode 100644 index 000000000000..d9f50d2dfc4b --- /dev/null +++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr @@ -0,0 +1,12 @@ +error: recursing into entrypoint `a` + --> tests/ui/crate_level_checks/entrypoint_recursion.rs:7:5 + | +LL | a(); + | ^ + | + = help: consider using another function for this recursion + = note: `-D clippy::main-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::main_recursion)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs new file mode 100644 index 000000000000..74763d67dd78 --- /dev/null +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -0,0 +1,13 @@ +//@check-pass +//@compile-flags: -Cpanic=abort +#![no_std] +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +fn main() { + main(); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/src/tools/clippy/tests/ui/double_comparison.fixed b/src/tools/clippy/tests/ui/double_comparison.fixed index 0680eb35ef97..29047b8a31cb 100644 --- a/src/tools/clippy/tests/ui/double_comparison.fixed +++ b/src/tools/clippy/tests/ui/double_comparison.fixed @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x < y { + //~^ double_comparisons + // do something + } + if x < y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } } diff --git a/src/tools/clippy/tests/ui/double_comparison.rs b/src/tools/clippy/tests/ui/double_comparison.rs index 18ab7d2c4254..13edb2a996a1 100644 --- a/src/tools/clippy/tests/ui/double_comparison.rs +++ b/src/tools/clippy/tests/ui/double_comparison.rs @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x != y && x <= y { + //~^ double_comparisons + // do something + } + if x <= y && x != y { + //~^ double_comparisons + // do something + } + if x != y && x >= y { + //~^ double_comparisons + // do something + } + if x >= y && x != y { + //~^ double_comparisons + // do something + } } diff --git a/src/tools/clippy/tests/ui/double_comparison.stderr b/src/tools/clippy/tests/ui/double_comparison.stderr index 984614c203eb..be7eba611cb0 100644 --- a/src/tools/clippy/tests/ui/double_comparison.stderr +++ b/src/tools/clippy/tests/ui/double_comparison.stderr @@ -49,5 +49,29 @@ error: this binary expression can be simplified LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` -error: aborting due to 8 previous errors +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:38:8 + | +LL | if x != y && x <= y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:42:8 + | +LL | if x <= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:46:8 + | +LL | if x != y && x >= y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:50:8 + | +LL | if x >= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units.fixed b/src/tools/clippy/tests/ui/duration_suboptimal_units.fixed new file mode 100644 index 000000000000..98c4b6e965ba --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units.fixed @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_mins(5) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(10); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(13); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_mins(1); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units.rs b/src/tools/clippy/tests/ui/duration_suboptimal_units.rs new file mode 100644 index 000000000000..c4f33a9f92e0 --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units.rs @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_secs(300) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(10 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_secs(60); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr b/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr new file mode 100644 index 000000000000..f129dbade8dc --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr @@ -0,0 +1,152 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:26:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:28:15 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:30:15 + | +LL | let dur = Duration::from_secs(10 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(10 * 60); +LL + let dur = Duration::from_mins(10); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:32:15 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:34:15 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:36:15 + | +LL | let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_hours(13); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:47:19 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:49:19 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:51:19 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:58:5 + | +LL | std::time::Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - std::time::Duration::from_secs(60); +LL + std::time::Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:62:16 + | +LL | assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); +LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:13:9 + | +LL | Duration::from_secs(300) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | let dur = mac!(duration); + | -------------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: try using from_mins + | +LL - Duration::from_secs(300) +LL + Duration::from_mins(5) + | + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.fixed b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.fixed new file mode 100644 index 000000000000..b0abcbb7bf03 --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.fixed @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_days(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_weeks(13); + //~^ duration_suboptimal_units +} diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.rs b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.rs new file mode 100644 index 000000000000..663476905c0f --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.rs @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units +} diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.stderr b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.stderr new file mode 100644 index 000000000000..98325358bfa6 --- /dev/null +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units_days_weeks.stderr @@ -0,0 +1,40 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:9:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:12:15 + | +LL | let dur = Duration::from_hours(24); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_days + | +LL - let dur = Duration::from_hours(24); +LL + let dur = Duration::from_days(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:15:15 + | +LL | let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_weeks + | +LL - let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_weeks(13); + | + +error: aborting due to 3 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 5fdcd5a7e078..677523489599 100644 --- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs +++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macro_derive.rs +//@aux-build:proc_macros.rs #![allow( unused, @@ -11,6 +12,7 @@ #[macro_use] extern crate proc_macro_derive; +extern crate proc_macros; fn empty() {} @@ -148,4 +150,34 @@ mod issue_13578 { impl<'a, T: 'a> Foo for Option where &'a T: Foo {} } +// no lint on proc macro generated code +mod proc_macro_generated { + use proc_macros::external; + + // no lint on external macro (extra unused lifetimes in impl block) + external! { + struct ExternalImplStruct; + + impl<'a> ExternalImplStruct { + fn foo() {} + } + } + + // no lint on external macro (extra unused lifetimes in method) + external! { + struct ExternalMethodStruct; + + impl ExternalMethodStruct { + fn bar<'a>(&self) {} + } + } + + // no lint on external macro (extra unused lifetimes in trait method) + external! { + trait ExternalUnusedLifetimeTrait { + fn unused_lt<'a>(x: u8) {} + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr b/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr index 0cecbbe80f76..d748376d476c 100644 --- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:19:14 + --> tests/ui/extra_unused_lifetimes.rs:21:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -8,37 +8,37 @@ LL | fn unused_lt<'a>(x: u8) {} = help: to override `-D warnings` add `#[allow(clippy::extra_unused_lifetimes)]` error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:47:10 + --> tests/ui/extra_unused_lifetimes.rs:49:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:74:22 + --> tests/ui/extra_unused_lifetimes.rs:76:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:86:10 + --> tests/ui/extra_unused_lifetimes.rs:88:10 | LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:93:10 + --> tests/ui/extra_unused_lifetimes.rs:95:10 | LL | impl<'b> Scalar { | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:95:26 + --> tests/ui/extra_unused_lifetimes.rs:97:26 | LL | pub fn something<'c>() -> Self { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:125:10 + --> tests/ui/extra_unused_lifetimes.rs:127:10 | LL | impl<'a, T: Source + ?Sized + 'a> Source for Box { | ^^ diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs index 6d2e63e7299a..6e0e2c5ea720 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else.rs @@ -11,6 +11,8 @@ unreachable_code )] +use std::ops::*; + struct Foo { bar: u8, } @@ -133,18 +135,6 @@ fn func() { fn f(val: &[u8]) {} -mod issue_5698 { - fn mul_not_always_commutative(x: i32, y: i32) -> i32 { - if x == 42 { - x * y - } else if x == 21 { - y * x - } else { - 0 - } - } -} - mod issue_8836 { fn do_not_lint() { if true { @@ -245,3 +235,73 @@ mod issue_11213 { } fn main() {} + +fn issue16416(x: bool, a: T, b: T) +where + T: Add + Sub + Mul + Div + Rem + BitAnd + BitOr + BitXor + PartialEq + Eq + PartialOrd + Ord + Shr + Shl + Copy, +{ + // Non-guaranteed-commutative operators + _ = if x { a * b } else { b * a }; + _ = if x { a + b } else { b + a }; + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + _ = if x { a & b } else { b & a }; + _ = if x { a ^ b } else { b ^ a }; + _ = if x { a | b } else { b | a }; + + // Guaranteed commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} + +fn issue16416_prim(x: bool, a: u32, b: u32) { + // Non-commutative operators + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + + // Commutative operators on primitive types + //~v if_same_then_else + _ = if x { a * b } else { b * a }; + //~v if_same_then_else + _ = if x { a + b } else { b + a }; + //~v if_same_then_else + _ = if x { a & b } else { b & a }; + //~v if_same_then_else + _ = if x { a ^ b } else { b ^ a }; + //~v if_same_then_else + _ = if x { a | b } else { b | a }; + + // Always commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr index b76da3fb1cb5..57396a566941 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:23:13 + --> tests/ui/if_same_then_else.rs:25:13 | LL | if true { | _____________^ @@ -12,7 +12,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:31:12 + --> tests/ui/if_same_then_else.rs:33:12 | LL | } else { | ____________^ @@ -27,43 +27,43 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::if_same_then_else)]` error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:67:21 + --> tests/ui/if_same_then_else.rs:69:21 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:67:34 + --> tests/ui/if_same_then_else.rs:69:34 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:70:21 + --> tests/ui/if_same_then_else.rs:72:21 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:70:35 + --> tests/ui/if_same_then_else.rs:72:35 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:82:21 + --> tests/ui/if_same_then_else.rs:84:21 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:82:33 + --> tests/ui/if_same_then_else.rs:84:33 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:85:13 + --> tests/ui/if_same_then_else.rs:87:13 | LL | if true { | _____________^ @@ -76,7 +76,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:92:12 + --> tests/ui/if_same_then_else.rs:94:12 | LL | } else { | ____________^ @@ -89,7 +89,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:238:14 + --> tests/ui/if_same_then_else.rs:228:14 | LL | if x { | ______________^ @@ -98,7 +98,7 @@ LL | | } else { | |_________^ | note: same as this - --> tests/ui/if_same_then_else.rs:240:16 + --> tests/ui/if_same_then_else.rs:230:16 | LL | } else { | ________________^ @@ -106,5 +106,209 @@ LL | | 0_u8.is_power_of_two() LL | | } | |_________^ -error: aborting due to 6 previous errors +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:257:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:257:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:259:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:259:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:263:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:263:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:265:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:265:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:267:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:267:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:269:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:269:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:282:14 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:282:29 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:284:14 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:284:29 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:286:14 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:286:29 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:288:14 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:288:29 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:290:14 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:290:29 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:294:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:294:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:296:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:296:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:300:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:300:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:302:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:302:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:304:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:304:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:306:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:306:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: aborting due to 23 previous errors diff --git a/src/tools/clippy/tests/ui/int_plus_one.fixed b/src/tools/clippy/tests/ui/int_plus_one.fixed index a1aba6bf7f64..cdd19515e9a7 100644 --- a/src/tools/clippy/tests/ui/int_plus_one.fixed +++ b/src/tools/clippy/tests/ui/int_plus_one.fixed @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/src/tools/clippy/tests/ui/int_plus_one.rs b/src/tools/clippy/tests/ui/int_plus_one.rs index f804fc9047de..8d7d2e8982d8 100644 --- a/src/tools/clippy/tests/ui/int_plus_one.rs +++ b/src/tools/clippy/tests/ui/int_plus_one.rs @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x >= y + 1; - //~^ int_plus_one - let _ = y + 1 <= x; - //~^ int_plus_one + let _ = x >= y + 1; //~ int_plus_one + let _ = x >= 1 + y; //~ int_plus_one + let _ = y + 1 <= x; //~ int_plus_one + let _ = 1 + y <= x; //~ int_plus_one - let _ = x - 1 >= y; - //~^ int_plus_one - let _ = y <= x - 1; - //~^ int_plus_one + let _ = x - 1 >= y; //~ int_plus_one + let _ = -1 + x >= y; //~ int_plus_one + let _ = y <= x - 1; //~ int_plus_one + let _ = y <= -1 + x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/src/tools/clippy/tests/ui/int_plus_one.stderr b/src/tools/clippy/tests/ui/int_plus_one.stderr index 052706028141..8bdff5680bdc 100644 --- a/src/tools/clippy/tests/ui/int_plus_one.stderr +++ b/src/tools/clippy/tests/ui/int_plus_one.stderr @@ -7,23 +7,47 @@ LL | let _ = x >= y + 1; = note: `-D clippy::int-plus-one` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::int_plus_one)]` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:8:13 + | +LL | let _ = x >= 1 + y; + | ^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:9:13 | LL | let _ = y + 1 <= x; | ^^^^^^^^^^ help: change it to: `y < x` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:10:13 + | +LL | let _ = 1 + y <= x; + | ^^^^^^^^^^ help: change it to: `y < x` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:12:13 | LL | let _ = x - 1 >= y; | ^^^^^^^^^^ help: change it to: `x > y` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:13:13 + | +LL | let _ = -1 + x >= y; + | ^^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:14:13 | LL | let _ = y <= x - 1; | ^^^^^^^^^^ help: change it to: `y < x` -error: aborting due to 4 previous errors +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:15:13 + | +LL | let _ = y <= -1 + x; + | ^^^^^^^^^^^ help: change it to: `y < x` + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/manual_checked_ops.rs b/src/tools/clippy/tests/ui/manual_checked_ops.rs new file mode 100644 index 000000000000..93630faa1086 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_checked_ops.rs @@ -0,0 +1,72 @@ +#![warn(clippy::manual_checked_ops)] + +fn main() { + let mut a = 10u32; + let mut b = 5u32; + + // Should trigger lint + if b != 0 { + //~^ manual_checked_ops + let _result = a / b; + let _another = (a + 1) / b; + } + + // Should trigger lint (compound assignment) + if b != 0 { + //~^ manual_checked_ops + a /= b; + } + + if b > 0 { + //~^ manual_checked_ops + let _result = a / b; + } + + if b == 0 { + //~^ manual_checked_ops + println!("zero"); + } else { + let _result = a / b; + } + + // Should NOT trigger (already using checked_div) + if let Some(result) = b.checked_div(a) { + println!("{result}"); + } + + // Should NOT trigger (signed integers are not linted) + let c = -5i32; + if c != 0 { + let _result = 10 / c; + } + + // Should NOT trigger (side effects in divisor) + if counter() > 0 { + let _ = 32 / counter(); + } + + // Should NOT trigger (divisor used before division) + if b > 0 { + use_value(b); + let _ = a / b; + } + + // Should NOT trigger (divisor may change during evaluation) + if b > 0 { + g(inc_and_return_value(&mut b), a / b); + } +} + +fn counter() -> u32 { + println!("counter"); + 1 +} + +fn use_value(_v: u32) {} + +fn inc_and_return_value(x: &mut u32) -> u32 { + *x += 1; + *x +} + +fn g(_lhs: u32, _rhs: u32) {} diff --git a/src/tools/clippy/tests/ui/manual_checked_ops.stderr b/src/tools/clippy/tests/ui/manual_checked_ops.stderr new file mode 100644 index 000000000000..311f319bad14 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_checked_ops.stderr @@ -0,0 +1,50 @@ +error: manual checked division + --> tests/ui/manual_checked_ops.rs:8:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here +LL | let _another = (a + 1) / b; + | ----------- ... and here + | + = help: consider using `checked_div` + = note: `-D clippy::manual-checked-ops` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_checked_ops)]` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:15:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | a /= b; + | ------ division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:20:8 + | +LL | if b > 0 { + | ^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:25:8 + | +LL | if b == 0 { + | ^^^^^^ check performed here +... +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_take.fixed b/src/tools/clippy/tests/ui/manual_take.fixed new file mode 100644 index 000000000000..5891bd49c81c --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take.fixed @@ -0,0 +1,57 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = !std::mem::take(&mut x); + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + std::mem::take(&mut x) +} diff --git a/src/tools/clippy/tests/ui/manual_take.rs b/src/tools/clippy/tests/ui/manual_take.rs new file mode 100644 index 000000000000..89903fcb2416 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take.rs @@ -0,0 +1,69 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + if x { + //~^ manual_take + x = false; + true + } else { + false + } +} diff --git a/src/tools/clippy/tests/ui/manual_take.stderr b/src/tools/clippy/tests/ui/manual_take.stderr new file mode 100644 index 000000000000..69ba7778a275 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take.stderr @@ -0,0 +1,53 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:9:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !std::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:62:5 + | +LL | / if x { +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | } + | |_____^ + | +help: use + | +LL - if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - } +LL + std::mem::take(&mut x) + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_take_nocore.rs b/src/tools/clippy/tests/ui/manual_take_nocore.rs new file mode 100644 index 000000000000..ef4f23395028 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take_nocore.rs @@ -0,0 +1,37 @@ +//@ check-pass +#![feature(no_core, lang_items)] +#![no_core] +#![allow(clippy::missing_safety_doc)] +#![warn(clippy::manual_take)] + +#[link(name = "c")] +unsafe extern "C" {} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub unsafe trait Freeze {} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() { + let mut x = true; + // this should not lint because we don't have std nor core + let _manual_take = if x { + x = false; + true + } else { + false + }; +} diff --git a/src/tools/clippy/tests/ui/manual_take_nostd.fixed b/src/tools/clippy/tests/ui/manual_take_nostd.fixed new file mode 100644 index 000000000000..123c5a91998c --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take_nostd.fixed @@ -0,0 +1,10 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = !core::mem::take(&mut x); + + let _lint = core::mem::take(&mut x); +} diff --git a/src/tools/clippy/tests/ui/manual_take_nostd.rs b/src/tools/clippy/tests/ui/manual_take_nostd.rs new file mode 100644 index 000000000000..0df352477b74 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take_nostd.rs @@ -0,0 +1,22 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _lint = if x { + //~^ manual_take + x = false; + true + } else { + false + }; +} diff --git a/src/tools/clippy/tests/ui/manual_take_nostd.stderr b/src/tools/clippy/tests/ui/manual_take_nostd.stderr new file mode 100644 index 000000000000..71a5066e4db3 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_take_nostd.stderr @@ -0,0 +1,54 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:7:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !core::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:15:17 + | +LL | let _lint = if x { + | _________________^ +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | }; + | |_____^ + | +help: use + | +LL - let _lint = if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - }; +LL + let _lint = core::mem::take(&mut x); + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.rs b/src/tools/clippy/tests/ui/map_unwrap_or.rs index fba81cb493cd..dccacd7df8af 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or.rs +++ b/src/tools/clippy/tests/ui/map_unwrap_or.rs @@ -156,3 +156,11 @@ mod issue_10579 { println!("{y:?}"); } } + +fn issue15752() { + struct Foo<'a>(&'a [u32]); + + let x = Some(Foo(&[1, 2, 3])); + x.map(|y| y.0).unwrap_or(&[]); + //~^ map_unwrap_or +} diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.stderr b/src/tools/clippy/tests/ui/map_unwrap_or.stderr index df0207c420e6..bd9e0eeb0bda 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or.stderr +++ b/src/tools/clippy/tests/ui/map_unwrap_or.stderr @@ -232,5 +232,11 @@ LL - let _ = opt.map(|x| x > 5).unwrap_or(false); LL + let _ = opt.is_some_and(|x| x > 5); | -error: aborting due to 15 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or.rs:164:5 + | +LL | x.map(|y| y.0).unwrap_or(&[]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed index 90f3cf8bab04..dca2536132d7 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed +++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -51,3 +56,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", o.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or_else(|()| 3, |y| y + 1)); + //~^ map_unwrap_or + + println!("{}", r.is_ok_and(|y| y == 1)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or_else(|_| 3, |y| y + 1)); + //~^ map_unwrap_or +} diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs index 1078c7a3cf34..c60cb082ae3c 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs +++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -57,3 +62,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + //~^ map_unwrap_or + + println!("{}", r.map(|y| y == 1).unwrap_or(false)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + //~^ map_unwrap_or +} diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr index 99e660f8dbd1..33a865d6769c 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr +++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:16:13 + --> tests/ui/map_unwrap_or_fixable.rs:21:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -11,7 +11,7 @@ LL | | .unwrap_or_else(|| 0); = help: to override `-D warnings` add `#[allow(clippy::map_unwrap_or)]` error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:47:13 + --> tests/ui/map_unwrap_or_fixable.rs:52:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -19,5 +19,89 @@ LL | let _ = res.map(|x| x + 1) LL | | .unwrap_or_else(|_e| 0); | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 2 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:69:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", o.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", o.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:71:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `o.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:73:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", r.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", r.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:75:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r.map_or_else(|()| 3, |y| y + 1)` + +error: called `map().unwrap_or(false)` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:78:20 + | +LL | println!("{}", r.map(|y| y == 1).unwrap_or(false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_ok_and()` instead + | +LL - println!("{}", r.map(|y| y == 1).unwrap_or(false)); +LL + println!("{}", r.is_ok_and(|y| y == 1)); + | + +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:84:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:88:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:92:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:96:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|_| 3, |y| y + 1)` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.rs b/src/tools/clippy/tests/ui/missing_trait_methods.rs index 7af186ba3322..67070a299951 100644 --- a/src/tools/clippy/tests/ui/missing_trait_methods.rs +++ b/src/tools/clippy/tests/ui/missing_trait_methods.rs @@ -62,3 +62,10 @@ impl MissingMultiple for Partial {} //~| missing_trait_methods fn main() {} + +//~v missing_trait_methods +impl PartialEq for Partial { + fn eq(&self, other: &Partial) -> bool { + todo!() + } +} diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.stderr b/src/tools/clippy/tests/ui/missing_trait_methods.stderr index d9fb8951ab3d..e5155ad587cb 100644 --- a/src/tools/clippy/tests/ui/missing_trait_methods.stderr +++ b/src/tools/clippy/tests/ui/missing_trait_methods.stderr @@ -60,5 +60,13 @@ help: implement the method LL | fn three() {} | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: missing trait method provided by default: `ne` + --> tests/ui/missing_trait_methods.rs:67:1 + | +LL | impl PartialEq for Partial { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: implement the missing `ne` method of the `PartialEq` trait + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed index 99027e79b664..2d59c1d42b05 100644 --- a/src/tools/clippy/tests/ui/needless_collect.fixed +++ b/src/tools/clippy/tests/ui/needless_collect.fixed @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + + iter.chain([1, 2]).map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + + //~^ needless_collect + + iter.chain(s).map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + + //~^ needless_collect + + + [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + + //~^ needless_collect + + + + + + + + [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + } +} diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs index 683cc49c9af3..346cddd88e70 100644 --- a/src/tools/clippy/tests/ui/needless_collect.rs +++ b/src/tools/clippy/tests/ui/needless_collect.rs @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.push(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_back(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + let mut ll = iter.collect::>(); + //~^ needless_collect + ll.extend(s); + ll.into_iter().map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_front(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_back(2); + v.push_front(3); + v.extend(iter2); + v.push_back(4); + v.push_front(5); + v.push_back(6); + v.into_iter().map(|x| x + 1).collect() + } +} diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr index c77674dc55d4..b10312224c8e 100644 --- a/src/tools/clippy/tests/ui/needless_collect.stderr +++ b/src/tools/clippy/tests/ui/needless_collect.stderr @@ -121,5 +121,115 @@ error: avoid using `collect()` when not needed LL | baz((0..10), (), ('a'..='z').collect::>()) | ^^^^^^^^^^^^^^^^^^^^ help: remove this call -error: aborting due to 20 previous errors +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:228:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:240:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ iter.chain([1, 2]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:248:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:268:27 + | +LL | let mut ll = iter.collect::>(); + | ^^^^^^^ +... +LL | ll.into_iter().map(|x| x + 1).collect() + | -------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain(s).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:275:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:286:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + | + +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/needless_continue.rs b/src/tools/clippy/tests/ui/needless_continue.rs index 88b7905e7fa8..3275dddf1a0f 100644 --- a/src/tools/clippy/tests/ui/needless_continue.rs +++ b/src/tools/clippy/tests/ui/needless_continue.rs @@ -342,3 +342,38 @@ fn issue15548() { } } } + +fn issue16256() { + fn some_condition() -> bool { + true + } + fn another_condition() -> bool { + true + } + + for _ in 0..5 { + if some_condition() { + // ... + continue; + } + + if another_condition() { + // ... + // "this `continue` expression is redundant" is posted on + // the `continue` node. + #[expect(clippy::needless_continue)] + continue; + } + } + + for _ in 0..5 { + // "This `else` block is redundant" is posted on the + // `else` node. + #[expect(clippy::needless_continue)] + if some_condition() { + // ... + } else { + continue; + } + } +} diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed index 15ca409c95bd..90a07454b4d7 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed +++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs index af9649d72987..6df38897f42d 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.rs +++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed index 3d416056226c..559c1bb94570 100644 --- a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed +++ b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed @@ -146,3 +146,39 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + + let mut stdin = stdin().lock().take(40); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + drop(stdin); + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + drop(lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs index d9c4ad543593..dff36baf383d 100644 --- a/src/tools/clippy/tests/ui/significant_drop_tightening.rs +++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs @@ -142,3 +142,36 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + let stdin = stdin().lock(); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + let mut stdin = stdin.take(40); + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr index 25cd9da73a10..785bee4970ec 100644 --- a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr +++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr @@ -83,5 +83,74 @@ LL | LL ~ | -error: aborting due to 4 previous errors +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:151:9 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let stdin = stdin().lock(); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: merge the temporary construction with its single usage + | +LL ~ +LL + let mut stdin = stdin().lock().take(40); +LL | +LL | let mut buffer = String::with_capacity(10); +LL | +LL ~ + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:155:13 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let mut stdin = stdin.take(40); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ } +LL + drop(stdin); + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:171:9 + | +LL | fn issue16343() { + | _________________- +LL | | fn get_items(x: &()) -> Vec<()> { +LL | | vec![*x] +... | +LL | | let lock = storage.lock().unwrap(); + | | ^^^^ +... | +LL | | } + | |_- temporary `lock` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ let items = get_items(&lock); +LL + drop(lock); + | + +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed index 17c1b541f77c..6604da70874d 100644 --- a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed +++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed @@ -1,37 +1,68 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); - let _ = cstring.as_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; - let _ = unsafe { (*pcstr).to_bytes().len() }; - //~^ strlen_on_c_strings + let _ = unsafe { (*pcstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } - let _ = unsafe { unsafe_identity(cstr).to_bytes().len() }; - //~^ strlen_on_c_strings - let _ = unsafe { unsafe_identity(cstr) }.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = unsafe { unsafe_identity(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value + let _ = unsafe { unsafe_identity(cstr) }.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; - let _ = unsafe { f(cstr).to_bytes().len() }; + let _ = unsafe { f(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = box_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = box_cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = arc_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.to_bytes().len(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.to_bytes().len(); + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.count_bytes(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.count_bytes(); //~^ strlen_on_c_strings } diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs index c641422f5df4..11fbdf585064 100644 --- a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs +++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs @@ -1,7 +1,6 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; @@ -9,29 +8,61 @@ fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; let _ = unsafe { strlen((*pcstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; let _ = unsafe { strlen(f(cstr).as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; //~^ strlen_on_c_strings } diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr b/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr index 84a93b99ee33..1f1b5ccdb0ef 100644 --- a/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr +++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.stderr @@ -1,47 +1,89 @@ -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:11:13 +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:10:13 | LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstring.as_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` | = note: `-D clippy::strlen-on-c-strings` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::strlen_on_c_strings)]` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:16:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:15:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:19:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:18:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:23:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:22:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `(*pcstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:29:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:28:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe_identity(cstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:31:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:30:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe { unsafe_identity(cstr) }.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:35:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:34:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `f(cstr).count_bytes()` -error: aborting due to 7 previous errors +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:40:13 + | +LL | let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstring.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:42:13 + | +LL | let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstr.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:44:13 + | +LL | let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `arc_cstring.count_bytes()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:51:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.to_bytes().len()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:55:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.to_bytes().len()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:62:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:66:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.1.fixed b/src/tools/clippy/tests/ui/suspicious_to_owned.1.fixed new file mode 100644 index 000000000000..6fd536a38ed1 --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_to_owned.1.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.2.fixed b/src/tools/clippy/tests/ui/suspicious_to_owned.2.fixed new file mode 100644 index 000000000000..841adf8ea274 --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_to_owned.2.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.rs b/src/tools/clippy/tests/ui/suspicious_to_owned.rs index 2eec05ccaf4c..f59b3fd6ed0c 100644 --- a/src/tools/clippy/tests/ui/suspicious_to_owned.rs +++ b/src/tools/clippy/tests/ui/suspicious_to_owned.rs @@ -1,4 +1,3 @@ -//@no-rustfix: overlapping suggestions #![warn(clippy::suspicious_to_owned)] #![warn(clippy::implicit_clone)] #![allow(clippy::redundant_clone)] diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr index f90bea5fb8ff..5fda1ed1cc9c 100644 --- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr +++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr @@ -1,71 +1,71 @@ -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:17:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:16:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | = note: `-D clippy::suspicious-to-owned` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_to_owned)]` -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned - --> tests/ui/suspicious_to_owned.rs:29:13 +error: this `to_owned` call clones the `Cow<'_, [char; 3]>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:28:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, Vec> itself and does not cause the Cow<'_, Vec> contents to become owned - --> tests/ui/suspicious_to_owned.rs:41:13 +error: this `to_owned` call clones the `Cow<'_, Vec>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:40:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:53:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:52:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:69:13 + --> tests/ui/suspicious_to_owned.rs:68:13 | LL | let _ = String::from(moo).to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::from(moo).clone()` @@ -74,7 +74,7 @@ LL | let _ = String::from(moo).to_owned(); = help: to override `-D warnings` add `#[allow(clippy::implicit_clone)]` error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:72:13 + --> tests/ui/suspicious_to_owned.rs:71:13 | LL | let _ = moos_vec.to_owned(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `moos_vec.clone()` diff --git a/src/tools/clippy/tests/ui/transmuting_null.rs b/src/tools/clippy/tests/ui/transmuting_null.rs index 00aa35dff803..efa4c5cfdc2d 100644 --- a/src/tools/clippy/tests/ui/transmuting_null.rs +++ b/src/tools/clippy/tests/ui/transmuting_null.rs @@ -47,9 +47,20 @@ fn transumute_single_expr_blocks() { } } +fn transmute_pointer_creators() { + unsafe { + let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + //~^ transmuting_null + + let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + //~^ transmuting_null + } +} + fn main() { one_liners(); transmute_const(); transmute_const_int(); transumute_single_expr_blocks(); + transmute_pointer_creators(); } diff --git a/src/tools/clippy/tests/ui/transmuting_null.stderr b/src/tools/clippy/tests/ui/transmuting_null.stderr index e1de391813bd..3c6c28f31d0d 100644 --- a/src/tools/clippy/tests/ui/transmuting_null.stderr +++ b/src/tools/clippy/tests/ui/transmuting_null.stderr @@ -37,5 +37,17 @@ error: transmuting a known null pointer into a reference LL | let _: &u64 = std::mem::transmute(const { u64::MIN as *const u64 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:52:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:55:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 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 10552431d65d..52c114339292 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed @@ -70,7 +70,7 @@ fn main() { let _ = r.is_ok_and(|x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.is_ok_and(func); diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs index 4b406ec2998b..dd2e1a569469 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.rs +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs @@ -74,7 +74,7 @@ fn main() { let _ = r.map_or(false, |x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.map_or(false, func); diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr index b8a22346c378..d11e7179f921 100644 --- a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr @@ -56,7 +56,7 @@ LL | | 6 >= 5 LL | | }); | |______^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| { LL + let _ = Some(5).is_some_and(|n| { @@ -68,7 +68,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Some(vec![5]).is_some_and(|n| n == [5]); @@ -80,7 +80,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); LL + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); @@ -92,7 +92,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == n); LL + let _ = Some(5).is_some_and(|n| n == n); @@ -104,7 +104,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); LL + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); @@ -116,7 +116,7 @@ error: this `map_or` can be simplified LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); @@ -152,7 +152,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| n == 5); LL + let _ = Some(5).is_none_or(|n| n == 5); @@ -164,7 +164,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| 5 == n); LL + let _ = Some(5).is_none_or(|n| 5 == n); @@ -212,7 +212,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, |x| x == 7); LL + let _ = r.is_ok_and(|x| x == 7); @@ -224,7 +224,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, func); LL + let _ = r.is_ok_and(func); @@ -236,7 +236,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, func); LL + let _ = Some(5).is_some_and(func); @@ -248,7 +248,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, func); LL + let _ = Some(5).is_none_or(func); @@ -272,7 +272,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.is_none_or(|n| n > 5) || (o as &Option).map_or(true, |n| n < 5) @@ -284,7 +284,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.map_or(true, |n| n > 5) || (o as &Option).is_none_or(|n| n < 5) @@ -296,7 +296,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) LL + o.is_none_or(|n| n > 5) @@ -308,7 +308,7 @@ error: this `map_or` can be simplified LL | let x = a.map_or(false, |a| a == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let x = a.map_or(false, |a| a == *s); LL + let x = a.is_some_and(|a| a == *s); @@ -320,7 +320,7 @@ error: this `map_or` can be simplified LL | let y = b.map_or(true, |b| b == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let y = b.map_or(true, |b| b == *s); LL + let y = b.is_none_or(|b| b == *s); @@ -356,7 +356,7 @@ error: this `map_or` can be simplified LL | _ = s.lock().unwrap().map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.lock().unwrap().map_or(false, |s| s == "foo"); LL + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); @@ -368,7 +368,7 @@ error: this `map_or` can be simplified LL | _ = s.map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.map_or(false, |s| s == "foo"); LL + _ = s.is_some_and(|s| s == "foo"); diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed index 5255ab173efb..6870470e74c5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by_key(|a| a.0); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by_key(|item1| item1.key); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by_key(|item1| item1.value.clone()); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by_key(|(_, s1)| *s1); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by_key(|Foo { bar: b1 }| *b1); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by_key(|Baz(b1)| *b1); + //~^ unnecessary_sort_by + + v.sort_by_key(|&Baz(b1)| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by_key(|&&b1| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by_key(|[a1, b1]| *a1); + //~^ unnecessary_sort_by + + v.sort_by_key(|[a1, b1]| a1 - b1); + //~^ unnecessary_sort_by +} diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs index 65db7ca3f137..d95306176817 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by(|a, b| a.0.cmp(&b.0)); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + //~^ unnecessary_sort_by + + v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + //~^ unnecessary_sort_by + + v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + //~^ unnecessary_sort_by +} diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr index a066554037fe..cc545d604ff3 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr @@ -2,76 +2,267 @@ error: consider using `sort` --> tests/ui/unnecessary_sort_by.rs:12:5 | LL | vec.sort_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| a.cmp(b)); +LL + vec.sort(); + | error: consider using `sort_unstable` --> tests/ui/unnecessary_sort_by.rs:14:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| a.cmp(b)); +LL + vec.sort_unstable(); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); +LL + vec.sort_by_key(|a| (a + 5).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); +LL + vec.sort_unstable_by_key(|a| id(-a)); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:22:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); +LL + vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:24:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); +LL + vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b))); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:35:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_by_key(|a| (***a).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:37:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_unstable_by_key(|a| (***a).abs()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:97:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_by_key(|a| a.name()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:99:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_unstable_by_key(|a| a.name()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:102:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_by_key(|b| std::cmp::Reverse(b.name())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:104:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); + | -error: aborting due to 12 previous errors +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:118:5 + | +LL | v.sort_by(|a, b| a.0.cmp(&b.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|a, b| a.0.cmp(&b.0)); +LL + v.sort_by_key(|a| a.0); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:136:5 + | +LL | items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); +LL + items.sort_by_key(|item1| item1.key); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:141:5 + | +LL | items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); +LL + items.sort_by_key(|item1| item1.value.clone()); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:147:5 + | +LL | v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); +LL + v.sort_by_key(|(_, s1)| *s1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:154:5 + | +LL | v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); +LL + v.sort_by_key(|Foo { bar: b1 }| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:159:5 + | +LL | v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); +LL + v.sort_by_key(|Baz(b1)| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:162:5 + | +LL | v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); +LL + v.sort_by_key(|&Baz(b1)| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:166:5 + | +LL | v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); +LL + v.sort_by_key(|&&b1| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:170:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); +LL + v.sort_by_key(|[a1, b1]| *a1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:173:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); +LL + v.sort_by_key(|[a1, b1]| a1 - b1); + | + +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by_no_core.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by_no_core.rs new file mode 100644 index 000000000000..cb0da6339cb3 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by_no_core.rs @@ -0,0 +1,26 @@ +//@check-pass +#![feature(no_core)] +#![no_std] +#![no_core] +extern crate alloc; +extern crate core as mycore; +use alloc::vec; +use alloc::vec::Vec; +use mycore::cmp::Ord as _; + +fn issue_11524() -> Vec { + let mut vec = vec![1, 2, 3]; + + // We could lint and suggest `vec.sort_by_key(|a| a + 1);`, but we don't bother to -- see the + // comment in the lint at line 194 + vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); + vec +} + +fn issue_11524_2() -> Vec { + let mut vec = vec![1, 2, 3]; + + // Should not lint, as even `vec.sort_by_key(|b| core::cmp::Reverse(b + 1));` would not compile + vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); + vec +} diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by_no_std.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by_no_std.stderr index de3ef4123514..b4dd6a6dbdc5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by_no_std.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by_no_std.stderr @@ -2,16 +2,27 @@ error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:10:5 | LL | vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| a + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); +LL + vec.sort_by_key(|a| a + 1); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:19:5 | LL | vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| core::cmp::Reverse(b + 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); +LL + vec.sort_by_key(|b| core::cmp::Reverse(b + 1)); + | error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/while_let_loop.rs b/src/tools/clippy/tests/ui/while_let_loop.rs index f28c504742fd..b5a362669ce2 100644 --- a/src/tools/clippy/tests/ui/while_let_loop.rs +++ b/src/tools/clippy/tests/ui/while_let_loop.rs @@ -253,3 +253,24 @@ fn let_assign() { } } } + +fn issue16378() { + // This does not lint today because of the extra statement(s) + // before the `break`. + // TODO: When the `break` statement/expr in the `let`/`else` is the + // only way to leave the loop, the lint could trigger and move + // the statements preceeding the `break` after the loop, as in: + // ```rust + // while let Some(x) = std::hint::black_box(None::) { + // println!("x = {x}"); + // } + // println!("fail"); + // ``` + loop { + let Some(x) = std::hint::black_box(None::) else { + println!("fail"); + break; + }; + println!("x = {x}"); + } +} diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 1b72931949c5..1d5b7926a8e3 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -6,12 +6,20 @@ use std::iter; use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; use crate::directives::DirectiveLine; +use crate::util::static_regex; + +#[cfg(test)] +mod tests; /// The value of an `aux-crate` directive. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct AuxCrate { + /// Contains `--extern` modifiers, if any. See the tracking issue for more + /// info: + /// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude`. + pub extern_modifiers: Option, /// With `aux-crate: foo=bar.rs` this will be `foo`. - /// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude:foo`. + /// With `aux-crate: noprelude:foo=bar.rs` this will be `foo`. pub name: String, /// With `aux-crate: foo=bar.rs` this will be `bar.rs`. pub path: String, @@ -74,9 +82,20 @@ pub(super) fn parse_and_update_aux( } fn parse_aux_crate(r: String) -> AuxCrate { - let mut parts = r.trim().splitn(2, '='); - AuxCrate { - name: parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), - path: parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), - } + let r = r.trim(); + + // Matches: + // name=path + // modifiers:name=path + let caps = static_regex!(r"^(?:(?[^=]*?):)?(?[^=]*)=(?.*)$") + .captures(r) + .unwrap_or_else(|| { + panic!("couldn't parse aux-crate value `{r}` (should be e.g. `log=log.rs`)") + }); + + let modifiers = caps.name("modifiers").map(|m| m.as_str().to_string()); + let name = caps["name"].to_string(); + let path = caps["path"].to_string(); + + AuxCrate { extern_modifiers: modifiers, name, path } } diff --git a/src/tools/compiletest/src/directives/auxiliary/tests.rs b/src/tools/compiletest/src/directives/auxiliary/tests.rs new file mode 100644 index 000000000000..ad205eaabfda --- /dev/null +++ b/src/tools/compiletest/src/directives/auxiliary/tests.rs @@ -0,0 +1,27 @@ +use super::*; + +#[test] +fn test_aux_crate_value_no_modifiers() { + assert_eq!( + AuxCrate { extern_modifiers: None, name: "foo".to_string(), path: "foo.rs".to_string() }, + parse_aux_crate("foo=foo.rs".to_string()) + ); +} + +#[test] +fn test_aux_crate_value_with_modifiers() { + assert_eq!( + AuxCrate { + extern_modifiers: Some("noprelude".to_string()), + name: "foo".to_string(), + path: "foo.rs".to_string() + }, + parse_aux_crate("noprelude:foo=foo.rs".to_string()) + ); +} + +#[test] +#[should_panic(expected = "couldn't parse aux-crate value `foo.rs` (should be e.g. `log=log.rs`)")] +fn test_aux_crate_value_invalid() { + parse_aux_crate("foo.rs".to_string()); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 901ce8421ebf..dfbe84d5da72 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1277,23 +1277,36 @@ impl<'test> TestCx<'test> { .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, lib_name)); - } - }; + let add_extern = |rustc: &mut Command, + extern_modifiers: Option<&str>, + 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 { + let modifiers_and_name = match extern_modifiers { + Some(modifiers) => format!("{modifiers}:{aux_name}"), + None => aux_name.to_string(), + }; + rustc.arg("--extern").arg(format!("{modifiers_and_name}={aux_dir}/{lib_name}")); + } + }; - for AuxCrate { name, path } in &self.props.aux.crates { + for AuxCrate { extern_modifiers, name, path } in &self.props.aux.crates { let aux_type = self.build_auxiliary(&path, &aux_dir, None); - add_extern(rustc, name, path, aux_type); + add_extern(rustc, extern_modifiers.as_deref(), name, path, aux_type); } for proc_macro in &self.props.aux.proc_macros { self.build_auxiliary(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); + add_extern( + rustc, + None, // `extern_modifiers` + &crate_name, + proc_macro, + AuxType::ProcMacro, + ); } // Build any `//@ aux-codegen-backend`, and pass the resulting library diff --git a/src/tools/enzyme b/src/tools/enzyme index 09f4820b78e2..eb72baf793a8 160000 --- a/src/tools/enzyme +++ b/src/tools/enzyme @@ -1 +1 @@ -Subproject commit 09f4820b78e2d71b85a3278bbb41dc3a012e84dd +Subproject commit eb72baf793a8385acb7dce614c81ba45c5be20fb diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 90ba52120ee8..fa15ee59b241 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -d10ac47c20152feb5e99b1c35a2e6830f77c66dc +5a07626f4b8802d2baa260b76b2e1d0714674efe diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index fc9971641088..6c7f3470600b 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -55,7 +55,7 @@ impl<'tcx> MiriMachine<'tcx> { Os::Linux => { Self::null_ptr_extern_statics( ecx, - &["__cxa_thread_atexit_impl", "__clock_gettime64"], + &["__cxa_thread_atexit_impl", "__clock_gettime64", "__clock_nanosleep_time64"], )?; Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx"])?; } diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index 48b0d83e8d82..c0820e4a6854 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -10,13 +10,13 @@ //! themselves having support libraries. All data over the TCP sockets is in a //! basically custom format suiting our needs. -#[cfg(all(not(windows), not(target_os = "motor")))] +#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))] use std::fs::Permissions; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::net::{SocketAddr, TcpListener, TcpStream}; -#[cfg(all(not(windows), not(target_os = "motor")))] +#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))] use std::os::unix::prelude::*; use std::path::{Path, PathBuf}; use std::process::{Command, ExitStatus, Stdio}; @@ -325,7 +325,7 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf ])); } -#[cfg(all(not(windows), not(target_os = "motor")))] +#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))] fn get_status_code(status: &ExitStatus) -> (u8, i32) { match status.code() { Some(n) => (0, n), @@ -333,7 +333,7 @@ fn get_status_code(status: &ExitStatus) -> (u8, i32) { } } -#[cfg(any(windows, target_os = "motor"))] +#[cfg(any(windows, target_os = "motor", target_os = "uefi"))] fn get_status_code(status: &ExitStatus) -> (u8, i32) { (0, status.code().unwrap()) } @@ -359,11 +359,11 @@ fn recv(dir: &Path, io: &mut B) -> PathBuf { dst } -#[cfg(all(not(windows), not(target_os = "motor")))] +#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))] fn set_permissions(path: &Path) { t!(fs::set_permissions(&path, Permissions::from_mode(0o755))); } -#[cfg(any(windows, target_os = "motor"))] +#[cfg(any(windows, target_os = "motor", target_os = "uefi"))] fn set_permissions(_path: &Path) {} fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex) { diff --git a/src/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs index 26bf6c5326f5..495f12c8f5d5 100644 --- a/src/tools/rustfmt/src/parse/macros/cfg_if.rs +++ b/src/tools/rustfmt/src/parse/macros/cfg_if.rs @@ -3,7 +3,7 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::ast; use rustc_ast::token::TokenKind; use rustc_parse::exp; -use rustc_parse::parser::ForceCollect; +use rustc_parse::parser::{AllowConstBlockItems, ForceCollect}; use rustc_span::symbol::kw; use crate::parse::macros::build_stream_parser; @@ -61,7 +61,7 @@ fn parse_cfg_if_inner<'a>( } while parser.token != TokenKind::CloseBrace && parser.token.kind != TokenKind::Eof { - let item = match parser.parse_item(ForceCollect::No) { + let item = match parser.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) { Ok(Some(item_ptr)) => *item_ptr, Ok(None) => continue, Err(err) => { diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index c063990dfa0b..552300b1b828 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -2,7 +2,7 @@ use rustc_ast::ast; use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_parse::MACRO_ARGUMENTS; -use rustc_parse::parser::{ForceCollect, Parser, Recovery}; +use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser, Recovery}; use rustc_session::parse::ParseSess; use rustc_span::symbol; @@ -67,7 +67,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { parse_macro_arg!( Item, NonterminalKind::Item, - |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No), + |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No, AllowConstBlockItems::Yes), |x: Option>| x ); diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c521b497a2d9..8abcba121e58 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -7,7 +7,9 @@ use rustc_span::{BytePos, Ident, Pos, Span, symbol}; use tracing::debug; use crate::attr::*; -use crate::comment::{CodeCharKind, CommentCodeSlices, contains_comment, rewrite_comment}; +use crate::comment::{ + CodeCharKind, CommentCodeSlices, contains_comment, recover_comment_removed, rewrite_comment, +}; use crate::config::{BraceStyle, Config, MacroSelector, StyleEdition}; use crate::coverage::transform_missing_snippet; use crate::items::{ @@ -533,6 +535,28 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } + ast::ItemKind::ConstBlock(ast::ConstBlockItem { + id: _, + span, + ref block, + }) => { + let context = &self.get_context(); + let offset = self.block_indent; + self.push_rewrite( + item.span, + block + .rewrite( + context, + Shape::legacy( + context.budget(offset.block_indent), + offset.block_only(), + ), + ) + .map(|rhs| { + recover_comment_removed(format!("const {rhs}"), span, context) + }), + ); + } ast::ItemKind::Fn(ref fn_kind) => { let ast::Fn { defaultness, diff --git a/src/tools/rustfmt/tests/source/const-block-items.rs b/src/tools/rustfmt/tests/source/const-block-items.rs new file mode 100644 index 000000000000..f30f0fe256a5 --- /dev/null +++ b/src/tools/rustfmt/tests/source/const-block-items.rs @@ -0,0 +1,24 @@ +#![feature(const_block_items)] + + const { + + + assert!(true) + } + + #[cfg(false)] const { assert!(false) } + + + #[cfg(false)] +// foo + const + + { + // bar + assert!(false) + // baz + } // 123 + + + #[expect(unused)] +pub const { let a = 1; assert!(true); } diff --git a/src/tools/rustfmt/tests/target/const-block-items.rs b/src/tools/rustfmt/tests/target/const-block-items.rs new file mode 100644 index 000000000000..bbf6dbf481c7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/const-block-items.rs @@ -0,0 +1,20 @@ +#![feature(const_block_items)] + +const { assert!(true) } + +#[cfg(false)] +const { assert!(false) } + +#[cfg(false)] +// foo +const { + // bar + assert!(false) + // baz +} // 123 + +#[expect(unused)] +const { + let a = 1; + assert!(true); +} diff --git a/tests/assembly-llvm/cstring-merging.rs b/tests/assembly-llvm/cstring-merging.rs index 03688e0068b7..9c1af4ebb4c0 100644 --- a/tests/assembly-llvm/cstring-merging.rs +++ b/tests/assembly-llvm/cstring-merging.rs @@ -1,5 +1,6 @@ // MIPS assembler uses the label prefix `$anon.` for local anonymous variables // other architectures (including ARM and x86-64) use the prefix `.Lanon.` +// Hexagon uses `.string` instead of `.asciz` for null-terminated strings //@ only-linux //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0 @@ -9,13 +10,13 @@ use std::ffi::CStr; // CHECK: .section .rodata.str1.{{[12]}},"aMS" // CHECK: {{(\.L|\$)}}anon.{{.+}}: -// CHECK-NEXT: .asciz "foo" +// CHECK-NEXT: .{{asciz|string}} "foo" #[unsafe(no_mangle)] static CSTR: &[u8; 4] = b"foo\0"; // CHECK-NOT: .section // CHECK: {{(\.L|\$)}}anon.{{.+}}: -// CHECK-NEXT: .asciz "bar" +// CHECK-NEXT: .{{asciz|string}} "bar" #[unsafe(no_mangle)] pub fn cstr() -> &'static CStr { c"bar" @@ -23,7 +24,7 @@ pub fn cstr() -> &'static CStr { // CHECK-NOT: .section // CHECK: {{(\.L|\$)}}anon.{{.+}}: -// CHECK-NEXT: .asciz "baz" +// CHECK-NEXT: .{{asciz|string}} "baz" #[unsafe(no_mangle)] pub fn manual_cstr() -> &'static str { "baz\0" diff --git a/tests/assembly-llvm/large_data_threshold.rs b/tests/assembly-llvm/large_data_threshold.rs new file mode 100644 index 000000000000..f3b37eb7f83d --- /dev/null +++ b/tests/assembly-llvm/large_data_threshold.rs @@ -0,0 +1,73 @@ +// Test for -Z large_data_threshold=... +// This test verifies that with the medium code model, data above the threshold +// is placed in large data sections (.ldata, .lbss, .lrodata). +//@ assembly-output: emit-asm +//@ compile-flags: -Ccode-model=medium -Zlarge-data-threshold=4 +//@ compile-flags: --target=x86_64-unknown-linux-gnu +//@ needs-llvm-components: x86 + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "drop_in_place"] +fn drop_in_place(_: *mut T) {} + +#[used] +#[no_mangle] +// U is below the threshold, should be in .data +static mut U: u16 = 123; + +#[used] +#[no_mangle] +// V is below the threshold, should be in .bss +static mut V: u16 = 0; + +#[used] +#[no_mangle] +// W is at the threshold, should be in .data +static mut W: u32 = 123; + +#[used] +#[no_mangle] +// X is at the threshold, should be in .bss +static mut X: u32 = 0; + +#[used] +#[no_mangle] +// Y is over the threshold, should be in .ldata +static mut Y: u64 = 123; + +#[used] +#[no_mangle] +// Z is over the threshold, should be in .lbss +static mut Z: u64 = 0; + +// CHECK: .section .data.U, +// CHECK-NOT: .section +// CHECK: U: +// CHECK: .section .bss.V, +// CHECK-NOT: .section +// CHECK: V: +// CHECK: .section .data.W, +// CHECK-NOT: .section +// CHECK: W: +// CHECK: .section .bss.X, +// CHECK-NOT: .section +// CHECK: X: +// CHECK: .section .ldata.Y, +// CHECK-NOT: .section +// CHECK: Y: +// CHECK: .section .lbss.Z, +// CHECK-NOT: .section +// CHECK: Z: diff --git a/tests/assembly-llvm/slice-is-ascii.rs b/tests/assembly-llvm/slice-is-ascii.rs new file mode 100644 index 000000000000..d01b321bf460 --- /dev/null +++ b/tests/assembly-llvm/slice-is-ascii.rs @@ -0,0 +1,32 @@ +//@ revisions: X86_64 LA64 +//@ assembly-output: emit-asm +//@ compile-flags: -C opt-level=3 +// +//@ [X86_64] only-x86_64 +//@ [X86_64] compile-flags: -C target-cpu=znver4 +//@ [X86_64] compile-flags: -C llvm-args=-x86-asm-syntax=intel +// +//@ [LA64] only-loongarch64 + +#![crate_type = "lib"] + +/// Verify `is_ascii` generates efficient code on different architectures: +/// +/// - x86_64: Must NOT use `kshiftrd`/`kshiftrq` (broken AVX-512 auto-vectorization). +/// The fix uses explicit SSE2 intrinsics (`pmovmskb`/`vpmovmskb`). +/// See: https://github.com/llvm/llvm-project/issues/176906 +/// +/// - loongarch64: Should use `vmskltz.b` instruction for the fast-path. +/// This architecture still relies on LLVM auto-vectorization. + +// X86_64-LABEL: test_is_ascii +// X86_64-NOT: kshiftrd +// X86_64-NOT: kshiftrq + +// LA64-LABEL: test_is_ascii +// LA64: vmskltz.b + +#[no_mangle] +pub fn test_is_ascii(s: &[u8]) -> bool { + s.is_ascii() +} diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 0eced9df3c46..0d5cd796aa48 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -139,6 +139,12 @@ //@ revisions: armv5te_unknown_linux_uclibceabi //@ [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi //@ [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm +//@ revisions: armv6_none_eabi +//@ [armv6_none_eabi] compile-flags: --target armv6-none-eabi +//@ [armv6_none_eabi] needs-llvm-components: arm +//@ revisions: armv6_none_eabihf +//@ [armv6_none_eabihf] compile-flags: --target armv6-none-eabihf +//@ [armv6_none_eabihf] needs-llvm-components: arm //@ revisions: armv6_unknown_freebsd //@ [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd //@ [armv6_unknown_freebsd] needs-llvm-components: arm @@ -559,6 +565,24 @@ //@ revisions: thumbv5te_none_eabi //@ [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi //@ [thumbv5te_none_eabi] needs-llvm-components: arm +//@ revisions: thumbv6_none_eabi +//@ [thumbv6_none_eabi] compile-flags: --target thumbv6-none-eabi +//@ [thumbv6_none_eabi] needs-llvm-components: arm +//@ revisions: thumbv7a_none_eabi +//@ [thumbv7a_none_eabi] compile-flags: --target thumbv7a-none-eabi +//@ [thumbv7a_none_eabi] needs-llvm-components: arm +//@ revisions: thumbv7a_none_eabihf +//@ [thumbv7a_none_eabihf] compile-flags: --target thumbv7a-none-eabihf +//@ [thumbv7a_none_eabihf] needs-llvm-components: arm +//@ revisions: thumbv7r_none_eabi +//@ [thumbv7r_none_eabi] compile-flags: --target thumbv7r-none-eabi +//@ [thumbv7r_none_eabi] needs-llvm-components: arm +//@ revisions: thumbv7r_none_eabihf +//@ [thumbv7r_none_eabihf] compile-flags: --target thumbv7r-none-eabihf +//@ [thumbv7r_none_eabihf] needs-llvm-components: arm +//@ revisions: thumbv8r_none_eabihf +//@ [thumbv8r_none_eabihf] compile-flags: --target thumbv8r-none-eabihf +//@ [thumbv8r_none_eabihf] needs-llvm-components: arm //@ revisions: thumbv6m_none_eabi //@ [thumbv6m_none_eabi] compile-flags: --target thumbv6m-none-eabi //@ [thumbv6m_none_eabi] needs-llvm-components: arm diff --git a/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs b/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs index 1da7de535f75..a4e5c885a139 100644 --- a/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs @@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN) -> Option Vec { - // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @{{.*}}__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) + // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @{{.*}}__rust_alloc(i64 noundef {{(range\(i64 0, -9223372036854775808\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234, let n = 1234_usize; diff --git a/tests/codegen-llvm/simd/splat.rs b/tests/codegen-llvm/simd/splat.rs new file mode 100644 index 000000000000..7a24162321bd --- /dev/null +++ b/tests/codegen-llvm/simd/splat.rs @@ -0,0 +1,33 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] +#![no_std] +#![feature(repr_simd, core_intrinsics)] +use core::intrinsics::simd::simd_splat; + +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + +// Test that `simd_splat` produces the canonical LLVM splat sequence. + +#[no_mangle] +unsafe fn int(x: u16) -> u16x2 { + // CHECK-LABEL: int + // CHECK: start: + // CHECK-NEXT: %0 = insertelement <2 x i16> poison, i16 %x, i64 0 + // CHECK-NEXT: %1 = shufflevector <2 x i16> %0, <2 x i16> poison, <2 x i32> zeroinitializer + // CHECK-NEXT: store + // CHECK-NEXT: ret + simd_splat(x) +} + +#[no_mangle] +unsafe fn float(x: f32) -> f32x4 { + // CHECK-LABEL: float + // CHECK: start: + // CHECK-NEXT: %0 = insertelement <4 x float> poison, float %x, i64 0 + // CHECK-NEXT: %1 = shufflevector <4 x float> %0, <4 x float> poison, <4 x i32> zeroinitializer + // CHECK-NEXT: store + // CHECK-NEXT: ret + simd_splat(x) +} diff --git a/tests/codegen-llvm/slice-is-ascii.rs b/tests/codegen-llvm/slice-is-ascii.rs deleted file mode 100644 index 67537c871a0a..000000000000 --- a/tests/codegen-llvm/slice-is-ascii.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ only-x86_64 -//@ compile-flags: -C opt-level=3 -C target-cpu=x86-64 -#![crate_type = "lib"] - -/// Check that the fast-path of `is_ascii` uses a `pmovmskb` instruction. -/// Platforms lacking an equivalent instruction use other techniques for -/// optimizing `is_ascii`. -// CHECK-LABEL: @is_ascii_autovectorized -#[no_mangle] -pub fn is_ascii_autovectorized(s: &[u8]) -> bool { - // CHECK: load <32 x i8> - // CHECK-NEXT: icmp slt <32 x i8> - // CHECK-NEXT: bitcast <32 x i1> - // CHECK-NEXT: icmp eq i32 - s.is_ascii() -} diff --git a/tests/run-make/reproducible-build/rmake.rs b/tests/run-make/reproducible-build/rmake.rs index 93fc30de07d7..993c2c8092a6 100644 --- a/tests/run-make/reproducible-build/rmake.rs +++ b/tests/run-make/reproducible-build/rmake.rs @@ -199,13 +199,9 @@ fn diff_dir_test(crate_type: CrateType, remap_type: RemapType) { .arg(format!("--remap-path-prefix={}=/b", base_dir.join("test").display())); } RemapType::Cwd { is_empty } => { - // FIXME(Oneirical): Building with crate type set to `bin` AND having -Cdebuginfo=2 - // (or `-g`, the shorthand form) enabled will cause reproducibility failures - // for multiple platforms. - // See https://github.com/rust-lang/rust/issues/89911 // FIXME(#129117): Windows rlib + `-Cdebuginfo=2` + `-Z remap-cwd-prefix=.` seems // to be unreproducible. - if !matches!(crate_type, CrateType::Bin) && !is_windows() { + if !is_windows() { compiler1.arg("-Cdebuginfo=2"); compiler2.arg("-Cdebuginfo=2"); } diff --git a/tests/rustdoc-gui/skip-navigation.goml b/tests/rustdoc-gui/skip-navigation.goml new file mode 100644 index 000000000000..50cb2d38b3e0 --- /dev/null +++ b/tests/rustdoc-gui/skip-navigation.goml @@ -0,0 +1,19 @@ +// This test ensures that the "Skip to main content" link works correctly +// for keyboard navigation (WCAG 2.4.1 compliance). +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" + +// The skip link should be hidden initially (positioned off-screen above viewport) +store-position: (".skip-main-content", {"y": y_before}) +store-size: (".skip-main-content", {"height": height_before}) +assert: |y_before| + |height_before| < 0 + +// The skip link should be the first focusable element when pressing Tab +press-key: "Tab" +wait-for: ".skip-main-content:focus" + +// When focused, the link should be visible (top: 0px) +assert-css: (".skip-main-content:focus", {"top": "0px"}) + +// Pressing Enter on the skip link should move focus to main content +press-key: "Enter" +wait-for: "#main-content:focus" diff --git a/tests/ui/issues/issue-16819.rs b/tests/ui/cfg/struct-field-empty.rs similarity index 70% rename from tests/ui/issues/issue-16819.rs rename to tests/ui/cfg/struct-field-empty.rs index 2805c82acfb2..eed69a0c03f0 100644 --- a/tests/ui/issues/issue-16819.rs +++ b/tests/ui/cfg/struct-field-empty.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass #![allow(unused_variables)] // `#[cfg]` on struct field permits empty unusable struct diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 6125e66320c8..89123c910082 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -131,7 +131,21 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `high-registers` `high-word` `hvx` +`hvx-ieee-fp` `hvx-length128b` +`hvx-length64b` +`hvx-qfloat` +`hvxv60` +`hvxv62` +`hvxv65` +`hvxv66` +`hvxv67` +`hvxv68` +`hvxv69` +`hvxv71` +`hvxv73` +`hvxv75` +`hvxv79` `hwdiv` `i8mm` `isa-68000` @@ -431,6 +445,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zksed` `zksh` `zkt` +`zreg` `ztso` `zvbb` `zvbc` diff --git a/tests/ui/consts/const-block-items/assert-fail.rs b/tests/ui/consts/const-block-items/assert-fail.rs new file mode 100644 index 000000000000..a7e3478666ef --- /dev/null +++ b/tests/ui/consts/const-block-items/assert-fail.rs @@ -0,0 +1,10 @@ +//@ check-fail + +#![feature(const_block_items)] + +const { assert!(false) } +//~^ ERROR: evaluation panicked: assertion failed: false [E0080] +const { assert!(2 + 2 == 5) } +//~^ ERROR: evaluation panicked: assertion failed: 2 + 2 == 5 [E0080] + +fn main() {} diff --git a/tests/ui/consts/const-block-items/assert-fail.stderr b/tests/ui/consts/const-block-items/assert-fail.stderr new file mode 100644 index 000000000000..b1444dc5e0d0 --- /dev/null +++ b/tests/ui/consts/const-block-items/assert-fail.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation panicked: assertion failed: false + --> $DIR/assert-fail.rs:5:9 + | +LL | const { assert!(false) } + | ^^^^^^^^^^^^^^ evaluation of `_` failed here + +error[E0080]: evaluation panicked: assertion failed: 2 + 2 == 5 + --> $DIR/assert-fail.rs:7:9 + | +LL | const { assert!(2 + 2 == 5) } + | ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-block-items/assert-pass.rs b/tests/ui/consts/const-block-items/assert-pass.rs new file mode 100644 index 000000000000..c409cc5b91f7 --- /dev/null +++ b/tests/ui/consts/const-block-items/assert-pass.rs @@ -0,0 +1,7 @@ +//@ check-pass +#![feature(const_block_items)] + +const { assert!(true) } +const { assert!(2 + 2 == 4) } + +fn main() {} diff --git a/tests/ui/consts/const-block-items/hir.rs b/tests/ui/consts/const-block-items/hir.rs new file mode 100644 index 000000000000..1d9c5e91b57e --- /dev/null +++ b/tests/ui/consts/const-block-items/hir.rs @@ -0,0 +1,10 @@ +//@ build-pass +//@ compile-flags: -Zunpretty=hir + +#![feature(const_block_items)] + +const { + // foo +} + +fn main() { } diff --git a/tests/ui/consts/const-block-items/hir.stdout b/tests/ui/consts/const-block-items/hir.stdout new file mode 100644 index 000000000000..e2df04e98d4e --- /dev/null +++ b/tests/ui/consts/const-block-items/hir.stdout @@ -0,0 +1,14 @@ +//@ build-pass +//@ compile-flags: -Zunpretty=hir + +#![feature(const_block_items)] +extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; + +const _: () = + { + // foo + }; + +fn main() { } diff --git a/tests/ui/consts/const-block-items/typecheck.rs b/tests/ui/consts/const-block-items/typecheck.rs new file mode 100644 index 000000000000..2e521cbfda05 --- /dev/null +++ b/tests/ui/consts/const-block-items/typecheck.rs @@ -0,0 +1,20 @@ +//@ check-fail + +#![feature(const_block_items)] + +const { + assert!(true); + 2 + 2 //~ ERROR: mismatched types [E0308] +} + + +const fn id(t: T) -> T { + t +} + +const { id(2) } +//~^ ERROR: mismatched types [E0308] +const { id(()) } + + +fn main() {} diff --git a/tests/ui/consts/const-block-items/typecheck.stderr b/tests/ui/consts/const-block-items/typecheck.stderr new file mode 100644 index 000000000000..93d1eb1bc9e4 --- /dev/null +++ b/tests/ui/consts/const-block-items/typecheck.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/typecheck.rs:7:5 + | +LL | 2 + 2 + | ^^^^^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/typecheck.rs:15:12 + | +LL | const { id(2) } + | -- ^ expected `()`, found integer + | | + | arguments to this function are incorrect + | +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/typecheck.rs:15:9 + | +LL | const { id(2) } + | ^^^-^ + | | + | this argument influences the return type of `id` +note: function defined here + --> $DIR/typecheck.rs:11:10 + | +LL | const fn id(t: T) -> T { + | ^^ ---- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-block-item-macro-codegen.rs b/tests/ui/consts/const-item-with-block-body/macro-codegen.rs similarity index 100% rename from tests/ui/consts/const-block-item-macro-codegen.rs rename to tests/ui/consts/const-item-with-block-body/macro-codegen.rs diff --git a/tests/ui/consts/const-block-item.rs b/tests/ui/consts/const-item-with-block-body/static.rs similarity index 100% rename from tests/ui/consts/const-block-item.rs rename to tests/ui/consts/const-item-with-block-body/static.rs diff --git a/tests/ui/consts/const-block-item.stderr b/tests/ui/consts/const-item-with-block-body/static.stderr similarity index 84% rename from tests/ui/consts/const-block-item.stderr rename to tests/ui/consts/const-item-with-block-body/static.stderr index b325976a60b6..feaabb92803f 100644 --- a/tests/ui/consts/const-block-item.stderr +++ b/tests/ui/consts/const-item-with-block-body/static.stderr @@ -1,5 +1,5 @@ warning: trait `Value` is never used - --> $DIR/const-block-item.rs:5:15 + --> $DIR/static.rs:5:15 | LL | pub trait Value { | ^^^^^ diff --git a/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs b/tests/ui/expr/if/expr-stack-overflow.rs similarity index 99% rename from tests/ui/issues/issue-74564-if-expr-stack-overflow.rs rename to tests/ui/expr/if/expr-stack-overflow.rs index c0ffed27e6fb..6fa09345c827 100644 --- a/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs +++ b/tests/ui/expr/if/expr-stack-overflow.rs @@ -1,3 +1,4 @@ +//! regression test for //@ build-pass // ignore-tidy-filelength #![crate_type = "rlib"] diff --git a/tests/ui/feature-gates/feature-gate-const-block-items.rs b/tests/ui/feature-gates/feature-gate-const-block-items.rs new file mode 100644 index 000000000000..5523633197bb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const-block-items.rs @@ -0,0 +1,7 @@ +//@ check-fail + +const { //~ ERROR: const block items are experimental + assert!(true) +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-const-block-items.stderr b/tests/ui/feature-gates/feature-gate-const-block-items.stderr new file mode 100644 index 000000000000..60a724f90712 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const-block-items.stderr @@ -0,0 +1,13 @@ +error[E0658]: const block items are experimental + --> $DIR/feature-gate-const-block-items.rs:3:1 + | +LL | const { + | ^^^^^ + | + = note: see issue #149226 for more information + = help: add `#![feature(const_block_items)]` 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/half-open-range-patterns/half-open-range-pats-semantics.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs index a89b22925128..df1b9e164c76 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs @@ -1,9 +1,11 @@ //@ run-pass +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f128) // Test half-open range patterns against their expression equivalents // via `.contains(...)` and make sure the dynamic semantics match. #![allow(unreachable_patterns)] +#![feature(cfg_target_has_reliable_f16_f128)] #![feature(f128)] #![feature(f16)] @@ -42,8 +44,7 @@ fn range_to_inclusive() { assert!(!yes!('b', ..='a')); // f16; `..=X` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f16)] { assert!(yes!(f16::NEG_INFINITY, ..=f16::NEG_INFINITY)); assert!(yes!(f16::NEG_INFINITY, ..=1.0f16)); @@ -64,8 +65,7 @@ fn range_to_inclusive() { assert!(!yes!(1.6f64, ..=-1.5f64)); // f128; `..=X` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f128)] { assert!(yes!(f128::NEG_INFINITY, ..=f128::NEG_INFINITY)); assert!(yes!(f128::NEG_INFINITY, ..=1.0f128)); @@ -106,8 +106,7 @@ fn range_to() { assert!(!yes!('b', ..'a')); // f16; `..X` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f16)] { assert!(yes!(f16::NEG_INFINITY, ..1.0f16)); assert!(!yes!(1.5f16, ..1.5f16)); @@ -131,8 +130,7 @@ fn range_to() { assert!(!yes!(1.6f64, ..1.5f64)); // f128; `..X` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f128)] { assert!(yes!(f128::NEG_INFINITY, ..1.0f128)); assert!(!yes!(1.5f128, ..1.5f128)); @@ -174,8 +172,7 @@ fn range_from() { assert!(yes!(core::char::MAX, core::char::MAX..)); // f16; `X..` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f16)] { assert!(yes!(f16::NEG_INFINITY, f16::NEG_INFINITY..)); assert!(yes!(f16::INFINITY, f16::NEG_INFINITY..)); @@ -208,8 +205,7 @@ fn range_from() { assert!(yes!(f64::INFINITY, f64::INFINITY..)); // f128; `X..` - // FIXME(f16_f128): remove gate when ABI issues are resolved - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f128)] { assert!(yes!(f128::NEG_INFINITY, f128::NEG_INFINITY..)); assert!(yes!(f128::INFINITY, f128::NEG_INFINITY..)); diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/impl-trait/impl-trait-in-generic-param.rs similarity index 87% rename from tests/ui/issues/issue-47715.rs rename to tests/ui/impl-trait/impl-trait-in-generic-param.rs index bf2b03351b29..4a6a76e4f2d1 100644 --- a/tests/ui/issues/issue-47715.rs +++ b/tests/ui/impl-trait/impl-trait-in-generic-param.rs @@ -1,3 +1,5 @@ +//! regression test for + trait Foo {} trait Bar {} diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/impl-trait/impl-trait-in-generic-param.stderr similarity index 85% rename from tests/ui/issues/issue-47715.stderr rename to tests/ui/impl-trait/impl-trait-in-generic-param.stderr index 8ed9ff439521..806a3cb22754 100644 --- a/tests/ui/issues/issue-47715.stderr +++ b/tests/ui/impl-trait/impl-trait-in-generic-param.stderr @@ -1,5 +1,5 @@ error[E0562]: `impl Trait` is not allowed in generics - --> $DIR/issue-47715.rs:9:37 + --> $DIR/impl-trait-in-generic-param.rs:11:37 | LL | struct Container> { | ^^^^^^^^ @@ -7,7 +7,7 @@ LL | struct Container> { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generics - --> $DIR/issue-47715.rs:14:30 + --> $DIR/impl-trait-in-generic-param.rs:16:30 | LL | enum Enum> { | ^^^^^^^^ @@ -15,7 +15,7 @@ LL | enum Enum> { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generics - --> $DIR/issue-47715.rs:19:32 + --> $DIR/impl-trait-in-generic-param.rs:21:32 | LL | union Union + Copy> { | ^^^^^^^^ @@ -23,7 +23,7 @@ LL | union Union + Copy> { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generics - --> $DIR/issue-47715.rs:24:30 + --> $DIR/impl-trait-in-generic-param.rs:26:30 | LL | type Type> = T; | ^^^^^^^^ diff --git a/tests/ui/issues/auxiliary/issue-11529.rs b/tests/ui/issues/auxiliary/issue-11529.rs deleted file mode 100644 index dd3ef4387057..000000000000 --- a/tests/ui/issues/auxiliary/issue-11529.rs +++ /dev/null @@ -1 +0,0 @@ -pub struct A<'a>(pub &'a isize); diff --git a/tests/ui/issues/issue-11529.rs b/tests/ui/issues/issue-11529.rs deleted file mode 100644 index 73940c22be4c..000000000000 --- a/tests/ui/issues/issue-11529.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -//@ aux-build:issue-11529.rs - - -extern crate issue_11529 as a; - -fn main() { - let one = 1; - let _a = a::A(&one); -} diff --git a/tests/ui/issues/issue-49934-errors.rs b/tests/ui/issues/issue-49934-errors.rs deleted file mode 100644 index dd14bac5e3a9..000000000000 --- a/tests/ui/issues/issue-49934-errors.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn foo<#[derive(Debug)] T>() { //~ ERROR expected non-macro attribute, found attribute macro - match 0 { - #[derive(Debug)] //~ ERROR expected non-macro attribute, found attribute macro - _ => (), - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-49934-errors.stderr b/tests/ui/issues/issue-49934-errors.stderr deleted file mode 100644 index 8c4c54170a10..000000000000 --- a/tests/ui/issues/issue-49934-errors.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: expected non-macro attribute, found attribute macro `derive` - --> $DIR/issue-49934-errors.rs:1:10 - | -LL | fn foo<#[derive(Debug)] T>() { - | ^^^^^^ not a non-macro attribute - -error: expected non-macro attribute, found attribute macro `derive` - --> $DIR/issue-49934-errors.rs:3:11 - | -LL | #[derive(Debug)] - | ^^^^^^ not a non-macro attribute - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lifetimes/auxiliary/lifetime-inference-across-mods.rs b/tests/ui/lifetimes/auxiliary/lifetime-inference-across-mods.rs new file mode 100644 index 000000000000..efc2798d916a --- /dev/null +++ b/tests/ui/lifetimes/auxiliary/lifetime-inference-across-mods.rs @@ -0,0 +1,2 @@ +//! auxiliary crate for +pub struct A<'a>(pub &'a isize); diff --git a/tests/ui/issues/issue-17068.rs b/tests/ui/lifetimes/for-loop-region-links.rs similarity index 77% rename from tests/ui/issues/issue-17068.rs rename to tests/ui/lifetimes/for-loop-region-links.rs index af565da3366b..0c86c211a00b 100644 --- a/tests/ui/issues/issue-17068.rs +++ b/tests/ui/lifetimes/for-loop-region-links.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass // Test that regionck creates the right region links in the pattern // binding of a for loop diff --git a/tests/ui/lifetimes/lifetime-inference-across-mods.rs b/tests/ui/lifetimes/lifetime-inference-across-mods.rs new file mode 100644 index 000000000000..224d2193d08c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-inference-across-mods.rs @@ -0,0 +1,11 @@ +//! regression test for +//@ run-pass +//@ aux-build:lifetime-inference-across-mods.rs + + +extern crate lifetime_inference_across_mods as a; + +fn main() { + let one = 1; + let _a = a::A(&one); +} diff --git a/tests/ui/issues/issue-11681.rs b/tests/ui/lifetimes/unit-struct-as-rvalue.rs similarity index 84% rename from tests/ui/issues/issue-11681.rs rename to tests/ui/lifetimes/unit-struct-as-rvalue.rs index 6d8810d80520..10c1d2517064 100644 --- a/tests/ui/issues/issue-11681.rs +++ b/tests/ui/lifetimes/unit-struct-as-rvalue.rs @@ -1,3 +1,4 @@ +//! regression test for // This tests verifies that unary structs and enum variants // are treated as rvalues and their lifetime is not bounded to // the static scope. diff --git a/tests/ui/issues/issue-11681.stderr b/tests/ui/lifetimes/unit-struct-as-rvalue.stderr similarity index 89% rename from tests/ui/issues/issue-11681.stderr rename to tests/ui/lifetimes/unit-struct-as-rvalue.stderr index 4f23ba86eecc..afb80331f356 100644 --- a/tests/ui/issues/issue-11681.stderr +++ b/tests/ui/lifetimes/unit-struct-as-rvalue.stderr @@ -1,5 +1,5 @@ error[E0515]: cannot return value referencing temporary value - --> $DIR/issue-11681.rs:13:10 + --> $DIR/unit-struct-as-rvalue.rs:14:10 | LL | let testValue = &Test; | ---- temporary value created here diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index fa06da5cbfbc..0367b8c2d023 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] #![feature(auto_traits)] #![feature(box_patterns)] +#![feature(const_block_items)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] @@ -369,6 +370,9 @@ fn test_item() { c1!(item, [ pub const S: () = {}; ], "pub const S: () = {};"); c1!(item, [ const S: (); ], "const S: ();"); + // ItemKind::ConstBlock + c1!(item, [ const {} ], "const {}"); + // ItemKind::Fn c1!(item, [ pub default const async unsafe extern "C" fn f() {} ], diff --git a/tests/ui/match/match-float.rs b/tests/ui/match/match-float.rs index 70283eaeec52..279bb5927ac4 100644 --- a/tests/ui/match/match-float.rs +++ b/tests/ui/match/match-float.rs @@ -1,12 +1,12 @@ //@ run-pass +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f128) // Makes sure we use `==` (not bitwise) semantics for float comparison. +#![feature(cfg_target_has_reliable_f16_f128)] #![feature(f128)] #![feature(f16)] -// FIXME(f16_f128): remove gates when ABI issues are resolved - -#[cfg(all(target_arch = "aarch64", target_os = "linux"))] +#[cfg(target_has_reliable_f16)] fn check_f16() { const F1: f16 = 0.0; const F2: f16 = -0.0; @@ -34,7 +34,7 @@ fn check_f64() { assert!(matches!(F2, F1)); } -#[cfg(all(target_arch = "aarch64", target_os = "linux"))] +#[cfg(target_has_reliable_f128)] fn check_f128() { const F1: f128 = 0.0; const F2: f128 = -0.0; @@ -45,10 +45,10 @@ fn check_f128() { } fn main() { - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f16)] check_f16(); check_f32(); check_f64(); - #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + #[cfg(target_has_reliable_f128)] check_f128(); } diff --git a/tests/ui/issues/issue-17877.rs b/tests/ui/match/match-large-array.rs similarity index 76% rename from tests/ui/issues/issue-17877.rs rename to tests/ui/match/match-large-array.rs index 7df0fffa41c8..e72777c443c5 100644 --- a/tests/ui/issues/issue-17877.rs +++ b/tests/ui/match/match-large-array.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass fn main() { diff --git a/tests/ui/issues/issue-16648.rs b/tests/ui/match/match-tuple-slice.rs similarity index 75% rename from tests/ui/issues/issue-16648.rs rename to tests/ui/match/match-tuple-slice.rs index 7f3d3217bee0..aaebf4401d09 100644 --- a/tests/ui/issues/issue-16648.rs +++ b/tests/ui/match/match-tuple-slice.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass fn main() { let x: (isize, &[isize]) = (2, &[1, 2]); diff --git a/tests/ui/parser/const-block-items/attrs.rs b/tests/ui/parser/const-block-items/attrs.rs new file mode 100644 index 000000000000..eb7a0554ea9c --- /dev/null +++ b/tests/ui/parser/const-block-items/attrs.rs @@ -0,0 +1,14 @@ +//@ check-pass + +#![feature(const_block_items)] + +#[cfg(false)] +const { assert!(false) } + +#[expect(unused)] +const { + let a = 1; + assert!(true); +} + +fn main() {} diff --git a/tests/ui/parser/const-block-items/inner-attr.rs b/tests/ui/parser/const-block-items/inner-attr.rs new file mode 100644 index 000000000000..5da3191760d2 --- /dev/null +++ b/tests/ui/parser/const-block-items/inner-attr.rs @@ -0,0 +1,12 @@ +#![feature(const_block_items)] + +// ATTENTION: if we ever start accepting inner attributes here, make sure `rustfmt` can handle them. +// see: https://github.com/rust-lang/rustfmt/issues/6158 + +const { + #![expect(unused)] //~ ERROR: an inner attribute is not permitted in this context + let a = 1; + assert!(true); +} + +fn main() {} diff --git a/tests/ui/parser/const-block-items/inner-attr.stderr b/tests/ui/parser/const-block-items/inner-attr.stderr new file mode 100644 index 000000000000..e0a70566332c --- /dev/null +++ b/tests/ui/parser/const-block-items/inner-attr.stderr @@ -0,0 +1,13 @@ +error: an inner attribute is not permitted in this context + --> $DIR/inner-attr.rs:7:5 + | +LL | #![expect(unused)] + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/const-block-items/macro-item.rs b/tests/ui/parser/const-block-items/macro-item.rs new file mode 100644 index 000000000000..0c07bfc203d2 --- /dev/null +++ b/tests/ui/parser/const-block-items/macro-item.rs @@ -0,0 +1,12 @@ +//@ check-pass +#![feature(const_block_items)] + +macro_rules! foo { + ($item:item) => { + $item + }; +} + +foo!(const {}); + +fn main() {} diff --git a/tests/ui/parser/const-block-items/macro-stmt.rs b/tests/ui/parser/const-block-items/macro-stmt.rs new file mode 100644 index 000000000000..38632d2eec33 --- /dev/null +++ b/tests/ui/parser/const-block-items/macro-stmt.rs @@ -0,0 +1,14 @@ +//@ check-fail + +#![feature(const_block_items)] + +macro_rules! foo { + ($item:item) => { + $item + //~^ ERROR: expected expression, found `` + }; +} + +fn main() { + foo!(const {}); +} diff --git a/tests/ui/parser/const-block-items/macro-stmt.stderr b/tests/ui/parser/const-block-items/macro-stmt.stderr new file mode 100644 index 000000000000..dce90e5daa4c --- /dev/null +++ b/tests/ui/parser/const-block-items/macro-stmt.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `` + --> $DIR/macro-stmt.rs:7:9 + | +LL | $item + | ^^^^^ expected expression +... +LL | foo!(const {}); + | -------------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/const-block-items/mod-in-fn.rs b/tests/ui/parser/const-block-items/mod-in-fn.rs new file mode 100644 index 000000000000..ec98f95a8448 --- /dev/null +++ b/tests/ui/parser/const-block-items/mod-in-fn.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#![feature(const_block_items)] + +fn main() { + mod foo { + const { assert!(true) } + } +} diff --git a/tests/ui/parser/const-block-items/pub.rs b/tests/ui/parser/const-block-items/pub.rs new file mode 100644 index 000000000000..b76d30d9bda1 --- /dev/null +++ b/tests/ui/parser/const-block-items/pub.rs @@ -0,0 +1,10 @@ +#![feature(const_block_items)] + +//@ check-pass + +// FIXME(const_block_items): `pub`` is useless here +pub const { + assert!(true); +} + +fn main() { } diff --git a/tests/ui/parser/const-block-items/unsafe.rs b/tests/ui/parser/const-block-items/unsafe.rs new file mode 100644 index 000000000000..f53dfab7a0a2 --- /dev/null +++ b/tests/ui/parser/const-block-items/unsafe.rs @@ -0,0 +1,10 @@ +#![feature(const_block_items)] + +const unsafe fn foo() -> bool { + true +} + +const unsafe { assert!(foo()) } +//~^ ERROR: expected one of `extern` or `fn`, found `{` + +fn main() { } diff --git a/tests/ui/parser/const-block-items/unsafe.stderr b/tests/ui/parser/const-block-items/unsafe.stderr new file mode 100644 index 000000000000..0d38af838b3e --- /dev/null +++ b/tests/ui/parser/const-block-items/unsafe.stderr @@ -0,0 +1,8 @@ +error: expected one of `extern` or `fn`, found `{` + --> $DIR/unsafe.rs:7:14 + | +LL | const unsafe { assert!(foo()) } + | ^ expected one of `extern` or `fn` + +error: aborting due to 1 previous error + diff --git a/tests/ui/pin-ergonomics/user-type-projection.rs b/tests/ui/pin-ergonomics/user-type-projection.rs new file mode 100644 index 000000000000..f482586b6ebc --- /dev/null +++ b/tests/ui/pin-ergonomics/user-type-projection.rs @@ -0,0 +1,19 @@ +#![crate_type = "rlib"] +#![feature(pin_ergonomics)] +#![expect(incomplete_features)] +//@ edition: 2024 +//@ check-pass + +// Test that we don't ICE when projecting user-type-annotations through a `&pin` pattern. +// +// Historically, this could occur when the code handling those projections did not know +// about `&pin` patterns, and incorrectly treated them as plain `&`/`&mut` patterns instead. + +struct Data { + x: u32 +} + +pub fn project_user_type_through_pin() -> u32 { + let &pin const Data { x }: &pin const Data = &pin const Data { x: 30 }; + x +} diff --git a/tests/ui/issues/issue-49934.rs b/tests/ui/proc-macro/derive-macro-invalid-placement.rs similarity index 75% rename from tests/ui/issues/issue-49934.rs rename to tests/ui/proc-macro/derive-macro-invalid-placement.rs index 119d84a06885..fd24bd7284a9 100644 --- a/tests/ui/issues/issue-49934.rs +++ b/tests/ui/proc-macro/derive-macro-invalid-placement.rs @@ -1,5 +1,14 @@ +//! regression test for + #![feature(stmt_expr_attributes)] +fn foo<#[derive(Debug)] T>() { //~ ERROR expected non-macro attribute, found attribute macro + match 0 { + #[derive(Debug)] //~ ERROR expected non-macro attribute, found attribute macro + _ => (), + } +} + fn main() { // fold_stmt (Item) #[allow(dead_code)] diff --git a/tests/ui/issues/issue-49934.stderr b/tests/ui/proc-macro/derive-macro-invalid-placement.stderr similarity index 66% rename from tests/ui/issues/issue-49934.stderr rename to tests/ui/proc-macro/derive-macro-invalid-placement.stderr index f2ff541bb992..48111f4d3a14 100644 --- a/tests/ui/issues/issue-49934.stderr +++ b/tests/ui/proc-macro/derive-macro-invalid-placement.stderr @@ -1,5 +1,17 @@ +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/derive-macro-invalid-placement.rs:5:10 + | +LL | fn foo<#[derive(Debug)] T>() { + | ^^^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/derive-macro-invalid-placement.rs:7:11 + | +LL | #[derive(Debug)] + | ^^^^^^ not a non-macro attribute + error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s - --> $DIR/issue-49934.rs:10:5 + --> $DIR/derive-macro-invalid-placement.rs:19:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ not applicable here @@ -7,7 +19,7 @@ LL | println!("Hello, world!"); | -------------------------- not a `struct`, `enum` or `union` error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s - --> $DIR/issue-49934.rs:14:5 + --> $DIR/derive-macro-invalid-placement.rs:23:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ not applicable here @@ -15,7 +27,7 @@ LL | "Hello, world!"; | ---------------- not a `struct`, `enum` or `union` error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s - --> $DIR/issue-49934.rs:18:5 + --> $DIR/derive-macro-invalid-placement.rs:27:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ not applicable here @@ -23,7 +35,7 @@ LL | let _ = "Hello, world!"; | ------------------------ not a `struct`, `enum` or `union` error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s - --> $DIR/issue-49934.rs:22:13 + --> $DIR/derive-macro-invalid-placement.rs:31:13 | LL | let _ = #[derive(Debug)] "Hello, world!"; | ^^^^^^^^^^^^^^^^ --------------- not a `struct`, `enum` or `union` @@ -31,13 +43,13 @@ LL | let _ = #[derive(Debug)] "Hello, world!"; | not applicable here error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s - --> $DIR/issue-49934.rs:27:9 + --> $DIR/derive-macro-invalid-placement.rs:36:9 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ not applicable here LL | "Hello, world!", | --------------- not a `struct`, `enum` or `union` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/simd/intrinsic/splat.rs b/tests/ui/simd/intrinsic/splat.rs new file mode 100644 index 000000000000..38260a124d44 --- /dev/null +++ b/tests/ui/simd/intrinsic/splat.rs @@ -0,0 +1,48 @@ +//@ run-pass +#![feature(repr_simd, core_intrinsics)] + +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + +use std::intrinsics::simd::simd_splat; + +fn main() { + unsafe { + let x: Simd = simd_splat(123u32); + let y: Simd = const { simd_splat(123u32) }; + assert_eq!(x.into_array(), [123; 1]); + assert_eq!(x.into_array(), y.into_array()); + + let x: u16x2 = simd_splat(42u16); + let y: u16x2 = const { simd_splat(42u16) }; + assert_eq!(x.into_array(), [42; 2]); + assert_eq!(x.into_array(), y.into_array()); + + let x: u128x4 = simd_splat(42u128); + let y: u128x4 = const { simd_splat(42u128) }; + assert_eq!(x.into_array(), [42; 4]); + assert_eq!(x.into_array(), y.into_array()); + + let x: i32x4 = simd_splat(-7i32); + let y: i32x4 = const { simd_splat(-7i32) }; + assert_eq!(x.into_array(), [-7; 4]); + assert_eq!(x.into_array(), y.into_array()); + + let x: f32x4 = simd_splat(42.0f32); + let y: f32x4 = const { simd_splat(42.0f32) }; + assert_eq!(x.into_array(), [42.0; 4]); + assert_eq!(x.into_array(), y.into_array()); + + let x: f64x2 = simd_splat(42.0f64); + let y: f64x2 = const { simd_splat(42.0f64) }; + assert_eq!(x.into_array(), [42.0; 2]); + assert_eq!(x.into_array(), y.into_array()); + + static ZERO: u8 = 0u8; + let x: Simd<*const u8, 2> = simd_splat(&raw const ZERO); + let y: Simd<*const u8, 2> = const { simd_splat(&raw const ZERO) }; + assert_eq!(x.into_array(), [&raw const ZERO; 2]); + assert_eq!(x.into_array(), y.into_array()); + } +} diff --git a/tests/ui/thir-print/str-patterns.stdout b/tests/ui/thir-print/str-patterns.stdout index 6941ab15130f..09212e7d68ae 100644 --- a/tests/ui/thir-print/str-patterns.stdout +++ b/tests/ui/thir-print/str-patterns.stdout @@ -10,6 +10,7 @@ Thir { span: $DIR/str-patterns.rs:11:9: 11:16 (#0), extra: None, kind: Deref { + pin: Not, subpattern: Pat { ty: str, span: $DIR/str-patterns.rs:11:9: 11:16 (#0), @@ -50,6 +51,7 @@ Thir { }, ), kind: Deref { + pin: Not, subpattern: Pat { ty: str, span: $DIR/str-patterns.rs:12:9: 12:17 (#0), diff --git a/tests/ui/issues/issue-18353.rs b/tests/ui/unsized/enum-struct-optimization.rs similarity index 75% rename from tests/ui/issues/issue-18353.rs rename to tests/ui/unsized/enum-struct-optimization.rs index 378caa9f3697..2e2bc64008a6 100644 --- a/tests/ui/issues/issue-18353.rs +++ b/tests/ui/unsized/enum-struct-optimization.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass #![allow(dead_code)] // Test that wrapping an unsized struct in an enum which gets optimised does