From: bors Date: Tue, 8 Dec 2020 01:15:26 +0000 (+0000) Subject: Auto merge of #79780 - camelid:use-summary_opts, r=GuillaumeGomez X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=d4aea0b7498fdb7dce496e42b10fb44e90cb1453;hp=2ee34a0923643f277775c874beb8990be4b1385c;p=rust.git Auto merge of #79780 - camelid:use-summary_opts, r=GuillaumeGomez Use `summary_opts()` in another spot I added `summary_opts()` before I cut the branch for #77686 (2 months ago!), so this "slipped through the cracks". --- diff --git a/Cargo.lock b/Cargo.lock index 85be4c392af..5c096e9f80c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,6 +569,7 @@ dependencies = [ "quine-mc_cluskey", "quote", "regex-syntax", + "rustc-semver", "semver 0.11.0", "serde", "smallvec 1.4.2", @@ -1924,17 +1925,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -[[package]] -name = "md-5" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "opaque-debug 0.2.3", -] - [[package]] name = "md-5" version = "0.9.1" @@ -2695,9 +2685,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.40" +version = "2.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c5fb83bc092c10e12ca863ab8922b1833382d5d248aaafca779886d3396a44" +checksum = "a2f1a4baaaf5c4a9aa30c708c339ae293d02976d2b7f1575a59f44558d25bfea" dependencies = [ "bitflags", "clap", @@ -3024,18 +3014,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174" +checksum = "81f7b9bc5a6f79b1f230833cb4c8f8928d48c129b21df5b372c202fb826c0b5e" dependencies = [ "smallvec 1.4.2", ] [[package]] name = "rustc-ap-rustc_ast" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12" +checksum = "3d77f313e9f30af93f2737f1a99d6552e26b702c5cef3bb65e35f5b4fe5191f1" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3050,9 +3040,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756" +checksum = "30408fbf42fa6fbeb383d3fce0f24d2490c3d12527beb2f48e6e728765bc8695" dependencies = [ "itertools 0.9.0", "rustc-ap-rustc_ast", @@ -3069,9 +3059,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9" +checksum = "d47b8a3adcccc204578b0ee9cd2f9952921fa43977f58343913cca04cce87043" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -3081,9 +3071,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a" +checksum = "66f5f53ecdbf7d8b47905936f93eb1fdae496137e94b7e4023a0b866b0e1a92d" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -3100,9 +3090,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68" +checksum = "3aa913fa40b90157067b17dd7ddfd5df0d8566e339ffa8351a638bdf3fc7ee81" dependencies = [ "arrayvec", "bitflags", @@ -3131,13 +3121,14 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c" +checksum = "5d4b4956287d7c4996409b8362aa69c0c9a6853751ff00ee0a6f78223c5ef3ad" dependencies = [ "annotate-snippets 0.8.0", "atty", "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_lint_defs", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", @@ -3150,9 +3141,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0" +checksum = "3fa908bb1b67230dd4309e93edefc6a6c2f3d8b6a195f77c47743c882114a22e" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -3173,9 +3164,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f" +checksum = "d9b7a1db115893ed7ed0db80f70d2246c1709de7854238acde76471495930f2a" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -3183,21 +3174,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4" +checksum = "55937887cb606cc72193ea3c5feb8bbbb810d812aa233b9a1e7749155c4a3501" [[package]] name = "rustc-ap-rustc_graphviz" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0" +checksum = "e39e179e616356927f0c4eda43e3a35d88476f91e1ac8e4a0a09661dbab44a6e" [[package]] name = "rustc-ap-rustc_index" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb" +checksum = "572d3962d6999f3b1a71d335308e939e204339d4ad36e6ebe7a591c9d4329f5d" dependencies = [ "arrayvec", "rustc-ap-rustc_macros", @@ -3206,18 +3197,32 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678" +checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec" dependencies = [ "unicode-xid", ] +[[package]] +name = "rustc-ap-rustc_lint_defs" +version = "691.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d39bda92aabd77e49ac8ad5e24fccf9d7245b8ff2bf1249ab98733e2e5a2863" +dependencies = [ + "rustc-ap-rustc_ast", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "tracing", +] + [[package]] name = "rustc-ap-rustc_macros" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8" +checksum = "a3295fbc9625197494e356e92d8ac08370eddafa60189861c7b2f084b3b5a6b8" dependencies = [ "proc-macro2", "quote", @@ -3227,9 +3232,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02" +checksum = "9ff5d0094396844efead43303a6eb25b8a4962e2c80fb0ea4a86e4101fbfd404" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -3247,9 +3252,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7" +checksum = "2d5cff6709a8b51a3730288a9ead17cabe8146b1c787db52298447ef7890140a" dependencies = [ "indexmap", "smallvec 1.4.2", @@ -3257,9 +3262,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a" +checksum = "36bb15ef12174b5ed6419a7e4260a899ce8927e8c8fd1f0cddf178818737dcdf" dependencies = [ "bitflags", "getopts", @@ -3269,6 +3274,7 @@ dependencies = [ "rustc-ap-rustc_errors", "rustc-ap-rustc_feature", "rustc-ap-rustc_fs_util", + "rustc-ap-rustc_lint_defs", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", @@ -3278,28 +3284,29 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8" +checksum = "104d349a32be9cfd3d39a5a70ad6c5e682ce262fc5cc8717d35a01e980c0d8b2" dependencies = [ "cfg-if 0.1.10", - "md-5 0.8.0", + "md-5", "rustc-ap-rustc_arena", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_index", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "scoped-tls", - "sha-1 0.8.2", + "sha-1 0.9.1", + "sha2", "tracing", "unicode-width", ] [[package]] name = "rustc-ap-rustc_target" -version = "686.0.0" +version = "691.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188" +checksum = "9d7ac4ded9a6aecb534744c836a160497985f0d53b272581e95e7890d31b9e17" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3359,6 +3366,12 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rustc-semver" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84" + [[package]] name = "rustc-std-workspace-alloc" version = "1.99.0" @@ -3386,6 +3399,7 @@ version = "1.0.0" dependencies = [ "byteorder", "crossbeam-utils 0.7.2", + "libc", "proc-macro2", "quote", "serde", @@ -4144,7 +4158,7 @@ name = "rustc_span" version = "0.0.0" dependencies = [ "cfg-if 0.1.10", - "md-5 0.9.1", + "md-5", "rustc_arena", "rustc_data_structures", "rustc_index", @@ -4335,7 +4349,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.27" +version = "1.4.29" dependencies = [ "annotate-snippets 0.6.1", "anyhow", diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index e0e78a4d609..6ad6e664316 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1307,7 +1307,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> { hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) } } }; - Some(op) + Some((op, *op_sp)) }) .collect(); @@ -1326,7 +1326,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> { } = *p { let op_sp = asm.operands[operand_idx].1; - match &operands[operand_idx] { + match &operands[operand_idx].0 { hir::InlineAsmOperand::In { reg, .. } | hir::InlineAsmOperand::Out { reg, .. } | hir::InlineAsmOperand::InOut { reg, .. } @@ -1385,8 +1385,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> { let mut used_input_regs = FxHashMap::default(); let mut used_output_regs = FxHashMap::default(); let mut required_features: Vec<&str> = vec![]; - for (idx, op) in operands.iter().enumerate() { - let op_sp = asm.operands[idx].1; + for (idx, &(ref op, op_sp)) in operands.iter().enumerate() { if let Some(reg) = op.reg() { // Make sure we don't accidentally carry features from the // previous iteration. @@ -1458,8 +1457,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> { skip = true; let idx2 = *o.get(); - let op2 = &operands[idx2]; - let op_sp2 = asm.operands[idx2].1; + let &(ref op2, op_sp2) = &operands[idx2]; let reg2 = match op2.reg() { Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r, _ => unreachable!(), diff --git a/compiler/rustc_error_codes/src/error_codes/E0390.md b/compiler/rustc_error_codes/src/error_codes/E0390.md index ecc5b5568ad..7a13160d098 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0390.md +++ b/compiler/rustc_error_codes/src/error_codes/E0390.md @@ -1,4 +1,4 @@ -A method was implemented on a primitive type. +A method or constant was implemented on a primitive type. Erroneous code example: @@ -12,7 +12,8 @@ impl *mut Foo {} // `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive ``` -This isn't allowed, but using a trait to implement a method is a good solution. +This isn't allowed, but using a trait to implement a method or constant +is a good solution. Example: ``` diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 44dfdcfccab..c7dc66b70fe 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -14,7 +14,7 @@ macro_rules! arena_types { // HIR types [few] hir_krate: rustc_hir::Crate<$tcx>, [] arm: rustc_hir::Arm<$tcx>, - [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, + [] asm_operand: (rustc_hir::InlineAsmOperand<$tcx>, Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, [] block: rustc_hir::Block<$tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 44dc6673564..280e863d474 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2143,7 +2143,7 @@ pub fn reg(&self) -> Option { #[derive(Debug, HashStable_Generic)] pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], - pub operands: &'hir [InlineAsmOperand<'hir>], + pub operands: &'hir [(InlineAsmOperand<'hir>, Span)], pub options: InlineAsmOptions, pub line_spans: &'hir [Span], } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3e8fc689acf..3c330c5d6c5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1191,7 +1191,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) walk_list!(visitor, visit_expr, optional_expression); } ExprKind::InlineAsm(ref asm) => { - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 25b09d76295..597c55b4bd7 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1462,7 +1462,7 @@ enum AsmArg<'a> { let mut args = vec![]; args.push(AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(&a.template))); - args.extend(a.operands.iter().map(|o| AsmArg::Operand(o))); + args.extend(a.operands.iter().map(|(o, _)| AsmArg::Operand(o))); if !a.options.is_empty() { args.push(AsmArg::Options(a.options)); } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 6781fbc95c0..8a60b196e5e 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -505,7 +505,7 @@ fn canonicalize( let canon_value = Canonical { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), - value: value.clone(), + value, }; return canon_value; } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index fa82dce0ae2..a9358c9610a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2742,6 +2742,50 @@ "detects deprecation attributes with no effect", } +declare_lint! { + /// The `unsupported_naked_functions` lint detects naked function + /// definitions that are unsupported but were previously accepted. + /// + /// ### Example + /// + /// ```rust + /// #![feature(naked_functions)] + /// + /// #[naked] + /// pub fn f() -> u32 { + /// 42 + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The naked functions must be defined using a single inline assembly + /// block. + /// + /// The execution must never fall through past the end of the assembly + /// code so the block must use `noreturn` option. The asm block can also + /// use `att_syntax` option, but other options are not allowed. + /// + /// The asm block must not contain any operands other than `const` and + /// `sym`. Additionally, naked function should specify a non-Rust ABI. + /// + /// While other definitions of naked functions were previously accepted, + /// they are unsupported and might not work reliably. This is a + /// [future-incompatible] lint that will transition into hard error in + /// the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub UNSUPPORTED_NAKED_FUNCTIONS, + Warn, + "unsupported naked function definitions", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #32408 ", + edition: None, + }; +} + declare_tool_lint! { pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL, Deny, @@ -2832,6 +2876,7 @@ UNINHABITED_STATIC, FUNCTION_ITEM_REFERENCES, USELESS_DEPRECATED, + UNSUPPORTED_NAKED_FUNCTIONS, ] } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 1883c89a151..13c8d6b2bcc 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -581,7 +581,7 @@ pub fn replace_escaping_bound_vars( let mut const_map = FxHashMap::default(); if !value.has_escaping_bound_vars() { - (value.clone(), region_map) + (value, region_map) } else { let mut real_fld_r = |br| *region_map.entry(br).or_insert_with(|| fld_r(br)); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5d8edcf70bf..2d7f417b64a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1683,34 +1683,59 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst<'tcx> = Placeholder>; -/// A `DefId` which is potentially bundled with its corresponding generic parameter -/// in case `did` is a const argument. +/// A `DefId` which, in case it is a const argument, is potentially bundled with +/// the `DefId` of the generic parameter it instantiates. /// -/// This is used to prevent cycle errors during typeck -/// as `type_of(const_arg)` depends on `typeck(owning_body)` -/// which once again requires the type of its generic arguments. -/// -/// Luckily we only need to deal with const arguments once we -/// know their corresponding parameters. We (ab)use this by -/// calling `type_of(param_did)` for these arguments. +/// This is used to avoid calls to `type_of` for const arguments during typeck +/// which cause cycle errors. /// /// ```rust /// #![feature(const_generics)] /// /// struct A; /// impl A { -/// fn foo(&self) -> usize { N } +/// fn foo(&self) -> [u8; N] { [0; N] } +/// // ^ const parameter /// } /// struct B; /// impl B { -/// fn foo(&self) -> usize { 42 } +/// fn foo(&self) -> usize { 42 } +/// // ^ const parameter /// } /// /// fn main() { /// let a = A; -/// a.foo::<7>(); +/// let _b = a.foo::<{ 3 + 7 }>(); +/// // ^^^^^^^^^ const argument /// } /// ``` +/// +/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know +/// which `foo` is used until we know the type of `a`. +/// +/// We only know the type of `a` once we are inside of `typeck(main)`. +/// We also end up normalizing the type of `_b` during `typeck(main)` which +/// requires us to evaluate the const argument. +/// +/// To evaluate that const argument we need to know its type, +/// which we would get using `type_of(const_arg)`. This requires us to +/// resolve `foo` as it can be either `usize` or `u8` in this example. +/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`, +/// which results in a cycle. +/// +/// In short we must not call `type_of(const_arg)` during `typeck(main)`. +/// +/// When first creating the `ty::Const` of the const argument inside of `typeck` we have +/// already resolved `foo` so we know which const parameter this argument instantiates. +/// This means that we also know the expected result of `type_of(const_arg)` even if we +/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is +/// trivial to compute. +/// +/// If we now want to use that constant in a place which potentionally needs its type +/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`, +/// except that instead of a `Ty` we bundle the `DefId` of the const parameter. +/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` +/// to get the type of `did`. #[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, HashStable)] @@ -1721,7 +1746,7 @@ pub struct WithOptConstParam { /// /// Note that even if `did` is a const argument, this may still be `None`. /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)` - /// to potentially update `param_did` in case it `None`. + /// to potentially update `param_did` in the case it is `None`. pub const_param_did: Option, } diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs index ec90f063a55..c2165db278f 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_mir/src/interpret/util.rs @@ -13,12 +13,13 @@ return Ok(()); } + struct FoundParam; struct UsedParamsNeedSubstVisitor<'tcx> { tcx: TyCtxt<'tcx>, } impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> { - type BreakTy = (); + type BreakTy = FoundParam; fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if !c.needs_subst() { @@ -26,7 +27,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow ControlFlow::BREAK, + ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), _ => c.super_visit_with(self), } } @@ -37,7 +38,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { } match *ty.kind() { - ty::Param(_) => ControlFlow::BREAK, + ty::Param(_) => ControlFlow::Break(FoundParam), ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) | ty::FnDef(def_id, substs) => { @@ -76,7 +77,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { } let mut vis = UsedParamsNeedSubstVisitor { tcx }; - if ty.visit_with(&mut vis).is_break() { + if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { throw_inval!(TooGeneric); } else { Ok(()) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index e404afeb698..e934d8ed9da 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -408,7 +408,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( operands: asm .operands .iter() - .map(|op| { + .map(|(op, _op_sp)| { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { InlineAsmOperand::In { reg, expr: expr.to_ref() } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b746256f5fe..22f308ff36d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -264,7 +264,7 @@ fn to_string(&self) -> String { TokenType::Ident => "identifier".to_string(), TokenType::Path => "path".to_string(), TokenType::Type => "type".to_string(), - TokenType::Const => "const".to_string(), + TokenType::Const => "a const expression".to_string(), } } } diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 956be925be8..711e8e87c6c 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -347,7 +347,7 @@ fn check_asm_operand_type( } fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, op) in asm.operands.iter().enumerate() { + for (idx, (op, _op_sp)) in asm.operands.iter().enumerate() { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { self.check_asm_operand_type(idx, reg, expr, asm.template, None); diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index debb873beb9..a64c6fa319c 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1174,7 +1174,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod }; // Do a first pass for writing outputs only - for op in asm.operands.iter().rev() { + for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Const { .. } @@ -1197,7 +1197,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod // Then do a second pass for inputs let mut succ = succ; - for op in asm.operands.iter().rev() { + for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr, .. } @@ -1454,7 +1454,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { } hir::ExprKind::InlineAsm(ref asm) => { - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 6ef45cdd391..5b50ef8627b 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,10 +1,16 @@ +//! Checks validity of naked functions. + +use rustc_ast::InlineAsmOptions; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::{ExprKind, HirId, InlineAsmOperand, StmtKind}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_session::lint::builtin::UNSUPPORTED_NAKED_FUNCTIONS; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_target::spec::abi::Abi; fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { tcx.hir().visit_item_likes_in_module( @@ -33,27 +39,52 @@ fn visit_fn( fk: FnKind<'v>, _fd: &'tcx hir::FnDecl<'tcx>, body_id: hir::BodyId, - _span: Span, - _hir_id: hir::HirId, + span: Span, + hir_id: HirId, ) { + let ident_span; + let fn_header; + match fk { - // Rejected during attribute check. Do not validate further. - FnKind::Closure(..) => return, - FnKind::ItemFn(..) | FnKind::Method(..) => {} + FnKind::Closure(..) => { + // Closures with a naked attribute are rejected during attribute + // check. Don't validate them any further. + return; + } + FnKind::ItemFn(ident, _, ref header, ..) => { + ident_span = ident.span; + fn_header = header; + } + + FnKind::Method(ident, ref sig, ..) => { + ident_span = ident.span; + fn_header = &sig.header; + } } let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked)); if naked { let body = self.tcx.hir().body(body_id); - check_params(self.tcx, body); - check_body(self.tcx, body); + check_abi(self.tcx, hir_id, fn_header.abi, ident_span); + check_no_patterns(self.tcx, body.params); + check_no_parameters_use(self.tcx, body); + check_asm(self.tcx, hir_id, body, span); } } } +/// Checks that function uses non-Rust ABI. +fn check_abi(tcx: TyCtxt<'_>, hir_id: HirId, abi: Abi, fn_ident_span: Span) { + if abi == Abi::Rust { + tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_ident_span, |lint| { + lint.build("Rust ABI is unsupported in naked functions").emit(); + }); + } +} + /// Checks that parameters don't use patterns. Mirrors the checks for function declarations. -fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) { - for param in body.params { +fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) { + for param in params { match param.pat.kind { hir::PatKind::Wild | hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {} @@ -69,23 +100,23 @@ fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) { } } -/// Checks that function parameters aren't referenced in the function body. -fn check_body<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) { +/// Checks that function parameters aren't used in the function body. +fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) { let mut params = hir::HirIdSet::default(); for param in body.params { param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| { params.insert(hir_id); }); } - CheckBody { tcx, params }.visit_body(body); + CheckParameters { tcx, params }.visit_body(body); } -struct CheckBody<'tcx> { +struct CheckParameters<'tcx> { tcx: TyCtxt<'tcx>, params: hir::HirIdSet, } -impl<'tcx> Visitor<'tcx> for CheckBody<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> { type Map = ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -103,11 +134,189 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { .sess .struct_span_err( expr.span, - "use of parameters not allowed inside naked functions", + "referencing function parameters is not allowed in naked functions", ) + .help("follow the calling convention in asm block to use parameters") .emit(); + return; } } hir::intravisit::walk_expr(self, expr); } } + +/// Checks that function body contains a single inline assembly block. +fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, body: &'tcx hir::Body<'tcx>, fn_span: Span) { + let mut this = CheckInlineAssembly { tcx, items: Vec::new() }; + this.visit_body(body); + if let &[(ItemKind::Asm, _)] = &this.items[..] { + // Ok. + } else { + tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| { + let mut diag = lint.build("naked functions must contain a single asm block"); + let mut has_asm = false; + for &(kind, span) in &this.items { + match kind { + ItemKind::Asm if has_asm => { + diag.span_label( + span, + "multiple asm blocks are unsupported in naked functions", + ); + } + ItemKind::Asm => has_asm = true, + ItemKind::NonAsm => { + diag.span_label(span, "non-asm is unsupported in naked functions"); + } + } + } + diag.emit(); + }); + } +} + +struct CheckInlineAssembly<'tcx> { + tcx: TyCtxt<'tcx>, + items: Vec<(ItemKind, Span)>, +} + +#[derive(Copy, Clone)] +enum ItemKind { + Asm, + NonAsm, +} + +impl<'tcx> CheckInlineAssembly<'tcx> { + fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) { + match expr.kind { + ExprKind::Box(..) + | ExprKind::ConstBlock(..) + | ExprKind::Array(..) + | ExprKind::Call(..) + | ExprKind::MethodCall(..) + | ExprKind::Tup(..) + | ExprKind::Binary(..) + | ExprKind::Unary(..) + | ExprKind::Lit(..) + | ExprKind::Cast(..) + | ExprKind::Type(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + | ExprKind::Closure(..) + | ExprKind::Assign(..) + | ExprKind::AssignOp(..) + | ExprKind::Field(..) + | ExprKind::Index(..) + | ExprKind::Path(..) + | ExprKind::AddrOf(..) + | ExprKind::Break(..) + | ExprKind::Continue(..) + | ExprKind::Ret(..) + | ExprKind::Struct(..) + | ExprKind::Repeat(..) + | ExprKind::Yield(..) => { + self.items.push((ItemKind::NonAsm, span)); + } + + ExprKind::InlineAsm(ref asm) => { + self.items.push((ItemKind::Asm, span)); + self.check_inline_asm(expr.hir_id, asm, span); + } + + ExprKind::LlvmInlineAsm(..) => { + self.items.push((ItemKind::Asm, span)); + self.tcx.struct_span_lint_hir( + UNSUPPORTED_NAKED_FUNCTIONS, + expr.hir_id, + span, + |lint| { + lint.build( + "the LLVM-style inline assembly is unsupported in naked functions", + ) + .help("use the new asm! syntax specified in RFC 2873") + .emit(); + }, + ); + } + + ExprKind::DropTemps(..) | ExprKind::Block(..) | ExprKind::Err => { + hir::intravisit::walk_expr(self, expr); + } + } + } + + fn check_inline_asm(&self, hir_id: HirId, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) { + let unsupported_operands: Vec = asm + .operands + .iter() + .filter_map(|&(ref op, op_sp)| match op { + InlineAsmOperand::Const { .. } | InlineAsmOperand::Sym { .. } => None, + InlineAsmOperand::In { .. } + | InlineAsmOperand::Out { .. } + | InlineAsmOperand::InOut { .. } + | InlineAsmOperand::SplitInOut { .. } => Some(op_sp), + }) + .collect(); + if !unsupported_operands.is_empty() { + self.tcx.struct_span_lint_hir( + UNSUPPORTED_NAKED_FUNCTIONS, + hir_id, + unsupported_operands, + |lint| { + lint.build("only `const` and `sym` operands are supported in naked functions") + .emit(); + }, + ); + } + + let unsupported_options: Vec<&'static str> = [ + (InlineAsmOptions::NOMEM, "`nomem`"), + (InlineAsmOptions::NOSTACK, "`nostack`"), + (InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"), + (InlineAsmOptions::PURE, "`pure`"), + (InlineAsmOptions::READONLY, "`readonly`"), + ] + .iter() + .filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None }) + .collect(); + + if !unsupported_options.is_empty() { + self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| { + lint.build(&format!( + "asm options unsupported in naked functions: {}", + unsupported_options.join(", ") + )) + .emit(); + }); + } + + if !asm.options.contains(InlineAsmOptions::NORETURN) { + self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| { + lint.build("asm in naked functions must use `noreturn` option").emit(); + }); + } + } +} + +impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { + type Map = ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { + match stmt.kind { + StmtKind::Item(..) => {} + StmtKind::Local(..) => { + self.items.push((ItemKind::NonAsm, stmt.span)); + } + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + self.check_expr(expr, stmt.span); + } + } + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + self.check_expr(&expr, expr.span); + } +} diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 54743ef9ce9..33cd509cbb8 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -49,7 +49,7 @@ fn normalize(&self, value: T) -> Result, NoSolution> self.param_env, ); if !value.has_projections() { - return Ok(Normalized { value: value.clone(), obligations: vec![] }); + return Ok(Normalized { value, obligations: vec![] }); } let mut normalizer = QueryNormalizer { diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0db5fda272a..b7e77f389f8 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -44,6 +44,13 @@ fn generic_arg_mismatch_err( // the match is non-exhaustive. _ => bug!("invalid generic parameter kind {}", kind), }; + + if let ParamKindOrd::Const { .. } = kind_ord { + if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg { + err.help("const arguments cannot yet be inferred with `_`"); + } + } + let arg_ord = match arg { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 489d836298f..ec7369fd3e8 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -462,39 +462,25 @@ pub(super) fn check_opaque<'tcx>( /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result /// in "inheriting lifetimes". +#[instrument(skip(tcx, span))] pub(super) fn check_opaque_for_inheriting_lifetimes( tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span, ) { let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id)); - debug!( - "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}", - def_id, span, item - ); - - #[derive(Debug)] - struct ProhibitOpaqueVisitor<'tcx> { - opaque_identity_ty: Ty<'tcx>, - generics: &'tcx ty::Generics, - } + debug!(?item, ?span); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { - type BreakTy = Option>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); - if t != self.opaque_identity_ty && t.super_visit_with(self).is_break() { - return ControlFlow::Break(Some(t)); - } - ControlFlow::CONTINUE - } + struct FoundParentLifetime; + struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics); + impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { + type BreakTy = FoundParentLifetime; fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r); + debug!("FindParentLifetimeVisitor: r={:?}", r); if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r { - if *index < self.generics.parent_count as u32 { - return ControlFlow::Break(None); + if *index < self.0.parent_count as u32 { + return ControlFlow::Break(FoundParentLifetime); } else { return ControlFlow::CONTINUE; } @@ -505,7 +491,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Unevaluated(..) = c.val { - // FIXME(#72219) We currenctly don't detect lifetimes within substs + // FIXME(#72219) We currently don't detect lifetimes within substs // which would violate this check. Even though the particular substitution is not used // within the const, this should still be fixed. return ControlFlow::CONTINUE; @@ -514,6 +500,26 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { + opaque_identity_ty: Ty<'tcx>, + generics: &'tcx ty::Generics, + } + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + type BreakTy = Ty<'tcx>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); + if t == self.opaque_identity_ty { + ControlFlow::CONTINUE + } else { + t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics)) + .map_break(|FoundParentLifetime| t) + } + } + } + if let ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, .. @@ -555,14 +561,12 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow, is_input: bool) { } fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr } => { self.check_expr_asm_operand(expr, true); diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 483ab2f58f2..0c1578498b8 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -44,8 +44,8 @@ struct InherentCollect<'tcx> { impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - let ty = match item.kind { - hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty, + let (ty, assoc_items) = match item.kind { + hir::ItemKind::Impl { of_trait: None, ref self_ty, items, .. } => (self_ty, items), _ => return, }; @@ -70,6 +70,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "bool", "bool", item.span, + assoc_items, ); } ty::Char => { @@ -80,6 +81,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "char", "char", item.span, + assoc_items, ); } ty::Str => { @@ -90,6 +92,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "str", "str", item.span, + assoc_items, ); } ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => { @@ -100,6 +103,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "slice_u8", "[u8]", item.span, + assoc_items, ); } ty::Slice(_) => { @@ -110,6 +114,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "slice", "[T]", item.span, + assoc_items, ); } ty::Array(_, _) => { @@ -120,6 +125,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "array", "[T; N]", item.span, + assoc_items, ); } ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not }) @@ -132,6 +138,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "const_slice_ptr", "*const [T]", item.span, + assoc_items, ); } ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut }) @@ -144,6 +151,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "mut_slice_ptr", "*mut [T]", item.span, + assoc_items, ); } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { @@ -154,6 +162,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "const_ptr", "*const T", item.span, + assoc_items, ); } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { @@ -164,6 +173,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "mut_ptr", "*mut T", item.span, + assoc_items, ); } ty::Int(ast::IntTy::I8) => { @@ -174,6 +184,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "i8", "i8", item.span, + assoc_items, ); } ty::Int(ast::IntTy::I16) => { @@ -184,6 +195,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "i16", "i16", item.span, + assoc_items, ); } ty::Int(ast::IntTy::I32) => { @@ -194,6 +206,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "i32", "i32", item.span, + assoc_items, ); } ty::Int(ast::IntTy::I64) => { @@ -204,6 +217,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "i64", "i64", item.span, + assoc_items, ); } ty::Int(ast::IntTy::I128) => { @@ -214,6 +228,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "i128", "i128", item.span, + assoc_items, ); } ty::Int(ast::IntTy::Isize) => { @@ -224,6 +239,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "isize", "isize", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::U8) => { @@ -234,6 +250,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "u8", "u8", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::U16) => { @@ -244,6 +261,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "u16", "u16", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::U32) => { @@ -254,6 +272,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "u32", "u32", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::U64) => { @@ -264,6 +283,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "u64", "u64", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::U128) => { @@ -274,6 +294,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "u128", "u128", item.span, + assoc_items, ); } ty::Uint(ast::UintTy::Usize) => { @@ -284,6 +305,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "usize", "usize", item.span, + assoc_items, ); } ty::Float(ast::FloatTy::F32) => { @@ -294,6 +316,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "f32", "f32", item.span, + assoc_items, ); } ty::Float(ast::FloatTy::F64) => { @@ -304,6 +327,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) { "f64", "f64", item.span, + assoc_items, ); } ty::Error(_) => {} @@ -369,6 +393,7 @@ fn check_primitive_impl( lang: &str, ty: &str, span: Span, + assoc_items: &[hir::ImplItemRef<'_>], ) { match (lang_def_id, lang_def_id2) { (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => { @@ -378,6 +403,32 @@ fn check_primitive_impl( // OK } _ => { + let to_implement = if assoc_items.len() == 0 { + String::new() + } else { + let plural = assoc_items.len() > 1; + let assoc_items_kind = { + let item_types = assoc_items.iter().map(|x| x.kind); + if item_types.clone().all(|x| x == hir::AssocItemKind::Const) { + "constant" + } else if item_types + .clone() + .all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } }) + { + "method" + } else { + "associated item" + } + }; + + format!( + " to implement {} {}{}", + if plural { "these" } else { "this" }, + assoc_items_kind, + if plural { "s" } else { "" } + ) + }; + struct_span_err!( self.tcx.sess, span, @@ -387,7 +438,7 @@ fn check_primitive_impl( lang, ty ) - .span_help(span, "consider using a trait to implement these methods") + .help(&format!("consider using a trait{}", to_implement)) .emit(); } } diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 1b51d5e0182..95848ac2c07 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -243,7 +243,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) { } hir::ExprKind::InlineAsm(ref asm) => { - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr, .. } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 5ede1ba8e2c..4834ca74b82 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -56,6 +56,20 @@ pub fn break_value(self) -> Option { ControlFlow::Break(x) => Some(x), } } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the break value in case it exists. + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn map_break(self, f: F) -> ControlFlow + where + F: FnOnce(B) -> T, + { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(x), + ControlFlow::Break(x) => ControlFlow::Break(f(x)), + } + } } impl ControlFlow { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index a944514f694..83cf47c8c8f 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1131,6 +1131,13 @@ pub fn rfind<'a, P>(&'a self, pat: P) -> Option /// assert_eq!(v, ["lion", "tiger", "leopard"]); /// ``` /// + /// If the pattern is a slice of chars, split on each occurrence of any of the characters: + /// + /// ``` + /// let v: Vec<&str> = "2020-11-03 23:59".split(&['-', ' ', ':', '@'][..]).collect(); + /// assert_eq!(v, ["2020", "11", "03", "23", "59"]); + /// ``` + /// /// A more complex pattern, using a closure: /// /// ``` diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index e2f0870ef0e..d1b0ad9e5f8 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1211,7 +1211,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { use super::kernel_copy::{copy_regular_files, CopyResult}; match copy_regular_files(reader.as_raw_fd(), writer.as_raw_fd(), max_len) { - CopyResult::Ended(result) => result, + CopyResult::Ended(bytes) => Ok(bytes), + CopyResult::Error(e, _) => Err(e), CopyResult::Fallback(written) => match io::copy::generic_copy(&mut reader, &mut writer) { Ok(bytes) => Ok(bytes + written), Err(e) => Err(e), diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index f08c828ecff..5bfac803153 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -167,10 +167,11 @@ fn copy(self) -> Result { if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() { let result = copy_regular_files(readfd, writefd, max_write); + result.update_take(reader); match result { - CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written), - CopyResult::Ended(err) => return err, + CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written), + CopyResult::Error(e, _) => return Err(e), CopyResult::Fallback(bytes) => written += bytes, } } @@ -182,20 +183,22 @@ fn copy(self) -> Result { // fall back to the generic copy loop. if input_meta.potential_sendfile_source() { let result = sendfile_splice(SpliceMode::Sendfile, readfd, writefd, max_write); + result.update_take(reader); match result { - CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written), - CopyResult::Ended(err) => return err, + CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written), + CopyResult::Error(e, _) => return Err(e), CopyResult::Fallback(bytes) => written += bytes, } } if input_meta.maybe_fifo() || output_meta.maybe_fifo() { let result = sendfile_splice(SpliceMode::Splice, readfd, writefd, max_write); + result.update_take(reader); match result { - CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written), - CopyResult::Ended(err) => return err, + CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written), + CopyResult::Error(e, _) => return Err(e), CopyResult::Fallback(0) => { /* use the fallback below */ } CopyResult::Fallback(_) => { unreachable!("splice should not return > 0 bytes on the fallback path") @@ -225,6 +228,9 @@ fn drain_to(&mut self, _writer: &mut W, _limit: u64) -> Result { Ok(0) } + /// Updates `Take` wrappers to remove the number of bytes copied. + fn taken(&mut self, _bytes: u64) {} + /// The minimum of the limit of all `Take<_>` wrappers, `u64::MAX` otherwise. /// This method does not account for data `BufReader` buffers and would underreport /// the limit of a `Take>>` type. Thus its result is only valid @@ -251,6 +257,10 @@ fn drain_to(&mut self, writer: &mut W, limit: u64) -> Result { (**self).drain_to(writer, limit) } + fn taken(&mut self, bytes: u64) { + (**self).taken(bytes); + } + fn min_limit(&self) -> u64 { (**self).min_limit() } @@ -407,6 +417,11 @@ fn drain_to(&mut self, writer: &mut W, outer_limit: u64) -> Result u64 { min(Take::limit(self), self.get_ref().min_limit()) } @@ -432,6 +447,10 @@ fn drain_to(&mut self, writer: &mut W, outer_limit: u64) -> Result u64 { self.get_ref().min_limit() } @@ -457,10 +476,21 @@ fn fd_to_meta(fd: &T) -> FdMeta { } pub(super) enum CopyResult { - Ended(Result), + Ended(u64), + Error(Error, u64), Fallback(u64), } +impl CopyResult { + fn update_take(&self, reader: &mut impl CopyRead) { + match *self { + CopyResult::Fallback(bytes) + | CopyResult::Ended(bytes) + | CopyResult::Error(_, bytes) => reader.taken(bytes), + } + } +} + /// linux-specific implementation that will attempt to use copy_file_range for copy offloading /// as the name says, it only works on regular files /// @@ -527,7 +557,7 @@ fn copy_file_range( // - copying from an overlay filesystem in docker. reported to occur on fedora 32. return CopyResult::Fallback(0); } - Ok(0) => return CopyResult::Ended(Ok(written)), // reached EOF + Ok(0) => return CopyResult::Ended(written), // reached EOF Ok(ret) => written += ret as u64, Err(err) => { return match err.raw_os_error() { @@ -545,12 +575,12 @@ fn copy_file_range( assert_eq!(written, 0); CopyResult::Fallback(0) } - _ => CopyResult::Ended(Err(err)), + _ => CopyResult::Error(err, written), }; } } } - CopyResult::Ended(Ok(written)) + CopyResult::Ended(written) } #[derive(PartialEq)] @@ -623,10 +653,10 @@ fn splice( Some(os_err) if mode == SpliceMode::Sendfile && os_err == libc::EOVERFLOW => { CopyResult::Fallback(written) } - _ => CopyResult::Ended(Err(err)), + _ => CopyResult::Error(err, written), }; } } } - CopyResult::Ended(Ok(written)) + CopyResult::Ended(written) } diff --git a/library/std/src/sys/unix/kernel_copy/tests.rs b/library/std/src/sys/unix/kernel_copy/tests.rs index 554ebd94022..3937a1ffa38 100644 --- a/library/std/src/sys/unix/kernel_copy/tests.rs +++ b/library/std/src/sys/unix/kernel_copy/tests.rs @@ -42,8 +42,15 @@ fn copy_specialization() -> Result<()> { assert_eq!(sink.buffer(), b"wxyz"); let copied = crate::io::copy(&mut source, &mut sink)?; - assert_eq!(copied, 10); - assert_eq!(sink.buffer().len(), 0); + assert_eq!(copied, 10, "copy obeyed limit imposed by Take"); + assert_eq!(sink.buffer().len(), 0, "sink buffer was flushed"); + assert_eq!(source.limit(), 0, "outer Take was exhausted"); + assert_eq!(source.get_ref().buffer().len(), 0, "source buffer should be drained"); + assert_eq!( + source.get_ref().get_ref().limit(), + 1, + "inner Take allowed reading beyond end of file, some bytes should be left" + ); let mut sink = sink.into_inner()?; sink.seek(SeekFrom::Start(0))?; @@ -210,7 +217,7 @@ fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) { ); match probe { - CopyResult::Ended(Ok(1)) => { + CopyResult::Ended(1) => { // splice works } _ => { diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 76056637a4c..b095c2dde62 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -78,9 +78,11 @@ fn test_env_set_var() { } #[test] -#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] +#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))] #[allow(deprecated)] fn env_home_dir() { + use std::path::PathBuf; + fn var_to_os_string(var: Result) -> Option { match var { Ok(var) => Some(OsString::from(var)), @@ -91,8 +93,6 @@ fn var_to_os_string(var: Result) -> Option { cfg_if::cfg_if! { if #[cfg(unix)] { - use std::path::PathBuf; - let oldhome = var_to_os_string(var("HOME")); set_var("HOME", "/home/MountainView"); @@ -110,8 +110,6 @@ fn var_to_os_string(var: Result) -> Option { if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } } else if #[cfg(windows)] { - use std::path::PathBuf; - let oldhome = var_to_os_string(var("HOME")); let olduserprofile = var_to_os_string(var("USERPROFILE")); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8c344338de7..16274430902 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2263,7 +2263,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec { name: None, attrs: self.attrs.clean(cx), source: self.span.clean(cx), - def_id: DefId::local(CRATE_DEF_INDEX), + def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), stability: None, const_stability: None, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index c080ad21c0f..5f640bfddf1 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -151,7 +151,12 @@ fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> { } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner { e.impls = self.get_impls(id, cache) } - self.index.borrow_mut().insert(id.into(), new_item); + let removed = self.index.borrow_mut().insert(id.into(), new_item.clone()); + // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check + // to make sure the items are unique. + if let Some(old_item) = removed { + assert_eq!(old_item, new_item); + } } Ok(()) diff --git a/src/librustdoc/json/types.rs b/src/librustdoc/json/types.rs index 10bf2a2acc5..9335fe9be1a 100644 --- a/src/librustdoc/json/types.rs +++ b/src/librustdoc/json/types.rs @@ -11,7 +11,7 @@ /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow /// tools to find or link to them. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Crate { /// The id of the root [`Module`] item of the local crate. pub root: Id, @@ -31,7 +31,7 @@ pub struct Crate { pub format_version: u32, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ExternalCrate { pub name: String, pub html_root_url: Option, @@ -41,7 +41,7 @@ pub struct ExternalCrate { /// information. This struct should contain enough to generate a link/reference to the item in /// question, or can be used by a tool that takes the json output of multiple crates to find /// the actual item definition with all the relevant info. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ItemSummary { /// Can be used to look up the name and html_root_url of the crate this item came from in the /// `external_crates` map. @@ -53,7 +53,7 @@ pub struct ItemSummary { pub kind: ItemKind, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Item { /// The unique identifier of this item. Can be used to find this item in various mappings. pub id: Id, @@ -79,7 +79,7 @@ pub struct Item { pub inner: ItemEnum, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Span { /// The path to the source file for this span relative to the path `rustdoc` was invoked with. pub filename: PathBuf, @@ -89,14 +89,14 @@ pub struct Span { pub end: (usize, usize), } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Deprecation { pub since: Option, pub note: Option, } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Visibility { Public, /// For the most part items are private by default. The exceptions are associated items of @@ -112,7 +112,7 @@ pub enum Visibility { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum GenericArgs { /// <'a, 32, B: Copy, C = u32> AngleBracketed { args: Vec, bindings: Vec }, @@ -121,14 +121,14 @@ pub enum GenericArgs { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum GenericArg { Lifetime(String), Type(Type), Const(Constant), } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Constant { #[serde(rename = "type")] pub type_: Type, @@ -137,14 +137,14 @@ pub struct Constant { pub is_literal: bool, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct TypeBinding { pub name: String, pub binding: TypeBindingKind, } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum TypeBindingKind { Equality(Type), Constraint(Vec), @@ -154,7 +154,7 @@ pub enum TypeBindingKind { pub struct Id(pub String); #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum ItemKind { Module, ExternCrate, @@ -184,7 +184,7 @@ pub enum ItemKind { } #[serde(untagged)] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum ItemEnum { ModuleItem(Module), ExternCrateItem { @@ -231,13 +231,13 @@ pub enum ItemEnum { }, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Module { pub is_crate: bool, pub items: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Struct { pub struct_type: StructType, pub generics: Generics, @@ -246,7 +246,7 @@ pub struct Struct { pub impls: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Enum { pub generics: Generics, pub variants_stripped: bool, @@ -256,7 +256,7 @@ pub struct Enum { #[serde(rename_all = "snake_case")] #[serde(tag = "variant_kind", content = "variant_inner")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Variant { Plain, Tuple(Vec), @@ -264,14 +264,14 @@ pub enum Variant { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum StructType { Plain, Tuple, Unit, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Function { pub decl: FnDecl, pub generics: Generics, @@ -279,7 +279,7 @@ pub struct Function { pub abi: String, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Method { pub decl: FnDecl, pub generics: Generics, @@ -287,20 +287,20 @@ pub struct Method { pub has_body: bool, } -#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)] pub struct Generics { pub params: Vec, pub where_predicates: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct GenericParamDef { pub name: String, pub kind: GenericParamDefKind, } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum GenericParamDefKind { Lifetime, Type { bounds: Vec, default: Option }, @@ -308,7 +308,7 @@ pub enum GenericParamDefKind { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec }, RegionPredicate { lifetime: String, bounds: Vec }, @@ -316,7 +316,7 @@ pub enum WherePredicate { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum GenericBound { TraitBound { #[serde(rename = "trait")] @@ -329,7 +329,7 @@ pub enum GenericBound { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum TraitBoundModifier { None, Maybe, @@ -338,7 +338,7 @@ pub enum TraitBoundModifier { #[serde(rename_all = "snake_case")] #[serde(tag = "kind", content = "inner")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Type { /// Structs, enums, and traits ResolvedPath { @@ -391,7 +391,7 @@ pub enum Type { }, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct FunctionPointer { pub is_unsafe: bool, pub generic_params: Vec, @@ -399,14 +399,14 @@ pub struct FunctionPointer { pub abi: String, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct FnDecl { pub inputs: Vec<(String, Type)>, pub output: Option, pub c_variadic: bool, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Trait { pub is_auto: bool, pub is_unsafe: bool, @@ -416,13 +416,13 @@ pub struct Trait { pub implementors: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct TraitAlias { pub generics: Generics, pub params: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Impl { pub is_unsafe: bool, pub generics: Generics, @@ -438,7 +438,7 @@ pub struct Impl { } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Import { /// The full path being imported. pub span: String, @@ -451,14 +451,14 @@ pub struct Import { pub glob: bool, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ProcMacro { pub kind: MacroKind, pub helpers: Vec, } #[serde(rename_all = "snake_case")] -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum MacroKind { /// A bang macro `foo!()`. Bang, @@ -468,20 +468,20 @@ pub enum MacroKind { Derive, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Typedef { #[serde(rename = "type")] pub type_: Type, pub generics: Generics, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct OpaqueTy { pub bounds: Vec, pub generics: Generics, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Static { #[serde(rename = "type")] pub type_: Type, diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected new file mode 100644 index 00000000000..65bb0c5fa03 --- /dev/null +++ b/src/test/rustdoc-json/nested.expected @@ -0,0 +1,196 @@ +{ + "crate_version": null, + "external_crates": {}, + "format_version": 1, + "includes_private": false, + "index": { + "0:0": { + "attrs": [], + "crate_id": 0, + "deprecation": null, + "docs": "", + "id": "0:0", + "inner": { + "is_crate": true, + "items": [ + "0:3" + ] + }, + "kind": "module", + "links": {}, + "name": "nested", + "source": { + "begin": [ + 2, + 0 + ], + "end": [ + 7, + 1 + ], + "filename": "$TEST_BASE_DIR/nested.rs" + }, + "visibility": "public" + }, + "0:3": { + "attrs": [], + "crate_id": 0, + "deprecation": null, + "docs": "", + "id": "0:3", + "inner": { + "is_crate": false, + "items": [ + "0:7", + "0:4" + ] + }, + "kind": "module", + "links": {}, + "name": "l1", + "source": { + "begin": [ + 2, + 0 + ], + "end": [ + 7, + 1 + ], + "filename": "$TEST_BASE_DIR/nested.rs" + }, + "visibility": "public" + }, + "0:4": { + "attrs": [], + "crate_id": 0, + "deprecation": null, + "docs": "", + "id": "0:4", + "inner": { + "is_crate": false, + "items": [ + "0:5" + ] + }, + "kind": "module", + "links": {}, + "name": "l3", + "source": { + "begin": [ + 3, + 4 + ], + "end": [ + 5, + 5 + ], + "filename": "$TEST_BASE_DIR/nested.rs" + }, + "visibility": "public" + }, + "0:5": { + "attrs": [], + "crate_id": 0, + "deprecation": null, + "docs": "", + "id": "0:5", + "inner": { + "fields": [], + "fields_stripped": false, + "generics": { + "params": [], + "where_predicates": [] + }, + "impls": [ + "0:10", + "0:11", + "0:12", + "0:14", + "0:15" + ], + "struct_type": "unit" + }, + "kind": "struct", + "links": {}, + "name": "L4", + "source": { + "begin": [ + 4, + 8 + ], + "end": [ + 4, + 22 + ], + "filename": "$TEST_BASE_DIR/nested.rs" + }, + "visibility": "public" + }, + "0:7": { + "attrs": [], + "crate_id": 0, + "deprecation": null, + "docs": "", + "id": "0:7", + "inner": { + "glob": false, + "id": "0:5", + "name": "L4", + "span": "l3::L4" + }, + "kind": "import", + "links": {}, + "name": null, + "source": { + "begin": [ + 6, + 4 + ], + "end": [ + 6, + 19 + ], + "filename": "$TEST_BASE_DIR/nested.rs" + }, + "visibility": "public" + } + }, + "paths": { + "0:0": { + "crate_id": 0, + "kind": "module", + "path": [ + "nested" + ] + }, + "0:3": { + "crate_id": 0, + "kind": "module", + "path": [ + "nested", + "l1" + ] + }, + "0:4": { + "crate_id": 0, + "kind": "module", + "path": [ + "nested", + "l1", + "l3" + ] + }, + "0:5": { + "crate_id": 0, + "kind": "struct", + "path": [ + "nested", + "l1", + "l3", + "L4" + ] + } + }, + "root": "0:0" +} \ No newline at end of file diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs new file mode 100644 index 00000000000..e460b343d37 --- /dev/null +++ b/src/test/rustdoc-json/nested.rs @@ -0,0 +1,7 @@ +// edition:2018 +pub mod l1 { + pub mod l3 { + pub struct L4; + } + pub use l3::L4; +} diff --git a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs new file mode 100644 index 00000000000..6cc02f78c62 --- /dev/null +++ b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs @@ -0,0 +1,18 @@ +#![crate_name = "foo"] +#![feature(lazy_normalization_consts)] +#![allow(incomplete_features)] + +// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate, +// which previously caused an ICE. + +pub struct Hasher { + cv_stack: T, +} + +unsafe impl Send for Hasher {} + +// @has foo/struct.Foo.html +// @has - '//code' 'impl Send for Foo' +pub struct Foo { + hasher: Hasher<[u8; 3]>, +} diff --git a/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs deleted file mode 100644 index 6cc02f78c62..00000000000 --- a/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![crate_name = "foo"] -#![feature(lazy_normalization_consts)] -#![allow(incomplete_features)] - -// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate, -// which previously caused an ICE. - -pub struct Hasher { - cv_stack: T, -} - -unsafe impl Send for Hasher {} - -// @has foo/struct.Foo.html -// @has - '//code' 'impl Send for Foo' -pub struct Foo { - hasher: Hasher<[u8; 3]>, -} diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs new file mode 100644 index 00000000000..a46ca4544a6 --- /dev/null +++ b/src/test/ui/asm/naked-functions.rs @@ -0,0 +1,169 @@ +// only-x86_64 +#![feature(asm)] +#![feature(llvm_asm)] +#![feature(naked_functions)] +#![feature(or_patterns)] +#![crate_type = "lib"] + +#[repr(C)] +pub struct P { x: u8, y: u16 } + +#[naked] +pub unsafe extern "C" fn patterns( + mut a: u32, + //~^ ERROR patterns not allowed in naked function parameters + &b: &i32, + //~^ ERROR patterns not allowed in naked function parameters + (None | Some(_)): Option>, + //~^ ERROR patterns not allowed in naked function parameters + P { x, y }: P, + //~^ ERROR patterns not allowed in naked function parameters +) { + asm!("", options(noreturn)) +} + +#[naked] +pub unsafe extern "C" fn inc(a: u32) -> u32 { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + a + 1 + //~^ ERROR referencing function parameters is not allowed in naked functions +} + +#[naked] +pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { + asm!("/* {0} */", in(reg) a, options(noreturn)); + //~^ ERROR referencing function parameters is not allowed in naked functions + //~| WARN only `const` and `sym` operands are supported in naked functions + //~| WARN this was previously accepted +} + +#[naked] +pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + (|| a + 1)() +} + +#[naked] +pub unsafe extern "C" fn unsupported_operands() { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + let mut a = 0usize; + let mut b = 0usize; + let mut c = 0usize; + let mut d = 0usize; + let mut e = 0usize; + const F: usize = 0usize; + static G: usize = 0usize; + asm!("/* {0} {1} {2} {3} {4} {5} {6} */", + //~^ WARN asm in naked functions must use `noreturn` option + //~| WARN this was previously accepted + in(reg) a, + //~^ WARN only `const` and `sym` operands are supported in naked functions + //~| WARN this was previously accepted + inlateout(reg) b, + inout(reg) c, + lateout(reg) d, + out(reg) e, + const F, + sym G, + ); +} + +#[naked] +pub extern "C" fn missing_assembly() { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted +} + +#[naked] +pub extern "C" fn too_many_asm_blocks() { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + asm!(""); + //~^ WARN asm in naked functions must use `noreturn` option + //~| WARN this was previously accepted + asm!(""); + //~^ WARN asm in naked functions must use `noreturn` option + //~| WARN this was previously accepted + asm!(""); + //~^ WARN asm in naked functions must use `noreturn` option + //~| WARN this was previously accepted + asm!("", options(noreturn)); +} + +pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { + #[naked] + pub extern "C" fn inner(y: usize) -> usize { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + *&y + //~^ ERROR referencing function parameters is not allowed in naked functions + } + inner +} + +#[naked] +unsafe extern "C" fn llvm() -> ! { + //~^ WARN naked functions must contain a single asm block + //~| WARN this was previously accepted + llvm_asm!(""); + //~^ WARN LLVM-style inline assembly is unsupported in naked functions + //~| WARN this was previously accepted + core::hint::unreachable_unchecked(); +} + +#[naked] +unsafe extern "C" fn invalid_options() { + asm!("", options(nomem, preserves_flags, noreturn)); + //~^ WARN asm options unsupported in naked functions: `nomem`, `preserves_flags` + //~| WARN this was previously accepted +} + +#[naked] +unsafe extern "C" fn invalid_options_continued() { + asm!("", options(readonly, nostack), options(pure)); + //~^ ERROR asm with `pure` option must have at least one output + //~| WARN asm options unsupported in naked functions: `nostack`, `pure`, `readonly` + //~| WARN this was previously accepted + //~| WARN asm in naked functions must use `noreturn` option + //~| WARN this was previously accepted +} + +#[naked] +pub unsafe fn default_abi() { + //~^ WARN Rust ABI is unsupported in naked functions + //~| WARN this was previously accepted + asm!("", options(noreturn)); +} + +#[naked] +pub unsafe extern "Rust" fn rust_abi() { + //~^ WARN Rust ABI is unsupported in naked functions + //~| WARN this was previously accepted + asm!("", options(noreturn)); +} + +#[naked] +pub extern "C" fn valid_a() -> T { + unsafe { asm!("", options(noreturn)); } +} + +#[naked] +pub extern "C" fn valid_b() { + unsafe { { { + asm!("", options(noreturn)); ; ; ; + } ; } ; } +} + +#[naked] +pub unsafe extern "C" fn valid_c() { + asm!("", options(noreturn)); +} + +#[cfg(target_arch = "x86_64")] +#[naked] +pub unsafe extern "C" fn valid_att_syntax() { + asm!("", options(noreturn, att_syntax)); +} diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr new file mode 100644 index 00000000000..076289427b5 --- /dev/null +++ b/src/test/ui/asm/naked-functions.stderr @@ -0,0 +1,300 @@ +error: asm with `pure` option must have at least one output + --> $DIR/naked-functions.rs:126:14 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:13:5 + | +LL | mut a: u32, + | ^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:15:5 + | +LL | &b: &i32, + | ^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:17:6 + | +LL | (None | Some(_)): Option>, + | ^^^^^^^^^^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:19:5 + | +LL | P { x, y }: P, + | ^^^^^^^^^^ + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:29:5 + | +LL | a + 1 + | ^ + | + = help: follow the calling convention in asm block to use parameters + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:26:1 + | +LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 { +LL | | +LL | | +LL | | a + 1 + | | ----- non-asm is unsupported in naked functions +LL | | +LL | | } + | |_^ + | + = note: `#[warn(unsupported_naked_functions)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:35:31 + | +LL | asm!("/* {0} */", in(reg) a, options(noreturn)); + | ^ + | + = help: follow the calling convention in asm block to use parameters + +warning: only `const` and `sym` operands are supported in naked functions + --> $DIR/naked-functions.rs:35:23 + | +LL | asm!("/* {0} */", in(reg) a, options(noreturn)); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:42:1 + | +LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { +LL | | +LL | | +LL | | (|| a + 1)() + | | ------------ non-asm is unsupported in naked functions +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: only `const` and `sym` operands are supported in naked functions + --> $DIR/naked-functions.rs:62:10 + | +LL | in(reg) a, + | ^^^^^^^^^ +... +LL | inlateout(reg) b, + | ^^^^^^^^^^^^^^^^ +LL | inout(reg) c, + | ^^^^^^^^^^^^ +LL | lateout(reg) d, + | ^^^^^^^^^^^^^^ +LL | out(reg) e, + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:59:5 + | +LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */", +LL | | +LL | | +LL | | in(reg) a, +... | +LL | | sym G, +LL | | ); + | |______^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:49:1 + | +LL | / pub unsafe extern "C" fn unsupported_operands() { +LL | | +LL | | +LL | | let mut a = 0usize; + | | ------------------- non-asm is unsupported in naked functions +LL | | let mut b = 0usize; + | | ------------------- non-asm is unsupported in naked functions +LL | | let mut c = 0usize; + | | ------------------- non-asm is unsupported in naked functions +LL | | let mut d = 0usize; + | | ------------------- non-asm is unsupported in naked functions +LL | | let mut e = 0usize; + | | ------------------- non-asm is unsupported in naked functions +... | +LL | | ); +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:75:1 + | +LL | / pub extern "C" fn missing_assembly() { +LL | | +LL | | +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:84:5 + | +LL | asm!(""); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:87:5 + | +LL | asm!(""); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:90:5 + | +LL | asm!(""); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:81:1 + | +LL | / pub extern "C" fn too_many_asm_blocks() { +LL | | +LL | | +LL | | asm!(""); +... | +LL | | asm!(""); + | | --------- multiple asm blocks are unsupported in naked functions +... | +LL | | asm!(""); + | | --------- multiple asm blocks are unsupported in naked functions +... | +LL | | asm!("", options(noreturn)); + | | ---------------------------- multiple asm blocks are unsupported in naked functions +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:101:11 + | +LL | *&y + | ^ + | + = help: follow the calling convention in asm block to use parameters + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:98:5 + | +LL | / pub extern "C" fn inner(y: usize) -> usize { +LL | | +LL | | +LL | | *&y + | | --- non-asm is unsupported in naked functions +LL | | +LL | | } + | |_____^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: the LLVM-style inline assembly is unsupported in naked functions + --> $DIR/naked-functions.rs:111:5 + | +LL | llvm_asm!(""); + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + = help: use the new asm! syntax specified in RFC 2873 + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:108:1 + | +LL | / unsafe extern "C" fn llvm() -> ! { +LL | | +LL | | +LL | | llvm_asm!(""); +... | +LL | | core::hint::unreachable_unchecked(); + | | ------------------------------------ non-asm is unsupported in naked functions +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm options unsupported in naked functions: `nomem`, `preserves_flags` + --> $DIR/naked-functions.rs:119:5 + | +LL | asm!("", options(nomem, preserves_flags, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` + --> $DIR/naked-functions.rs:126:5 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:126:5 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: Rust ABI is unsupported in naked functions + --> $DIR/naked-functions.rs:135:15 + | +LL | pub unsafe fn default_abi() { + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: Rust ABI is unsupported in naked functions + --> $DIR/naked-functions.rs:142:29 + | +LL | pub unsafe extern "Rust" fn rust_abi() { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +error: aborting due to 8 previous errors; 19 warnings emitted + diff --git a/src/test/ui/asm/naked-params.rs b/src/test/ui/asm/naked-params.rs deleted file mode 100644 index 46a4fc11e5a..00000000000 --- a/src/test/ui/asm/naked-params.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Check that use of function parameters is validate in naked functions. -// -// ignore-wasm32 asm unsupported -#![feature(asm)] -#![feature(naked_functions)] -#![feature(or_patterns)] -#![crate_type = "lib"] - -#[repr(C)] -pub struct P { x: u8, y: u16 } - -#[naked] -pub unsafe extern "C" fn f( - mut a: u32, - //~^ ERROR patterns not allowed in naked function parameters - &b: &i32, - //~^ ERROR patterns not allowed in naked function parameters - (None | Some(_)): Option>, - //~^ ERROR patterns not allowed in naked function parameters - P { x, y }: P, - //~^ ERROR patterns not allowed in naked function parameters -) { - asm!("", options(noreturn)) -} - -#[naked] -pub unsafe extern "C" fn inc(a: u32) -> u32 { - a + 1 - //~^ ERROR use of parameters not allowed inside naked functions -} - -#[naked] -pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { - asm!("/* {0} */", in(reg) a, options(noreturn)); - //~^ ERROR use of parameters not allowed inside naked functions -} - -#[naked] -pub unsafe extern "C" fn sum(x: u32, y: u32) -> u32 { - // FIXME: Should be detected by asm-only check. - (|| { x + y})() -} - -pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { - #[naked] - pub extern "C" fn inner(y: usize) -> usize { - *&y - //~^ ERROR use of parameters not allowed inside naked functions - } - inner -} diff --git a/src/test/ui/asm/naked-params.stderr b/src/test/ui/asm/naked-params.stderr deleted file mode 100644 index 1a99e5109fc..00000000000 --- a/src/test/ui/asm/naked-params.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error: patterns not allowed in naked function parameters - --> $DIR/naked-params.rs:14:5 - | -LL | mut a: u32, - | ^^^^^ - -error: patterns not allowed in naked function parameters - --> $DIR/naked-params.rs:16:5 - | -LL | &b: &i32, - | ^^ - -error: patterns not allowed in naked function parameters - --> $DIR/naked-params.rs:18:6 - | -LL | (None | Some(_)): Option>, - | ^^^^^^^^^^^^^^ - -error: patterns not allowed in naked function parameters - --> $DIR/naked-params.rs:20:5 - | -LL | P { x, y }: P, - | ^^^^^^^^^^ - -error: use of parameters not allowed inside naked functions - --> $DIR/naked-params.rs:28:5 - | -LL | a + 1 - | ^ - -error: use of parameters not allowed inside naked functions - --> $DIR/naked-params.rs:34:31 - | -LL | asm!("/* {0} */", in(reg) a, options(noreturn)); - | ^ - -error: use of parameters not allowed inside naked functions - --> $DIR/naked-params.rs:47:11 - | -LL | *&y - | ^ - -error: aborting due to 7 previous errors - diff --git a/src/test/ui/auxiliary/extern-prelude-vec.rs b/src/test/ui/auxiliary/extern-prelude-vec.rs deleted file mode 100644 index a643c888910..00000000000 --- a/src/test/ui/auxiliary/extern-prelude-vec.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![crate_name = "Vec"] - -pub fn new(arg1: f32, arg2: ()) {} diff --git a/src/test/ui/auxiliary/extern-prelude.rs b/src/test/ui/auxiliary/extern-prelude.rs deleted file mode 100644 index 2fdfd85a1da..00000000000 --- a/src/test/ui/auxiliary/extern-prelude.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub struct S; - -impl S { - pub fn external(&self) {} -} diff --git a/src/test/ui/const-generics/issues/issue-62878.full.stderr b/src/test/ui/const-generics/issues/issue-62878.full.stderr index fc70be40497..dce2e27c71a 100644 --- a/src/test/ui/const-generics/issues/issue-62878.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.full.stderr @@ -9,6 +9,8 @@ error[E0747]: type provided when a constant was expected | LL | foo::<_, {[1]}>(); | ^ + | + = help: const arguments cannot yet be inferred with `_` error[E0308]: mismatched types --> $DIR/issue-62878.rs:11:15 diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.rs b/src/test/ui/const-generics/min_const_generics/inferred_const.rs new file mode 100644 index 00000000000..dcd069ce3b0 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/inferred_const.rs @@ -0,0 +1,8 @@ +#![feature(min_const_generics)] +fn foo(data: [u32; N]) -> [u32; K] { + [0; K] +} +fn main() { + let a = foo::<_, 2>([0, 1, 2]); + //~^ ERROR type provided when a constant was expected +} diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.stderr b/src/test/ui/const-generics/min_const_generics/inferred_const.stderr new file mode 100644 index 00000000000..e17105b2aa9 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/inferred_const.stderr @@ -0,0 +1,11 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/inferred_const.rs:6:19 + | +LL | let a = foo::<_, 2>([0, 1, 2]); + | ^ + | + = help: const arguments cannot yet be inferred with `_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/derives/issue-36617.rs b/src/test/ui/derives/issue-36617.rs new file mode 100644 index 00000000000..1102f3c4640 --- /dev/null +++ b/src/test/ui/derives/issue-36617.rs @@ -0,0 +1,4 @@ +#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions + //~| ERROR cannot determine resolution for the derive macro `Copy` + +fn main() {} diff --git a/src/test/ui/derives/issue-36617.stderr b/src/test/ui/derives/issue-36617.stderr new file mode 100644 index 00000000000..dc6ef169259 --- /dev/null +++ b/src/test/ui/derives/issue-36617.stderr @@ -0,0 +1,17 @@ +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-36617.rs:1:1 + | +LL | #![derive(Copy)] + | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]` + +error: cannot determine resolution for the derive macro `Copy` + --> $DIR/issue-36617.rs:1:11 + | +LL | #![derive(Copy)] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/double-import.rs b/src/test/ui/double-import.rs deleted file mode 100644 index e7325368b4d..00000000000 --- a/src/test/ui/double-import.rs +++ /dev/null @@ -1,15 +0,0 @@ -// This tests that conflicting imports shows both `use` lines -// when reporting the error. - -mod sub1 { - pub fn foo() {} // implementation 1 -} - -mod sub2 { - pub fn foo() {} // implementation 2 -} - -use sub1::foo; -use sub2::foo; //~ ERROR the name `foo` is defined multiple times - -fn main() {} diff --git a/src/test/ui/double-import.stderr b/src/test/ui/double-import.stderr deleted file mode 100644 index 7a4e8e5d3b9..00000000000 --- a/src/test/ui/double-import.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `foo` is defined multiple times - --> $DIR/double-import.rs:13:5 - | -LL | use sub1::foo; - | --------- previous import of the value `foo` here -LL | use sub2::foo; - | ^^^^^^^^^ `foo` reimported here - | - = note: `foo` must be defined only once in the value namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use sub2::foo as other_foo; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/env-vars.rs b/src/test/ui/env-vars.rs index f73902c4006..f5035bb2c69 100644 --- a/src/test/ui/env-vars.rs +++ b/src/test/ui/env-vars.rs @@ -5,6 +5,14 @@ fn main() { for (k, v) in vars_os() { + // On Windows, the environment variable NUMBER_OF_PROCESSORS has special meaning. + // Unfortunately, you can get different answers, depending on whether you are + // enumerating all environment variables or querying a specific variable. + // This was causing this test to fail on machines with more than 64 processors. + if cfg!(target_os = "windows") && k == "NUMBER_OF_PROCESSORS" { + continue; + } + let v2 = var_os(&k); assert!(v2.as_ref().map(|s| &**s) == Some(&*v), "bad vars->var transition: {:?} {:?} {:?}", k, v, v2); diff --git a/src/test/ui/error-codes/E0390.stderr b/src/test/ui/error-codes/E0390.stderr index 3ca3a77c74f..be47e93d19a 100644 --- a/src/test/ui/error-codes/E0390.stderr +++ b/src/test/ui/error-codes/E0390.stderr @@ -4,11 +4,7 @@ error[E0390]: only a single inherent implementation marked with `#[lang = "mut_p LL | impl *mut Foo {} | ^^^^^^^^^^^^^^^^ | -help: consider using a trait to implement these methods - --> $DIR/E0390.rs:5:1 - | -LL | impl *mut Foo {} - | ^^^^^^^^^^^^^^^^ + = help: consider using a trait error: aborting due to previous error diff --git a/src/test/ui/export-glob-imports-target.rs b/src/test/ui/export-glob-imports-target.rs deleted file mode 100644 index 4df807ea4c9..00000000000 --- a/src/test/ui/export-glob-imports-target.rs +++ /dev/null @@ -1,22 +0,0 @@ -// run-pass - -#![allow(non_upper_case_globals)] -#![allow(dead_code)] -// Test that a glob-export functions as an import -// when referenced within its own local scope. - -// Modified to not use export since it's going away. --pcw - -// pretty-expanded FIXME #23616 - -mod foo { - use foo::bar::*; - pub mod bar { - pub static a : isize = 10; - } - pub fn zum() { - let _b = a; - } -} - -pub fn main() { } diff --git a/src/test/ui/extern-prelude-fail.rs b/src/test/ui/extern-prelude-fail.rs deleted file mode 100644 index 7d387025ad4..00000000000 --- a/src/test/ui/extern-prelude-fail.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags:--extern extern_prelude -// aux-build:extern-prelude.rs - -// Extern prelude names are not available by absolute paths - -fn main() { - use extern_prelude::S; //~ ERROR unresolved import `extern_prelude` - let s = ::extern_prelude::S; //~ ERROR failed to resolve -} diff --git a/src/test/ui/extern-prelude-fail.stderr b/src/test/ui/extern-prelude-fail.stderr deleted file mode 100644 index a59f4c952bb..00000000000 --- a/src/test/ui/extern-prelude-fail.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0432]: unresolved import `extern_prelude` - --> $DIR/extern-prelude-fail.rs:7:9 - | -LL | use extern_prelude::S; - | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? - -error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`? - --> $DIR/extern-prelude-fail.rs:8:15 - | -LL | let s = ::extern_prelude::S; - | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0432, E0433. -For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/extern-prelude.rs b/src/test/ui/extern-prelude.rs deleted file mode 100644 index 50fed6034aa..00000000000 --- a/src/test/ui/extern-prelude.rs +++ /dev/null @@ -1,31 +0,0 @@ -// build-pass (FIXME(62277): could be check-pass?) -// compile-flags:--extern extern_prelude --extern Vec -// aux-build:extern-prelude.rs -// aux-build:extern-prelude-vec.rs - -fn basic() { - // It works - let s = extern_prelude::S; - s.external(); -} - -fn shadow_mod() { - // Local module shadows `extern_prelude` from extern prelude - mod extern_prelude { - pub struct S; - - impl S { - pub fn internal(&self) {} - } - } - - let s = extern_prelude::S; - s.internal(); // OK -} - -fn shadow_prelude() { - // Extern prelude shadows standard library prelude - let x = Vec::new(0f32, ()); // OK -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.rs b/src/test/ui/feature-gates/feature-gate-naked_functions.rs index 16a51a1e82f..06bddc422cf 100644 --- a/src/test/ui/feature-gates/feature-gate-naked_functions.rs +++ b/src/test/ui/feature-gates/feature-gate-naked_functions.rs @@ -1,11 +1,15 @@ +#![feature(asm)] + #[naked] //~^ the `#[naked]` attribute is an experimental feature -fn naked() {} +extern "C" fn naked() { + asm!("", options(noreturn)) +} #[naked] //~^ the `#[naked]` attribute is an experimental feature -fn naked_2() -> isize { - 0 +extern "C" fn naked_2() -> isize { + asm!("", options(noreturn)) } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr index e24dde5429d..d95561d2013 100644 --- a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:1:1 + --> $DIR/feature-gate-naked_functions.rs:3:1 | LL | #[naked] | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:5:1 + --> $DIR/feature-gate-naked_functions.rs:9:1 | LL | #[naked] | ^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs index dad8c2a2909..94dda17aad7 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -7,7 +7,7 @@ trait X { const _: () = { fn f1<'a>(arg : Box>) {} - //~^ ERROR: expected one of `>`, const, lifetime, or type, found `:` + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `:` //~| ERROR: expected parameter name, found `>` //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` //~| ERROR: constant provided when a type was expected @@ -15,7 +15,7 @@ fn f1<'a>(arg : Box>) {} const _: () = { fn f1<'a>(arg : Box>) {} - //~^ ERROR: expected one of `>`, const, lifetime, or type, found `=` + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `=` }; fn main() {} diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index 583697f0b67..8a5e2c29c36 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `:` +error: expected one of `>`, a const expression, lifetime, or type, found `:` --> $DIR/trait-path-missing-gen_arg.rs:9:30 | LL | fn f1<'a>(arg : Box>) {} - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type | help: expressions must be enclosed in braces to be used as const generic arguments | @@ -24,11 +24,11 @@ LL | fn f1<'a>(arg : Box>) {} | expected one of `!`, `)`, `+`, `,`, or `::` | help: missing `,` -error: expected one of `>`, const, lifetime, or type, found `=` +error: expected one of `>`, a const expression, lifetime, or type, found `=` --> $DIR/trait-path-missing-gen_arg.rs:17:30 | LL | fn f1<'a>(arg : Box>) {} - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/trait-path-missing-gen_arg.rs:1:12 diff --git a/src/test/ui/glob-resolve1.rs b/src/test/ui/glob-resolve1.rs deleted file mode 100644 index 32660fdb418..00000000000 --- a/src/test/ui/glob-resolve1.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Make sure that globs only bring in public things. - -use bar::*; - -mod bar { - use self::fpriv as import; - fn fpriv() {} - extern { - fn epriv(); - } - enum A { A1 } - pub enum B { B1 } - - struct C; - - type D = isize; -} - -fn foo() {} - -fn main() { - fpriv(); //~ ERROR cannot find function `fpriv` in this scope - epriv(); //~ ERROR cannot find function `epriv` in this scope - B; //~ ERROR expected value, found enum `B` - C; //~ ERROR cannot find value `C` in this scope - import(); //~ ERROR: cannot find function `import` in this scope - - foo::(); //~ ERROR: cannot find type `A` in this scope - foo::(); //~ ERROR: cannot find type `C` in this scope - foo::(); //~ ERROR: cannot find type `D` in this scope -} - -mod other { - pub fn import() {} -} diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr deleted file mode 100644 index cd128c1ea0b..00000000000 --- a/src/test/ui/glob-resolve1.stderr +++ /dev/null @@ -1,118 +0,0 @@ -error[E0425]: cannot find function `fpriv` in this scope - --> $DIR/glob-resolve1.rs:22:5 - | -LL | fpriv(); - | ^^^^^ not found in this scope - | -help: consider importing this function - | -LL | use bar::fpriv; - | - -error[E0425]: cannot find function `epriv` in this scope - --> $DIR/glob-resolve1.rs:23:5 - | -LL | epriv(); - | ^^^^^ not found in this scope - | -help: consider importing this function - | -LL | use bar::epriv; - | - -error[E0423]: expected value, found enum `B` - --> $DIR/glob-resolve1.rs:24:5 - | -LL | B; - | ^ - | -note: the enum is defined here - --> $DIR/glob-resolve1.rs:12:5 - | -LL | pub enum B { B1 } - | ^^^^^^^^^^^^^^^^^ -help: you might have meant to use the following enum variant - | -LL | B::B1; - | ^^^^^ - -error[E0425]: cannot find value `C` in this scope - --> $DIR/glob-resolve1.rs:25:5 - | -LL | C; - | ^ not found in this scope - | -help: consider importing this unit struct - | -LL | use bar::C; - | - -error[E0425]: cannot find function `import` in this scope - --> $DIR/glob-resolve1.rs:26:5 - | -LL | import(); - | ^^^^^^ not found in this scope - | -help: consider importing this function - | -LL | use other::import; - | - -error[E0412]: cannot find type `A` in this scope - --> $DIR/glob-resolve1.rs:28:11 - | -LL | pub enum B { B1 } - | ---------- similarly named enum `B` defined here -... -LL | foo::(); - | ^ - | -help: an enum with a similar name exists - | -LL | foo::(); - | ^ -help: consider importing this enum - | -LL | use bar::A; - | - -error[E0412]: cannot find type `C` in this scope - --> $DIR/glob-resolve1.rs:29:11 - | -LL | pub enum B { B1 } - | ---------- similarly named enum `B` defined here -... -LL | foo::(); - | ^ - | -help: an enum with a similar name exists - | -LL | foo::(); - | ^ -help: consider importing this struct - | -LL | use bar::C; - | - -error[E0412]: cannot find type `D` in this scope - --> $DIR/glob-resolve1.rs:30:11 - | -LL | pub enum B { B1 } - | ---------- similarly named enum `B` defined here -... -LL | foo::(); - | ^ - | -help: an enum with a similar name exists - | -LL | foo::(); - | ^ -help: consider importing this type alias - | -LL | use bar::D; - | - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0412, E0423, E0425. -For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/hidden-rt-injection.rs b/src/test/ui/hidden-rt-injection.rs deleted file mode 100644 index 3ca04f93493..00000000000 --- a/src/test/ui/hidden-rt-injection.rs +++ /dev/null @@ -1,8 +0,0 @@ -// This is testing that users can't access the runtime crate. - -mod m { - // The rt has been called both 'native' and 'rt' - use native; //~ ERROR unresolved import -} - -fn main() { } diff --git a/src/test/ui/hidden-rt-injection.stderr b/src/test/ui/hidden-rt-injection.stderr deleted file mode 100644 index 3e288b72ec6..00000000000 --- a/src/test/ui/hidden-rt-injection.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `native` - --> $DIR/hidden-rt-injection.rs:5:9 - | -LL | use native; - | ^^^^^^ no `native` in the root - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/hidden-rt-injection2.rs b/src/test/ui/hidden-rt-injection2.rs deleted file mode 100644 index 2af113c05e0..00000000000 --- a/src/test/ui/hidden-rt-injection2.rs +++ /dev/null @@ -1,8 +0,0 @@ -// This is testing that users can't access the runtime crate. - -mod m { - // The rt has been called both 'native' and 'rt' - use rt; //~ ERROR unresolved import -} - -fn main() { } diff --git a/src/test/ui/hidden-rt-injection2.stderr b/src/test/ui/hidden-rt-injection2.stderr deleted file mode 100644 index 73f89b5856d..00000000000 --- a/src/test/ui/hidden-rt-injection2.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `rt` - --> $DIR/hidden-rt-injection2.rs:5:9 - | -LL | use rt; - | ^^ no `rt` in the root - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/import.rs b/src/test/ui/import.rs deleted file mode 100644 index 3170dd2fae1..00000000000 --- a/src/test/ui/import.rs +++ /dev/null @@ -1,17 +0,0 @@ -use zed::bar; -use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432] - //~| no `baz` in `zed` - //~| HELP a similar name exists in the module - //~| SUGGESTION bar - - -mod zed { - pub fn bar() { println!("bar"); } - use foo; //~ ERROR unresolved import `foo` [E0432] - //~^ no `foo` in the root -} - -fn main() { - zed::foo(); //~ ERROR `foo` is private - bar(); -} diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr deleted file mode 100644 index 797712e2db9..00000000000 --- a/src/test/ui/import.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0432]: unresolved import `zed::baz` - --> $DIR/import.rs:2:5 - | -LL | use zed::baz; - | ^^^^^--- - | | | - | | help: a similar name exists in the module: `bar` - | no `baz` in `zed` - -error[E0432]: unresolved import `foo` - --> $DIR/import.rs:10:9 - | -LL | use foo; - | ^^^ no `foo` in the root - -error[E0603]: unresolved item import `foo` is private - --> $DIR/import.rs:15:10 - | -LL | zed::foo(); - | ^^^ private unresolved item import - | -note: the unresolved item import `foo` is defined here - --> $DIR/import.rs:10:9 - | -LL | use foo; - | ^^^ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0432, E0603. -For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/import2.rs b/src/test/ui/import2.rs deleted file mode 100644 index 036d6bc07e2..00000000000 --- a/src/test/ui/import2.rs +++ /dev/null @@ -1,10 +0,0 @@ -use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432] - //~^ could not find `zed` in `baz` - -mod baz {} -mod zed { - pub fn bar() { println!("bar3"); } -} -fn main() { - bar(); -} diff --git a/src/test/ui/import2.stderr b/src/test/ui/import2.stderr deleted file mode 100644 index da888979c30..00000000000 --- a/src/test/ui/import2.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `baz::zed` - --> $DIR/import2.rs:1:10 - | -LL | use baz::zed::bar; - | ^^^ could not find `zed` in `baz` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/import3.rs b/src/test/ui/import3.rs deleted file mode 100644 index 2c6ac9a00e1..00000000000 --- a/src/test/ui/import3.rs +++ /dev/null @@ -1,4 +0,0 @@ -// error-pattern: unresolved -use main::bar; - -fn main() { println!("foo"); } diff --git a/src/test/ui/import3.stderr b/src/test/ui/import3.stderr deleted file mode 100644 index 7bb413be59f..00000000000 --- a/src/test/ui/import3.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `main` - --> $DIR/import3.rs:2:5 - | -LL | use main::bar; - | ^^^^ maybe a missing crate `main`? - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/import4.rs b/src/test/ui/import4.rs deleted file mode 100644 index ba3b7fbf535..00000000000 --- a/src/test/ui/import4.rs +++ /dev/null @@ -1,7 +0,0 @@ -// error-pattern: import - - -mod a { pub use b::foo; } -mod b { pub use a::foo; } - -fn main() { println!("loop"); } diff --git a/src/test/ui/import4.stderr b/src/test/ui/import4.stderr deleted file mode 100644 index e0b478f1aec..00000000000 --- a/src/test/ui/import4.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `a::foo` - --> $DIR/import4.rs:5:17 - | -LL | mod b { pub use a::foo; } - | ^^^^^^ no `foo` in `a` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/auxiliary/issue-36881-aux.rs b/src/test/ui/imports/auxiliary/issue-36881-aux.rs new file mode 100644 index 00000000000..e373b64384f --- /dev/null +++ b/src/test/ui/imports/auxiliary/issue-36881-aux.rs @@ -0,0 +1 @@ +pub trait Foo {} diff --git a/src/test/ui/imports/auxiliary/issue-52891.rs b/src/test/ui/imports/auxiliary/issue-52891.rs new file mode 100644 index 00000000000..07598118322 --- /dev/null +++ b/src/test/ui/imports/auxiliary/issue-52891.rs @@ -0,0 +1,33 @@ +pub mod a { + pub mod inner { + } +} + +pub mod b { + pub mod inner { + } +} + +pub mod c {} + +pub mod d {} + +pub mod e {} + +pub mod f {} + +pub mod g {} + +pub mod h {} + +pub mod i {} + +pub mod j {} + +pub mod k {} + +pub mod l {} + +pub mod m {} + +pub mod n {} diff --git a/src/test/ui/imports/auxiliary/issue-59764.rs b/src/test/ui/imports/auxiliary/issue-59764.rs new file mode 100644 index 00000000000..a92eed968d0 --- /dev/null +++ b/src/test/ui/imports/auxiliary/issue-59764.rs @@ -0,0 +1,18 @@ +pub mod foo { + #[macro_export] + macro_rules! makro { + ($foo:ident) => { + fn $foo() { } + } + } + + pub fn baz() {} + + pub fn foobar() {} + + pub mod barbaz { + pub fn barfoo() {} + } +} + +pub fn foobaz() {} diff --git a/src/test/ui/imports/double-import.rs b/src/test/ui/imports/double-import.rs new file mode 100644 index 00000000000..e7325368b4d --- /dev/null +++ b/src/test/ui/imports/double-import.rs @@ -0,0 +1,15 @@ +// This tests that conflicting imports shows both `use` lines +// when reporting the error. + +mod sub1 { + pub fn foo() {} // implementation 1 +} + +mod sub2 { + pub fn foo() {} // implementation 2 +} + +use sub1::foo; +use sub2::foo; //~ ERROR the name `foo` is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/double-import.stderr b/src/test/ui/imports/double-import.stderr new file mode 100644 index 00000000000..7a4e8e5d3b9 --- /dev/null +++ b/src/test/ui/imports/double-import.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `foo` is defined multiple times + --> $DIR/double-import.rs:13:5 + | +LL | use sub1::foo; + | --------- previous import of the value `foo` here +LL | use sub2::foo; + | ^^^^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use sub2::foo as other_foo; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/export-glob-imports-target.rs b/src/test/ui/imports/export-glob-imports-target.rs new file mode 100644 index 00000000000..4df807ea4c9 --- /dev/null +++ b/src/test/ui/imports/export-glob-imports-target.rs @@ -0,0 +1,22 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +// Test that a glob-export functions as an import +// when referenced within its own local scope. + +// Modified to not use export since it's going away. --pcw + +// pretty-expanded FIXME #23616 + +mod foo { + use foo::bar::*; + pub mod bar { + pub static a : isize = 10; + } + pub fn zum() { + let _b = a; + } +} + +pub fn main() { } diff --git a/src/test/ui/imports/glob-resolve1.rs b/src/test/ui/imports/glob-resolve1.rs new file mode 100644 index 00000000000..32660fdb418 --- /dev/null +++ b/src/test/ui/imports/glob-resolve1.rs @@ -0,0 +1,35 @@ +// Make sure that globs only bring in public things. + +use bar::*; + +mod bar { + use self::fpriv as import; + fn fpriv() {} + extern { + fn epriv(); + } + enum A { A1 } + pub enum B { B1 } + + struct C; + + type D = isize; +} + +fn foo() {} + +fn main() { + fpriv(); //~ ERROR cannot find function `fpriv` in this scope + epriv(); //~ ERROR cannot find function `epriv` in this scope + B; //~ ERROR expected value, found enum `B` + C; //~ ERROR cannot find value `C` in this scope + import(); //~ ERROR: cannot find function `import` in this scope + + foo::(); //~ ERROR: cannot find type `A` in this scope + foo::(); //~ ERROR: cannot find type `C` in this scope + foo::(); //~ ERROR: cannot find type `D` in this scope +} + +mod other { + pub fn import() {} +} diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr new file mode 100644 index 00000000000..cd128c1ea0b --- /dev/null +++ b/src/test/ui/imports/glob-resolve1.stderr @@ -0,0 +1,118 @@ +error[E0425]: cannot find function `fpriv` in this scope + --> $DIR/glob-resolve1.rs:22:5 + | +LL | fpriv(); + | ^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use bar::fpriv; + | + +error[E0425]: cannot find function `epriv` in this scope + --> $DIR/glob-resolve1.rs:23:5 + | +LL | epriv(); + | ^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use bar::epriv; + | + +error[E0423]: expected value, found enum `B` + --> $DIR/glob-resolve1.rs:24:5 + | +LL | B; + | ^ + | +note: the enum is defined here + --> $DIR/glob-resolve1.rs:12:5 + | +LL | pub enum B { B1 } + | ^^^^^^^^^^^^^^^^^ +help: you might have meant to use the following enum variant + | +LL | B::B1; + | ^^^^^ + +error[E0425]: cannot find value `C` in this scope + --> $DIR/glob-resolve1.rs:25:5 + | +LL | C; + | ^ not found in this scope + | +help: consider importing this unit struct + | +LL | use bar::C; + | + +error[E0425]: cannot find function `import` in this scope + --> $DIR/glob-resolve1.rs:26:5 + | +LL | import(); + | ^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use other::import; + | + +error[E0412]: cannot find type `A` in this scope + --> $DIR/glob-resolve1.rs:28:11 + | +LL | pub enum B { B1 } + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ + | +help: an enum with a similar name exists + | +LL | foo::(); + | ^ +help: consider importing this enum + | +LL | use bar::A; + | + +error[E0412]: cannot find type `C` in this scope + --> $DIR/glob-resolve1.rs:29:11 + | +LL | pub enum B { B1 } + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ + | +help: an enum with a similar name exists + | +LL | foo::(); + | ^ +help: consider importing this struct + | +LL | use bar::C; + | + +error[E0412]: cannot find type `D` in this scope + --> $DIR/glob-resolve1.rs:30:11 + | +LL | pub enum B { B1 } + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ + | +help: an enum with a similar name exists + | +LL | foo::(); + | ^ +help: consider importing this type alias + | +LL | use bar::D; + | + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0412, E0423, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/imports/import-rpass.rs b/src/test/ui/imports/import-rpass.rs new file mode 100644 index 00000000000..de8bf626114 --- /dev/null +++ b/src/test/ui/imports/import-rpass.rs @@ -0,0 +1,12 @@ +// run-pass +mod foo { + pub fn x(y: isize) { println!("{}", y); } +} + +mod bar { + use foo::x; + use foo::x as z; + pub fn thing() { x(10); z(10); } +} + +pub fn main() { bar::thing(); } diff --git a/src/test/ui/imports/import.rs b/src/test/ui/imports/import.rs index de8bf626114..3170dd2fae1 100644 --- a/src/test/ui/imports/import.rs +++ b/src/test/ui/imports/import.rs @@ -1,12 +1,17 @@ -// run-pass -mod foo { - pub fn x(y: isize) { println!("{}", y); } -} +use zed::bar; +use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432] + //~| no `baz` in `zed` + //~| HELP a similar name exists in the module + //~| SUGGESTION bar + -mod bar { - use foo::x; - use foo::x as z; - pub fn thing() { x(10); z(10); } +mod zed { + pub fn bar() { println!("bar"); } + use foo; //~ ERROR unresolved import `foo` [E0432] + //~^ no `foo` in the root } -pub fn main() { bar::thing(); } +fn main() { + zed::foo(); //~ ERROR `foo` is private + bar(); +} diff --git a/src/test/ui/imports/import.stderr b/src/test/ui/imports/import.stderr new file mode 100644 index 00000000000..797712e2db9 --- /dev/null +++ b/src/test/ui/imports/import.stderr @@ -0,0 +1,31 @@ +error[E0432]: unresolved import `zed::baz` + --> $DIR/import.rs:2:5 + | +LL | use zed::baz; + | ^^^^^--- + | | | + | | help: a similar name exists in the module: `bar` + | no `baz` in `zed` + +error[E0432]: unresolved import `foo` + --> $DIR/import.rs:10:9 + | +LL | use foo; + | ^^^ no `foo` in the root + +error[E0603]: unresolved item import `foo` is private + --> $DIR/import.rs:15:10 + | +LL | zed::foo(); + | ^^^ private unresolved item import + | +note: the unresolved item import `foo` is defined here + --> $DIR/import.rs:10:9 + | +LL | use foo; + | ^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0432, E0603. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/import2-rpass.rs b/src/test/ui/imports/import2-rpass.rs new file mode 100644 index 00000000000..7b70f799ebf --- /dev/null +++ b/src/test/ui/imports/import2-rpass.rs @@ -0,0 +1,9 @@ +// run-pass + +use zed::bar; + +mod zed { + pub fn bar() { println!("bar"); } +} + +pub fn main() { bar(); } diff --git a/src/test/ui/imports/import2.rs b/src/test/ui/imports/import2.rs index 7b70f799ebf..036d6bc07e2 100644 --- a/src/test/ui/imports/import2.rs +++ b/src/test/ui/imports/import2.rs @@ -1,9 +1,10 @@ -// run-pass - -use zed::bar; +use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432] + //~^ could not find `zed` in `baz` +mod baz {} mod zed { - pub fn bar() { println!("bar"); } + pub fn bar() { println!("bar3"); } +} +fn main() { + bar(); } - -pub fn main() { bar(); } diff --git a/src/test/ui/imports/import2.stderr b/src/test/ui/imports/import2.stderr new file mode 100644 index 00000000000..da888979c30 --- /dev/null +++ b/src/test/ui/imports/import2.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `baz::zed` + --> $DIR/import2.rs:1:10 + | +LL | use baz::zed::bar; + | ^^^ could not find `zed` in `baz` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/import3-rpass.rs b/src/test/ui/imports/import3-rpass.rs new file mode 100644 index 00000000000..17797aed359 --- /dev/null +++ b/src/test/ui/imports/import3-rpass.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_imports)] + +use baz::zed; +use baz::zed::bar; + +mod baz { + pub mod zed { + pub fn bar() { println!("bar2"); } + } +} + +pub fn main() { bar(); } diff --git a/src/test/ui/imports/import3.rs b/src/test/ui/imports/import3.rs index 17797aed359..2c6ac9a00e1 100644 --- a/src/test/ui/imports/import3.rs +++ b/src/test/ui/imports/import3.rs @@ -1,13 +1,4 @@ -// run-pass -#![allow(unused_imports)] +// error-pattern: unresolved +use main::bar; -use baz::zed; -use baz::zed::bar; - -mod baz { - pub mod zed { - pub fn bar() { println!("bar2"); } - } -} - -pub fn main() { bar(); } +fn main() { println!("foo"); } diff --git a/src/test/ui/imports/import3.stderr b/src/test/ui/imports/import3.stderr new file mode 100644 index 00000000000..7bb413be59f --- /dev/null +++ b/src/test/ui/imports/import3.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `main` + --> $DIR/import3.rs:2:5 + | +LL | use main::bar; + | ^^^^ maybe a missing crate `main`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/import4-rpass.rs b/src/test/ui/imports/import4-rpass.rs new file mode 100644 index 00000000000..4fda5386112 --- /dev/null +++ b/src/test/ui/imports/import4-rpass.rs @@ -0,0 +1,9 @@ +// run-pass + +use zed::bar; + +mod zed { + pub fn bar() { println!("bar"); } +} + +pub fn main() { let _zed = 42; bar(); } diff --git a/src/test/ui/imports/import4.rs b/src/test/ui/imports/import4.rs index 4fda5386112..ba3b7fbf535 100644 --- a/src/test/ui/imports/import4.rs +++ b/src/test/ui/imports/import4.rs @@ -1,9 +1,7 @@ -// run-pass +// error-pattern: import -use zed::bar; -mod zed { - pub fn bar() { println!("bar"); } -} +mod a { pub use b::foo; } +mod b { pub use a::foo; } -pub fn main() { let _zed = 42; bar(); } +fn main() { println!("loop"); } diff --git a/src/test/ui/imports/import4.stderr b/src/test/ui/imports/import4.stderr new file mode 100644 index 00000000000..e0b478f1aec --- /dev/null +++ b/src/test/ui/imports/import4.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `a::foo` + --> $DIR/import4.rs:5:17 + | +LL | mod b { pub use a::foo; } + | ^^^^^^ no `foo` in `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-13404.rs b/src/test/ui/imports/issue-13404.rs new file mode 100644 index 00000000000..c5af827d50c --- /dev/null +++ b/src/test/ui/imports/issue-13404.rs @@ -0,0 +1,10 @@ +use a::f; +use b::f; //~ ERROR: unresolved import `b::f` [E0432] + //~^ no `f` in `b` + +mod a { pub fn f() {} } +mod b { } + +fn main() { + f(); +} diff --git a/src/test/ui/imports/issue-13404.stderr b/src/test/ui/imports/issue-13404.stderr new file mode 100644 index 00000000000..1f50debb07b --- /dev/null +++ b/src/test/ui/imports/issue-13404.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `b::f` + --> $DIR/issue-13404.rs:2:5 + | +LL | use b::f; + | ^^^^ no `f` in `b` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-1697.rs b/src/test/ui/imports/issue-1697.rs new file mode 100644 index 00000000000..5cd76d21f91 --- /dev/null +++ b/src/test/ui/imports/issue-1697.rs @@ -0,0 +1,6 @@ +// Testing that we don't fail abnormally after hitting the errors + +use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432] + //~^ maybe a missing crate `unresolved`? + +fn main() {} diff --git a/src/test/ui/imports/issue-1697.stderr b/src/test/ui/imports/issue-1697.stderr new file mode 100644 index 00000000000..a76fd309914 --- /dev/null +++ b/src/test/ui/imports/issue-1697.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `unresolved` + --> $DIR/issue-1697.rs:3:5 + | +LL | use unresolved::*; + | ^^^^^^^^^^ maybe a missing crate `unresolved`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-18083.rs b/src/test/ui/imports/issue-18083.rs new file mode 100644 index 00000000000..36420ec142e --- /dev/null +++ b/src/test/ui/imports/issue-18083.rs @@ -0,0 +1,25 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_imports)] +// These crossed imports should resolve fine, and not block on +// each other and be reported as unresolved. + +mod a { + use b::{B}; + pub use self::inner::A; + + mod inner { + pub struct A; + } +} + +mod b { + use a::{A}; + pub use self::inner::B; + + mod inner { + pub struct B; + } +} + +fn main() {} diff --git a/src/test/ui/imports/issue-19498.rs b/src/test/ui/imports/issue-19498.rs new file mode 100644 index 00000000000..5fe6742f55e --- /dev/null +++ b/src/test/ui/imports/issue-19498.rs @@ -0,0 +1,13 @@ +use self::A; +use self::B; +mod A {} //~ ERROR the name `A` is defined multiple times +//~| `A` redefined here +pub mod B {} //~ ERROR the name `B` is defined multiple times +//~| `B` redefined here +mod C { + use C::D; + mod D {} //~ ERROR the name `D` is defined multiple times + //~| `D` redefined here +} + +fn main() {} diff --git a/src/test/ui/imports/issue-19498.stderr b/src/test/ui/imports/issue-19498.stderr new file mode 100644 index 00000000000..cc1d649d610 --- /dev/null +++ b/src/test/ui/imports/issue-19498.stderr @@ -0,0 +1,47 @@ +error[E0255]: the name `A` is defined multiple times + --> $DIR/issue-19498.rs:3:1 + | +LL | use self::A; + | ------- previous import of the module `A` here +LL | use self::B; +LL | mod A {} + | ^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use self::A as OtherA; + | ^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `B` is defined multiple times + --> $DIR/issue-19498.rs:5:1 + | +LL | use self::B; + | ------- previous import of the module `B` here +... +LL | pub mod B {} + | ^^^^^^^^^ `B` redefined here + | + = note: `B` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use self::B as OtherB; + | ^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `D` is defined multiple times + --> $DIR/issue-19498.rs:9:5 + | +LL | use C::D; + | ---- previous import of the module `D` here +LL | mod D {} + | ^^^^^ `D` redefined here + | + = note: `D` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use C::D as OtherD; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/imports/issue-24081.rs b/src/test/ui/imports/issue-24081.rs new file mode 100644 index 00000000000..10983ce11b5 --- /dev/null +++ b/src/test/ui/imports/issue-24081.rs @@ -0,0 +1,18 @@ +use std::ops::Add; +use std::ops::Sub; +use std::ops::Mul; +use std::ops::Div; +use std::ops::Rem; + +type Add = bool; //~ ERROR the name `Add` is defined multiple times +//~| `Add` redefined here +struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times +//~| `Sub` redefined here +enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times +//~| `Mul` redefined here +mod Div { } //~ ERROR the name `Div` is defined multiple times +//~| `Div` redefined here +trait Rem { } //~ ERROR the name `Rem` is defined multiple times +//~| `Rem` redefined here + +fn main() {} diff --git a/src/test/ui/imports/issue-24081.stderr b/src/test/ui/imports/issue-24081.stderr new file mode 100644 index 00000000000..647048c7c20 --- /dev/null +++ b/src/test/ui/imports/issue-24081.stderr @@ -0,0 +1,78 @@ +error[E0255]: the name `Add` is defined multiple times + --> $DIR/issue-24081.rs:7:1 + | +LL | use std::ops::Add; + | ------------- previous import of the trait `Add` here +... +LL | type Add = bool; + | ^^^^^^^^^^^^^^^^ `Add` redefined here + | + = note: `Add` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Add as OtherAdd; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `Sub` is defined multiple times + --> $DIR/issue-24081.rs:9:1 + | +LL | use std::ops::Sub; + | ------------- previous import of the trait `Sub` here +... +LL | struct Sub { x: f32 } + | ^^^^^^^^^^ `Sub` redefined here + | + = note: `Sub` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Sub as OtherSub; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `Mul` is defined multiple times + --> $DIR/issue-24081.rs:11:1 + | +LL | use std::ops::Mul; + | ------------- previous import of the trait `Mul` here +... +LL | enum Mul { A, B } + | ^^^^^^^^ `Mul` redefined here + | + = note: `Mul` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Mul as OtherMul; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `Div` is defined multiple times + --> $DIR/issue-24081.rs:13:1 + | +LL | use std::ops::Div; + | ------------- previous import of the trait `Div` here +... +LL | mod Div { } + | ^^^^^^^ `Div` redefined here + | + = note: `Div` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Div as OtherDiv; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `Rem` is defined multiple times + --> $DIR/issue-24081.rs:15:1 + | +LL | use std::ops::Rem; + | ------------- previous import of the trait `Rem` here +... +LL | trait Rem { } + | ^^^^^^^^^ `Rem` redefined here + | + = note: `Rem` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Rem as OtherRem; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/imports/issue-25396.rs b/src/test/ui/imports/issue-25396.rs new file mode 100644 index 00000000000..301658d2344 --- /dev/null +++ b/src/test/ui/imports/issue-25396.rs @@ -0,0 +1,29 @@ +#![allow(non_camel_case_types)] + +use foo::baz; +use bar::baz; //~ ERROR the name `baz` is defined multiple times + +use foo::Quux; +use bar::Quux; //~ ERROR the name `Quux` is defined multiple times + +use foo::blah; +use bar::blah; //~ ERROR the name `blah` is defined multiple times + +use foo::WOMP; +use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times + +fn main() {} + +mod foo { + pub mod baz {} + pub trait Quux { } + pub type blah = (f64, u32); + pub const WOMP: u8 = 5; +} + +mod bar { + pub mod baz {} + pub type Quux = i32; + pub struct blah { x: i8 } + pub const WOMP: i8 = -5; +} diff --git a/src/test/ui/imports/issue-25396.stderr b/src/test/ui/imports/issue-25396.stderr new file mode 100644 index 00000000000..38dc9ef1035 --- /dev/null +++ b/src/test/ui/imports/issue-25396.stderr @@ -0,0 +1,59 @@ +error[E0252]: the name `baz` is defined multiple times + --> $DIR/issue-25396.rs:4:5 + | +LL | use foo::baz; + | -------- previous import of the module `baz` here +LL | use bar::baz; + | ^^^^^^^^ `baz` reimported here + | + = note: `baz` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::baz as other_baz; + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0252]: the name `Quux` is defined multiple times + --> $DIR/issue-25396.rs:7:5 + | +LL | use foo::Quux; + | --------- previous import of the trait `Quux` here +LL | use bar::Quux; + | ^^^^^^^^^ `Quux` reimported here + | + = note: `Quux` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::Quux as OtherQuux; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0252]: the name `blah` is defined multiple times + --> $DIR/issue-25396.rs:10:5 + | +LL | use foo::blah; + | --------- previous import of the type `blah` here +LL | use bar::blah; + | ^^^^^^^^^ `blah` reimported here + | + = note: `blah` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::blah as other_blah; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0252]: the name `WOMP` is defined multiple times + --> $DIR/issue-25396.rs:13:5 + | +LL | use foo::WOMP; + | --------- previous import of the value `WOMP` here +LL | use bar::WOMP; + | ^^^^^^^^^ `WOMP` reimported here + | + = note: `WOMP` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::WOMP as OtherWOMP; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-26886.rs b/src/test/ui/imports/issue-26886.rs new file mode 100644 index 00000000000..6e6d406c656 --- /dev/null +++ b/src/test/ui/imports/issue-26886.rs @@ -0,0 +1,8 @@ +use std::sync::{self, Arc}; +use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times + //~| `Arc` must be defined only once in the type namespace of this module +use std::sync; //~ ERROR the name `sync` is defined multiple times + //~| `sync` must be defined only once in the type namespace of this module + +fn main() { +} diff --git a/src/test/ui/imports/issue-26886.stderr b/src/test/ui/imports/issue-26886.stderr new file mode 100644 index 00000000000..e2b925ec5a7 --- /dev/null +++ b/src/test/ui/imports/issue-26886.stderr @@ -0,0 +1,24 @@ +error[E0252]: the name `Arc` is defined multiple times + --> $DIR/issue-26886.rs:2:5 + | +LL | use std::sync::{self, Arc}; + | --- previous import of the type `Arc` here +LL | use std::sync::Arc; + | ^^^^^^^^^^^^^^ `Arc` reimported here + | + = note: `Arc` must be defined only once in the type namespace of this module + +error[E0252]: the name `sync` is defined multiple times + --> $DIR/issue-26886.rs:4:5 + | +LL | use std::sync::{self, Arc}; + | ---- previous import of the module `sync` here +... +LL | use std::sync; + | ^^^^^^^^^ `sync` reimported here + | + = note: `sync` must be defined only once in the type namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-28134.rs b/src/test/ui/imports/issue-28134.rs new file mode 100644 index 00000000000..1ed2d330b51 --- /dev/null +++ b/src/test/ui/imports/issue-28134.rs @@ -0,0 +1,4 @@ +// compile-flags: --test + +#![allow(soft_unstable)] +#![test] //~ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/imports/issue-28134.stderr b/src/test/ui/imports/issue-28134.stderr new file mode 100644 index 00000000000..8ed4d015f32 --- /dev/null +++ b/src/test/ui/imports/issue-28134.stderr @@ -0,0 +1,10 @@ +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-28134.rs:4:4 + | +LL | #![test] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to previous error + diff --git a/src/test/ui/imports/issue-28388-1.rs b/src/test/ui/imports/issue-28388-1.rs new file mode 100644 index 00000000000..14de621405d --- /dev/null +++ b/src/test/ui/imports/issue-28388-1.rs @@ -0,0 +1,5 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +use foo::{}; //~ ERROR unresolved import `foo` + +fn main() {} diff --git a/src/test/ui/imports/issue-28388-1.stderr b/src/test/ui/imports/issue-28388-1.stderr new file mode 100644 index 00000000000..7f5e47aa84f --- /dev/null +++ b/src/test/ui/imports/issue-28388-1.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `foo` + --> $DIR/issue-28388-1.rs:3:5 + | +LL | use foo::{}; + | ^^^^^^^ no `foo` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-28388-2.rs b/src/test/ui/imports/issue-28388-2.rs new file mode 100644 index 00000000000..024b0388bc6 --- /dev/null +++ b/src/test/ui/imports/issue-28388-2.rs @@ -0,0 +1,10 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +mod m { + mod n {} +} + +use m::n::{}; +//~^ ERROR module `n` is private + +fn main() {} diff --git a/src/test/ui/imports/issue-28388-2.stderr b/src/test/ui/imports/issue-28388-2.stderr new file mode 100644 index 00000000000..1afaf622be7 --- /dev/null +++ b/src/test/ui/imports/issue-28388-2.stderr @@ -0,0 +1,15 @@ +error[E0603]: module `n` is private + --> $DIR/issue-28388-2.rs:7:8 + | +LL | use m::n::{}; + | ^ private module + | +note: the module `n` is defined here + --> $DIR/issue-28388-2.rs:4:5 + | +LL | mod n {} + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/imports/issue-2937.rs b/src/test/ui/imports/issue-2937.rs new file mode 100644 index 00000000000..335df5c07e2 --- /dev/null +++ b/src/test/ui/imports/issue-2937.rs @@ -0,0 +1,6 @@ +use m::f as x; //~ ERROR unresolved import `m::f` [E0432] + //~^ no `f` in `m` + +mod m {} + +fn main() {} diff --git a/src/test/ui/imports/issue-2937.stderr b/src/test/ui/imports/issue-2937.stderr new file mode 100644 index 00000000000..428634828f9 --- /dev/null +++ b/src/test/ui/imports/issue-2937.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `m::f` + --> $DIR/issue-2937.rs:1:5 + | +LL | use m::f as x; + | ^^^^^^^^^ no `f` in `m` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-30560.rs b/src/test/ui/imports/issue-30560.rs new file mode 100644 index 00000000000..d8d4ca608f1 --- /dev/null +++ b/src/test/ui/imports/issue-30560.rs @@ -0,0 +1,9 @@ +type Alias = (); +use Alias::*; //~ ERROR unresolved import `Alias` [E0432] + +use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432] + +trait T {} +use T::*; //~ ERROR items in traits are not importable + +fn main() {} diff --git a/src/test/ui/imports/issue-30560.stderr b/src/test/ui/imports/issue-30560.stderr new file mode 100644 index 00000000000..b74134aaccc --- /dev/null +++ b/src/test/ui/imports/issue-30560.stderr @@ -0,0 +1,21 @@ +error: items in traits are not importable. + --> $DIR/issue-30560.rs:7:5 + | +LL | use T::*; + | ^^^^ + +error[E0432]: unresolved import `Alias` + --> $DIR/issue-30560.rs:2:5 + | +LL | use Alias::*; + | ^^^^^ `Alias` is a type alias, not a module + +error[E0432]: unresolved import `std::io::Result` + --> $DIR/issue-30560.rs:4:14 + | +LL | use std::io::Result::*; + | ^^^^^^ `Result` is a type alias, not a module + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-31212.rs b/src/test/ui/imports/issue-31212.rs new file mode 100644 index 00000000000..556f0d18f9f --- /dev/null +++ b/src/test/ui/imports/issue-31212.rs @@ -0,0 +1,10 @@ +// This checks that a path that cannot be resolved because of an indeterminate import +// does not trigger an ICE. + +mod foo { + pub use self::*; //~ ERROR unresolved +} + +fn main() { + foo::f(); //~ ERROR cannot find function `f` in module `foo` +} diff --git a/src/test/ui/imports/issue-31212.stderr b/src/test/ui/imports/issue-31212.stderr new file mode 100644 index 00000000000..0bb56b361cb --- /dev/null +++ b/src/test/ui/imports/issue-31212.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::*` + --> $DIR/issue-31212.rs:5:13 + | +LL | pub use self::*; + | ^^^^^^^ cannot glob-import a module into itself + +error[E0425]: cannot find function `f` in module `foo` + --> $DIR/issue-31212.rs:9:10 + | +LL | foo::f(); + | ^ not found in `foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.fixed b/src/test/ui/imports/issue-32354-suggest-import-rename.fixed new file mode 100644 index 00000000000..27f1b8964e2 --- /dev/null +++ b/src/test/ui/imports/issue-32354-suggest-import-rename.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_imports)] + +pub mod extension1 { + pub trait ConstructorExtension {} +} + +pub mod extension2 { + pub trait ConstructorExtension {} +} + +use extension1::ConstructorExtension; +use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.rs b/src/test/ui/imports/issue-32354-suggest-import-rename.rs new file mode 100644 index 00000000000..5a7f234d5fa --- /dev/null +++ b/src/test/ui/imports/issue-32354-suggest-import-rename.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_imports)] + +pub mod extension1 { + pub trait ConstructorExtension {} +} + +pub mod extension2 { + pub trait ConstructorExtension {} +} + +use extension1::ConstructorExtension; +use extension2::ConstructorExtension; //~ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.stderr b/src/test/ui/imports/issue-32354-suggest-import-rename.stderr new file mode 100644 index 00000000000..96684309a00 --- /dev/null +++ b/src/test/ui/imports/issue-32354-suggest-import-rename.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `ConstructorExtension` is defined multiple times + --> $DIR/issue-32354-suggest-import-rename.rs:14:5 + | +LL | use extension1::ConstructorExtension; + | -------------------------------- previous import of the trait `ConstructorExtension` here +LL | use extension2::ConstructorExtension; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here + | + = note: `ConstructorExtension` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use extension2::ConstructorExtension as OtherConstructorExtension; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-32833.rs b/src/test/ui/imports/issue-32833.rs new file mode 100644 index 00000000000..379eedde726 --- /dev/null +++ b/src/test/ui/imports/issue-32833.rs @@ -0,0 +1,7 @@ +use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432] + //~^ no `Foo` in `bar` +mod bar { + use Foo; +} + +fn main() {} diff --git a/src/test/ui/imports/issue-32833.stderr b/src/test/ui/imports/issue-32833.stderr new file mode 100644 index 00000000000..430cc0fda26 --- /dev/null +++ b/src/test/ui/imports/issue-32833.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `bar::Foo` + --> $DIR/issue-32833.rs:1:5 + | +LL | use bar::Foo; + | ^^^^^^^^ no `Foo` in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-33464.rs b/src/test/ui/imports/issue-33464.rs new file mode 100644 index 00000000000..a0edb5fdb6f --- /dev/null +++ b/src/test/ui/imports/issue-33464.rs @@ -0,0 +1,10 @@ +// Make sure that the spans of import errors are correct. + +use abc::one_el; +//~^ ERROR +use abc::{a, bbb, cccccc}; +//~^ ERROR +use a_very_long_name::{el, el2}; +//~^ ERROR + +fn main() {} diff --git a/src/test/ui/imports/issue-33464.stderr b/src/test/ui/imports/issue-33464.stderr new file mode 100644 index 00000000000..d3bf404c99a --- /dev/null +++ b/src/test/ui/imports/issue-33464.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `abc` + --> $DIR/issue-33464.rs:3:5 + | +LL | use abc::one_el; + | ^^^ maybe a missing crate `abc`? + +error[E0432]: unresolved import `abc` + --> $DIR/issue-33464.rs:5:5 + | +LL | use abc::{a, bbb, cccccc}; + | ^^^ maybe a missing crate `abc`? + +error[E0432]: unresolved import `a_very_long_name` + --> $DIR/issue-33464.rs:7:5 + | +LL | use a_very_long_name::{el, el2}; + | ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`? + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-36881.rs b/src/test/ui/imports/issue-36881.rs new file mode 100644 index 00000000000..04313872d27 --- /dev/null +++ b/src/test/ui/imports/issue-36881.rs @@ -0,0 +1,6 @@ +// aux-build:issue-36881-aux.rs + +fn main() { + extern crate issue_36881_aux; + use issue_36881_aux::Foo; //~ ERROR unresolved import +} diff --git a/src/test/ui/imports/issue-36881.stderr b/src/test/ui/imports/issue-36881.stderr new file mode 100644 index 00000000000..caf9d5d6d62 --- /dev/null +++ b/src/test/ui/imports/issue-36881.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `issue_36881_aux` + --> $DIR/issue-36881.rs:5:9 + | +LL | use issue_36881_aux::Foo; + | ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-37887.rs b/src/test/ui/imports/issue-37887.rs new file mode 100644 index 00000000000..58f0c6b651a --- /dev/null +++ b/src/test/ui/imports/issue-37887.rs @@ -0,0 +1,4 @@ +fn main() { + extern crate libc; //~ ERROR use of unstable + use libc::*; //~ ERROR unresolved import +} diff --git a/src/test/ui/imports/issue-37887.stderr b/src/test/ui/imports/issue-37887.stderr new file mode 100644 index 00000000000..944d544098a --- /dev/null +++ b/src/test/ui/imports/issue-37887.stderr @@ -0,0 +1,19 @@ +error[E0432]: unresolved import `libc` + --> $DIR/issue-37887.rs:3:9 + | +LL | use libc::*; + | ^^^^ maybe a missing crate `libc`? + +error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/issue-37887.rs:2:5 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27812 for more information + = help: add `#![feature(rustc_private)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0658. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-38293.rs b/src/test/ui/imports/issue-38293.rs new file mode 100644 index 00000000000..3b1393600ba --- /dev/null +++ b/src/test/ui/imports/issue-38293.rs @@ -0,0 +1,16 @@ +// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace. + +mod foo { + pub fn f() { } +} +use foo::f::{self}; //~ ERROR unresolved import `foo::f` + +mod bar { + pub fn baz() {} + pub mod baz {} +} +use bar::baz::{self}; + +fn main() { + baz(); //~ ERROR expected function, found module `baz` +} diff --git a/src/test/ui/imports/issue-38293.stderr b/src/test/ui/imports/issue-38293.stderr new file mode 100644 index 00000000000..d2450ab1250 --- /dev/null +++ b/src/test/ui/imports/issue-38293.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `foo::f` + --> $DIR/issue-38293.rs:6:14 + | +LL | use foo::f::{self}; + | ^^^^ no `f` in `foo` + +error[E0423]: expected function, found module `baz` + --> $DIR/issue-38293.rs:15:5 + | +LL | baz(); + | ^^^ not a function + | +help: consider importing this function instead + | +LL | use bar::baz; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0432. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/imports/issue-4366-2.rs b/src/test/ui/imports/issue-4366-2.rs new file mode 100644 index 00000000000..c777b750252 --- /dev/null +++ b/src/test/ui/imports/issue-4366-2.rs @@ -0,0 +1,26 @@ +// ensures that 'use foo:*' doesn't import non-public item + +use m1::*; + +mod foo { + pub fn foo() {} +} +mod a { + pub mod b { + use foo::foo; + type Bar = isize; + } + pub mod sub { + use a::b::*; + fn sub() -> Bar { 1 } + //~^ ERROR cannot find type `Bar` in this scope + } +} + +mod m1 { + fn foo() {} +} + +fn main() { + foo(); //~ ERROR expected function, found module `foo` +} diff --git a/src/test/ui/imports/issue-4366-2.stderr b/src/test/ui/imports/issue-4366-2.stderr new file mode 100644 index 00000000000..a86ec7fabea --- /dev/null +++ b/src/test/ui/imports/issue-4366-2.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-4366-2.rs:15:21 + | +LL | fn sub() -> Bar { 1 } + | ^^^ not found in this scope + | +help: consider importing this type alias + | +LL | use a::b::Bar; + | + +error[E0423]: expected function, found module `foo` + --> $DIR/issue-4366-2.rs:25:5 + | +LL | foo(); + | ^^^ not a function + | +help: consider importing this function instead + | +LL | use foo::foo; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/imports/issue-4366.rs b/src/test/ui/imports/issue-4366.rs new file mode 100644 index 00000000000..9ec2e58ecad --- /dev/null +++ b/src/test/ui/imports/issue-4366.rs @@ -0,0 +1,26 @@ +// regression test for issue 4366 + +// ensures that 'use foo:*' doesn't import non-public 'use' statements in the +// module 'foo' + +use m1::*; + +mod foo { + pub fn foo() {} +} +mod a { + pub mod b { + use foo::foo; + type Bar = isize; + } + pub mod sub { + use a::b::*; + fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope + } +} + +mod m1 { + fn foo() {} +} + +fn main() {} diff --git a/src/test/ui/imports/issue-4366.stderr b/src/test/ui/imports/issue-4366.stderr new file mode 100644 index 00000000000..469ea93e904 --- /dev/null +++ b/src/test/ui/imports/issue-4366.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/issue-4366.rs:18:29 + | +LL | fn sub() -> isize { foo(); 1 } + | ^^^ not found in this scope + | +help: consider importing this function + | +LL | use foo::foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed new file mode 100644 index 00000000000..b463848ae94 --- /dev/null +++ b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -0,0 +1,5 @@ +// run-rustfix + +extern crate std as other_std; +fn main() {} +//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs new file mode 100644 index 00000000000..1b491ac7efe --- /dev/null +++ b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs @@ -0,0 +1,5 @@ +// run-rustfix + +extern crate std; +fn main() {} +//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr new file mode 100644 index 00000000000..25aca4cb7ec --- /dev/null +++ b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -0,0 +1,15 @@ +error[E0259]: the name `std` is defined multiple times + --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1 + | +LL | extern crate std; + | ^^^^^^^^^^^^^^^^^ `std` reimported here + | + = note: `std` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_std; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs new file mode 100644 index 00000000000..e9f7fefb6fb --- /dev/null +++ b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs @@ -0,0 +1 @@ +pub const FOO: usize = *&0; diff --git a/src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs new file mode 100644 index 00000000000..e9f7fefb6fb --- /dev/null +++ b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs @@ -0,0 +1 @@ +pub const FOO: usize = *&0; diff --git a/src/test/ui/imports/issue-45829/import-self.rs b/src/test/ui/imports/issue-45829/import-self.rs new file mode 100644 index 00000000000..2dc4331ced7 --- /dev/null +++ b/src/test/ui/imports/issue-45829/import-self.rs @@ -0,0 +1,19 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{self}; +//~^ ERROR is defined multiple times + +use foo as self; +//~^ ERROR expected identifier + +use foo::self; //~ ERROR is defined multiple times +//~^ ERROR `self` imports are only allowed within a { } list + +use foo::A; +use foo::{self as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/import-self.stderr b/src/test/ui/imports/issue-45829/import-self.stderr new file mode 100644 index 00000000000..158e81cdd96 --- /dev/null +++ b/src/test/ui/imports/issue-45829/import-self.stderr @@ -0,0 +1,69 @@ +error: expected identifier, found keyword `self` + --> $DIR/import-self.rs:9:12 + | +LL | use foo as self; + | ^^^^ expected identifier, found keyword + +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/import-self.rs:12:8 + | +LL | use foo::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL | use foo; + | -- +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use foo::{self}; + | ^ ^ + +error[E0255]: the name `foo` is defined multiple times + --> $DIR/import-self.rs:6:11 + | +LL | mod foo { + | ------- previous definition of the module `foo` here +... +LL | use foo::{self}; + | ^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as other_foo}; + | ^^^^^^^^^^^^^^^^^ + +error[E0255]: the name `foo` is defined multiple times + --> $DIR/import-self.rs:12:5 + | +LL | mod foo { + | ------- previous definition of the module `foo` here +... +LL | use foo::self; + | ^^^^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo as other_foo; + | ^^^^^^^^^^^^^^^^ + +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-self.rs:16:11 + | +LL | use foo::A; + | ------ previous import of the type `A` here +LL | use foo::{self as A}; + | ^^^^^^^^^ `A` reimported here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as OtherA}; + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0252, E0255, E0429. +For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-45829/import-twice.rs b/src/test/ui/imports/issue-45829/import-twice.rs new file mode 100644 index 00000000000..e5a8bb7adf6 --- /dev/null +++ b/src/test/ui/imports/issue-45829/import-twice.rs @@ -0,0 +1,9 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{A, A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/import-twice.stderr b/src/test/ui/imports/issue-45829/import-twice.stderr new file mode 100644 index 00000000000..656b011bc3b --- /dev/null +++ b/src/test/ui/imports/issue-45829/import-twice.stderr @@ -0,0 +1,13 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-twice.rs:6:14 + | +LL | use foo::{A, A}; + | - ^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-45829/issue-45829.rs b/src/test/ui/imports/issue-45829/issue-45829.rs new file mode 100644 index 00000000000..1e76e4b140e --- /dev/null +++ b/src/test/ui/imports/issue-45829/issue-45829.rs @@ -0,0 +1,9 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{A, B as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/issue-45829.stderr b/src/test/ui/imports/issue-45829/issue-45829.stderr new file mode 100644 index 00000000000..a7ebc7171bc --- /dev/null +++ b/src/test/ui/imports/issue-45829/issue-45829.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/issue-45829.rs:6:14 + | +LL | use foo::{A, B as A}; + | - ^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, B as OtherA}; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-45829/rename-extern-vs-use.rs b/src/test/ui/imports/issue-45829/rename-extern-vs-use.rs new file mode 100644 index 00000000000..aef7aa35cf5 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern-vs-use.rs @@ -0,0 +1,11 @@ +// aux-build:issue-45829-b.rs + +mod foo { + pub mod bar {} +} + +use foo::bar; +extern crate issue_45829_b as bar; +//~^ ERROR the name `bar` is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr b/src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr new file mode 100644 index 00000000000..98fd8a623fe --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr @@ -0,0 +1,17 @@ +error[E0254]: the name `bar` is defined multiple times + --> $DIR/rename-extern-vs-use.rs:8:1 + | +LL | use foo::bar; + | -------- previous import of the module `bar` here +LL | extern crate issue_45829_b as bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here + | + = note: `bar` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_bar; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/src/test/ui/imports/issue-45829/rename-extern-with-tab.rs b/src/test/ui/imports/issue-45829/rename-extern-with-tab.rs new file mode 100644 index 00000000000..0da8b826c90 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern-with-tab.rs @@ -0,0 +1,8 @@ +// aux-build:issue-45829-a.rs +// aux-build:issue-45829-b.rs + +extern crate issue_45829_a; +extern crate issue_45829_b as issue_45829_a; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr new file mode 100644 index 00000000000..2c4e8ce996b --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `issue_45829_a` is defined multiple times + --> $DIR/rename-extern-with-tab.rs:5:1 + | +LL | extern crate issue_45829_a; + | --------------------------- previous import of the extern crate `issue_45829_a` here +LL | extern crate issue_45829_b as issue_45829_a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here + | + = note: `issue_45829_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_issue_45829_a; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/imports/issue-45829/rename-extern.rs b/src/test/ui/imports/issue-45829/rename-extern.rs new file mode 100644 index 00000000000..7dbda69322e --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern.rs @@ -0,0 +1,8 @@ +// aux-build:issue-45829-a.rs +// aux-build:issue-45829-b.rs + +extern crate issue_45829_a; +extern crate issue_45829_b as issue_45829_a; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-extern.stderr b/src/test/ui/imports/issue-45829/rename-extern.stderr new file mode 100644 index 00000000000..209ae2201f9 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-extern.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `issue_45829_a` is defined multiple times + --> $DIR/rename-extern.rs:5:1 + | +LL | extern crate issue_45829_a; + | --------------------------- previous import of the extern crate `issue_45829_a` here +LL | extern crate issue_45829_b as issue_45829_a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here + | + = note: `issue_45829_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_issue_45829_a; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/imports/issue-45829/rename-use-vs-extern.rs b/src/test/ui/imports/issue-45829/rename-use-vs-extern.rs new file mode 100644 index 00000000000..0cf3a77fd7c --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-use-vs-extern.rs @@ -0,0 +1,7 @@ +// aux-build:issue-45829-b.rs + +extern crate issue_45829_b; +use std as issue_45829_b; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr b/src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr new file mode 100644 index 00000000000..6b917d55747 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr @@ -0,0 +1,17 @@ +error[E0254]: the name `issue_45829_b` is defined multiple times + --> $DIR/rename-use-vs-extern.rs:4:5 + | +LL | extern crate issue_45829_b; + | --------------------------- previous import of the extern crate `issue_45829_b` here +LL | use std as issue_45829_b; + | ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here + | + = note: `issue_45829_b` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std as other_issue_45829_b; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/src/test/ui/imports/issue-45829/rename-use-with-tabs.rs b/src/test/ui/imports/issue-45829/rename-use-with-tabs.rs new file mode 100644 index 00000000000..86c5fa00fdb --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-use-with-tabs.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct A; + + pub mod bar { + pub struct B; + } +} + +use foo::{A, bar::B as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr new file mode 100644 index 00000000000..3baad6cd72f --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/rename-use-with-tabs.rs:9:14 + | +LL | use foo::{A, bar::B as A}; + | - ^^^^^^^^^^^^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, bar::B as OtherA}; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-45829/rename-with-path.rs b/src/test/ui/imports/issue-45829/rename-with-path.rs new file mode 100644 index 00000000000..e278a878937 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-with-path.rs @@ -0,0 +1,4 @@ +use std::{collections::HashMap as A, sync::Arc as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-45829/rename-with-path.stderr b/src/test/ui/imports/issue-45829/rename-with-path.stderr new file mode 100644 index 00000000000..ba83eeaa813 --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename-with-path.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/rename-with-path.rs:1:38 + | +LL | use std::{collections::HashMap as A, sync::Arc as A}; + | ------------------------- ^^^^^^^^^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::{collections::HashMap as A, sync::Arc as OtherA}; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-45829/rename.rs b/src/test/ui/imports/issue-45829/rename.rs new file mode 100644 index 00000000000..1c45956c66a --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename.rs @@ -0,0 +1,7 @@ +use core; +use std as core; +//~^ ERROR is defined multiple times + +fn main() { + 1 + 1; +} diff --git a/src/test/ui/imports/issue-45829/rename.stderr b/src/test/ui/imports/issue-45829/rename.stderr new file mode 100644 index 00000000000..8f12d92d6fb --- /dev/null +++ b/src/test/ui/imports/issue-45829/rename.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `core` is defined multiple times + --> $DIR/rename.rs:2:5 + | +LL | use core; + | ---- previous import of the module `core` here +LL | use std as core; + | ^^^^^^^^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std as other_core; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-47623.rs b/src/test/ui/imports/issue-47623.rs new file mode 100644 index 00000000000..ad8aa4c1a2b --- /dev/null +++ b/src/test/ui/imports/issue-47623.rs @@ -0,0 +1,3 @@ +use self; //~ERROR `self` imports are only allowed within a { } list + +fn main() {} diff --git a/src/test/ui/imports/issue-47623.stderr b/src/test/ui/imports/issue-47623.stderr new file mode 100644 index 00000000000..53968a2960c --- /dev/null +++ b/src/test/ui/imports/issue-47623.stderr @@ -0,0 +1,9 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/issue-47623.rs:1:5 + | +LL | use self; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0429`. diff --git a/src/test/ui/imports/issue-4865-1.rs b/src/test/ui/imports/issue-4865-1.rs new file mode 100644 index 00000000000..68fbee37d01 --- /dev/null +++ b/src/test/ui/imports/issue-4865-1.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_imports)] +// This should resolve fine. +// Prior to fix, the crossed imports between a and b +// would block on the glob import, itself never being resolved +// because these previous imports were not resolved. + +pub mod a { + use b::fn_b; + use c::*; + + pub fn fn_a(){ + } +} + +pub mod b { + use a::fn_a; + use c::*; + + pub fn fn_b(){ + } +} + +pub mod c{ + pub fn fn_c(){ + } +} + +use a::fn_a; +use b::fn_b; + +fn main() { +} diff --git a/src/test/ui/imports/issue-4865-2.rs b/src/test/ui/imports/issue-4865-2.rs new file mode 100644 index 00000000000..cbe1d0d32c6 --- /dev/null +++ b/src/test/ui/imports/issue-4865-2.rs @@ -0,0 +1,24 @@ +// run-pass +// Previously, this would have failed to resolve due to the circular +// block between `use say` and `pub use hello::*`. +// +// Now, as `use say` is not `pub`, the glob import can resolve +// without any problem and this resolves fine. + +pub use hello::*; + +pub mod say { + pub fn hello() { println!("hello"); } +} + +pub mod hello { + use say; + + pub fn hello() { + say::hello(); + } +} + +fn main() { + hello(); +} diff --git a/src/test/ui/imports/issue-4865-3.rs b/src/test/ui/imports/issue-4865-3.rs new file mode 100644 index 00000000000..12f9bba18d8 --- /dev/null +++ b/src/test/ui/imports/issue-4865-3.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_imports)] +// This should resolve fine even with the circular imports as +// they are not `pub`. + +pub mod a { + use b::*; +} + +pub mod b { + use a::*; +} + +use a::*; + +fn main() { +} diff --git a/src/test/ui/imports/issue-52891.fixed b/src/test/ui/imports/issue-52891.fixed new file mode 100644 index 00000000000..e694b5c9b15 --- /dev/null +++ b/src/test/ui/imports/issue-52891.fixed @@ -0,0 +1,37 @@ +// aux-build:issue-52891.rs +// run-rustfix + +#![allow(warnings)] + +extern crate issue_52891; + +// Check that we don't suggest renaming duplicate imports but instead +// suggest removing one. + +use issue_52891::a; + //~ ERROR `a` is defined multiple times + +use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times +use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times +use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times + +use issue_52891::{//~ ERROR `a` is defined multiple times + h, + i}; +use issue_52891::{j, + //~ ERROR `a` is defined multiple times + k}; +use issue_52891::{l, + m}; //~ ERROR `a` is defined multiple times + +use issue_52891::a::inner; +use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times + + +//~^ ERROR `issue_52891` is defined multiple times + + +#[macro_use] +use issue_52891::n; //~ ERROR `n` is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-52891.rs b/src/test/ui/imports/issue-52891.rs new file mode 100644 index 00000000000..cd4b40629ab --- /dev/null +++ b/src/test/ui/imports/issue-52891.rs @@ -0,0 +1,38 @@ +// aux-build:issue-52891.rs +// run-rustfix + +#![allow(warnings)] + +extern crate issue_52891; + +// Check that we don't suggest renaming duplicate imports but instead +// suggest removing one. + +use issue_52891::a; +use issue_52891::a; //~ ERROR `a` is defined multiple times + +use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times +use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times +use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times + +use issue_52891::{a, //~ ERROR `a` is defined multiple times + h, + i}; +use issue_52891::{j, + a, //~ ERROR `a` is defined multiple times + k}; +use issue_52891::{l, + m, + a}; //~ ERROR `a` is defined multiple times + +use issue_52891::a::inner; +use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times + +use issue_52891::{self}; +//~^ ERROR `issue_52891` is defined multiple times + +use issue_52891::n; +#[macro_use] +use issue_52891::n; //~ ERROR `n` is defined multiple times + +fn main() {} diff --git a/src/test/ui/imports/issue-52891.stderr b/src/test/ui/imports/issue-52891.stderr new file mode 100644 index 00000000000..6e6e42ddc2d --- /dev/null +++ b/src/test/ui/imports/issue-52891.stderr @@ -0,0 +1,131 @@ +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:12:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +LL | use issue_52891::a; + | ^^^^^^^^^^^^^^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:14:19 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{a, b, c}; + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:15:22 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{d, a, e}; + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:16:25 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{f, g, a}; + | ^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:18:19 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{a, + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:22:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | a, + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:26:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | a}; + | ^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `inner` is defined multiple times + --> $DIR/issue-52891.rs:29:5 + | +LL | use issue_52891::a::inner; + | --------------------- previous import of the module `inner` here +LL | use issue_52891::b::inner; + | ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here + | + = note: `inner` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use issue_52891::b::inner as other_inner; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0254]: the name `issue_52891` is defined multiple times + --> $DIR/issue-52891.rs:31:19 + | +LL | extern crate issue_52891; + | ------------------------- previous import of the extern crate `issue_52891` here +... +LL | use issue_52891::{self}; + | ------------------^^^^-- + | | | + | | `issue_52891` reimported here + | help: remove unnecessary import + | + = note: `issue_52891` must be defined only once in the type namespace of this module + +error[E0252]: the name `n` is defined multiple times + --> $DIR/issue-52891.rs:36:5 + | +LL | use issue_52891::n; + | -------------- previous import of the module `n` here +LL | #[macro_use] +LL | use issue_52891::n; + | ^^^^^^^^^^^^^^ `n` reimported here + | + = note: `n` must be defined only once in the type namespace of this module + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0252, E0254. +For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-53565.rs b/src/test/ui/imports/issue-53565.rs new file mode 100644 index 00000000000..114a53a92ca --- /dev/null +++ b/src/test/ui/imports/issue-53565.rs @@ -0,0 +1,7 @@ +use std::time::{foo, bar, buzz}; +//~^ ERROR unresolved imports +use std::time::{abc, def}; +//~^ ERROR unresolved imports +fn main(){ + println!("Hello World!"); +} diff --git a/src/test/ui/imports/issue-53565.stderr b/src/test/ui/imports/issue-53565.stderr new file mode 100644 index 00000000000..71c3b2aaaf2 --- /dev/null +++ b/src/test/ui/imports/issue-53565.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz` + --> $DIR/issue-53565.rs:1:17 + | +LL | use std::time::{foo, bar, buzz}; + | ^^^ ^^^ ^^^^ no `buzz` in `time` + | | | + | | no `bar` in `time` + | no `foo` in `time` + +error[E0432]: unresolved imports `std::time::abc`, `std::time::def` + --> $DIR/issue-53565.rs:3:17 + | +LL | use std::time::{abc, def}; + | ^^^ ^^^ no `def` in `time` + | | + | no `abc` in `time` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-59764.rs b/src/test/ui/imports/issue-59764.rs new file mode 100644 index 00000000000..09dee8c2732 --- /dev/null +++ b/src/test/ui/imports/issue-59764.rs @@ -0,0 +1,136 @@ +// aux-build:issue-59764.rs +// compile-flags:--extern issue_59764 +// edition:2018 + +#![allow(warnings)] + +// This tests the suggestion to import macros from the root of a crate. This aims to capture +// the case where a user attempts to import a macro from the definition location instead of the +// root of the crate and the macro is annotated with `#![macro_export]`. + +// Edge cases.. + +mod multiple_imports_same_line_at_end { + use issue_59764::foo::{baz, makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_at_end_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_multiline_at_end { + use issue_59764::foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_same_line_in_middle { + use issue_59764::foo::{baz, makro, foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_in_middle_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar, + }; +} + +mod multiple_imports_multiline_in_middle { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar + }; +} + +mod nested_imports { + use issue_59764::{foobaz, foo::makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiline_multiple_imports_trailing_comma { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }, + }; +} + +mod nested_multiline_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + } + }; +} + +mod doubly_nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod doubly_multiline_nested_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + barbaz::{ + barfoo, + } + } + }; +} + +mod renamed_import { + use issue_59764::foo::makro as baz; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod renamed_multiple_imports { + use issue_59764::foo::{baz, makro as foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod lots_of_whitespace { + use + issue_59764::{ + + foobaz, + + + foo::{baz, + + makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + + }; +} + +// Simple case.. + +use issue_59764::foo::makro; +//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] + +makro!(bar); +//~^ ERROR cannot determine resolution for the macro `makro` + +fn main() { + bar(); + //~^ ERROR cannot find function `bar` in this scope [E0425] +} diff --git a/src/test/ui/imports/issue-59764.stderr b/src/test/ui/imports/issue-59764.stderr new file mode 100644 index 00000000000..f266e908ecc --- /dev/null +++ b/src/test/ui/imports/issue-59764.stderr @@ -0,0 +1,241 @@ +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:14:33 + | +LL | use issue_59764::foo::{baz, makro}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{baz}}; + | ^^^^^^^^^ --^^ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:21:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:28:9 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:33:33 + | +LL | use issue_59764::foo::{baz, makro, foobar}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{baz, foobar}}; + | ^^^^^^^^^ -- ^^ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:40:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | foobar, +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:48:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foo::{ +LL | baz, +LL | +LL | foobar +LL | }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:54:31 + | +LL | use issue_59764::{foobaz, foo::makro}; + | ^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz}; + | ^^^^^^^ -- + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:59:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz, foo::{baz}}; + | ^^^^^^^ -- + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:68:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:78:13 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:84:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; + | ^^^^^^^ -- + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:93:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL | + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:102:9 + | +LL | use issue_59764::foo::makro as baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro as baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:107:33 + | +LL | use issue_59764::foo::{baz, makro as foobar}; + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::{makro as foobar, foo::{baz}}; + | ^^^^^^^^^^^^^^^^^^^ --^^ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:120:17 + | +LL | makro as foobar} + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | issue_59764::{makro as foobar, +LL | +LL | foobaz, +LL | +LL | +LL | foo::{baz} + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:127:5 + | +LL | use issue_59764::foo::makro; + | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro; + | ^^^^^^^^^^^^^^^^^^ + +error: cannot determine resolution for the macro `makro` + --> $DIR/issue-59764.rs:130:1 + | +LL | makro!(bar); + | ^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/issue-59764.rs:134:5 + | +LL | bar(); + | ^^^ not found in this scope + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/imports/issue-8208.rs b/src/test/ui/imports/issue-8208.rs new file mode 100644 index 00000000000..1c566938f9d --- /dev/null +++ b/src/test/ui/imports/issue-8208.rs @@ -0,0 +1,17 @@ +use self::*; //~ ERROR: unresolved import `self::*` [E0432] + //~^ cannot glob-import a module into itself + +mod foo { + use foo::*; //~ ERROR: unresolved import `foo::*` [E0432] + //~^ cannot glob-import a module into itself + + mod bar { + use super::bar::*; + //~^ ERROR: unresolved import `super::bar::*` [E0432] + //~| cannot glob-import a module into itself + } + +} + +fn main() { +} diff --git a/src/test/ui/imports/issue-8208.stderr b/src/test/ui/imports/issue-8208.stderr new file mode 100644 index 00000000000..e59aea12cda --- /dev/null +++ b/src/test/ui/imports/issue-8208.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `self::*` + --> $DIR/issue-8208.rs:1:5 + | +LL | use self::*; + | ^^^^^^^ cannot glob-import a module into itself + +error[E0432]: unresolved import `foo::*` + --> $DIR/issue-8208.rs:5:9 + | +LL | use foo::*; + | ^^^^^^ cannot glob-import a module into itself + +error[E0432]: unresolved import `super::bar::*` + --> $DIR/issue-8208.rs:9:13 + | +LL | use super::bar::*; + | ^^^^^^^^^^^^^ cannot glob-import a module into itself + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-8640.rs b/src/test/ui/imports/issue-8640.rs new file mode 100644 index 00000000000..51a02a32ec8 --- /dev/null +++ b/src/test/ui/imports/issue-8640.rs @@ -0,0 +1,10 @@ +#[allow(unused_imports)] + +mod foo { + use baz::bar; + mod bar {} + //~^ ERROR the name `bar` is defined multiple times +} +mod baz { pub mod bar {} } + +fn main() {} diff --git a/src/test/ui/imports/issue-8640.stderr b/src/test/ui/imports/issue-8640.stderr new file mode 100644 index 00000000000..4ce63945464 --- /dev/null +++ b/src/test/ui/imports/issue-8640.stderr @@ -0,0 +1,17 @@ +error[E0255]: the name `bar` is defined multiple times + --> $DIR/issue-8640.rs:5:5 + | +LL | use baz::bar; + | -------- previous import of the module `bar` here +LL | mod bar {} + | ^^^^^^^ `bar` redefined here + | + = note: `bar` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use baz::bar as other_bar; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/imports/resolve_self_super_hint.rs b/src/test/ui/imports/resolve_self_super_hint.rs new file mode 100644 index 00000000000..a14ec5b7290 --- /dev/null +++ b/src/test/ui/imports/resolve_self_super_hint.rs @@ -0,0 +1,27 @@ +mod a { + extern crate alloc; + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::alloc + mod b { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION super::alloc + mod c { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION a::alloc + mod d { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION a::alloc + } + } + } +} + +fn main() {} diff --git a/src/test/ui/imports/resolve_self_super_hint.stderr b/src/test/ui/imports/resolve_self_super_hint.stderr new file mode 100644 index 00000000000..bc862553b5b --- /dev/null +++ b/src/test/ui/imports/resolve_self_super_hint.stderr @@ -0,0 +1,33 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:3:9 + | +LL | use alloc::HashMap; + | ^^^^^ help: a similar path exists: `self::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:8:13 + | +LL | use alloc::HashMap; + | ^^^^^ help: a similar path exists: `super::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:13:17 + | +LL | use alloc::HashMap; + | ^^^^^ + | | + | unresolved import + | help: a similar path exists: `a::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:18:21 + | +LL | use alloc::HashMap; + | ^^^^^ + | | + | unresolved import + | help: a similar path exists: `a::alloc` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/auxiliary/issue-36881-aux.rs b/src/test/ui/issues/auxiliary/issue-36881-aux.rs deleted file mode 100644 index e373b64384f..00000000000 --- a/src/test/ui/issues/auxiliary/issue-36881-aux.rs +++ /dev/null @@ -1 +0,0 @@ -pub trait Foo {} diff --git a/src/test/ui/issues/auxiliary/issue-52891.rs b/src/test/ui/issues/auxiliary/issue-52891.rs deleted file mode 100644 index 07598118322..00000000000 --- a/src/test/ui/issues/auxiliary/issue-52891.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub mod a { - pub mod inner { - } -} - -pub mod b { - pub mod inner { - } -} - -pub mod c {} - -pub mod d {} - -pub mod e {} - -pub mod f {} - -pub mod g {} - -pub mod h {} - -pub mod i {} - -pub mod j {} - -pub mod k {} - -pub mod l {} - -pub mod m {} - -pub mod n {} diff --git a/src/test/ui/issues/auxiliary/issue-59764.rs b/src/test/ui/issues/auxiliary/issue-59764.rs deleted file mode 100644 index a92eed968d0..00000000000 --- a/src/test/ui/issues/auxiliary/issue-59764.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub mod foo { - #[macro_export] - macro_rules! makro { - ($foo:ident) => { - fn $foo() { } - } - } - - pub fn baz() {} - - pub fn foobar() {} - - pub mod barbaz { - pub fn barfoo() {} - } -} - -pub fn foobaz() {} diff --git a/src/test/ui/issues/auxiliary/lint-stability.rs b/src/test/ui/issues/auxiliary/lint-stability.rs deleted file mode 100644 index de4058887cf..00000000000 --- a/src/test/ui/issues/auxiliary/lint-stability.rs +++ /dev/null @@ -1,188 +0,0 @@ -#![crate_name="lint_stability"] -#![crate_type = "lib"] -#![feature(staged_api)] -#![feature(associated_type_defaults)] -#![stable(feature = "lint_stability", since = "1.0.0")] - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub fn deprecated() {} -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub fn deprecated_text() {} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "99.99.99", reason = "text")] -pub fn deprecated_future() {} - -#[unstable(feature = "unstable_test_feature", issue = "none")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub fn deprecated_unstable() {} -#[unstable(feature = "unstable_test_feature", issue = "none")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub fn deprecated_unstable_text() {} - -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub fn unstable() {} -#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] -pub fn unstable_text() {} - -#[stable(feature = "rust1", since = "1.0.0")] -pub fn stable() {} -#[stable(feature = "rust1", since = "1.0.0")] -pub fn stable_text() {} - -#[stable(feature = "rust1", since = "1.0.0")] -pub struct MethodTester; - -impl MethodTester { - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - pub fn method_deprecated(&self) {} - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - pub fn method_deprecated_text(&self) {} - - #[unstable(feature = "unstable_test_feature", issue = "none")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - pub fn method_deprecated_unstable(&self) {} - #[unstable(feature = "unstable_test_feature", issue = "none")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - pub fn method_deprecated_unstable_text(&self) {} - - #[unstable(feature = "unstable_test_feature", issue = "none")] - pub fn method_unstable(&self) {} - #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] - pub fn method_unstable_text(&self) {} - - #[stable(feature = "rust1", since = "1.0.0")] - pub fn method_stable(&self) {} - #[stable(feature = "rust1", since = "1.0.0")] - pub fn method_stable_text(&self) {} -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -pub trait Trait { - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - fn trait_deprecated(&self) {} - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - fn trait_deprecated_text(&self) {} - - #[unstable(feature = "unstable_test_feature", issue = "none")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - fn trait_deprecated_unstable(&self) {} - #[unstable(feature = "unstable_test_feature", issue = "none")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - fn trait_deprecated_unstable_text(&self) {} - - #[unstable(feature = "unstable_test_feature", issue = "none")] - fn trait_unstable(&self) {} - #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] - fn trait_unstable_text(&self) {} - - #[stable(feature = "rust1", since = "1.0.0")] - fn trait_stable(&self) {} - #[stable(feature = "rust1", since = "1.0.0")] - fn trait_stable_text(&self) {} -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -pub trait TraitWithAssociatedTypes { - #[unstable(feature = "unstable_test_feature", issue = "none")] - type TypeUnstable = u8; - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - type TypeDeprecated = u8; -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -impl Trait for MethodTester {} - -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub trait UnstableTrait { fn dummy(&self) { } } - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub trait DeprecatedTrait { - #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { } -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedStruct { - #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize -} -#[unstable(feature = "unstable_test_feature", issue = "none")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedUnstableStruct { - #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize -} -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub struct UnstableStruct { - #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize -} -#[stable(feature = "rust1", since = "1.0.0")] -pub struct StableStruct { - #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize -} -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub enum UnstableEnum {} -#[stable(feature = "rust1", since = "1.0.0")] -pub enum StableEnum {} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedUnitStruct; -#[unstable(feature = "unstable_test_feature", issue = "none")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedUnstableUnitStruct; -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub struct UnstableUnitStruct; -#[stable(feature = "rust1", since = "1.0.0")] -pub struct StableUnitStruct; - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -pub enum Enum { - #[stable(feature = "stable_test_feature", since = "1.0.0")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - DeprecatedVariant, - #[unstable(feature = "unstable_test_feature", issue = "none")] - #[rustc_deprecated(since = "1.0.0", reason = "text")] - DeprecatedUnstableVariant, - #[unstable(feature = "unstable_test_feature", issue = "none")] - UnstableVariant, - - #[stable(feature = "rust1", since = "1.0.0")] - StableVariant, -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); -#[unstable(feature = "unstable_test_feature", issue = "none")] -#[rustc_deprecated(since = "1.0.0", reason = "text")] -pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); -#[unstable(feature = "unstable_test_feature", issue = "none")] -pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); -#[stable(feature = "rust1", since = "1.0.0")] -pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[macro_export] -macro_rules! macro_test { - () => (deprecated()); -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[macro_export] -macro_rules! macro_test_arg { - ($func:expr) => ($func); -} - -#[stable(feature = "stable_test_feature", since = "1.0.0")] -#[macro_export] -macro_rules! macro_test_arg_nested { - ($func:ident) => (macro_test_arg!($func())); -} diff --git a/src/test/ui/issues/issue-13404.rs b/src/test/ui/issues/issue-13404.rs deleted file mode 100644 index c5af827d50c..00000000000 --- a/src/test/ui/issues/issue-13404.rs +++ /dev/null @@ -1,10 +0,0 @@ -use a::f; -use b::f; //~ ERROR: unresolved import `b::f` [E0432] - //~^ no `f` in `b` - -mod a { pub fn f() {} } -mod b { } - -fn main() { - f(); -} diff --git a/src/test/ui/issues/issue-13404.stderr b/src/test/ui/issues/issue-13404.stderr deleted file mode 100644 index 1f50debb07b..00000000000 --- a/src/test/ui/issues/issue-13404.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `b::f` - --> $DIR/issue-13404.rs:2:5 - | -LL | use b::f; - | ^^^^ no `f` in `b` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-1697.rs b/src/test/ui/issues/issue-1697.rs deleted file mode 100644 index 5cd76d21f91..00000000000 --- a/src/test/ui/issues/issue-1697.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Testing that we don't fail abnormally after hitting the errors - -use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432] - //~^ maybe a missing crate `unresolved`? - -fn main() {} diff --git a/src/test/ui/issues/issue-1697.stderr b/src/test/ui/issues/issue-1697.stderr deleted file mode 100644 index a76fd309914..00000000000 --- a/src/test/ui/issues/issue-1697.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `unresolved` - --> $DIR/issue-1697.rs:3:5 - | -LL | use unresolved::*; - | ^^^^^^^^^^ maybe a missing crate `unresolved`? - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-18083.rs b/src/test/ui/issues/issue-18083.rs deleted file mode 100644 index 36420ec142e..00000000000 --- a/src/test/ui/issues/issue-18083.rs +++ /dev/null @@ -1,25 +0,0 @@ -// check-pass -#![allow(dead_code)] -#![allow(unused_imports)] -// These crossed imports should resolve fine, and not block on -// each other and be reported as unresolved. - -mod a { - use b::{B}; - pub use self::inner::A; - - mod inner { - pub struct A; - } -} - -mod b { - use a::{A}; - pub use self::inner::B; - - mod inner { - pub struct B; - } -} - -fn main() {} diff --git a/src/test/ui/issues/issue-19498.rs b/src/test/ui/issues/issue-19498.rs deleted file mode 100644 index 5fe6742f55e..00000000000 --- a/src/test/ui/issues/issue-19498.rs +++ /dev/null @@ -1,13 +0,0 @@ -use self::A; -use self::B; -mod A {} //~ ERROR the name `A` is defined multiple times -//~| `A` redefined here -pub mod B {} //~ ERROR the name `B` is defined multiple times -//~| `B` redefined here -mod C { - use C::D; - mod D {} //~ ERROR the name `D` is defined multiple times - //~| `D` redefined here -} - -fn main() {} diff --git a/src/test/ui/issues/issue-19498.stderr b/src/test/ui/issues/issue-19498.stderr deleted file mode 100644 index cc1d649d610..00000000000 --- a/src/test/ui/issues/issue-19498.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error[E0255]: the name `A` is defined multiple times - --> $DIR/issue-19498.rs:3:1 - | -LL | use self::A; - | ------- previous import of the module `A` here -LL | use self::B; -LL | mod A {} - | ^^^^^ `A` redefined here - | - = note: `A` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use self::A as OtherA; - | ^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `B` is defined multiple times - --> $DIR/issue-19498.rs:5:1 - | -LL | use self::B; - | ------- previous import of the module `B` here -... -LL | pub mod B {} - | ^^^^^^^^^ `B` redefined here - | - = note: `B` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use self::B as OtherB; - | ^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `D` is defined multiple times - --> $DIR/issue-19498.rs:9:5 - | -LL | use C::D; - | ---- previous import of the module `D` here -LL | mod D {} - | ^^^^^ `D` redefined here - | - = note: `D` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use C::D as OtherD; - | ^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/issues/issue-20616-3.rs b/src/test/ui/issues/issue-20616-3.rs index 780038c11b8..b2371051c78 100644 --- a/src/test/ui/issues/issue-20616-3.rs +++ b/src/test/ui/issues/issue-20616-3.rs @@ -11,7 +11,7 @@ type Type_3 = Box; -//~^ error: expected one of `>`, const, lifetime, or type, found `,` +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` //type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` diff --git a/src/test/ui/issues/issue-20616-3.stderr b/src/test/ui/issues/issue-20616-3.stderr index 2f8cf8a79ed..b535c7a3267 100644 --- a/src/test/ui/issues/issue-20616-3.stderr +++ b/src/test/ui/issues/issue-20616-3.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `,` +error: expected one of `>`, a const expression, lifetime, or type, found `,` --> $DIR/issue-20616-3.rs:13:24 | LL | type Type_3 = Box; - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/issues/issue-20616-4.rs index 85aa9c1146d..a71f47ca4bf 100644 --- a/src/test/ui/issues/issue-20616-4.rs +++ b/src/test/ui/issues/issue-20616-4.rs @@ -14,7 +14,7 @@ type Type_4 = Type_1_<'static,, T>; -//~^ error: expected one of `>`, const, lifetime, or type, found `,` +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` type Type_5_<'a> = Type_1_<'a, ()>; diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/issues/issue-20616-4.stderr index 3be6c2e78ce..2b3b75f3119 100644 --- a/src/test/ui/issues/issue-20616-4.stderr +++ b/src/test/ui/issues/issue-20616-4.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `,` +error: expected one of `>`, a const expression, lifetime, or type, found `,` --> $DIR/issue-20616-4.rs:16:34 | LL | type Type_4 = Type_1_<'static,, T>; - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/issues/issue-20616-5.rs index c0c6bc6dd97..b96d09d59ae 100644 --- a/src/test/ui/issues/issue-20616-5.rs +++ b/src/test/ui/issues/issue-20616-5.rs @@ -20,7 +20,7 @@ type Type_5<'a> = Type_1_<'a, (),,>; -//~^ error: expected one of `>`, const, lifetime, or type, found `,` +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/issues/issue-20616-5.stderr index b90fbf60051..1ec1dbde695 100644 --- a/src/test/ui/issues/issue-20616-5.stderr +++ b/src/test/ui/issues/issue-20616-5.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `,` +error: expected one of `>`, a const expression, lifetime, or type, found `,` --> $DIR/issue-20616-5.rs:22:34 | LL | type Type_5<'a> = Type_1_<'a, (),,>; - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/issues/issue-20616-6.rs index 73c75bdc45f..a2c45ecec7a 100644 --- a/src/test/ui/issues/issue-20616-6.rs +++ b/src/test/ui/issues/issue-20616-6.rs @@ -23,7 +23,7 @@ type Type_6 = Type_5_<'a,,>; -//~^ error: expected one of `>`, const, lifetime, or type, found `,` +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` //type Type_7 = Box<(),,>; // error: expected type, found `,` diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/issues/issue-20616-6.stderr index ea1c15ba423..7401abdd091 100644 --- a/src/test/ui/issues/issue-20616-6.stderr +++ b/src/test/ui/issues/issue-20616-6.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `,` +error: expected one of `>`, a const expression, lifetime, or type, found `,` --> $DIR/issue-20616-6.rs:25:26 | LL | type Type_6 = Type_5_<'a,,>; - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs index 8beeebd7a95..67209c02adf 100644 --- a/src/test/ui/issues/issue-20616-7.rs +++ b/src/test/ui/issues/issue-20616-7.rs @@ -26,7 +26,7 @@ type Type_7 = Box<(),,>; -//~^ error: expected one of `>`, const, lifetime, or type, found `,` +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` //type Type_8<'a,,> = &'a (); // error: expected ident, found `,` diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr index dcd199902fc..e2c3efe8447 100644 --- a/src/test/ui/issues/issue-20616-7.stderr +++ b/src/test/ui/issues/issue-20616-7.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found `,` +error: expected one of `>`, a const expression, lifetime, or type, found `,` --> $DIR/issue-20616-7.rs:28:22 | LL | type Type_7 = Box<(),,>; - | ^ expected one of `>`, const, lifetime, or type + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24081.rs b/src/test/ui/issues/issue-24081.rs deleted file mode 100644 index 10983ce11b5..00000000000 --- a/src/test/ui/issues/issue-24081.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::ops::Add; -use std::ops::Sub; -use std::ops::Mul; -use std::ops::Div; -use std::ops::Rem; - -type Add = bool; //~ ERROR the name `Add` is defined multiple times -//~| `Add` redefined here -struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times -//~| `Sub` redefined here -enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times -//~| `Mul` redefined here -mod Div { } //~ ERROR the name `Div` is defined multiple times -//~| `Div` redefined here -trait Rem { } //~ ERROR the name `Rem` is defined multiple times -//~| `Rem` redefined here - -fn main() {} diff --git a/src/test/ui/issues/issue-24081.stderr b/src/test/ui/issues/issue-24081.stderr deleted file mode 100644 index 647048c7c20..00000000000 --- a/src/test/ui/issues/issue-24081.stderr +++ /dev/null @@ -1,78 +0,0 @@ -error[E0255]: the name `Add` is defined multiple times - --> $DIR/issue-24081.rs:7:1 - | -LL | use std::ops::Add; - | ------------- previous import of the trait `Add` here -... -LL | type Add = bool; - | ^^^^^^^^^^^^^^^^ `Add` redefined here - | - = note: `Add` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::ops::Add as OtherAdd; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `Sub` is defined multiple times - --> $DIR/issue-24081.rs:9:1 - | -LL | use std::ops::Sub; - | ------------- previous import of the trait `Sub` here -... -LL | struct Sub { x: f32 } - | ^^^^^^^^^^ `Sub` redefined here - | - = note: `Sub` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::ops::Sub as OtherSub; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `Mul` is defined multiple times - --> $DIR/issue-24081.rs:11:1 - | -LL | use std::ops::Mul; - | ------------- previous import of the trait `Mul` here -... -LL | enum Mul { A, B } - | ^^^^^^^^ `Mul` redefined here - | - = note: `Mul` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::ops::Mul as OtherMul; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `Div` is defined multiple times - --> $DIR/issue-24081.rs:13:1 - | -LL | use std::ops::Div; - | ------------- previous import of the trait `Div` here -... -LL | mod Div { } - | ^^^^^^^ `Div` redefined here - | - = note: `Div` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::ops::Div as OtherDiv; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `Rem` is defined multiple times - --> $DIR/issue-24081.rs:15:1 - | -LL | use std::ops::Rem; - | ------------- previous import of the trait `Rem` here -... -LL | trait Rem { } - | ^^^^^^^^^ `Rem` redefined here - | - = note: `Rem` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::ops::Rem as OtherRem; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/issues/issue-25396.rs b/src/test/ui/issues/issue-25396.rs deleted file mode 100644 index 301658d2344..00000000000 --- a/src/test/ui/issues/issue-25396.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![allow(non_camel_case_types)] - -use foo::baz; -use bar::baz; //~ ERROR the name `baz` is defined multiple times - -use foo::Quux; -use bar::Quux; //~ ERROR the name `Quux` is defined multiple times - -use foo::blah; -use bar::blah; //~ ERROR the name `blah` is defined multiple times - -use foo::WOMP; -use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times - -fn main() {} - -mod foo { - pub mod baz {} - pub trait Quux { } - pub type blah = (f64, u32); - pub const WOMP: u8 = 5; -} - -mod bar { - pub mod baz {} - pub type Quux = i32; - pub struct blah { x: i8 } - pub const WOMP: i8 = -5; -} diff --git a/src/test/ui/issues/issue-25396.stderr b/src/test/ui/issues/issue-25396.stderr deleted file mode 100644 index 38dc9ef1035..00000000000 --- a/src/test/ui/issues/issue-25396.stderr +++ /dev/null @@ -1,59 +0,0 @@ -error[E0252]: the name `baz` is defined multiple times - --> $DIR/issue-25396.rs:4:5 - | -LL | use foo::baz; - | -------- previous import of the module `baz` here -LL | use bar::baz; - | ^^^^^^^^ `baz` reimported here - | - = note: `baz` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use bar::baz as other_baz; - | ^^^^^^^^^^^^^^^^^^^^^ - -error[E0252]: the name `Quux` is defined multiple times - --> $DIR/issue-25396.rs:7:5 - | -LL | use foo::Quux; - | --------- previous import of the trait `Quux` here -LL | use bar::Quux; - | ^^^^^^^^^ `Quux` reimported here - | - = note: `Quux` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use bar::Quux as OtherQuux; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error[E0252]: the name `blah` is defined multiple times - --> $DIR/issue-25396.rs:10:5 - | -LL | use foo::blah; - | --------- previous import of the type `blah` here -LL | use bar::blah; - | ^^^^^^^^^ `blah` reimported here - | - = note: `blah` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use bar::blah as other_blah; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0252]: the name `WOMP` is defined multiple times - --> $DIR/issue-25396.rs:13:5 - | -LL | use foo::WOMP; - | --------- previous import of the value `WOMP` here -LL | use bar::WOMP; - | ^^^^^^^^^ `WOMP` reimported here - | - = note: `WOMP` must be defined only once in the value namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use bar::WOMP as OtherWOMP; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-26886.rs b/src/test/ui/issues/issue-26886.rs deleted file mode 100644 index 6e6d406c656..00000000000 --- a/src/test/ui/issues/issue-26886.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::sync::{self, Arc}; -use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times - //~| `Arc` must be defined only once in the type namespace of this module -use std::sync; //~ ERROR the name `sync` is defined multiple times - //~| `sync` must be defined only once in the type namespace of this module - -fn main() { -} diff --git a/src/test/ui/issues/issue-26886.stderr b/src/test/ui/issues/issue-26886.stderr deleted file mode 100644 index e2b925ec5a7..00000000000 --- a/src/test/ui/issues/issue-26886.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0252]: the name `Arc` is defined multiple times - --> $DIR/issue-26886.rs:2:5 - | -LL | use std::sync::{self, Arc}; - | --- previous import of the type `Arc` here -LL | use std::sync::Arc; - | ^^^^^^^^^^^^^^ `Arc` reimported here - | - = note: `Arc` must be defined only once in the type namespace of this module - -error[E0252]: the name `sync` is defined multiple times - --> $DIR/issue-26886.rs:4:5 - | -LL | use std::sync::{self, Arc}; - | ---- previous import of the module `sync` here -... -LL | use std::sync; - | ^^^^^^^^^ `sync` reimported here - | - = note: `sync` must be defined only once in the type namespace of this module - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-28075.rs b/src/test/ui/issues/issue-28075.rs deleted file mode 100644 index 6b4ea46f361..00000000000 --- a/src/test/ui/issues/issue-28075.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Unstable entities should be caught in import lists - -// aux-build:lint-stability.rs - -#![allow(warnings)] - -extern crate lint_stability; - -use lint_stability::{unstable, deprecated}; -//~^ ERROR use of unstable library feature 'unstable_test_feature' - -fn main() { -} diff --git a/src/test/ui/issues/issue-28075.stderr b/src/test/ui/issues/issue-28075.stderr deleted file mode 100644 index 7e53bb54457..00000000000 --- a/src/test/ui/issues/issue-28075.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/issue-28075.rs:9:22 - | -LL | use lint_stability::{unstable, deprecated}; - | ^^^^^^^^ - | - = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs deleted file mode 100644 index 1ed2d330b51..00000000000 --- a/src/test/ui/issues/issue-28134.rs +++ /dev/null @@ -1,4 +0,0 @@ -// compile-flags: --test - -#![allow(soft_unstable)] -#![test] //~ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr deleted file mode 100644 index 8ed4d015f32..00000000000 --- a/src/test/ui/issues/issue-28134.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-28134.rs:4:4 - | -LL | #![test] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-28388-1.rs b/src/test/ui/issues/issue-28388-1.rs deleted file mode 100644 index 14de621405d..00000000000 --- a/src/test/ui/issues/issue-28388-1.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. - -use foo::{}; //~ ERROR unresolved import `foo` - -fn main() {} diff --git a/src/test/ui/issues/issue-28388-1.stderr b/src/test/ui/issues/issue-28388-1.stderr deleted file mode 100644 index 7f5e47aa84f..00000000000 --- a/src/test/ui/issues/issue-28388-1.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `foo` - --> $DIR/issue-28388-1.rs:3:5 - | -LL | use foo::{}; - | ^^^^^^^ no `foo` in the root - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-28388-2.rs b/src/test/ui/issues/issue-28388-2.rs deleted file mode 100644 index 024b0388bc6..00000000000 --- a/src/test/ui/issues/issue-28388-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. - -mod m { - mod n {} -} - -use m::n::{}; -//~^ ERROR module `n` is private - -fn main() {} diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr deleted file mode 100644 index 1afaf622be7..00000000000 --- a/src/test/ui/issues/issue-28388-2.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0603]: module `n` is private - --> $DIR/issue-28388-2.rs:7:8 - | -LL | use m::n::{}; - | ^ private module - | -note: the module `n` is defined here - --> $DIR/issue-28388-2.rs:4:5 - | -LL | mod n {} - | ^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/issues/issue-28388-3.rs b/src/test/ui/issues/issue-28388-3.rs deleted file mode 100644 index 7ba99350121..00000000000 --- a/src/test/ui/issues/issue-28388-3.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. - -// aux-build:lint-stability.rs - -extern crate lint_stability; - -use lint_stability::UnstableEnum::{}; -//~^ ERROR use of unstable library feature 'unstable_test_feature' -use lint_stability::StableEnum::{}; // OK - -fn main() {} diff --git a/src/test/ui/issues/issue-28388-3.stderr b/src/test/ui/issues/issue-28388-3.stderr deleted file mode 100644 index d2e46683b90..00000000000 --- a/src/test/ui/issues/issue-28388-3.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/issue-28388-3.rs:7:5 - | -LL | use lint_stability::UnstableEnum::{}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-2937.rs b/src/test/ui/issues/issue-2937.rs deleted file mode 100644 index 335df5c07e2..00000000000 --- a/src/test/ui/issues/issue-2937.rs +++ /dev/null @@ -1,6 +0,0 @@ -use m::f as x; //~ ERROR unresolved import `m::f` [E0432] - //~^ no `f` in `m` - -mod m {} - -fn main() {} diff --git a/src/test/ui/issues/issue-2937.stderr b/src/test/ui/issues/issue-2937.stderr deleted file mode 100644 index 428634828f9..00000000000 --- a/src/test/ui/issues/issue-2937.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `m::f` - --> $DIR/issue-2937.rs:1:5 - | -LL | use m::f as x; - | ^^^^^^^^^ no `f` in `m` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-30560.rs b/src/test/ui/issues/issue-30560.rs deleted file mode 100644 index d8d4ca608f1..00000000000 --- a/src/test/ui/issues/issue-30560.rs +++ /dev/null @@ -1,9 +0,0 @@ -type Alias = (); -use Alias::*; //~ ERROR unresolved import `Alias` [E0432] - -use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432] - -trait T {} -use T::*; //~ ERROR items in traits are not importable - -fn main() {} diff --git a/src/test/ui/issues/issue-30560.stderr b/src/test/ui/issues/issue-30560.stderr deleted file mode 100644 index b74134aaccc..00000000000 --- a/src/test/ui/issues/issue-30560.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: items in traits are not importable. - --> $DIR/issue-30560.rs:7:5 - | -LL | use T::*; - | ^^^^ - -error[E0432]: unresolved import `Alias` - --> $DIR/issue-30560.rs:2:5 - | -LL | use Alias::*; - | ^^^^^ `Alias` is a type alias, not a module - -error[E0432]: unresolved import `std::io::Result` - --> $DIR/issue-30560.rs:4:14 - | -LL | use std::io::Result::*; - | ^^^^^^ `Result` is a type alias, not a module - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-30730.rs b/src/test/ui/issues/issue-30730.rs deleted file mode 100644 index d6be90c8148..00000000000 --- a/src/test/ui/issues/issue-30730.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(unused)] -#![deny(warnings)] -use std::thread; -//~^ ERROR: unused import -fn main() {} diff --git a/src/test/ui/issues/issue-30730.stderr b/src/test/ui/issues/issue-30730.stderr deleted file mode 100644 index b299e99a3a9..00000000000 --- a/src/test/ui/issues/issue-30730.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: unused import: `std::thread` - --> $DIR/issue-30730.rs:3:5 - | -LL | use std::thread; - | ^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-30730.rs:2:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ - = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-31212.rs b/src/test/ui/issues/issue-31212.rs deleted file mode 100644 index 556f0d18f9f..00000000000 --- a/src/test/ui/issues/issue-31212.rs +++ /dev/null @@ -1,10 +0,0 @@ -// This checks that a path that cannot be resolved because of an indeterminate import -// does not trigger an ICE. - -mod foo { - pub use self::*; //~ ERROR unresolved -} - -fn main() { - foo::f(); //~ ERROR cannot find function `f` in module `foo` -} diff --git a/src/test/ui/issues/issue-31212.stderr b/src/test/ui/issues/issue-31212.stderr deleted file mode 100644 index 0bb56b361cb..00000000000 --- a/src/test/ui/issues/issue-31212.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0432]: unresolved import `self::*` - --> $DIR/issue-31212.rs:5:13 - | -LL | pub use self::*; - | ^^^^^^^ cannot glob-import a module into itself - -error[E0425]: cannot find function `f` in module `foo` - --> $DIR/issue-31212.rs:9:10 - | -LL | foo::f(); - | ^ not found in `foo` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0425, E0432. -For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.fixed b/src/test/ui/issues/issue-32354-suggest-import-rename.fixed deleted file mode 100644 index 27f1b8964e2..00000000000 --- a/src/test/ui/issues/issue-32354-suggest-import-rename.fixed +++ /dev/null @@ -1,16 +0,0 @@ -// run-rustfix - -#![allow(unused_imports)] - -pub mod extension1 { - pub trait ConstructorExtension {} -} - -pub mod extension2 { - pub trait ConstructorExtension {} -} - -use extension1::ConstructorExtension; -use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.rs b/src/test/ui/issues/issue-32354-suggest-import-rename.rs deleted file mode 100644 index 5a7f234d5fa..00000000000 --- a/src/test/ui/issues/issue-32354-suggest-import-rename.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-rustfix - -#![allow(unused_imports)] - -pub mod extension1 { - pub trait ConstructorExtension {} -} - -pub mod extension2 { - pub trait ConstructorExtension {} -} - -use extension1::ConstructorExtension; -use extension2::ConstructorExtension; //~ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.stderr b/src/test/ui/issues/issue-32354-suggest-import-rename.stderr deleted file mode 100644 index 96684309a00..00000000000 --- a/src/test/ui/issues/issue-32354-suggest-import-rename.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `ConstructorExtension` is defined multiple times - --> $DIR/issue-32354-suggest-import-rename.rs:14:5 - | -LL | use extension1::ConstructorExtension; - | -------------------------------- previous import of the trait `ConstructorExtension` here -LL | use extension2::ConstructorExtension; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here - | - = note: `ConstructorExtension` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use extension2::ConstructorExtension as OtherConstructorExtension; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-32833.rs b/src/test/ui/issues/issue-32833.rs deleted file mode 100644 index 379eedde726..00000000000 --- a/src/test/ui/issues/issue-32833.rs +++ /dev/null @@ -1,7 +0,0 @@ -use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432] - //~^ no `Foo` in `bar` -mod bar { - use Foo; -} - -fn main() {} diff --git a/src/test/ui/issues/issue-32833.stderr b/src/test/ui/issues/issue-32833.stderr deleted file mode 100644 index 430cc0fda26..00000000000 --- a/src/test/ui/issues/issue-32833.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `bar::Foo` - --> $DIR/issue-32833.rs:1:5 - | -LL | use bar::Foo; - | ^^^^^^^^ no `Foo` in `bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-33464.rs b/src/test/ui/issues/issue-33464.rs deleted file mode 100644 index a0edb5fdb6f..00000000000 --- a/src/test/ui/issues/issue-33464.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Make sure that the spans of import errors are correct. - -use abc::one_el; -//~^ ERROR -use abc::{a, bbb, cccccc}; -//~^ ERROR -use a_very_long_name::{el, el2}; -//~^ ERROR - -fn main() {} diff --git a/src/test/ui/issues/issue-33464.stderr b/src/test/ui/issues/issue-33464.stderr deleted file mode 100644 index d3bf404c99a..00000000000 --- a/src/test/ui/issues/issue-33464.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0432]: unresolved import `abc` - --> $DIR/issue-33464.rs:3:5 - | -LL | use abc::one_el; - | ^^^ maybe a missing crate `abc`? - -error[E0432]: unresolved import `abc` - --> $DIR/issue-33464.rs:5:5 - | -LL | use abc::{a, bbb, cccccc}; - | ^^^ maybe a missing crate `abc`? - -error[E0432]: unresolved import `a_very_long_name` - --> $DIR/issue-33464.rs:7:5 - | -LL | use a_very_long_name::{el, el2}; - | ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`? - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs deleted file mode 100644 index 1102f3c4640..00000000000 --- a/src/test/ui/issues/issue-36617.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions - //~| ERROR cannot determine resolution for the derive macro `Copy` - -fn main() {} diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr deleted file mode 100644 index dc6ef169259..00000000000 --- a/src/test/ui/issues/issue-36617.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-36617.rs:1:1 - | -LL | #![derive(Copy)] - | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]` - -error: cannot determine resolution for the derive macro `Copy` - --> $DIR/issue-36617.rs:1:11 - | -LL | #![derive(Copy)] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/issues/issue-36881.rs b/src/test/ui/issues/issue-36881.rs deleted file mode 100644 index 04313872d27..00000000000 --- a/src/test/ui/issues/issue-36881.rs +++ /dev/null @@ -1,6 +0,0 @@ -// aux-build:issue-36881-aux.rs - -fn main() { - extern crate issue_36881_aux; - use issue_36881_aux::Foo; //~ ERROR unresolved import -} diff --git a/src/test/ui/issues/issue-36881.stderr b/src/test/ui/issues/issue-36881.stderr deleted file mode 100644 index caf9d5d6d62..00000000000 --- a/src/test/ui/issues/issue-36881.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `issue_36881_aux` - --> $DIR/issue-36881.rs:5:9 - | -LL | use issue_36881_aux::Foo; - | ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`? - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-37887.rs b/src/test/ui/issues/issue-37887.rs deleted file mode 100644 index 58f0c6b651a..00000000000 --- a/src/test/ui/issues/issue-37887.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - extern crate libc; //~ ERROR use of unstable - use libc::*; //~ ERROR unresolved import -} diff --git a/src/test/ui/issues/issue-37887.stderr b/src/test/ui/issues/issue-37887.stderr deleted file mode 100644 index 944d544098a..00000000000 --- a/src/test/ui/issues/issue-37887.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0432]: unresolved import `libc` - --> $DIR/issue-37887.rs:3:9 - | -LL | use libc::*; - | ^^^^ maybe a missing crate `libc`? - -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/issue-37887.rs:2:5 - | -LL | extern crate libc; - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #27812 for more information - = help: add `#![feature(rustc_private)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0432, E0658. -For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-38293.rs b/src/test/ui/issues/issue-38293.rs deleted file mode 100644 index 3b1393600ba..00000000000 --- a/src/test/ui/issues/issue-38293.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace. - -mod foo { - pub fn f() { } -} -use foo::f::{self}; //~ ERROR unresolved import `foo::f` - -mod bar { - pub fn baz() {} - pub mod baz {} -} -use bar::baz::{self}; - -fn main() { - baz(); //~ ERROR expected function, found module `baz` -} diff --git a/src/test/ui/issues/issue-38293.stderr b/src/test/ui/issues/issue-38293.stderr deleted file mode 100644 index d2450ab1250..00000000000 --- a/src/test/ui/issues/issue-38293.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0432]: unresolved import `foo::f` - --> $DIR/issue-38293.rs:6:14 - | -LL | use foo::f::{self}; - | ^^^^ no `f` in `foo` - -error[E0423]: expected function, found module `baz` - --> $DIR/issue-38293.rs:15:5 - | -LL | baz(); - | ^^^ not a function - | -help: consider importing this function instead - | -LL | use bar::baz; - | - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0423, E0432. -For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/issues/issue-4366-2.rs b/src/test/ui/issues/issue-4366-2.rs deleted file mode 100644 index c777b750252..00000000000 --- a/src/test/ui/issues/issue-4366-2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// ensures that 'use foo:*' doesn't import non-public item - -use m1::*; - -mod foo { - pub fn foo() {} -} -mod a { - pub mod b { - use foo::foo; - type Bar = isize; - } - pub mod sub { - use a::b::*; - fn sub() -> Bar { 1 } - //~^ ERROR cannot find type `Bar` in this scope - } -} - -mod m1 { - fn foo() {} -} - -fn main() { - foo(); //~ ERROR expected function, found module `foo` -} diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr deleted file mode 100644 index a86ec7fabea..00000000000 --- a/src/test/ui/issues/issue-4366-2.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0412]: cannot find type `Bar` in this scope - --> $DIR/issue-4366-2.rs:15:21 - | -LL | fn sub() -> Bar { 1 } - | ^^^ not found in this scope - | -help: consider importing this type alias - | -LL | use a::b::Bar; - | - -error[E0423]: expected function, found module `foo` - --> $DIR/issue-4366-2.rs:25:5 - | -LL | foo(); - | ^^^ not a function - | -help: consider importing this function instead - | -LL | use foo::foo; - | - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0412, E0423. -For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-4366.rs b/src/test/ui/issues/issue-4366.rs deleted file mode 100644 index 9ec2e58ecad..00000000000 --- a/src/test/ui/issues/issue-4366.rs +++ /dev/null @@ -1,26 +0,0 @@ -// regression test for issue 4366 - -// ensures that 'use foo:*' doesn't import non-public 'use' statements in the -// module 'foo' - -use m1::*; - -mod foo { - pub fn foo() {} -} -mod a { - pub mod b { - use foo::foo; - type Bar = isize; - } - pub mod sub { - use a::b::*; - fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope - } -} - -mod m1 { - fn foo() {} -} - -fn main() {} diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr deleted file mode 100644 index 469ea93e904..00000000000 --- a/src/test/ui/issues/issue-4366.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0425]: cannot find function `foo` in this scope - --> $DIR/issue-4366.rs:18:29 - | -LL | fn sub() -> isize { foo(); 1 } - | ^^^ not found in this scope - | -help: consider importing this function - | -LL | use foo::foo; - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed deleted file mode 100644 index b463848ae94..00000000000 --- a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed +++ /dev/null @@ -1,5 +0,0 @@ -// run-rustfix - -extern crate std as other_std; -fn main() {} -//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs deleted file mode 100644 index 1b491ac7efe..00000000000 --- a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs +++ /dev/null @@ -1,5 +0,0 @@ -// run-rustfix - -extern crate std; -fn main() {} -//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr deleted file mode 100644 index 25aca4cb7ec..00000000000 --- a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0259]: the name `std` is defined multiple times - --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1 - | -LL | extern crate std; - | ^^^^^^^^^^^^^^^^^ `std` reimported here - | - = note: `std` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | extern crate std as other_std; - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs deleted file mode 100644 index e9f7fefb6fb..00000000000 --- a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs +++ /dev/null @@ -1 +0,0 @@ -pub const FOO: usize = *&0; diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs deleted file mode 100644 index e9f7fefb6fb..00000000000 --- a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs +++ /dev/null @@ -1 +0,0 @@ -pub const FOO: usize = *&0; diff --git a/src/test/ui/issues/issue-45829/import-self.rs b/src/test/ui/issues/issue-45829/import-self.rs deleted file mode 100644 index 2dc4331ced7..00000000000 --- a/src/test/ui/issues/issue-45829/import-self.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod foo { - pub struct A; - pub struct B; -} - -use foo::{self}; -//~^ ERROR is defined multiple times - -use foo as self; -//~^ ERROR expected identifier - -use foo::self; //~ ERROR is defined multiple times -//~^ ERROR `self` imports are only allowed within a { } list - -use foo::A; -use foo::{self as A}; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/import-self.stderr b/src/test/ui/issues/issue-45829/import-self.stderr deleted file mode 100644 index 158e81cdd96..00000000000 --- a/src/test/ui/issues/issue-45829/import-self.stderr +++ /dev/null @@ -1,69 +0,0 @@ -error: expected identifier, found keyword `self` - --> $DIR/import-self.rs:9:12 - | -LL | use foo as self; - | ^^^^ expected identifier, found keyword - -error[E0429]: `self` imports are only allowed within a { } list - --> $DIR/import-self.rs:12:8 - | -LL | use foo::self; - | ^^^^^^ - | -help: consider importing the module directly - | -LL | use foo; - | -- -help: alternatively, use the multi-path `use` syntax to import `self` - | -LL | use foo::{self}; - | ^ ^ - -error[E0255]: the name `foo` is defined multiple times - --> $DIR/import-self.rs:6:11 - | -LL | mod foo { - | ------- previous definition of the module `foo` here -... -LL | use foo::{self}; - | ^^^^ `foo` reimported here - | - = note: `foo` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use foo::{self as other_foo}; - | ^^^^^^^^^^^^^^^^^ - -error[E0255]: the name `foo` is defined multiple times - --> $DIR/import-self.rs:12:5 - | -LL | mod foo { - | ------- previous definition of the module `foo` here -... -LL | use foo::self; - | ^^^^^^^^^ `foo` reimported here - | - = note: `foo` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use foo as other_foo; - | ^^^^^^^^^^^^^^^^ - -error[E0252]: the name `A` is defined multiple times - --> $DIR/import-self.rs:16:11 - | -LL | use foo::A; - | ------ previous import of the type `A` here -LL | use foo::{self as A}; - | ^^^^^^^^^ `A` reimported here - | - = note: `A` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use foo::{self as OtherA}; - | ^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0252, E0255, E0429. -For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/import-twice.rs b/src/test/ui/issues/issue-45829/import-twice.rs deleted file mode 100644 index e5a8bb7adf6..00000000000 --- a/src/test/ui/issues/issue-45829/import-twice.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod foo { - pub struct A; - pub struct B; -} - -use foo::{A, A}; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/import-twice.stderr b/src/test/ui/issues/issue-45829/import-twice.stderr deleted file mode 100644 index 656b011bc3b..00000000000 --- a/src/test/ui/issues/issue-45829/import-twice.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0252]: the name `A` is defined multiple times - --> $DIR/import-twice.rs:6:14 - | -LL | use foo::{A, A}; - | - ^ `A` reimported here - | | - | previous import of the type `A` here - | - = note: `A` must be defined only once in the type namespace of this module - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/issue-45829.rs b/src/test/ui/issues/issue-45829/issue-45829.rs deleted file mode 100644 index 1e76e4b140e..00000000000 --- a/src/test/ui/issues/issue-45829/issue-45829.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod foo { - pub struct A; - pub struct B; -} - -use foo::{A, B as A}; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/issue-45829.stderr b/src/test/ui/issues/issue-45829/issue-45829.stderr deleted file mode 100644 index a7ebc7171bc..00000000000 --- a/src/test/ui/issues/issue-45829/issue-45829.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `A` is defined multiple times - --> $DIR/issue-45829.rs:6:14 - | -LL | use foo::{A, B as A}; - | - ^^^^^^ `A` reimported here - | | - | previous import of the type `A` here - | - = note: `A` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use foo::{A, B as OtherA}; - | ^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs b/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs deleted file mode 100644 index aef7aa35cf5..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs +++ /dev/null @@ -1,11 +0,0 @@ -// aux-build:issue-45829-b.rs - -mod foo { - pub mod bar {} -} - -use foo::bar; -extern crate issue_45829_b as bar; -//~^ ERROR the name `bar` is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr b/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr deleted file mode 100644 index 98fd8a623fe..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0254]: the name `bar` is defined multiple times - --> $DIR/rename-extern-vs-use.rs:8:1 - | -LL | use foo::bar; - | -------- previous import of the module `bar` here -LL | extern crate issue_45829_b as bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here - | - = note: `bar` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | extern crate issue_45829_b as other_bar; - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0254`. diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs deleted file mode 100644 index 0da8b826c90..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs +++ /dev/null @@ -1,8 +0,0 @@ -// aux-build:issue-45829-a.rs -// aux-build:issue-45829-b.rs - -extern crate issue_45829_a; -extern crate issue_45829_b as issue_45829_a; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr deleted file mode 100644 index 2c4e8ce996b..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0259]: the name `issue_45829_a` is defined multiple times - --> $DIR/rename-extern-with-tab.rs:5:1 - | -LL | extern crate issue_45829_a; - | --------------------------- previous import of the extern crate `issue_45829_a` here -LL | extern crate issue_45829_b as issue_45829_a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here - | - = note: `issue_45829_a` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | extern crate issue_45829_b as other_issue_45829_a; - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/issues/issue-45829/rename-extern.rs b/src/test/ui/issues/issue-45829/rename-extern.rs deleted file mode 100644 index 7dbda69322e..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern.rs +++ /dev/null @@ -1,8 +0,0 @@ -// aux-build:issue-45829-a.rs -// aux-build:issue-45829-b.rs - -extern crate issue_45829_a; -extern crate issue_45829_b as issue_45829_a; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-extern.stderr b/src/test/ui/issues/issue-45829/rename-extern.stderr deleted file mode 100644 index 209ae2201f9..00000000000 --- a/src/test/ui/issues/issue-45829/rename-extern.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0259]: the name `issue_45829_a` is defined multiple times - --> $DIR/rename-extern.rs:5:1 - | -LL | extern crate issue_45829_a; - | --------------------------- previous import of the extern crate `issue_45829_a` here -LL | extern crate issue_45829_b as issue_45829_a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here - | - = note: `issue_45829_a` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | extern crate issue_45829_b as other_issue_45829_a; - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs b/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs deleted file mode 100644 index 0cf3a77fd7c..00000000000 --- a/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs +++ /dev/null @@ -1,7 +0,0 @@ -// aux-build:issue-45829-b.rs - -extern crate issue_45829_b; -use std as issue_45829_b; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr b/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr deleted file mode 100644 index 6b917d55747..00000000000 --- a/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0254]: the name `issue_45829_b` is defined multiple times - --> $DIR/rename-use-vs-extern.rs:4:5 - | -LL | extern crate issue_45829_b; - | --------------------------- previous import of the extern crate `issue_45829_b` here -LL | use std as issue_45829_b; - | ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here - | - = note: `issue_45829_b` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std as other_issue_45829_b; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0254`. diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs deleted file mode 100644 index 86c5fa00fdb..00000000000 --- a/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs +++ /dev/null @@ -1,12 +0,0 @@ -mod foo { - pub struct A; - - pub mod bar { - pub struct B; - } -} - -use foo::{A, bar::B as A}; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr deleted file mode 100644 index 3baad6cd72f..00000000000 --- a/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `A` is defined multiple times - --> $DIR/rename-use-with-tabs.rs:9:14 - | -LL | use foo::{A, bar::B as A}; - | - ^^^^^^^^^^^^^^^^^ `A` reimported here - | | - | previous import of the type `A` here - | - = note: `A` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use foo::{A, bar::B as OtherA}; - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/rename-with-path.rs b/src/test/ui/issues/issue-45829/rename-with-path.rs deleted file mode 100644 index e278a878937..00000000000 --- a/src/test/ui/issues/issue-45829/rename-with-path.rs +++ /dev/null @@ -1,4 +0,0 @@ -use std::{collections::HashMap as A, sync::Arc as A}; -//~^ ERROR is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-with-path.stderr b/src/test/ui/issues/issue-45829/rename-with-path.stderr deleted file mode 100644 index ba83eeaa813..00000000000 --- a/src/test/ui/issues/issue-45829/rename-with-path.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `A` is defined multiple times - --> $DIR/rename-with-path.rs:1:38 - | -LL | use std::{collections::HashMap as A, sync::Arc as A}; - | ------------------------- ^^^^^^^^^^^^^^ `A` reimported here - | | - | previous import of the type `A` here - | - = note: `A` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std::{collections::HashMap as A, sync::Arc as OtherA}; - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/rename.rs b/src/test/ui/issues/issue-45829/rename.rs deleted file mode 100644 index 1c45956c66a..00000000000 --- a/src/test/ui/issues/issue-45829/rename.rs +++ /dev/null @@ -1,7 +0,0 @@ -use core; -use std as core; -//~^ ERROR is defined multiple times - -fn main() { - 1 + 1; -} diff --git a/src/test/ui/issues/issue-45829/rename.stderr b/src/test/ui/issues/issue-45829/rename.stderr deleted file mode 100644 index 8f12d92d6fb..00000000000 --- a/src/test/ui/issues/issue-45829/rename.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0252]: the name `core` is defined multiple times - --> $DIR/rename.rs:2:5 - | -LL | use core; - | ---- previous import of the module `core` here -LL | use std as core; - | ^^^^^^^^^^^ `core` reimported here - | - = note: `core` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use std as other_core; - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-46576.rs b/src/test/ui/issues/issue-46576.rs deleted file mode 100644 index 15f458f3844..00000000000 --- a/src/test/ui/issues/issue-46576.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![allow(dead_code)] -#![deny(unused_imports)] - -use std::fs::File; -use std::io::{BufRead, BufReader, Read}; -//~^ ERROR unused import: `BufRead` - -pub fn read_from_file(path: &str) { - let file = File::open(&path).unwrap(); - let mut reader = BufReader::new(file); - let mut s = String::new(); - reader.read_to_string(&mut s).unwrap(); -} - -pub fn read_lines(s: &str) { - for _line in s.lines() { - - } -} - -fn main() {} diff --git a/src/test/ui/issues/issue-46576.stderr b/src/test/ui/issues/issue-46576.stderr deleted file mode 100644 index 6f4d97068b3..00000000000 --- a/src/test/ui/issues/issue-46576.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unused import: `BufRead` - --> $DIR/issue-46576.rs:5:15 - | -LL | use std::io::{BufRead, BufReader, Read}; - | ^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-46576.rs:2:9 - | -LL | #![deny(unused_imports)] - | ^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-47623.rs b/src/test/ui/issues/issue-47623.rs deleted file mode 100644 index ad8aa4c1a2b..00000000000 --- a/src/test/ui/issues/issue-47623.rs +++ /dev/null @@ -1,3 +0,0 @@ -use self; //~ERROR `self` imports are only allowed within a { } list - -fn main() {} diff --git a/src/test/ui/issues/issue-47623.stderr b/src/test/ui/issues/issue-47623.stderr deleted file mode 100644 index 53968a2960c..00000000000 --- a/src/test/ui/issues/issue-47623.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0429]: `self` imports are only allowed within a { } list - --> $DIR/issue-47623.rs:1:5 - | -LL | use self; - | ^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0429`. diff --git a/src/test/ui/issues/issue-4865-1.rs b/src/test/ui/issues/issue-4865-1.rs deleted file mode 100644 index 68fbee37d01..00000000000 --- a/src/test/ui/issues/issue-4865-1.rs +++ /dev/null @@ -1,33 +0,0 @@ -// run-pass -#![allow(unused_imports)] -// This should resolve fine. -// Prior to fix, the crossed imports between a and b -// would block on the glob import, itself never being resolved -// because these previous imports were not resolved. - -pub mod a { - use b::fn_b; - use c::*; - - pub fn fn_a(){ - } -} - -pub mod b { - use a::fn_a; - use c::*; - - pub fn fn_b(){ - } -} - -pub mod c{ - pub fn fn_c(){ - } -} - -use a::fn_a; -use b::fn_b; - -fn main() { -} diff --git a/src/test/ui/issues/issue-4865-2.rs b/src/test/ui/issues/issue-4865-2.rs deleted file mode 100644 index cbe1d0d32c6..00000000000 --- a/src/test/ui/issues/issue-4865-2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// run-pass -// Previously, this would have failed to resolve due to the circular -// block between `use say` and `pub use hello::*`. -// -// Now, as `use say` is not `pub`, the glob import can resolve -// without any problem and this resolves fine. - -pub use hello::*; - -pub mod say { - pub fn hello() { println!("hello"); } -} - -pub mod hello { - use say; - - pub fn hello() { - say::hello(); - } -} - -fn main() { - hello(); -} diff --git a/src/test/ui/issues/issue-4865-3.rs b/src/test/ui/issues/issue-4865-3.rs deleted file mode 100644 index 12f9bba18d8..00000000000 --- a/src/test/ui/issues/issue-4865-3.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass -#![allow(unused_imports)] -// This should resolve fine even with the circular imports as -// they are not `pub`. - -pub mod a { - use b::*; -} - -pub mod b { - use a::*; -} - -use a::*; - -fn main() { -} diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs deleted file mode 100644 index 752bb345b70..00000000000 --- a/src/test/ui/issues/issue-49074.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Check that unknown attribute error is shown even if there are unresolved macros. - -#[marco_use] // typo -//~^ ERROR cannot find attribute `marco_use` in this scope -mod foo { - macro_rules! bar { - () => (); - } -} - -fn main() { - bar!(); //~ ERROR cannot find macro `bar` in this scope -} diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr deleted file mode 100644 index bbfeb4ea948..00000000000 --- a/src/test/ui/issues/issue-49074.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: cannot find macro `bar` in this scope - --> $DIR/issue-49074.rs:12:4 - | -LL | bar!(); - | ^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - -error: cannot find attribute `marco_use` in this scope - --> $DIR/issue-49074.rs:3:3 - | -LL | #[marco_use] // typo - | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/issues/issue-52891.fixed b/src/test/ui/issues/issue-52891.fixed deleted file mode 100644 index e694b5c9b15..00000000000 --- a/src/test/ui/issues/issue-52891.fixed +++ /dev/null @@ -1,37 +0,0 @@ -// aux-build:issue-52891.rs -// run-rustfix - -#![allow(warnings)] - -extern crate issue_52891; - -// Check that we don't suggest renaming duplicate imports but instead -// suggest removing one. - -use issue_52891::a; - //~ ERROR `a` is defined multiple times - -use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times -use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times -use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times - -use issue_52891::{//~ ERROR `a` is defined multiple times - h, - i}; -use issue_52891::{j, - //~ ERROR `a` is defined multiple times - k}; -use issue_52891::{l, - m}; //~ ERROR `a` is defined multiple times - -use issue_52891::a::inner; -use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times - - -//~^ ERROR `issue_52891` is defined multiple times - - -#[macro_use] -use issue_52891::n; //~ ERROR `n` is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-52891.rs b/src/test/ui/issues/issue-52891.rs deleted file mode 100644 index cd4b40629ab..00000000000 --- a/src/test/ui/issues/issue-52891.rs +++ /dev/null @@ -1,38 +0,0 @@ -// aux-build:issue-52891.rs -// run-rustfix - -#![allow(warnings)] - -extern crate issue_52891; - -// Check that we don't suggest renaming duplicate imports but instead -// suggest removing one. - -use issue_52891::a; -use issue_52891::a; //~ ERROR `a` is defined multiple times - -use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times -use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times -use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times - -use issue_52891::{a, //~ ERROR `a` is defined multiple times - h, - i}; -use issue_52891::{j, - a, //~ ERROR `a` is defined multiple times - k}; -use issue_52891::{l, - m, - a}; //~ ERROR `a` is defined multiple times - -use issue_52891::a::inner; -use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times - -use issue_52891::{self}; -//~^ ERROR `issue_52891` is defined multiple times - -use issue_52891::n; -#[macro_use] -use issue_52891::n; //~ ERROR `n` is defined multiple times - -fn main() {} diff --git a/src/test/ui/issues/issue-52891.stderr b/src/test/ui/issues/issue-52891.stderr deleted file mode 100644 index 6e6e42ddc2d..00000000000 --- a/src/test/ui/issues/issue-52891.stderr +++ /dev/null @@ -1,131 +0,0 @@ -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:12:5 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -LL | use issue_52891::a; - | ^^^^^^^^^^^^^^ `a` reimported here - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:14:19 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | use issue_52891::{a, b, c}; - | ^-- - | | - | `a` reimported here - | help: remove unnecessary import - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:15:22 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | use issue_52891::{d, a, e}; - | ^-- - | | - | `a` reimported here - | help: remove unnecessary import - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:16:25 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | use issue_52891::{f, g, a}; - | ^ `a` reimported here - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:18:19 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | use issue_52891::{a, - | ^-- - | | - | `a` reimported here - | help: remove unnecessary import - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:22:5 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | a, - | ^-- - | | - | `a` reimported here - | help: remove unnecessary import - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `a` is defined multiple times - --> $DIR/issue-52891.rs:26:5 - | -LL | use issue_52891::a; - | -------------- previous import of the module `a` here -... -LL | a}; - | ^ `a` reimported here - | - = note: `a` must be defined only once in the type namespace of this module - -error[E0252]: the name `inner` is defined multiple times - --> $DIR/issue-52891.rs:29:5 - | -LL | use issue_52891::a::inner; - | --------------------- previous import of the module `inner` here -LL | use issue_52891::b::inner; - | ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here - | - = note: `inner` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use issue_52891::b::inner as other_inner; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0254]: the name `issue_52891` is defined multiple times - --> $DIR/issue-52891.rs:31:19 - | -LL | extern crate issue_52891; - | ------------------------- previous import of the extern crate `issue_52891` here -... -LL | use issue_52891::{self}; - | ------------------^^^^-- - | | | - | | `issue_52891` reimported here - | help: remove unnecessary import - | - = note: `issue_52891` must be defined only once in the type namespace of this module - -error[E0252]: the name `n` is defined multiple times - --> $DIR/issue-52891.rs:36:5 - | -LL | use issue_52891::n; - | -------------- previous import of the module `n` here -LL | #[macro_use] -LL | use issue_52891::n; - | ^^^^^^^^^^^^^^ `n` reimported here - | - = note: `n` must be defined only once in the type namespace of this module - -error: aborting due to 10 previous errors - -Some errors have detailed explanations: E0252, E0254. -For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-53565.rs b/src/test/ui/issues/issue-53565.rs deleted file mode 100644 index 114a53a92ca..00000000000 --- a/src/test/ui/issues/issue-53565.rs +++ /dev/null @@ -1,7 +0,0 @@ -use std::time::{foo, bar, buzz}; -//~^ ERROR unresolved imports -use std::time::{abc, def}; -//~^ ERROR unresolved imports -fn main(){ - println!("Hello World!"); -} diff --git a/src/test/ui/issues/issue-53565.stderr b/src/test/ui/issues/issue-53565.stderr deleted file mode 100644 index 71c3b2aaaf2..00000000000 --- a/src/test/ui/issues/issue-53565.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz` - --> $DIR/issue-53565.rs:1:17 - | -LL | use std::time::{foo, bar, buzz}; - | ^^^ ^^^ ^^^^ no `buzz` in `time` - | | | - | | no `bar` in `time` - | no `foo` in `time` - -error[E0432]: unresolved imports `std::time::abc`, `std::time::def` - --> $DIR/issue-53565.rs:3:17 - | -LL | use std::time::{abc, def}; - | ^^^ ^^^ no `def` in `time` - | | - | no `abc` in `time` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-56411-aux.rs b/src/test/ui/issues/issue-56411-aux.rs deleted file mode 100644 index c8e5a059810..00000000000 --- a/src/test/ui/issues/issue-56411-aux.rs +++ /dev/null @@ -1,5 +0,0 @@ -// check-pass - -struct T {} - -fn main() {} diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs deleted file mode 100644 index 163651a7ef6..00000000000 --- a/src/test/ui/issues/issue-56411.rs +++ /dev/null @@ -1,18 +0,0 @@ -macro_rules! import { - ( $(($path:expr, $name:ident)),* ) => { - $( - #[path = $path] - mod $name; - pub use self::$name; - //~^ ERROR the name `issue_56411_aux` is defined multiple times - //~| ERROR `issue_56411_aux` is private, and cannot be re-exported - - )* - } -} - -import!(("issue-56411-aux.rs", issue_56411_aux)); - -fn main() { - println!("Hello, world!"); -} diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr deleted file mode 100644 index 3ac8dc548ae..00000000000 --- a/src/test/ui/issues/issue-56411.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0255]: the name `issue_56411_aux` is defined multiple times - --> $DIR/issue-56411.rs:6:21 - | -LL | mod $name; - | ---------- previous definition of the module `issue_56411_aux` here -LL | pub use self::$name; - | ^^^^^^^^^^^ - | | - | `issue_56411_aux` reimported here - | you can use `as` to change the binding name of the import -... -LL | import!(("issue-56411-aux.rs", issue_56411_aux)); - | ------------------------------------------------- in this macro invocation - | - = note: `issue_56411_aux` must be defined only once in the type namespace of this module - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0365]: `issue_56411_aux` is private, and cannot be re-exported - --> $DIR/issue-56411.rs:6:21 - | -LL | pub use self::$name; - | ^^^^^^^^^^^ re-export of private `issue_56411_aux` -... -LL | import!(("issue-56411-aux.rs", issue_56411_aux)); - | ------------------------------------------------- in this macro invocation - | - = note: consider declaring type or module `issue_56411_aux` with `pub` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0255, E0365. -For more information about an error, try `rustc --explain E0255`. diff --git a/src/test/ui/issues/issue-59764.rs b/src/test/ui/issues/issue-59764.rs deleted file mode 100644 index 09dee8c2732..00000000000 --- a/src/test/ui/issues/issue-59764.rs +++ /dev/null @@ -1,136 +0,0 @@ -// aux-build:issue-59764.rs -// compile-flags:--extern issue_59764 -// edition:2018 - -#![allow(warnings)] - -// This tests the suggestion to import macros from the root of a crate. This aims to capture -// the case where a user attempts to import a macro from the definition location instead of the -// root of the crate and the macro is annotated with `#![macro_export]`. - -// Edge cases.. - -mod multiple_imports_same_line_at_end { - use issue_59764::foo::{baz, makro}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod multiple_imports_multiline_at_end_trailing_comma { - use issue_59764::foo::{ - baz, - makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }; -} - -mod multiple_imports_multiline_at_end { - use issue_59764::foo::{ - baz, - makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }; -} - -mod multiple_imports_same_line_in_middle { - use issue_59764::foo::{baz, makro, foobar}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod multiple_imports_multiline_in_middle_trailing_comma { - use issue_59764::foo::{ - baz, - makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - foobar, - }; -} - -mod multiple_imports_multiline_in_middle { - use issue_59764::foo::{ - baz, - makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - foobar - }; -} - -mod nested_imports { - use issue_59764::{foobaz, foo::makro}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod nested_multiple_imports { - use issue_59764::{foobaz, foo::{baz, makro}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod nested_multiline_multiple_imports_trailing_comma { - use issue_59764::{ - foobaz, - foo::{ - baz, - makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - }, - }; -} - -mod nested_multiline_multiple_imports { - use issue_59764::{ - foobaz, - foo::{ - baz, - makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - } - }; -} - -mod doubly_nested_multiple_imports { - use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod doubly_multiline_nested_multiple_imports { - use issue_59764::{ - foobaz, - foo::{ - baz, - makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - barbaz::{ - barfoo, - } - } - }; -} - -mod renamed_import { - use issue_59764::foo::makro as baz; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod renamed_multiple_imports { - use issue_59764::foo::{baz, makro as foobar}; - //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] -} - -mod lots_of_whitespace { - use - issue_59764::{ - - foobaz, - - - foo::{baz, - - makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] - - }; -} - -// Simple case.. - -use issue_59764::foo::makro; -//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] - -makro!(bar); -//~^ ERROR cannot determine resolution for the macro `makro` - -fn main() { - bar(); - //~^ ERROR cannot find function `bar` in this scope [E0425] -} diff --git a/src/test/ui/issues/issue-59764.stderr b/src/test/ui/issues/issue-59764.stderr deleted file mode 100644 index f266e908ecc..00000000000 --- a/src/test/ui/issues/issue-59764.stderr +++ /dev/null @@ -1,241 +0,0 @@ -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:14:33 - | -LL | use issue_59764::foo::{baz, makro}; - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{baz}}; - | ^^^^^^^^^ --^^ - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:21:9 - | -LL | makro, - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{ -LL | baz, -LL | -LL | }}; - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:28:9 - | -LL | makro - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{ -LL | baz, -LL | -LL | }}; - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:33:33 - | -LL | use issue_59764::foo::{baz, makro, foobar}; - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{baz, foobar}}; - | ^^^^^^^^^ -- ^^ - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:40:9 - | -LL | makro, - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{ -LL | baz, -LL | -LL | foobar, -LL | }}; - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:48:9 - | -LL | makro, - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foo::{ -LL | baz, -LL | -LL | foobar -LL | }}; - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:54:31 - | -LL | use issue_59764::{foobaz, foo::makro}; - | ^^^^^^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foobaz}; - | ^^^^^^^ -- - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:59:42 - | -LL | use issue_59764::{foobaz, foo::{baz, makro}}; - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foobaz, foo::{baz}}; - | ^^^^^^^ -- - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:68:13 - | -LL | makro, - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, -LL | foobaz, -LL | foo::{ -LL | baz, -LL | - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:78:13 - | -LL | makro - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, -LL | foobaz, -LL | foo::{ -LL | baz, -LL | - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:84:42 - | -LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; - | ^^^^^^^ -- - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:93:13 - | -LL | makro, - | ^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro, -LL | foobaz, -LL | foo::{ -LL | baz, -LL | - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:102:9 - | -LL | use issue_59764::foo::makro as baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::makro as baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:107:33 - | -LL | use issue_59764::foo::{baz, makro as foobar}; - | ^^^^^^^^^^^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::{makro as foobar, foo::{baz}}; - | ^^^^^^^^^^^^^^^^^^^ --^^ - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:120:17 - | -LL | makro as foobar} - | ^^^^^^^^^^^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | issue_59764::{makro as foobar, -LL | -LL | foobaz, -LL | -LL | -LL | foo::{baz} - | - -error[E0432]: unresolved import `issue_59764::foo::makro` - --> $DIR/issue-59764.rs:127:5 - | -LL | use issue_59764::foo::makro; - | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` - | - = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined -help: a macro with this name exists at the root of the crate - | -LL | use issue_59764::makro; - | ^^^^^^^^^^^^^^^^^^ - -error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:130:1 - | -LL | makro!(bar); - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:134:5 - | -LL | bar(); - | ^^^ not found in this scope - -error: aborting due to 18 previous errors - -Some errors have detailed explanations: E0425, E0432. -For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-59896.rs b/src/test/ui/issues/issue-59896.rs deleted file mode 100644 index ff9f19acf84..00000000000 --- a/src/test/ui/issues/issue-59896.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![deny(unused_imports)] - -struct S; - -fn main() { - use S; //~ ERROR the item `S` is imported redundantly - - let _s = S; -} diff --git a/src/test/ui/issues/issue-59896.stderr b/src/test/ui/issues/issue-59896.stderr deleted file mode 100644 index 95b7938ae03..00000000000 --- a/src/test/ui/issues/issue-59896.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: the item `S` is imported redundantly - --> $DIR/issue-59896.rs:6:9 - | -LL | struct S; - | --------- the item `S` is already defined here -... -LL | use S; - | ^ - | -note: the lint level is defined here - --> $DIR/issue-59896.rs:1:9 - | -LL | #![deny(unused_imports)] - | ^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-70041.rs b/src/test/ui/issues/issue-70041.rs deleted file mode 100644 index 22e42295eed..00000000000 --- a/src/test/ui/issues/issue-70041.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-flags: --edition=2018 -// run-pass - -macro_rules! regex { - //~^ WARN unused macro definition - () => {}; -} - -#[allow(dead_code)] -use regex; -//~^ WARN unused import - -fn main() {} diff --git a/src/test/ui/issues/issue-70041.stderr b/src/test/ui/issues/issue-70041.stderr deleted file mode 100644 index ecd618eae8b..00000000000 --- a/src/test/ui/issues/issue-70041.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: unused macro definition - --> $DIR/issue-70041.rs:4:1 - | -LL | / macro_rules! regex { -LL | | -LL | | () => {}; -LL | | } - | |_^ - | - = note: `#[warn(unused_macros)]` on by default - -warning: unused import: `regex` - --> $DIR/issue-70041.rs:10:5 - | -LL | use regex; - | ^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: 2 warnings emitted - diff --git a/src/test/ui/issues/issue-8208.rs b/src/test/ui/issues/issue-8208.rs deleted file mode 100644 index 1c566938f9d..00000000000 --- a/src/test/ui/issues/issue-8208.rs +++ /dev/null @@ -1,17 +0,0 @@ -use self::*; //~ ERROR: unresolved import `self::*` [E0432] - //~^ cannot glob-import a module into itself - -mod foo { - use foo::*; //~ ERROR: unresolved import `foo::*` [E0432] - //~^ cannot glob-import a module into itself - - mod bar { - use super::bar::*; - //~^ ERROR: unresolved import `super::bar::*` [E0432] - //~| cannot glob-import a module into itself - } - -} - -fn main() { -} diff --git a/src/test/ui/issues/issue-8208.stderr b/src/test/ui/issues/issue-8208.stderr deleted file mode 100644 index e59aea12cda..00000000000 --- a/src/test/ui/issues/issue-8208.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0432]: unresolved import `self::*` - --> $DIR/issue-8208.rs:1:5 - | -LL | use self::*; - | ^^^^^^^ cannot glob-import a module into itself - -error[E0432]: unresolved import `foo::*` - --> $DIR/issue-8208.rs:5:9 - | -LL | use foo::*; - | ^^^^^^ cannot glob-import a module into itself - -error[E0432]: unresolved import `super::bar::*` - --> $DIR/issue-8208.rs:9:13 - | -LL | use super::bar::*; - | ^^^^^^^^^^^^^ cannot glob-import a module into itself - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-8640.rs b/src/test/ui/issues/issue-8640.rs deleted file mode 100644 index 51a02a32ec8..00000000000 --- a/src/test/ui/issues/issue-8640.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[allow(unused_imports)] - -mod foo { - use baz::bar; - mod bar {} - //~^ ERROR the name `bar` is defined multiple times -} -mod baz { pub mod bar {} } - -fn main() {} diff --git a/src/test/ui/issues/issue-8640.stderr b/src/test/ui/issues/issue-8640.stderr deleted file mode 100644 index 4ce63945464..00000000000 --- a/src/test/ui/issues/issue-8640.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0255]: the name `bar` is defined multiple times - --> $DIR/issue-8640.rs:5:5 - | -LL | use baz::bar; - | -------- previous import of the module `bar` here -LL | mod bar {} - | ^^^^^^^ `bar` redefined here - | - = note: `bar` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | use baz::bar as other_bar; - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/kinds-of-primitive-impl.rs b/src/test/ui/kinds-of-primitive-impl.rs new file mode 100644 index 00000000000..cbd4d7ae904 --- /dev/null +++ b/src/test/ui/kinds-of-primitive-impl.rs @@ -0,0 +1,23 @@ +// ignore-tidy-linelength + + +impl u8 { +//~^ error: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive + pub const B: u8 = 0; +} + +impl str { +//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive + fn foo() {} + fn bar(self) {} +} + +impl char { +//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive + pub const B: u8 = 0; + pub const C: u8 = 0; + fn foo() {} + fn bar(self) {} +} + +fn main() {} diff --git a/src/test/ui/kinds-of-primitive-impl.stderr b/src/test/ui/kinds-of-primitive-impl.stderr new file mode 100644 index 00000000000..d19c85b17f9 --- /dev/null +++ b/src/test/ui/kinds-of-primitive-impl.stderr @@ -0,0 +1,40 @@ +error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive + --> $DIR/kinds-of-primitive-impl.rs:4:1 + | +LL | / impl u8 { +LL | | +LL | | pub const B: u8 = 0; +LL | | } + | |_^ + | + = help: consider using a trait to implement this constant + +error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive + --> $DIR/kinds-of-primitive-impl.rs:9:1 + | +LL | / impl str { +LL | | +LL | | fn foo() {} +LL | | fn bar(self) {} +LL | | } + | |_^ + | + = help: consider using a trait to implement these methods + +error[E0390]: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive + --> $DIR/kinds-of-primitive-impl.rs:15:1 + | +LL | / impl char { +LL | | +LL | | pub const B: u8 = 0; +LL | | pub const C: u8 = 0; +LL | | fn foo() {} +LL | | fn bar(self) {} +LL | | } + | |_^ + | + = help: consider using a trait to implement these associated items + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0390`. diff --git a/src/test/ui/modules/issue-56411-aux.rs b/src/test/ui/modules/issue-56411-aux.rs new file mode 100644 index 00000000000..c8e5a059810 --- /dev/null +++ b/src/test/ui/modules/issue-56411-aux.rs @@ -0,0 +1,5 @@ +// check-pass + +struct T {} + +fn main() {} diff --git a/src/test/ui/modules/issue-56411.rs b/src/test/ui/modules/issue-56411.rs new file mode 100644 index 00000000000..163651a7ef6 --- /dev/null +++ b/src/test/ui/modules/issue-56411.rs @@ -0,0 +1,18 @@ +macro_rules! import { + ( $(($path:expr, $name:ident)),* ) => { + $( + #[path = $path] + mod $name; + pub use self::$name; + //~^ ERROR the name `issue_56411_aux` is defined multiple times + //~| ERROR `issue_56411_aux` is private, and cannot be re-exported + + )* + } +} + +import!(("issue-56411-aux.rs", issue_56411_aux)); + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/modules/issue-56411.stderr b/src/test/ui/modules/issue-56411.stderr new file mode 100644 index 00000000000..3ac8dc548ae --- /dev/null +++ b/src/test/ui/modules/issue-56411.stderr @@ -0,0 +1,33 @@ +error[E0255]: the name `issue_56411_aux` is defined multiple times + --> $DIR/issue-56411.rs:6:21 + | +LL | mod $name; + | ---------- previous definition of the module `issue_56411_aux` here +LL | pub use self::$name; + | ^^^^^^^^^^^ + | | + | `issue_56411_aux` reimported here + | you can use `as` to change the binding name of the import +... +LL | import!(("issue-56411-aux.rs", issue_56411_aux)); + | ------------------------------------------------- in this macro invocation + | + = note: `issue_56411_aux` must be defined only once in the type namespace of this module + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0365]: `issue_56411_aux` is private, and cannot be re-exported + --> $DIR/issue-56411.rs:6:21 + | +LL | pub use self::$name; + | ^^^^^^^^^^^ re-export of private `issue_56411_aux` +... +LL | import!(("issue-56411-aux.rs", issue_56411_aux)); + | ------------------------------------------------- in this macro invocation + | + = note: consider declaring type or module `issue_56411_aux` with `pub` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0255, E0365. +For more information about an error, try `rustc --explain E0255`. diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs index f9a9d071a3d..a8dee5bbda4 100644 --- a/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs +++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.rs @@ -1,2 +1,2 @@ type mut_box = Box; -//~^ ERROR expected one of `>`, const, lifetime, or type, found keyword `mut` +//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut` diff --git a/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr index 0703caf5bed..39db0be9fbb 100644 --- a/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr +++ b/src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr @@ -1,8 +1,8 @@ -error: expected one of `>`, const, lifetime, or type, found keyword `mut` +error: expected one of `>`, a const expression, lifetime, or type, found keyword `mut` --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20 | LL | type mut_box = Box; - | ^^^ expected one of `>`, const, lifetime, or type + | ^^^ expected one of `>`, a const expression, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/resolve-pseudo-shadowing.rs b/src/test/ui/resolve-pseudo-shadowing.rs deleted file mode 100644 index 85c684ca032..00000000000 --- a/src/test/ui/resolve-pseudo-shadowing.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass -// check that type parameters can't "shadow" qualified paths. - -fn check(_c: Clone) { - fn check2() { - let _ = <() as std::clone::Clone>::clone(&()); - } - check2(); -} - -fn main() { check(()); } diff --git a/src/test/ui/resolve/auxiliary/extern-prelude-vec.rs b/src/test/ui/resolve/auxiliary/extern-prelude-vec.rs new file mode 100644 index 00000000000..a643c888910 --- /dev/null +++ b/src/test/ui/resolve/auxiliary/extern-prelude-vec.rs @@ -0,0 +1,3 @@ +#![crate_name = "Vec"] + +pub fn new(arg1: f32, arg2: ()) {} diff --git a/src/test/ui/resolve/auxiliary/extern-prelude.rs b/src/test/ui/resolve/auxiliary/extern-prelude.rs new file mode 100644 index 00000000000..2fdfd85a1da --- /dev/null +++ b/src/test/ui/resolve/auxiliary/extern-prelude.rs @@ -0,0 +1,5 @@ +pub struct S; + +impl S { + pub fn external(&self) {} +} diff --git a/src/test/ui/resolve/extern-prelude-fail.rs b/src/test/ui/resolve/extern-prelude-fail.rs new file mode 100644 index 00000000000..7d387025ad4 --- /dev/null +++ b/src/test/ui/resolve/extern-prelude-fail.rs @@ -0,0 +1,9 @@ +// compile-flags:--extern extern_prelude +// aux-build:extern-prelude.rs + +// Extern prelude names are not available by absolute paths + +fn main() { + use extern_prelude::S; //~ ERROR unresolved import `extern_prelude` + let s = ::extern_prelude::S; //~ ERROR failed to resolve +} diff --git a/src/test/ui/resolve/extern-prelude-fail.stderr b/src/test/ui/resolve/extern-prelude-fail.stderr new file mode 100644 index 00000000000..a59f4c952bb --- /dev/null +++ b/src/test/ui/resolve/extern-prelude-fail.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `extern_prelude` + --> $DIR/extern-prelude-fail.rs:7:9 + | +LL | use extern_prelude::S; + | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + +error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`? + --> $DIR/extern-prelude-fail.rs:8:15 + | +LL | let s = ::extern_prelude::S; + | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/resolve/extern-prelude.rs b/src/test/ui/resolve/extern-prelude.rs new file mode 100644 index 00000000000..50fed6034aa --- /dev/null +++ b/src/test/ui/resolve/extern-prelude.rs @@ -0,0 +1,31 @@ +// build-pass (FIXME(62277): could be check-pass?) +// compile-flags:--extern extern_prelude --extern Vec +// aux-build:extern-prelude.rs +// aux-build:extern-prelude-vec.rs + +fn basic() { + // It works + let s = extern_prelude::S; + s.external(); +} + +fn shadow_mod() { + // Local module shadows `extern_prelude` from extern prelude + mod extern_prelude { + pub struct S; + + impl S { + pub fn internal(&self) {} + } + } + + let s = extern_prelude::S; + s.internal(); // OK +} + +fn shadow_prelude() { + // Extern prelude shadows standard library prelude + let x = Vec::new(0f32, ()); // OK +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-49074.rs b/src/test/ui/resolve/issue-49074.rs new file mode 100644 index 00000000000..752bb345b70 --- /dev/null +++ b/src/test/ui/resolve/issue-49074.rs @@ -0,0 +1,13 @@ +// Check that unknown attribute error is shown even if there are unresolved macros. + +#[marco_use] // typo +//~^ ERROR cannot find attribute `marco_use` in this scope +mod foo { + macro_rules! bar { + () => (); + } +} + +fn main() { + bar!(); //~ ERROR cannot find macro `bar` in this scope +} diff --git a/src/test/ui/resolve/issue-49074.stderr b/src/test/ui/resolve/issue-49074.stderr new file mode 100644 index 00000000000..bbfeb4ea948 --- /dev/null +++ b/src/test/ui/resolve/issue-49074.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `bar` in this scope + --> $DIR/issue-49074.rs:12:4 + | +LL | bar!(); + | ^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find attribute `marco_use` in this scope + --> $DIR/issue-49074.rs:3:3 + | +LL | #[marco_use] // typo + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/resolve/resolve-pseudo-shadowing.rs b/src/test/ui/resolve/resolve-pseudo-shadowing.rs new file mode 100644 index 00000000000..85c684ca032 --- /dev/null +++ b/src/test/ui/resolve/resolve-pseudo-shadowing.rs @@ -0,0 +1,11 @@ +// run-pass +// check that type parameters can't "shadow" qualified paths. + +fn check(_c: Clone) { + fn check2() { + let _ = <() as std::clone::Clone>::clone(&()); + } + check2(); +} + +fn main() { check(()); } diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs deleted file mode 100644 index a14ec5b7290..00000000000 --- a/src/test/ui/resolve_self_super_hint.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod a { - extern crate alloc; - use alloc::HashMap; - //~^ ERROR unresolved import `alloc` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION self::alloc - mod b { - use alloc::HashMap; - //~^ ERROR unresolved import `alloc` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION super::alloc - mod c { - use alloc::HashMap; - //~^ ERROR unresolved import `alloc` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION a::alloc - mod d { - use alloc::HashMap; - //~^ ERROR unresolved import `alloc` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION a::alloc - } - } - } -} - -fn main() {} diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr deleted file mode 100644 index bc862553b5b..00000000000 --- a/src/test/ui/resolve_self_super_hint.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:3:9 - | -LL | use alloc::HashMap; - | ^^^^^ help: a similar path exists: `self::alloc` - -error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:8:13 - | -LL | use alloc::HashMap; - | ^^^^^ help: a similar path exists: `super::alloc` - -error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:13:17 - | -LL | use alloc::HashMap; - | ^^^^^ - | | - | unresolved import - | help: a similar path exists: `a::alloc` - -error[E0432]: unresolved import `alloc` - --> $DIR/resolve_self_super_hint.rs:18:21 - | -LL | use alloc::HashMap; - | ^^^^^ - | | - | unresolved import - | help: a similar path exists: `a::alloc` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index c60ff7dc934..70ec0e3033c 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,15 +1,19 @@ -#![feature(naked_functions)] +#![feature(asm, naked_functions)] #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` #[naked] -fn f() {} +extern "C" fn f() { + asm!("", options(noreturn)); +} struct S; impl S { #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` #[naked] - fn g() {} + extern "C" fn g() { + asm!("", options(noreturn)); + } } fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 211cd3f16ba..1b49148d629 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -5,7 +5,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:10:5 + --> $DIR/error-with-naked.rs:12:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/single-primitive-inherent-impl.stderr b/src/test/ui/single-primitive-inherent-impl.stderr index d357afa3b38..50a0d5bef86 100644 --- a/src/test/ui/single-primitive-inherent-impl.stderr +++ b/src/test/ui/single-primitive-inherent-impl.stderr @@ -6,13 +6,7 @@ LL | | LL | | } | |_^ | -help: consider using a trait to implement these methods - --> $DIR/single-primitive-inherent-impl.rs:11:1 - | -LL | / impl str { -LL | | -LL | | } - | |_^ + = help: consider using a trait error: aborting due to previous error diff --git a/src/test/ui/stability-attribute/auxiliary/lint-stability.rs b/src/test/ui/stability-attribute/auxiliary/lint-stability.rs new file mode 100644 index 00000000000..de4058887cf --- /dev/null +++ b/src/test/ui/stability-attribute/auxiliary/lint-stability.rs @@ -0,0 +1,188 @@ +#![crate_name="lint_stability"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(associated_type_defaults)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub fn deprecated() {} +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub fn deprecated_text() {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "99.99.99", reason = "text")] +pub fn deprecated_future() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub fn deprecated_unstable() {} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub fn deprecated_unstable_text() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn unstable() {} +#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] +pub fn unstable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct MethodTester; + +impl MethodTester { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + pub fn method_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + pub fn method_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + pub fn method_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + fn trait_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + fn trait_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + fn trait_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait TraitWithAssociatedTypes { + #[unstable(feature = "unstable_test_feature", issue = "none")] + type TypeUnstable = u8; + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + type TypeDeprecated = u8; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +impl Trait for MethodTester {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub trait UnstableTrait { fn dummy(&self) { } } + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub trait DeprecatedTrait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub enum UnstableEnum {} +#[stable(feature = "rust1", since = "1.0.0")] +pub enum StableEnum {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedUnstableUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableUnitStruct; +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableUnitStruct; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[rustc_deprecated(since = "1.0.0", reason = "text")] + DeprecatedUnstableVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[rustc_deprecated(since = "1.0.0", reason = "text")] +pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test { + () => (deprecated()); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg { + ($func:expr) => ($func); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg_nested { + ($func:ident) => (macro_test_arg!($func())); +} diff --git a/src/test/ui/stability-attribute/issue-28075.rs b/src/test/ui/stability-attribute/issue-28075.rs new file mode 100644 index 00000000000..6b4ea46f361 --- /dev/null +++ b/src/test/ui/stability-attribute/issue-28075.rs @@ -0,0 +1,13 @@ +// Unstable entities should be caught in import lists + +// aux-build:lint-stability.rs + +#![allow(warnings)] + +extern crate lint_stability; + +use lint_stability::{unstable, deprecated}; +//~^ ERROR use of unstable library feature 'unstable_test_feature' + +fn main() { +} diff --git a/src/test/ui/stability-attribute/issue-28075.stderr b/src/test/ui/stability-attribute/issue-28075.stderr new file mode 100644 index 00000000000..7e53bb54457 --- /dev/null +++ b/src/test/ui/stability-attribute/issue-28075.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/issue-28075.rs:9:22 + | +LL | use lint_stability::{unstable, deprecated}; + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/stability-attribute/issue-28388-3.rs b/src/test/ui/stability-attribute/issue-28388-3.rs new file mode 100644 index 00000000000..7ba99350121 --- /dev/null +++ b/src/test/ui/stability-attribute/issue-28388-3.rs @@ -0,0 +1,11 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +// aux-build:lint-stability.rs + +extern crate lint_stability; + +use lint_stability::UnstableEnum::{}; +//~^ ERROR use of unstable library feature 'unstable_test_feature' +use lint_stability::StableEnum::{}; // OK + +fn main() {} diff --git a/src/test/ui/stability-attribute/issue-28388-3.stderr b/src/test/ui/stability-attribute/issue-28388-3.stderr new file mode 100644 index 00000000000..d2e46683b90 --- /dev/null +++ b/src/test/ui/stability-attribute/issue-28388-3.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/issue-28388-3.rs:7:5 + | +LL | use lint_stability::UnstableEnum::{}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/unused/issue-30730.rs b/src/test/ui/unused/issue-30730.rs new file mode 100644 index 00000000000..d6be90c8148 --- /dev/null +++ b/src/test/ui/unused/issue-30730.rs @@ -0,0 +1,5 @@ +#![warn(unused)] +#![deny(warnings)] +use std::thread; +//~^ ERROR: unused import +fn main() {} diff --git a/src/test/ui/unused/issue-30730.stderr b/src/test/ui/unused/issue-30730.stderr new file mode 100644 index 00000000000..b299e99a3a9 --- /dev/null +++ b/src/test/ui/unused/issue-30730.stderr @@ -0,0 +1,15 @@ +error: unused import: `std::thread` + --> $DIR/issue-30730.rs:3:5 + | +LL | use std::thread; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-30730.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/src/test/ui/unused/issue-46576.rs b/src/test/ui/unused/issue-46576.rs new file mode 100644 index 00000000000..15f458f3844 --- /dev/null +++ b/src/test/ui/unused/issue-46576.rs @@ -0,0 +1,21 @@ +#![allow(dead_code)] +#![deny(unused_imports)] + +use std::fs::File; +use std::io::{BufRead, BufReader, Read}; +//~^ ERROR unused import: `BufRead` + +pub fn read_from_file(path: &str) { + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + let mut s = String::new(); + reader.read_to_string(&mut s).unwrap(); +} + +pub fn read_lines(s: &str) { + for _line in s.lines() { + + } +} + +fn main() {} diff --git a/src/test/ui/unused/issue-46576.stderr b/src/test/ui/unused/issue-46576.stderr new file mode 100644 index 00000000000..6f4d97068b3 --- /dev/null +++ b/src/test/ui/unused/issue-46576.stderr @@ -0,0 +1,14 @@ +error: unused import: `BufRead` + --> $DIR/issue-46576.rs:5:15 + | +LL | use std::io::{BufRead, BufReader, Read}; + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-46576.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/unused/issue-59896.rs b/src/test/ui/unused/issue-59896.rs new file mode 100644 index 00000000000..ff9f19acf84 --- /dev/null +++ b/src/test/ui/unused/issue-59896.rs @@ -0,0 +1,9 @@ +#![deny(unused_imports)] + +struct S; + +fn main() { + use S; //~ ERROR the item `S` is imported redundantly + + let _s = S; +} diff --git a/src/test/ui/unused/issue-59896.stderr b/src/test/ui/unused/issue-59896.stderr new file mode 100644 index 00000000000..95b7938ae03 --- /dev/null +++ b/src/test/ui/unused/issue-59896.stderr @@ -0,0 +1,17 @@ +error: the item `S` is imported redundantly + --> $DIR/issue-59896.rs:6:9 + | +LL | struct S; + | --------- the item `S` is already defined here +... +LL | use S; + | ^ + | +note: the lint level is defined here + --> $DIR/issue-59896.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/unused/issue-70041.rs b/src/test/ui/unused/issue-70041.rs new file mode 100644 index 00000000000..22e42295eed --- /dev/null +++ b/src/test/ui/unused/issue-70041.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2018 +// run-pass + +macro_rules! regex { + //~^ WARN unused macro definition + () => {}; +} + +#[allow(dead_code)] +use regex; +//~^ WARN unused import + +fn main() {} diff --git a/src/test/ui/unused/issue-70041.stderr b/src/test/ui/unused/issue-70041.stderr new file mode 100644 index 00000000000..ecd618eae8b --- /dev/null +++ b/src/test/ui/unused/issue-70041.stderr @@ -0,0 +1,21 @@ +warning: unused macro definition + --> $DIR/issue-70041.rs:4:1 + | +LL | / macro_rules! regex { +LL | | +LL | | () => {}; +LL | | } + | |_^ + | + = note: `#[warn(unused_macros)]` on by default + +warning: unused import: `regex` + --> $DIR/issue-70041.rs:10:5 + | +LL | use regex; + | ^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +warning: 2 warnings emitted + diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index 7509d90c6c2..784463fe0df 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -128,14 +128,14 @@ jobs: SYSROOT=$(rustc --print sysroot) echo "$SYSROOT/bin" >> $GITHUB_PATH - - name: Build - run: cargo build --features deny-warnings + - name: Build with internal lints + run: cargo build --features deny-warnings,internal-lints - - name: Test - run: cargo test --features deny-warnings + - name: Test with internal lints + run: cargo test --features deny-warnings,internal-lints - - name: Test clippy_lints - run: cargo test --features deny-warnings + - name: Test clippy_lints with internal lints + run: cargo test --features deny-warnings,internal-lints working-directory: clippy_lints - name: Test rustc_tools_util diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index b9e4b0e6704..c7e02aaf4e1 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -1770,6 +1770,7 @@ Released 2018-09-13 [`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned [`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity [`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if +[`collapsible_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator @@ -2056,6 +2057,7 @@ Released 2018-09-13 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive @@ -2073,6 +2075,7 @@ Released 2018-09-13 [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl +[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index a8e2123656e..f8c26e2d456 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -14,11 +14,16 @@ All contributors are expected to follow the [Rust Code of Conduct]. - [Contributing to Clippy](#contributing-to-clippy) - [Getting started](#getting-started) + - [High level approach](#high-level-approach) - [Finding something to fix/improve](#finding-something-to-fiximprove) - [Writing code](#writing-code) - [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work) - [How Clippy works](#how-clippy-works) - [Fixing build failures caused by Rust](#fixing-build-failures-caused-by-rust) + - [Patching git-subtree to work with big repos](#patching-git-subtree-to-work-with-big-repos) + - [Performing the sync](#performing-the-sync) + - [Syncing back changes in Clippy to [`rust-lang/rust`]](#syncing-back-changes-in-clippy-to-rust-langrust) + - [Defining remotes](#defining-remotes) - [Issue and PR triage](#issue-and-pr-triage) - [Bors and Homu](#bors-and-homu) - [Contributions](#contributions) @@ -320,8 +325,8 @@ commands [here][homu_instructions]. [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug [homu]: https://github.com/rust-lang/homu -[homu_instructions]: https://buildbot2.rust-lang.org/homu/ -[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy +[homu_instructions]: https://bors.rust-lang.org/ +[homu_queue]: https://bors.rust-lang.org/queue/clippy ## Contributions diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 1ddcd18598d..a765390c603 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -32,7 +32,7 @@ path = "src/driver.rs" clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update semver = "0.11" -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } tempfile = { version = "3.1.0", optional = true } [dev-dependencies] @@ -49,8 +49,9 @@ derive-new = "0.5" rustc-workspace-hack = "1.0.0" [build-dependencies] -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } [features] deny-warnings = [] integration = ["tempfile"] +internal-lints = ["clippy_lints/internal-lints"] diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index 1da626b505d..fddf0614a0b 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -182,7 +182,7 @@ cargo clippy -- -W clippy::lint_name ``` This also works with lint groups. For example you -can run Clippy with warnings for all lints enabled: +can run Clippy with warnings for all lints enabled: ```terminal cargo clippy -- -W clippy::pedantic ``` @@ -194,6 +194,33 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::... ``` Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`. +### Specifying the minimum supported Rust version + +Projects that intend to support old versions of Rust can disable lints pertaining to newer features by +specifying the minimum supported Rust version (MSRV) in the clippy configuration file. + +```toml +msrv = "1.30.0" +``` + +The MSRV can also be specified as an inner attribute, like below. + +```rust +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.30.0"] + +fn main() { + ... +} +``` + +You can also omit the patch version when specifying the MSRV, so `msrv = 1.30` +is equivalent to `msrv = 1.30.0`. + +Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly. + +Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv) + ## Contributing If you want to contribute to Clippy, you can find more information in [CONTRIBUTING.md](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md). diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 43cb2954b74..f51c45e9eb5 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -146,16 +146,30 @@ pub fn gen_deprecated<'a>(lints: impl Iterator) -> Vec } #[must_use] -pub fn gen_register_lint_list<'a>(lints: impl Iterator) -> Vec { - let pre = " store.register_lints(&[".to_string(); - let post = " ]);".to_string(); - let mut inner = lints +pub fn gen_register_lint_list<'a>( + internal_lints: impl Iterator, + usable_lints: impl Iterator, +) -> Vec { + let header = " store.register_lints(&[".to_string(); + let footer = " ]);".to_string(); + let internal_lints = internal_lints + .sorted_by_key(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) + .map(|l| { + format!( + " #[cfg(feature = \"internal-lints\")]\n &{}::{},", + l.module, + l.name.to_uppercase() + ) + }); + let other_lints = usable_lints + .sorted_by_key(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) .map(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) - .sorted() - .collect::>(); - inner.insert(0, pre); - inner.push(post); - inner + .sorted(); + let mut lint_list = vec![header]; + lint_list.extend(internal_lints); + lint_list.extend(other_lints); + lint_list.push(footer); + lint_list } /// Gathers all files in `src/clippy_lints` and gathers all lints inside diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index fcf093f8835..edf6c5f57a4 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -68,7 +68,7 @@ pub fn run(update_mode: UpdateMode) { "end register lints", false, update_mode == UpdateMode::Change, - || gen_register_lint_list(usable_lints.iter().chain(internal_lints.iter())), + || gen_register_lint_list(internal_lints.iter(), usable_lints.iter()), ) .changed; diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index d9471d25197..7697eba650a 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -28,6 +28,7 @@ smallvec = { version = "1", features = ["union"] } toml = "0.5.3" unicode-normalization = "0.1" semver = "0.11" +rustc-semver="1.1.0" # NOTE: cargo requires serde feat in its url dep # see url = { version = "2.1.0", features = ["serde"] } @@ -36,3 +37,5 @@ syn = { version = "1", features = ["full"] } [features] deny-warnings = [] +# build clippy with internal lints enabled, off by default +internal-lints = [] diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 15505fd79f4..3edbe723922 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -5,7 +5,6 @@ span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; -use rustc_span::lev_distance::find_best_match_for_name; use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_errors::Applicability; use rustc_hir::{ @@ -15,6 +14,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::Span; use rustc_span::sym; use rustc_span::symbol::{Symbol, SymbolStr}; diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs new file mode 100644 index 00000000000..a34ba2d00a8 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs @@ -0,0 +1,172 @@ +use crate::utils::visitors::LocalUsedVisitor; +use crate::utils::{span_lint_and_then, SpanlessEq}; +use if_chain::if_chain; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{DefIdTree, TyCtxt}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{MultiSpan, Span}; + +declare_clippy_lint! { + /// **What it does:** Finds nested `match` or `if let` expressions where the patterns may be "collapsed" together + /// without adding any branches. + /// + /// Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only + /// cases where merging would most likely make the code more readable. + /// + /// **Why is this bad?** It is unnecessarily verbose and complex. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// fn func(opt: Option>) { + /// let n = match opt { + /// Some(n) => match n { + /// Ok(n) => n, + /// _ => return, + /// } + /// None => return, + /// }; + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn func(opt: Option>) { + /// let n = match opt { + /// Some(Ok(n)) => n, + /// _ => return, + /// }; + /// } + /// ``` + pub COLLAPSIBLE_MATCH, + style, + "Nested `match` or `if let` expressions where the patterns may be \"collapsed\" together." +} + +declare_lint_pass!(CollapsibleMatch => [COLLAPSIBLE_MATCH]); + +impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let ExprKind::Match(_expr, arms, _source) = expr.kind { + if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(arm, cx.tcx)) { + for arm in arms { + check_arm(arm, wild_arm, cx); + } + } + } + } +} + +fn check_arm(arm: &Arm<'_>, wild_outer_arm: &Arm<'_>, cx: &LateContext<'_>) { + if_chain! { + let expr = strip_singleton_blocks(arm.body); + if let ExprKind::Match(expr_in, arms_inner, _) = expr.kind; + // the outer arm pattern and the inner match + if expr_in.span.ctxt() == arm.pat.span.ctxt(); + // there must be no more than two arms in the inner match for this lint + if arms_inner.len() == 2; + // no if guards on the inner match + if arms_inner.iter().all(|arm| arm.guard.is_none()); + // match expression must be a local binding + // match { .. } + if let ExprKind::Path(QPath::Resolved(None, path)) = expr_in.kind; + if let Res::Local(binding_id) = path.res; + // one of the branches must be "wild-like" + if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(arm_inner, cx.tcx)); + let (wild_inner_arm, non_wild_inner_arm) = + (&arms_inner[wild_inner_arm_idx], &arms_inner[1 - wild_inner_arm_idx]); + if !pat_contains_or(non_wild_inner_arm.pat); + // the binding must come from the pattern of the containing match arm + // .... => match { .. } + if let Some(binding_span) = find_pat_binding(arm.pat, binding_id); + // the "wild-like" branches must be equal + if SpanlessEq::new(cx).eq_expr(wild_inner_arm.body, wild_outer_arm.body); + // the binding must not be used in the if guard + if !matches!(arm.guard, Some(Guard::If(guard)) if LocalUsedVisitor::new(binding_id).check_expr(guard)); + // ...or anywhere in the inner match + if !arms_inner.iter().any(|arm| LocalUsedVisitor::new(binding_id).check_arm(arm)); + then { + span_lint_and_then( + cx, + COLLAPSIBLE_MATCH, + expr.span, + "Unnecessary nested match", + |diag| { + let mut help_span = MultiSpan::from_spans(vec![binding_span, non_wild_inner_arm.pat.span]); + help_span.push_span_label(binding_span, "Replace this binding".into()); + help_span.push_span_label(non_wild_inner_arm.pat.span, "with this pattern".into()); + diag.span_help(help_span, "The outer pattern can be modified to include the inner pattern."); + }, + ); + } + } +} + +fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> { + while let ExprKind::Block(block, _) = expr.kind { + match (block.stmts, block.expr) { + ([stmt], None) => match stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => expr = e, + _ => break, + }, + ([], Some(e)) => expr = e, + _ => break, + } + } + expr +} + +/// A "wild-like" pattern is wild ("_") or `None`. +/// For this lint to apply, both the outer and inner match expressions +/// must have "wild-like" branches that can be combined. +fn arm_is_wild_like(arm: &Arm<'_>, tcx: TyCtxt<'_>) -> bool { + if arm.guard.is_some() { + return false; + } + match arm.pat.kind { + PatKind::Binding(..) | PatKind::Wild => true, + PatKind::Path(QPath::Resolved(None, path)) if is_none_ctor(path.res, tcx) => true, + _ => false, + } +} + +fn find_pat_binding(pat: &Pat<'_>, hir_id: HirId) -> Option { + let mut span = None; + pat.walk_short(|p| match &p.kind { + // ignore OR patterns + PatKind::Or(_) => false, + PatKind::Binding(_bm, _, _ident, _) => { + let found = p.hir_id == hir_id; + if found { + span = Some(p.span); + } + !found + }, + _ => true, + }); + span +} + +fn pat_contains_or(pat: &Pat<'_>) -> bool { + let mut result = false; + pat.walk(|p| { + let is_or = matches!(p.kind, PatKind::Or(_)); + result |= is_or; + !is_or + }); + result +} + +fn is_none_ctor(res: Res, tcx: TyCtxt<'_>) -> bool { + if let Some(none_id) = tcx.lang_items().option_none_variant() { + if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = res { + if let Some(variant_id) = tcx.parent(id) { + return variant_id == none_id; + } + } + } + false +} diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index 99f161a0510..ae1143b2c50 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -12,7 +12,8 @@ /// **Why is this bad?** `if` is not guaranteed to be exhaustive and conditionals can get /// repetitive /// - /// **Known problems:** None. + /// **Known problems:** The match statement may be slower due to the compiler + /// not inlining the call to cmp. See issue #5354 /// /// **Example:** /// ```rust,ignore diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 612c5355338..f69f6f1412a 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -280,8 +280,7 @@ fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Op // only take assignments to fields where the left-hand side field is a field of // the same binding as the previous statement if let ExprKind::Field(ref binding, field_ident) = assign_lhs.kind; - if let ExprKind::Path(ref qpath) = binding.kind; - if let QPath::Resolved(_, path) = qpath; + if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind; if let Some(second_binding_name) = path.segments.last(); if second_binding_name.ident.name == binding_name; then { diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 1c3285ed701..bec0c9f93a0 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -51,26 +51,6 @@ macro_rules! declare_deprecated_lint { "`Vec::as_mut_slice` has been stabilized in 1.7" } -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This used to check for `.to_string()` method calls on values - /// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be - /// specialized to be as efficient as `to_owned`. - pub STR_TO_STRING, - "using `str::to_string` is common even today and specialization will likely happen soon" -} - -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This used to check for `.to_string()` method calls on values - /// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be - /// specialized to be as efficient as `clone`. - pub STRING_TO_STRING, - "using `string::to_string` is common even today and specialization will likely happen soon" -} - declare_deprecated_lint! { /// **What it does:** Nothing. This lint has been deprecated. /// diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs index 3201adbf9a0..6308f6e2e7e 100644 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/eq_op.rs @@ -1,10 +1,10 @@ use crate::utils::{ - eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of, multispan_sugg, snippet, span_lint, - span_lint_and_then, + ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of, + multispan_sugg, snippet, span_lint, span_lint_and_then, }; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, BorrowKind, Expr, ExprKind, StmtKind}; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -102,7 +102,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) { return; } - if is_valid_operator(op) && eq_expr_value(cx, left, right) { + if is_useless_with_eq_exprs(higher::binop(op.node)) && eq_expr_value(cx, left, right) { span_lint( cx, EQ_OP, @@ -245,22 +245,3 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { } } } - -fn is_valid_operator(op: BinOp) -> bool { - matches!( - op.node, - BinOpKind::Sub - | BinOpKind::Div - | BinOpKind::Eq - | BinOpKind::Lt - | BinOpKind::Le - | BinOpKind::Gt - | BinOpKind::Ge - | BinOpKind::Ne - | BinOpKind::And - | BinOpKind::Or - | BinOpKind::BitXor - | BinOpKind::BitAnd - | BinOpKind::BitOr - ) -} diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs index e0a1f4c5ca4..1194bd7e55e 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs @@ -41,8 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for OkIfLet { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { //begin checking variables - if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match - if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let + if let ExprKind::Match(ref op, ref body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result.ok(, _) if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index ed7f3b9293d..03e95c9e27f 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -68,8 +68,7 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let StmtKind::Semi(expr, ..) = &stmt.kind; // make sure it's a break, otherwise we want to skip - if let ExprKind::Break(.., break_expr) = &expr.kind; - if let Some(break_expr) = break_expr; + if let ExprKind::Break(.., Some(break_expr)) = &expr.kind; then { lint(cx, expr.span, break_expr.span, LINT_BREAK); } diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index b57fe8dc426..3a01acd8fdc 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -59,8 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(target) = subtracts_one(cx, e); // Extracting out the variable name - if let ExprKind::Path(ref assign_path) = target.kind; - if let QPath::Resolved(_, ref ares_path) = assign_path; + if let ExprKind::Path(QPath::Resolved(_, ref ares_path)) = target.kind; then { // Handle symmetric conditions in the if statement diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index 8998fae09de..0927d218446 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -58,12 +58,12 @@ fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) { return; } - // skip initial items + // skip initial items and trailing semicolons let stmts = item .stmts .iter() .map(|stmt| &stmt.kind) - .skip_while(|s| matches!(**s, StmtKind::Item(..))); + .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty)); // lint on all further items for stmt in stmts { diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 025ff86da39..a76595ed089 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -52,8 +52,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Const(hir_ty, _) = &item.kind; let ty = hir_ty_to_ty(cx.tcx, hir_ty); if let ty::Array(element_type, cst) = ty.kind(); - if let ConstKind::Value(val) = cst.val; - if let ConstValue::Scalar(element_count) = val; + if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val; if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx); if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes()); if self.maximum_allowed_size < element_count * element_size; diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 9fd3780e14e..9a448ab1256 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -43,8 +43,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Repeat(_, _) = expr.kind; if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind(); - if let ConstKind::Value(val) = cst.val; - if let ConstValue::Scalar(element_count) = val; + if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val; if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx); if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes()); if self.maximum_allowed_size < element_count * element_size; diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 8243b0a29bc..0d2d95324c4 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -1,12 +1,11 @@ +use crate::utils::visitors::LocalUsedVisitor; use crate::utils::{higher, qpath_res, snippet, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_hir::intravisit; use rustc_hir::BindingAnnotation; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -66,10 +65,10 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; if let hir::StmtKind::Expr(ref if_) = expr.kind; if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_); - if !used_in_expr(cx, canonical_id, cond); + if !LocalUsedVisitor::new(canonical_id).check_expr(cond); if let hir::ExprKind::Block(ref then, _) = then.kind; if let Some(value) = check_assign(cx, canonical_id, &*then); - if !used_in_expr(cx, canonical_id, value); + if !LocalUsedVisitor::new(canonical_id).check_expr(value); then { let span = stmt.span.to(if_.span); @@ -136,32 +135,6 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { } } -struct UsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - id: hir::HirId, - used: bool, -} - -impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if let hir::ExprKind::Path(ref qpath) = expr.kind; - if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id); - if self.id == local_id; - then { - self.used = true; - return; - } - } - intravisit::walk_expr(self, expr); - } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } -} - fn check_assign<'tcx>( cx: &LateContext<'tcx>, decl: hir::HirId, @@ -176,18 +149,10 @@ fn check_assign<'tcx>( if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id); if decl == local_id; then { - let mut v = UsedVisitor { - cx, - id: decl, - used: false, - }; - - for s in block.stmts.iter().take(block.stmts.len()-1) { - intravisit::walk_stmt(&mut v, s); + let mut v = LocalUsedVisitor::new(decl); - if v.used { - return None; - } + if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| v.check_stmt(stmt)) { + return None; } return Some(value); @@ -196,9 +161,3 @@ fn check_assign<'tcx>( None } - -fn used_in_expr<'tcx>(cx: &LateContext<'tcx>, id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> bool { - let mut v = UsedVisitor { cx, id, used: false }; - intravisit::walk_expr(&mut v, expr); - v.used -} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 7e8cbd00c22..2b99ed570b1 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -44,6 +44,7 @@ extern crate rustc_trait_selection; extern crate rustc_typeck; +use crate::utils::parse_msrv; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; use rustc_session::Session; @@ -171,6 +172,7 @@ macro_rules! declare_clippy_lint { mod checked_conversions; mod cognitive_complexity; mod collapsible_if; +mod collapsible_match; mod comparison_chain; mod copies; mod copy_iterator; @@ -304,9 +306,11 @@ macro_rules! declare_clippy_lint { mod serde_api; mod shadow; mod single_component_path_imports; +mod size_of_in_element_count; mod slow_vector_initialization; mod stable_sort_primitive; mod strings; +mod suspicious_operation_groupings; mod suspicious_trait_impl; mod swap; mod tabs_in_doc_comments; @@ -440,14 +444,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::unstable_as_mut_slice", "`Vec::as_mut_slice` has been stabilized in 1.7", ); - store.register_removed( - "clippy::str_to_string", - "using `str::to_string` is common even today and specialization will likely happen soon", - ); - store.register_removed( - "clippy::string_to_string", - "using `string::to_string` is common even today and specialization will likely happen soon", - ); store.register_removed( "clippy::misaligned_transmute", "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", @@ -504,6 +500,24 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: // begin register lints, do not remove this comment, it’s used in `update_lints` store.register_lints(&[ + #[cfg(feature = "internal-lints")] + &utils::internal_lints::CLIPPY_LINTS_INTERNAL, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::COMPILER_LINT_FUNCTIONS, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::DEFAULT_LINT, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::INVALID_PATHS, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::LINT_WITHOUT_LINT_PASS, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::OUTER_EXPN_EXPN_DATA, + #[cfg(feature = "internal-lints")] + &utils::internal_lints::PRODUCE_ICE, &approx_const::APPROX_CONSTANT, &arithmetic::FLOAT_ARITHMETIC, &arithmetic::INTEGER_ARITHMETIC, @@ -537,6 +551,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &checked_conversions::CHECKED_CONVERSIONS, &cognitive_complexity::COGNITIVE_COMPLEXITY, &collapsible_if::COLLAPSIBLE_IF, + &collapsible_match::COLLAPSIBLE_MATCH, &comparison_chain::COMPARISON_CHAIN, &copies::IFS_SAME_COND, &copies::IF_SAME_THEN_ELSE, @@ -833,12 +848,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &shadow::SHADOW_SAME, &shadow::SHADOW_UNRELATED, &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, + &size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, &stable_sort_primitive::STABLE_SORT_PRIMITIVE, &strings::STRING_ADD, &strings::STRING_ADD_ASSIGN, &strings::STRING_FROM_UTF8_AS_BYTES, &strings::STRING_LIT_AS_BYTES, + &strings::STRING_TO_STRING, + &strings::STR_TO_STRING, + &suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS, &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, &swap::ALMOST_SWAPPED, @@ -907,15 +926,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unwrap_in_result::UNWRAP_IN_RESULT, &use_self::USE_SELF, &useless_conversion::USELESS_CONVERSION, - &utils::internal_lints::CLIPPY_LINTS_INTERNAL, - &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, - &utils::internal_lints::COMPILER_LINT_FUNCTIONS, - &utils::internal_lints::DEFAULT_LINT, - &utils::internal_lints::INVALID_PATHS, - &utils::internal_lints::LINT_WITHOUT_LINT_PASS, - &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, - &utils::internal_lints::OUTER_EXPN_EXPN_DATA, - &utils::internal_lints::PRODUCE_ICE, &vec::USELESS_VEC, &vec_resize_to_zero::VEC_RESIZE_TO_ZERO, &verbose_file_reads::VERBOSE_FILE_READS, @@ -934,14 +944,22 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ]); // end register lints, do not remove this comment, it’s used in `update_lints` + // all the internal lints + #[cfg(feature = "internal-lints")] + { + store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal); + store.register_early_pass(|| box utils::internal_lints::ProduceIce); + store.register_late_pass(|| box utils::inspector::DeepCodeInspector); + store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); + store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new()); + store.register_late_pass(|| box utils::internal_lints::InvalidPaths); + store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default()); + store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem); + store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass); + } + store.register_late_pass(|| box utils::author::Author); store.register_late_pass(|| box await_holding_invalid::AwaitHolding); store.register_late_pass(|| box serde_api::SerdeAPI); - store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new()); - store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default()); - store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass); - store.register_late_pass(|| box utils::internal_lints::InvalidPaths); - store.register_late_pass(|| box utils::inspector::DeepCodeInspector); - store.register_late_pass(|| box utils::author::Author); let vec_box_size_threshold = conf.vec_box_size_threshold; store.register_late_pass(move || box types::Types::new(vec_box_size_threshold)); store.register_late_pass(|| box booleans::NonminimalBool); @@ -964,12 +982,25 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box len_zero::LenZero); store.register_late_pass(|| box attrs::Attributes); store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions); + store.register_late_pass(|| box collapsible_match::CollapsibleMatch); store.register_late_pass(|| box unicode::Unicode); store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd); store.register_late_pass(|| box strings::StringAdd); store.register_late_pass(|| box implicit_return::ImplicitReturn); store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub); - store.register_late_pass(|| box methods::Methods); + + let msrv = conf.msrv.as_ref().and_then(|s| { + parse_msrv(s, None, None).or_else(|| { + sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s)); + None + }) + }); + + store.register_late_pass(move || box methods::Methods::new(msrv)); + store.register_late_pass(move || box matches::Matches::new(msrv)); + store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv)); + store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv)); + store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount); store.register_late_pass(|| box map_clone::MapClone); store.register_late_pass(|| box map_err_ignore::MapErrIgnore); store.register_late_pass(|| box shadow::Shadow); @@ -983,7 +1014,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box types::Casts); let type_complexity_threshold = conf.type_complexity_threshold; store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold)); - store.register_late_pass(|| box matches::Matches::default()); store.register_late_pass(|| box minmax::MinMaxPass); store.register_late_pass(|| box open_options::OpenOptions); store.register_late_pass(|| box zero_div_zero::ZeroDiv); @@ -1057,6 +1087,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box types::UnitArg); store.register_late_pass(|| box double_comparison::DoubleComparisons); store.register_late_pass(|| box question_mark::QuestionMark); + store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings); store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl); store.register_late_pass(|| box map_unit_fn::MapUnit); store.register_late_pass(|| box inherent_impl::MultipleInherentImpl::default()); @@ -1107,10 +1138,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata); store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies); - store.register_early_pass(|| box literal_representation::LiteralDigitGrouping); + let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; + store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability)); let literal_representation_threshold = conf.literal_representation_threshold; store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold)); - store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal); let enum_variant_name_threshold = conf.enum_variant_name_threshold; store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold)); store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments); @@ -1124,7 +1155,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold)); store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic); store.register_early_pass(|| box as_conversions::AsConversions); - store.register_early_pass(|| box utils::internal_lints::ProduceIce); store.register_late_pass(|| box let_underscore::LetUnderscore); store.register_late_pass(|| box atomic_ordering::AtomicOrdering); store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports); @@ -1140,16 +1170,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box dereference::Dereferencing); store.register_late_pass(|| box option_if_let_else::OptionIfLetElse); store.register_late_pass(|| box future_not_send::FutureNotSend); - store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_late_pass(|| box if_let_mutex::IfLetMutex); store.register_late_pass(|| box mut_mutex_lock::MutMutexLock); store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); - store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); store.register_early_pass(|| box redundant_field_names::RedundantFieldNames); store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero); store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn); - let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold, @@ -1166,14 +1193,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box manual_ok_or::ManualOkOr); store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync); - store.register_late_pass(|| box manual_strip::ManualStrip); - store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem); let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::>(); store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods)); store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax); store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax); store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops); - + store.register_late_pass(|| box strings::StrToString); + store.register_late_pass(|| box strings::StringToString); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1192,6 +1218,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&integer_division::INTEGER_DIVISION), LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE), LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION), + LintId::of(&map_err_ignore::MAP_ERR_IGNORE), LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM), LintId::of(&mem_forget::MEM_FORGET), @@ -1215,6 +1242,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&shadow::SHADOW_REUSE), LintId::of(&shadow::SHADOW_SAME), LintId::of(&strings::STRING_ADD), + LintId::of(&strings::STRING_TO_STRING), + LintId::of(&strings::STR_TO_STRING), LintId::of(&types::RC_BUFFER), LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT), LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), @@ -1256,7 +1285,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EXPLICIT_ITER_LOOP), LintId::of(¯o_use::MACRO_USE_IMPORTS), LintId::of(&manual_ok_or::MANUAL_OK_OR), - LintId::of(&map_err_ignore::MAP_ERR_IGNORE), LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::MATCH_BOOL), LintId::of(&matches::MATCH_SAME_ARMS), @@ -1304,6 +1332,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&wildcard_imports::WILDCARD_IMPORTS), ]); + #[cfg(feature = "internal-lints")] store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL), LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), @@ -1337,6 +1366,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&bytecount::NAIVE_BYTECOUNT), LintId::of(&collapsible_if::COLLAPSIBLE_IF), + LintId::of(&collapsible_match::COLLAPSIBLE_MATCH), LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), @@ -1533,9 +1563,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&self_assignment::SELF_ASSIGNMENT), LintId::of(&serde_api::SERDE_API_MISUSE), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES), + LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), LintId::of(&swap::ALMOST_SWAPPED), @@ -1602,6 +1634,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&blacklisted_name::BLACKLISTED_NAME), LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(&collapsible_if::COLLAPSIBLE_IF), + LintId::of(&collapsible_match::COLLAPSIBLE_MATCH), LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT), LintId::of(&doc::MISSING_SAFETY_DOC), @@ -1687,6 +1720,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&returns::LET_AND_RETURN), LintId::of(&returns::NEEDLESS_RETURN), LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), LintId::of(&try_err::TRY_ERR), @@ -1839,6 +1873,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(®ex::INVALID_REGEX), LintId::of(&self_assignment::SELF_ASSIGNMENT), LintId::of(&serde_api::SERDE_API_MISUSE), + LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), LintId::of(&swap::ALMOST_SWAPPED), @@ -1930,14 +1965,6 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) { "unstable_as_mut_slice", "`Vec::as_mut_slice` has been stabilized in 1.7", ); - store.register_removed( - "str_to_string", - "using `str::to_string` is common even today and specialization will likely happen soon", - ); - store.register_removed( - "string_to_string", - "using `string::to_string` is common even today and specialization will likely happen soon", - ); store.register_removed( "misaligned_transmute", "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index e8a741683da..87a957a9bd2 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -11,7 +11,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { /// **What it does:** Warns if a long integral or floating-point constant does @@ -32,7 +32,7 @@ /// ``` pub UNREADABLE_LITERAL, pedantic, - "long integer literal without underscores" + "long literal without underscores" } declare_clippy_lint! { @@ -208,7 +208,13 @@ fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: rustc_s } } -declare_lint_pass!(LiteralDigitGrouping => [ +#[allow(clippy::module_name_repetitions)] +#[derive(Copy, Clone)] +pub struct LiteralDigitGrouping { + lint_fraction_readability: bool, +} + +impl_lint_pass!(LiteralDigitGrouping => [ UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, LARGE_DIGIT_GROUPS, @@ -223,7 +229,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { } if let ExprKind::Lit(ref lit) = expr.kind { - Self::check_lit(cx, lit) + self.check_lit(cx, lit) } } } @@ -232,7 +238,13 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12]; impl LiteralDigitGrouping { - fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { + pub fn new(lint_fraction_readability: bool) -> Self { + Self { + lint_fraction_readability, + } + } + + fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { if_chain! { if let Some(src) = snippet_opt(cx, lit.span); if let Some(mut num_lit) = NumericLiteral::from_lit(&src, &lit); @@ -247,9 +259,12 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { let result = (|| { - let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix)?; + let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?; if let Some(fraction) = num_lit.fraction { - let fractional_group_size = Self::get_group_size(fraction.rsplit('_'), num_lit.radix)?; + let fractional_group_size = Self::get_group_size( + fraction.rsplit('_'), + num_lit.radix, + self.lint_fraction_readability)?; let consistent = Self::parts_consistent(integral_group_size, fractional_group_size, @@ -363,7 +378,11 @@ fn parts_consistent( /// Returns the size of the digit groups (or None if ungrouped) if successful, /// otherwise returns a `WarningType` for linting. - fn get_group_size<'a>(groups: impl Iterator, radix: Radix) -> Result, WarningType> { + fn get_group_size<'a>( + groups: impl Iterator, + radix: Radix, + lint_unreadable: bool, + ) -> Result, WarningType> { let mut groups = groups.map(str::len); let first = groups.next().expect("At least one group"); @@ -380,7 +399,7 @@ fn get_group_size<'a>(groups: impl Iterator, radix: Radix) -> Re } else { Ok(Some(second)) } - } else if first > 5 { + } else if first > 5 && lint_unreadable { Err(WarningType::UnreadableLiteral) } else { Ok(None) diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 0d31e9cfc3d..1bd96b2b4c8 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -2,6 +2,7 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::{is_unused, mutated_variables}; +use crate::utils::visitors::LocalUsedVisitor; use crate::utils::{ contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, @@ -767,7 +768,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { ExprKind::InlineAsm(ref asm) => asm .operands .iter() - .map(|o| match o { + .map(|(o, _)| match o { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } | InlineAsmOperand::Const { expr } @@ -1919,8 +1920,7 @@ fn check_for_single_element_loop<'tcx>( if_chain! { if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind; if let PatKind::Binding(.., target, _) = pat.kind; - if let ExprKind::Array(ref arg_expr_list) = arg_expr.kind; - if let [arg_expression] = arg_expr_list; + if let ExprKind::Array([arg_expression]) = arg_expr.kind; if let ExprKind::Path(ref list_item) = arg_expression.kind; if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name); if let ExprKind::Block(ref block, _) = body.kind; @@ -2025,8 +2025,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option let node_str = cx.tcx.hir().get(hir_id); if_chain! { if let Node::Binding(pat) = node_str; - if let PatKind::Binding(bind_ann, ..) = pat.kind; - if let BindingAnnotation::Mutable = bind_ann; + if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind; then { return Some(hir_id); } @@ -2071,28 +2070,6 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool { } } -struct LocalUsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - local: HirId, - used: bool, -} - -impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if same_var(self.cx, expr, self.local) { - self.used = true; - } else { - walk_expr(self, expr); - } - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::None - } -} - struct VarVisitor<'a, 'tcx> { /// context reference cx: &'a LateContext<'tcx>, @@ -2126,11 +2103,7 @@ fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Ex then { let index_used_directly = same_var(self.cx, idx, self.var); let indexed_indirectly = { - let mut used_visitor = LocalUsedVisitor { - cx: self.cx, - local: self.var, - used: false, - }; + let mut used_visitor = LocalUsedVisitor::new(self.var); walk_expr(&mut used_visitor, idx); used_visitor.used }; @@ -2950,7 +2923,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo for ref stmt in block.stmts { if_chain! { if let StmtKind::Local( - Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. }, + Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. }, init: Some(ref init_expr), .. } ) = stmt.kind; if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind; @@ -2964,6 +2937,16 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident); if iter_calls.len() == 1; then { + let mut used_count_visitor = UsedCountVisitor { + cx, + id: *pat_id, + count: 0, + }; + walk_block(&mut used_count_visitor, block); + if used_count_visitor.count > 1 { + return; + } + // Suggest replacing iter_call with iter_replacement, and removing stmt let iter_call = &iter_calls[0]; span_lint_and_then( @@ -3087,6 +3070,28 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap { } } +struct UsedCountVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + id: HirId, + count: usize, +} + +impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + if same_var(self.cx, expr, self.id) { + self.count += 1; + } else { + walk_expr(self, expr); + } + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) + } +} + /// Detect the occurrences of calls to `iter` or `into_iter` for the /// given identifier fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option> { diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index a1450b0d5fe..91849e74887 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -1,12 +1,15 @@ -use crate::utils::{snippet_opt, span_lint_and_then}; +use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then}; use if_chain::if_chain; use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind}; use rustc_attr as attr; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; +const MANUAL_NON_EXHAUSTIVE_MSRV: RustcVersion = RustcVersion::new(1, 40, 0); + declare_clippy_lint! { /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. /// @@ -55,10 +58,26 @@ "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]" } -declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); +#[derive(Clone)] +pub struct ManualNonExhaustive { + msrv: Option, +} + +impl ManualNonExhaustive { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); impl EarlyLintPass for ManualNonExhaustive { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) { + return; + } + match &item.kind { ItemKind::Enum(def, _) => { check_manual_non_exhaustive_enum(cx, item, &def.variants); @@ -73,6 +92,8 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { _ => {}, } } + + extract_msrv_attr!(EarlyContext); } fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) { diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 4afb0ab3bad..3c4368a3545 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,7 +1,7 @@ use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ - eq_expr_value, higher, match_def_path, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then, + eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then, }; use if_chain::if_chain; @@ -10,13 +10,16 @@ use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::BinOpKind; use rustc_hir::{BorrowKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::Span; +const MANUAL_STRIP_MSRV: RustcVersion = RustcVersion::new(1, 45, 0); + declare_clippy_lint! { /// **What it does:** /// Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using @@ -51,7 +54,18 @@ "suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing" } -declare_lint_pass!(ManualStrip => [MANUAL_STRIP]); +pub struct ManualStrip { + msrv: Option, +} + +impl ManualStrip { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(ManualStrip => [MANUAL_STRIP]); #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum StripKind { @@ -61,6 +75,10 @@ enum StripKind { impl<'tcx> LateLintPass<'tcx> for ManualStrip { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) { + return; + } + if_chain! { if let Some((cond, then, _)) = higher::if_block(&expr); if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind; @@ -114,6 +132,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } } } + + extract_msrv_attr!(LateContext); } // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise. @@ -199,8 +219,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { if is_ref_str(self.cx, ex); let unref = peel_ref(ex); if let ExprKind::Index(indexed, index) = &unref.kind; - if let Some(range) = higher::range(index); - if let higher::Range { start, end, .. } = range; + if let Some(higher::Range { start, end, .. }) = higher::range(index); if let ExprKind::Path(path) = &indexed.kind; if qpath_res(self.cx, path, ex.hir_id) == self.target; then { diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs index 5298e16a04d..f3c0515b9bc 100644 --- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs +++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs @@ -99,7 +99,7 @@ /// } /// ``` pub MAP_ERR_IGNORE, - pedantic, + restriction, "`map_err` should not ignore the original error" } @@ -133,9 +133,9 @@ fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { cx, MAP_ERR_IGNORE, body_span, - "`map_err(|_|...` ignores the original error", + "`map_err(|_|...` wildcard pattern discards the original error", None, - "Consider wrapping the error in an enum variant", + "Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)", ); } } diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index c6dca54e250..274d20cfa80 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -3,8 +3,8 @@ use crate::utils::usage::is_unused; use crate::utils::{ expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, - is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, - snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, + is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, meets_msrv, multispan_sugg, remove_blocks, + snippet, snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, }; use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash}; @@ -20,6 +20,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty, TyS}; +use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::{sym, Symbol}; @@ -411,8 +412,8 @@ } declare_clippy_lint! { - /// **What it does:** Lint for redundant pattern matching over `Result` or - /// `Option` + /// **What it does:** Lint for redundant pattern matching over `Result`, `Option`, + /// `std::task::Poll` or `std::net::IpAddr` /// /// **Why is this bad?** It's more concise and clear to just use the proper /// utility function @@ -422,10 +423,16 @@ /// **Example:** /// /// ```rust + /// # use std::task::Poll; + /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// if let Ok(_) = Ok::(42) {} /// if let Err(_) = Err::(42) {} /// if let None = None::<()> {} /// if let Some(_) = Some(42) {} + /// if let Poll::Pending = Poll::Pending::<()> {} + /// if let Poll::Ready(_) = Poll::Ready(42) {} + /// if let IpAddr::V4(_) = IpAddr::V4(Ipv4Addr::LOCALHOST) {} + /// if let IpAddr::V6(_) = IpAddr::V6(Ipv6Addr::LOCALHOST) {} /// match Ok::(42) { /// Ok(_) => true, /// Err(_) => false, @@ -435,10 +442,16 @@ /// The more idiomatic use would be: /// /// ```rust + /// # use std::task::Poll; + /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// if Ok::(42).is_ok() {} /// if Err::(42).is_err() {} /// if None::<()>.is_none() {} /// if Some(42).is_some() {} + /// if Poll::Pending::<()>.is_pending() {} + /// if Poll::Ready(42).is_ready() {} + /// if IpAddr::V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + /// if IpAddr::V6(Ipv6Addr::LOCALHOST).is_ipv6() {} /// Ok::(42).is_ok(); /// ``` pub REDUNDANT_PATTERN_MATCHING, @@ -452,7 +465,8 @@ /// /// **Why is this bad?** Readability and needless complexity. /// - /// **Known problems:** None + /// **Known problems:** This lint falsely triggers, if there are arms with + /// `cfg` attributes that remove an arm evaluating to `false`. /// /// **Example:** /// ```rust @@ -521,9 +535,20 @@ #[derive(Default)] pub struct Matches { + msrv: Option, infallible_destructuring_match_linted: bool, } +impl Matches { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { + msrv, + ..Matches::default() + } + } +} + impl_lint_pass!(Matches => [ SINGLE_MATCH, MATCH_REF_PATS, @@ -543,6 +568,8 @@ pub struct Matches { MATCH_SAME_ARMS, ]); +const MATCH_LIKE_MATCHES_MACRO_MSRV: RustcVersion = RustcVersion::new(1, 42, 0); + impl<'tcx> LateLintPass<'tcx> for Matches { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) { @@ -550,7 +577,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } redundant_pattern_match::check(cx, expr); - if !check_match_like_matches(cx, expr) { + + if meets_msrv(self.msrv.as_ref(), &MATCH_LIKE_MATCHES_MACRO_MSRV) { + if !check_match_like_matches(cx, expr) { + lint_match_arms(cx, expr); + } + } else { lint_match_arms(cx, expr); } @@ -614,8 +646,7 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if_chain! { if !in_external_macro(cx.sess(), pat.span); if !in_macro(pat.span); - if let PatKind::Struct(ref qpath, fields, true) = pat.kind; - if let QPath::Resolved(_, ref path) = qpath; + if let PatKind::Struct(QPath::Resolved(_, ref path), fields, true) = pat.kind; if let Some(def_id) = path.res.opt_def_id(); let ty = cx.tcx.type_of(def_id); if let ty::Adt(def, _) = ty.kind(); @@ -634,6 +665,8 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { } } } + + extract_msrv_attr!(LateContext); } #[rustfmt::skip] @@ -922,16 +955,14 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) if let QPath::Resolved(_, p) = path { missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); } - } else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind { - if let QPath::Resolved(_, p) = path { - // Some simple checks for exhaustive patterns. - // There is a room for improvements to detect more cases, - // but it can be more expensive to do so. - let is_pattern_exhaustive = - |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None)); - if patterns.iter().all(is_pattern_exhaustive) { - missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); - } + } else if let PatKind::TupleStruct(QPath::Resolved(_, p), ref patterns, ..) = arm.pat.kind { + // Some simple checks for exhaustive patterns. + // There is a room for improvements to detect more cases, + // but it can be more expensive to do so. + let is_pattern_exhaustive = + |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None)); + if patterns.iter().all(is_pattern_exhaustive) { + missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); } } } @@ -1134,13 +1165,16 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr if b0 != b1; let if_guard = &b0_arms[0].guard; if if_guard.is_none() || b0_arms.len() == 1; + if b0_arms[0].attrs.is_empty(); if b0_arms[1..].iter() .all(|arm| { find_bool_lit(&arm.body.kind, desugared).map_or(false, |b| b == b0) && - arm.guard.is_none() + arm.guard.is_none() && arm.attrs.is_empty() }); then { - let mut applicability = Applicability::MachineApplicable; + // The suggestion may be incorrect, because some arms can have `cfg` attributes + // evaluated into `false` and so such arms will be stripped before. + let mut applicability = Applicability::MaybeIncorrect; let pat = { use itertools::Itertools as _; b0_arms.iter() @@ -1403,8 +1437,7 @@ fn is_ref_some_arm(arm: &Arm<'_>) -> Option { if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).kind; if let ExprKind::Path(ref some_path) = e.kind; if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; - if let ExprKind::Path(ref qpath) = args[0].kind; - if let &QPath::Resolved(_, ref path2) = qpath; + if let ExprKind::Path(QPath::Resolved(_, ref path2)) = args[0].kind; if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; then { return Some(rb) @@ -1538,6 +1571,12 @@ fn find_sugg_for_if_let<'tcx>( "is_err()" } else if match_qpath(path, &paths::OPTION_SOME) { "is_some()" + } else if match_qpath(path, &paths::POLL_READY) { + "is_ready()" + } else if match_qpath(path, &paths::IPADDR_V4) { + "is_ipv4()" + } else if match_qpath(path, &paths::IPADDR_V6) { + "is_ipv6()" } else { return; } @@ -1545,7 +1584,15 @@ fn find_sugg_for_if_let<'tcx>( return; } }, - PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()", + PatKind::Path(ref path) => { + if match_qpath(path, &paths::OPTION_NONE) { + "is_none()" + } else if match_qpath(path, &paths::POLL_PENDING) { + "is_pending()" + } else { + return; + } + }, _ => return, }; @@ -1610,6 +1657,17 @@ fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: & "is_ok()", "is_err()", ) + .or_else(|| { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::IPADDR_V4, + &paths::IPADDR_V6, + "is_ipv4()", + "is_ipv6()", + ) + }) } else { None } @@ -1628,6 +1686,17 @@ fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: & "is_some()", "is_none()", ) + .or_else(|| { + find_good_method_for_match( + arms, + path_left, + path_right, + &paths::POLL_READY, + &paths::POLL_PENDING, + "is_ready()", + "is_pending()", + ) + }) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 40a62575861..44c974b9d98 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -90,8 +90,7 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option return Some(MinMax::Max), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index fa174404365..8002c27a5e9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -14,13 +14,12 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; -use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty, TyS}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::{sym, SymbolStr}; @@ -28,11 +27,12 @@ use crate::utils::eager_or_lazy::is_lazyness_candidate; use crate::utils::usage::mutated_variables; use crate::utils::{ - contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, - is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, - match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty, - single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, - span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq, + contains_return, contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, + implements_trait, in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, + match_def_path, match_qpath, match_trait_method, match_type, match_var, meets_msrv, method_calls, + method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, + snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, + walk_ptrs_ty_depth, SpanlessEq, }; declare_clippy_lint! { @@ -1404,7 +1404,18 @@ "use `.collect()` instead of `::from_iter()`" } -declare_lint_pass!(Methods => [ +pub struct Methods { + msrv: Option, +} + +impl Methods { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(Methods => [ UNWRAP_USED, EXPECT_USED, SHOULD_IMPLEMENT_TRAIT, @@ -1531,8 +1542,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { check_pointer_offset(cx, expr, arg_lists[0]) }, ["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]), - ["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false), - ["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true), + ["map", "as_ref"] => { + lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref()) + }, + ["map", "as_mut"] => { + lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref()) + }, ["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"), ["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"), ["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"), @@ -1738,6 +1753,8 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_> } } } + + extract_msrv_attr!(LateContext); } /// Checks for the `OR_FUN_CALL` lint. @@ -3453,6 +3470,8 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { ); } +const OPTION_AS_REF_DEREF_MSRV: RustcVersion = RustcVersion::new(1, 40, 0); + /// lint use of `_.as_ref().map(Deref::deref)` for `Option`s fn lint_option_as_ref_deref<'tcx>( cx: &LateContext<'tcx>, @@ -3460,7 +3479,12 @@ fn lint_option_as_ref_deref<'tcx>( as_ref_args: &[hir::Expr<'_>], map_args: &[hir::Expr<'_>], is_mut: bool, + msrv: Option<&RustcVersion>, ) { + if !meets_msrv(msrv, &OPTION_AS_REF_DEREF_MSRV) { + return; + } + let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not); let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]); @@ -3846,36 +3870,6 @@ fn is_bool(ty: &hir::Ty<'_>) -> bool { } } -// Returns `true` if `expr` contains a return expression -fn contains_return(expr: &hir::Expr<'_>) -> bool { - struct RetCallFinder { - found: bool, - } - - impl<'tcx> intravisit::Visitor<'tcx> for RetCallFinder { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if self.found { - return; - } - if let hir::ExprKind::Ret(..) = &expr.kind { - self.found = true; - } else { - intravisit::walk_expr(self, expr); - } - } - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } - } - - let mut visitor = RetCallFinder { found: false }; - visitor.visit_expr(expr); - visitor.found -} - fn check_pointer_offset(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { if_chain! { if args.len() == 2; diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 308e92057b7..0512d74c7b1 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -18,7 +18,7 @@ use crate::utils::{ get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_integer_const, iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, span_lint_hir_and_then, SpanlessEq, + span_lint_and_then, span_lint_hir_and_then, unsext, SpanlessEq, }; declare_clippy_lint! { @@ -139,12 +139,14 @@ } declare_clippy_lint! { - /// **What it does:** Checks for getting the remainder of a division by one. + /// **What it does:** Checks for getting the remainder of a division by one or minus + /// one. /// - /// **Why is this bad?** The result can only ever be zero. No one will write - /// such code deliberately, unless trying to win an Underhanded Rust - /// Contest. Even for that contest, it's probably a bad idea. Use something more - /// underhanded. + /// **Why is this bad?** The result for a divisor of one can only ever be zero; for + /// minus one it can cause panic/overflow (if the left operand is the minimal value of + /// the respective integer type) or results in zero. No one will write such code + /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that + /// contest, it's probably a bad idea. Use something more underhanded. /// /// **Known problems:** None. /// @@ -152,10 +154,11 @@ /// ```rust /// # let x = 1; /// let a = x % 1; + /// let a = x % -1; /// ``` pub MODULO_ONE, correctness, - "taking a number modulo 1, which always returns 0" + "taking a number modulo +/-1, which can either panic/overflow or always returns 0" } declare_clippy_lint! { @@ -378,60 +381,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { return; }, ExprKind::Binary(ref cmp, ref left, ref right) => { - let op = cmp.node; - if op.is_comparison() { - check_nan(cx, left, expr); - check_nan(cx, right, expr); - check_to_owned(cx, left, right, true); - check_to_owned(cx, right, left, false); - } - if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { - if is_allowed(cx, left) || is_allowed(cx, right) { - return; - } - - // Allow comparing the results of signum() - if is_signum(cx, left) && is_signum(cx, right) { - return; - } - - if let Some(name) = get_item_name(cx, expr) { - let name = name.as_str(); - if name == "eq" - || name == "ne" - || name == "is_nan" - || name.starts_with("eq_") - || name.ends_with("_eq") - { - return; - } - } - let is_comparing_arrays = is_array(cx, left) || is_array(cx, right); - let (lint, msg) = get_lint_and_message( - is_named_constant(cx, left) || is_named_constant(cx, right), - is_comparing_arrays, - ); - span_lint_and_then(cx, lint, expr.span, msg, |diag| { - let lhs = Sugg::hir(cx, left, ".."); - let rhs = Sugg::hir(cx, right, ".."); - - if !is_comparing_arrays { - diag.span_suggestion( - expr.span, - "consider comparing them within some margin of error", - format!( - "({}).abs() {} error_margin", - lhs - rhs, - if op == BinOpKind::Eq { '<' } else { '>' } - ), - Applicability::HasPlaceholders, // snippet - ); - } - diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`"); - }); - } else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) { - span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); - } + check_binary(cx, expr, cmp, left, right); + return; }, _ => {}, } @@ -744,3 +695,74 @@ fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) } } } + +fn check_binary( + cx: &LateContext<'a>, + expr: &Expr<'_>, + cmp: &rustc_span::source_map::Spanned, + left: &'a Expr<'_>, + right: &'a Expr<'_>, +) { + let op = cmp.node; + if op.is_comparison() { + check_nan(cx, left, expr); + check_nan(cx, right, expr); + check_to_owned(cx, left, right, true); + check_to_owned(cx, right, left, false); + } + if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { + if is_allowed(cx, left) || is_allowed(cx, right) { + return; + } + + // Allow comparing the results of signum() + if is_signum(cx, left) && is_signum(cx, right) { + return; + } + + if let Some(name) = get_item_name(cx, expr) { + let name = name.as_str(); + if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || name.ends_with("_eq") { + return; + } + } + let is_comparing_arrays = is_array(cx, left) || is_array(cx, right); + let (lint, msg) = get_lint_and_message( + is_named_constant(cx, left) || is_named_constant(cx, right), + is_comparing_arrays, + ); + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + let lhs = Sugg::hir(cx, left, ".."); + let rhs = Sugg::hir(cx, right, ".."); + + if !is_comparing_arrays { + diag.span_suggestion( + expr.span, + "consider comparing them within some margin of error", + format!( + "({}).abs() {} error_margin", + lhs - rhs, + if op == BinOpKind::Eq { '<' } else { '>' } + ), + Applicability::HasPlaceholders, // snippet + ); + } + diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`"); + }); + } else if op == BinOpKind::Rem { + if is_integer_const(cx, right, 1) { + span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); + } + + if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() { + if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) { + span_lint( + cx, + MODULO_ONE, + expr.span, + "any number modulo -1 will panic/overflow or result in 0", + ); + } + }; + } +} diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index a799a644e97..42f97b2ac49 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -6,7 +6,6 @@ use crate::utils::{ higher, is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg, }; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; @@ -198,13 +197,9 @@ struct ExpressionInfoWithSpan { } fn is_unary_not(e: &Expr<'_>) -> (bool, Span) { - if_chain! { - if let ExprKind::Unary(unop, operand) = e.kind; - if let UnOp::UnNot = unop; - then { - return (true, operand.span); - } - }; + if let ExprKind::Unary(UnOp::UnNot, operand) = e.kind { + return (true, operand.span); + } (false, e.span) } diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index 31b03ecd101..359620cc079 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -66,7 +66,7 @@ /// ``` pub UNREACHABLE, restriction, - "`unreachable!` should not be present in production code" + "usage of the `unreachable!` macro" } declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); @@ -85,12 +85,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } else if is_expn_of(expr.span, "todo").is_some() { span_lint(cx, TODO, span, "`todo` should not be present in production code"); } else if is_expn_of(expr.span, "unreachable").is_some() { - span_lint( - cx, - UNREACHABLE, - span, - "`unreachable` should not be present in production code", - ); + span_lint(cx, UNREACHABLE, span, "usage of the `unreachable!` macro"); } else if is_expn_of(expr.span, "panic").is_some() { span_lint(cx, PANIC, span, "`panic` should not be present in production code"); } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index d9b280b7a85..b91233ac582 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -176,8 +176,7 @@ fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { if block.stmts.len() == 1; if let Some(expr) = block.stmts.iter().last(); if let StmtKind::Semi(ref expr) = expr.kind; - if let ExprKind::Ret(ret_expr) = expr.kind; - if let Some(ret_expr) = ret_expr; + if let ExprKind::Ret(Some(ret_expr)) = expr.kind; then { return Some(ret_expr); diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 49cb2ffc4e3..f398b3fff25 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -104,7 +104,7 @@ struct ClosureUsageCount<'a, 'tcx> { cx: &'a LateContext<'tcx>, path: &'tcx hir::Path<'tcx>, count: usize, - }; + } impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> { type Map = Map<'tcx>; @@ -124,7 +124,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } - }; + } let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 }; closure_usage_count.visit_block(block); closure_usage_count.count diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs new file mode 100644 index 00000000000..ea7a76146f5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -0,0 +1,145 @@ +//! Lint on use of `size_of` or `size_of_val` of T in an expression +//! expecting a count of T + +use crate::utils::{match_def_path, paths, span_lint_and_help}; +use if_chain::if_chain; +use rustc_hir::BinOpKind; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty, TyS, TypeAndMut}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Detects expressions where + /// `size_of::` or `size_of_val::` is used as a + /// count of elements of type `T` + /// + /// **Why is this bad?** These functions expect a count + /// of `T` and not a number of bytes + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust,no_run + /// # use std::ptr::copy_nonoverlapping; + /// # use std::mem::size_of; + /// const SIZE: usize = 128; + /// let x = [2u8; SIZE]; + /// let mut y = [2u8; SIZE]; + /// unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::() * SIZE) }; + /// ``` + pub SIZE_OF_IN_ELEMENT_COUNT, + correctness, + "using `size_of::` or `size_of_val::` where a count of elements of `T` is expected" +} + +declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]); + +fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option> { + match expr.kind { + ExprKind::Call(count_func, _func_args) => { + if_chain! { + if let ExprKind::Path(ref count_func_qpath) = count_func.kind; + if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id(); + if match_def_path(cx, def_id, &paths::MEM_SIZE_OF) + || match_def_path(cx, def_id, &paths::MEM_SIZE_OF_VAL); + then { + cx.typeck_results().node_substs(count_func.hir_id).types().next() + } else { + None + } + } + }, + ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node || BinOpKind::Div == op.node => { + get_size_of_ty(cx, left).or_else(|| get_size_of_ty(cx, right)) + }, + ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr), + _ => None, + } +} + +fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> { + const FUNCTIONS: [&[&str]; 8] = [ + &paths::COPY_NONOVERLAPPING, + &paths::COPY, + &paths::WRITE_BYTES, + &paths::PTR_SWAP_NONOVERLAPPING, + &paths::PTR_SLICE_FROM_RAW_PARTS, + &paths::PTR_SLICE_FROM_RAW_PARTS_MUT, + &paths::SLICE_FROM_RAW_PARTS, + &paths::SLICE_FROM_RAW_PARTS_MUT, + ]; + const METHODS: [&str; 11] = [ + "write_bytes", + "copy_to", + "copy_from", + "copy_to_nonoverlapping", + "copy_from_nonoverlapping", + "add", + "wrapping_add", + "sub", + "wrapping_sub", + "offset", + "wrapping_offset", + ]; + + if_chain! { + // Find calls to ptr::{copy, copy_nonoverlapping} + // and ptr::{swap_nonoverlapping, write_bytes}, + if let ExprKind::Call(func, [.., count]) = expr.kind; + if let ExprKind::Path(ref func_qpath) = func.kind; + if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); + if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path)); + + // Get the pointee type + if let Some(pointee_ty) = cx.typeck_results().node_substs(func.hir_id).types().next(); + then { + return Some((pointee_ty, count)); + } + }; + if_chain! { + // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods + if let ExprKind::MethodCall(method_path, _, [ptr_self, .., count], _) = expr.kind; + let method_ident = method_path.ident.as_str(); + if METHODS.iter().any(|m| *m == &*method_ident); + + // Get the pointee type + if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) = + cx.typeck_results().expr_ty(ptr_self).kind(); + then { + return Some((pointee_ty, count)); + } + }; + None +} + +impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + const HELP_MSG: &str = "use a count of elements instead of a count of bytes\ + , it already gets multiplied by the size of the type"; + + const LINT_MSG: &str = "found a count of bytes \ + instead of a count of elements of `T`"; + + if_chain! { + // Find calls to functions with an element count parameter and get + // the pointee type and count parameter expression + if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr); + + // Find a size_of call in the count parameter expression and + // check that it's the same type + if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr); + if TyS::same_type(pointee_ty, ty_used_for_size_of); + then { + span_lint_and_help( + cx, + SIZE_OF_IN_ELEMENT_COUNT, + count_expr.span, + LINT_MSG, + None, + HELP_MSG + ); + } + }; + } +} diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index ede37624f71..77e79073378 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -2,6 +2,7 @@ use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -11,7 +12,7 @@ use crate::utils::SpanlessEq; use crate::utils::{ get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint, - span_lint_and_sugg, + span_lint_and_help, span_lint_and_sugg, }; declare_clippy_lint! { @@ -221,8 +222,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if method_names[0] == sym!(as_bytes); // Check for slicer - if let ExprKind::Struct(ref path, _, _) = right.kind; - if let QPath::LangItem(LangItem::Range, _) = path; + if let ExprKind::Struct(QPath::LangItem(LangItem::Range, _), _, _) = right.kind; then { let mut applicability = Applicability::MachineApplicable; @@ -289,3 +289,100 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { } } } + +declare_clippy_lint! { + /// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`. + /// + /// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string. + /// When called on a `&str` it turns the `&str` into the owned variant `String`, which can be better + /// expressed with `.to_owned()`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// let _ = "str".to_string(); + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// let _ = "str".to_owned(); + /// ``` + pub STR_TO_STRING, + restriction, + "using `to_string()` on a `&str`, which should be `to_owned()`" +} + +declare_lint_pass!(StrToString => [STR_TO_STRING]); + +impl LateLintPass<'_> for StrToString { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(path, _, args, _) = &expr.kind; + if path.ident.name == sym!(to_string); + let ty = cx.typeck_results().expr_ty(&args[0]); + if let ty::Ref(_, ty, ..) = ty.kind(); + if *ty.kind() == ty::Str; + then { + span_lint_and_help( + cx, + STR_TO_STRING, + expr.span, + "`to_string()` called on a `&str`", + None, + "consider using `.to_owned()`", + ); + } + } + } +} + +declare_clippy_lint! { + /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`. + /// + /// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string. + /// When called on a `String` it only clones the `String`, which can be better expressed with `.clone()`. + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// let msg = String::from("Hello World"); + /// let _ = msg.to_string(); + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// let msg = String::from("Hello World"); + /// let _ = msg.clone(); + /// ``` + pub STRING_TO_STRING, + restriction, + "using `to_string()` on a `String`, which should be `clone()`" +} + +declare_lint_pass!(StringToString => [STRING_TO_STRING]); + +impl LateLintPass<'_> for StringToString { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(path, _, args, _) = &expr.kind; + if path.ident.name == sym!(to_string); + let ty = cx.typeck_results().expr_ty(&args[0]); + if is_type_diagnostic_item(cx, ty, sym!(string_type)); + then { + span_lint_and_help( + cx, + STRING_TO_STRING, + expr.span, + "`to_string()` called on a `String`", + None, + "consider using `.clone()`", + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs new file mode 100644 index 00000000000..cccd24ccf94 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -0,0 +1,693 @@ +use crate::utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter}; +use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use core::ops::{Add, AddAssign}; +use if_chain::if_chain; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Spanned; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** + /// Checks for unlikely usages of binary operators that are almost + /// certainly typos and/or copy/paste errors, given the other usages + /// of binary operators nearby. + /// **Why is this bad?** + /// They are probably bugs and if they aren't then they look like bugs + /// and you should add a comment explaining why you are doing such an + /// odd set of operations. + /// **Known problems:** + /// There may be some false positives if you are trying to do something + /// unusual that happens to look like a typo. + /// + /// **Example:** + /// + /// ```rust + /// struct Vec3 { + /// x: f64, + /// y: f64, + /// z: f64, + /// } + /// + /// impl Eq for Vec3 {} + /// + /// impl PartialEq for Vec3 { + /// fn eq(&self, other: &Self) -> bool { + /// // This should trigger the lint because `self.x` is compared to `other.y` + /// self.x == other.y && self.y == other.y && self.z == other.z + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// # struct Vec3 { + /// # x: f64, + /// # y: f64, + /// # z: f64, + /// # } + /// // same as above except: + /// impl PartialEq for Vec3 { + /// fn eq(&self, other: &Self) -> bool { + /// // Note we now compare other.x to self.x + /// self.x == other.x && self.y == other.y && self.z == other.z + /// } + /// } + /// ``` + pub SUSPICIOUS_OPERATION_GROUPINGS, + style, + "groupings of binary operations that look suspiciously like typos" +} + +declare_lint_pass!(SuspiciousOperationGroupings => [SUSPICIOUS_OPERATION_GROUPINGS]); + +impl EarlyLintPass for SuspiciousOperationGroupings { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if expr.span.from_expansion() { + return; + } + + if let Some(binops) = extract_related_binops(&expr.kind) { + check_binops(cx, &binops.iter().collect::>()); + + let mut op_types = Vec::with_capacity(binops.len()); + // We could use a hashmap, etc. to avoid being O(n*m) here, but + // we want the lints to be emitted in a consistent order. Besides, + // m, (the number of distinct `BinOpKind`s in `binops`) + // will often be small, and does have an upper limit. + binops.iter().map(|b| b.op).for_each(|op| { + if !op_types.contains(&op) { + op_types.push(op); + } + }); + + for op_type in op_types { + let ops: Vec<_> = binops.iter().filter(|b| b.op == op_type).collect(); + + check_binops(cx, &ops); + } + } + } +} + +fn check_binops(cx: &EarlyContext<'_>, binops: &[&BinaryOp<'_>]) { + let binop_count = binops.len(); + if binop_count < 2 { + // Single binary operation expressions would likely be false + // positives. + return; + } + + let mut one_ident_difference_count = 0; + let mut no_difference_info = None; + let mut double_difference_info = None; + let mut expected_ident_loc = None; + + let mut paired_identifiers = FxHashSet::default(); + + for (i, BinaryOp { left, right, op, .. }) in binops.iter().enumerate() { + match ident_difference_expr(left, right) { + IdentDifference::NoDifference => { + if is_useless_with_eq_exprs(*op) { + // The `eq_op` lint should catch this in this case. + return; + } + + no_difference_info = Some(i); + }, + IdentDifference::Single(ident_loc) => { + one_ident_difference_count += 1; + if let Some(previous_expected) = expected_ident_loc { + if previous_expected != ident_loc { + // This expression doesn't match the form we're + // looking for. + return; + } + } else { + expected_ident_loc = Some(ident_loc); + } + + // If there was only a single difference, all other idents + // must have been the same, and thus were paired. + for id in skip_index(IdentIter::from(*left), ident_loc.index) { + paired_identifiers.insert(id); + } + }, + IdentDifference::Double(ident_loc1, ident_loc2) => { + double_difference_info = Some((i, ident_loc1, ident_loc2)); + }, + IdentDifference::Multiple | IdentDifference::NonIdent => { + // It's too hard to know whether this is a bug or not. + return; + }, + } + } + + let mut applicability = Applicability::MachineApplicable; + + if let Some(expected_loc) = expected_ident_loc { + match (no_difference_info, double_difference_info) { + (Some(i), None) => attempt_to_emit_no_difference_lint(cx, binops, i, expected_loc), + (None, Some((double_difference_index, ident_loc1, ident_loc2))) => { + if_chain! { + if one_ident_difference_count == binop_count - 1; + if let Some(binop) = binops.get(double_difference_index); + then { + let changed_loc = if ident_loc1 == expected_loc { + ident_loc2 + } else if ident_loc2 == expected_loc { + ident_loc1 + } else { + // This expression doesn't match the form we're + // looking for. + return; + }; + + if let Some(sugg) = ident_swap_sugg( + cx, + &paired_identifiers, + binop, + changed_loc, + &mut applicability, + ) { + emit_suggestion( + cx, + binop.span, + sugg, + applicability, + ); + } + } + } + }, + _ => {}, + } + } +} + +fn attempt_to_emit_no_difference_lint( + cx: &EarlyContext<'_>, + binops: &[&BinaryOp<'_>], + i: usize, + expected_loc: IdentLocation, +) { + if let Some(binop) = binops.get(i).cloned() { + // We need to try and figure out which identifier we should + // suggest using instead. Since there could be multiple + // replacement candidates in a given expression, and we're + // just taking the first one, we may get some bad lint + // messages. + let mut applicability = Applicability::MaybeIncorrect; + + // We assume that the correct ident is one used elsewhere in + // the other binops, in a place that there was a single + // difference between idents before. + let old_left_ident = get_ident(binop.left, expected_loc); + let old_right_ident = get_ident(binop.right, expected_loc); + + for b in skip_index(binops.iter(), i) { + if_chain! { + if let (Some(old_ident), Some(new_ident)) = + (old_left_ident, get_ident(b.left, expected_loc)); + if old_ident != new_ident; + if let Some(sugg) = suggestion_with_swapped_ident( + cx, + binop.left, + expected_loc, + new_ident, + &mut applicability, + ); + then { + emit_suggestion( + cx, + binop.span, + replace_left_sugg(cx, &binop, &sugg, &mut applicability), + applicability, + ); + return; + } + } + + if_chain! { + if let (Some(old_ident), Some(new_ident)) = + (old_right_ident, get_ident(b.right, expected_loc)); + if old_ident != new_ident; + if let Some(sugg) = suggestion_with_swapped_ident( + cx, + binop.right, + expected_loc, + new_ident, + &mut applicability, + ); + then { + emit_suggestion( + cx, + binop.span, + replace_right_sugg(cx, &binop, &sugg, &mut applicability), + applicability, + ); + return; + } + } + } + } +} + +fn emit_suggestion(cx: &EarlyContext<'_>, span: Span, sugg: String, applicability: Applicability) { + span_lint_and_sugg( + cx, + SUSPICIOUS_OPERATION_GROUPINGS, + span, + "This sequence of operators looks suspiciously like a bug.", + "I think you meant", + sugg, + applicability, + ) +} + +fn ident_swap_sugg( + cx: &EarlyContext<'_>, + paired_identifiers: &FxHashSet, + binop: &BinaryOp<'_>, + location: IdentLocation, + applicability: &mut Applicability, +) -> Option { + let left_ident = get_ident(&binop.left, location)?; + let right_ident = get_ident(&binop.right, location)?; + + let sugg = match ( + paired_identifiers.contains(&left_ident), + paired_identifiers.contains(&right_ident), + ) { + (true, true) | (false, false) => { + // We don't have a good guess of what ident should be + // used instead, in these cases. + *applicability = Applicability::MaybeIncorrect; + + // We arbitraily choose one side to suggest changing, + // since we don't have a better guess. If the user + // ends up duplicating a clause, the `logic_bug` lint + // should catch it. + + let right_suggestion = + suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?; + + replace_right_sugg(cx, binop, &right_suggestion, applicability) + }, + (false, true) => { + // We haven't seen a pair involving the left one, so + // it's probably what is wanted. + + let right_suggestion = + suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?; + + replace_right_sugg(cx, binop, &right_suggestion, applicability) + }, + (true, false) => { + // We haven't seen a pair involving the right one, so + // it's probably what is wanted. + let left_suggestion = suggestion_with_swapped_ident(cx, &binop.left, location, right_ident, applicability)?; + + replace_left_sugg(cx, binop, &left_suggestion, applicability) + }, + }; + + Some(sugg) +} + +fn replace_left_sugg( + cx: &EarlyContext<'_>, + binop: &BinaryOp<'_>, + left_suggestion: &str, + applicability: &mut Applicability, +) -> String { + format!( + "{} {} {}", + left_suggestion, + binop.op.to_string(), + snippet_with_applicability(cx, binop.right.span, "..", applicability), + ) +} + +fn replace_right_sugg( + cx: &EarlyContext<'_>, + binop: &BinaryOp<'_>, + right_suggestion: &str, + applicability: &mut Applicability, +) -> String { + format!( + "{} {} {}", + snippet_with_applicability(cx, binop.left.span, "..", applicability), + binop.op.to_string(), + right_suggestion, + ) +} + +#[derive(Clone, Debug)] +struct BinaryOp<'exprs> { + op: BinOpKind, + span: Span, + left: &'exprs Expr, + right: &'exprs Expr, +} + +impl BinaryOp<'exprs> { + fn new(op: BinOpKind, span: Span, (left, right): (&'exprs Expr, &'exprs Expr)) -> Self { + Self { op, span, left, right } + } +} + +fn strip_non_ident_wrappers(expr: &Expr) -> &Expr { + let mut output = expr; + loop { + output = match &output.kind { + ExprKind::Paren(ref inner) | ExprKind::Unary(_, ref inner) => inner, + _ => { + return output; + }, + }; + } +} + +fn extract_related_binops(kind: &ExprKind) -> Option>> { + append_opt_vecs(chained_binops(kind), if_statment_binops(kind)) +} + +fn if_statment_binops(kind: &ExprKind) -> Option>> { + match kind { + ExprKind::If(ref condition, _, _) => chained_binops(&condition.kind), + ExprKind::Paren(ref e) => if_statment_binops(&e.kind), + ExprKind::Block(ref block, _) => { + let mut output = None; + for stmt in &block.stmts { + match stmt.kind { + StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => { + output = append_opt_vecs(output, if_statment_binops(&e.kind)); + }, + _ => {}, + } + } + output + }, + _ => None, + } +} + +fn append_opt_vecs(target_opt: Option>, source_opt: Option>) -> Option> { + match (target_opt, source_opt) { + (Some(mut target), Some(mut source)) => { + target.reserve(source.len()); + for op in source.drain(..) { + target.push(op); + } + Some(target) + }, + (Some(v), None) | (None, Some(v)) => Some(v), + (None, None) => None, + } +} + +fn chained_binops(kind: &ExprKind) -> Option>> { + match kind { + ExprKind::Binary(_, left_outer, right_outer) => chained_binops_helper(left_outer, right_outer), + ExprKind::Paren(ref e) | ExprKind::Unary(_, ref e) => chained_binops(&e.kind), + _ => None, + } +} + +fn chained_binops_helper(left_outer: &'expr Expr, right_outer: &'expr Expr) -> Option>> { + match (&left_outer.kind, &right_outer.kind) { + ( + ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e), + ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e), + ) => chained_binops_helper(left_e, right_e), + (ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e), _) => chained_binops_helper(left_e, right_outer), + (_, ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e)) => { + chained_binops_helper(left_outer, right_e) + }, + ( + ExprKind::Binary(Spanned { node: left_op, .. }, ref left_left, ref left_right), + ExprKind::Binary(Spanned { node: right_op, .. }, ref right_left, ref right_right), + ) => match ( + chained_binops_helper(left_left, left_right), + chained_binops_helper(right_left, right_right), + ) { + (Some(mut left_ops), Some(mut right_ops)) => { + left_ops.reserve(right_ops.len()); + for op in right_ops.drain(..) { + left_ops.push(op); + } + Some(left_ops) + }, + (Some(mut left_ops), _) => { + left_ops.push(BinaryOp::new(*right_op, right_outer.span, (right_left, right_right))); + Some(left_ops) + }, + (_, Some(mut right_ops)) => { + right_ops.insert(0, BinaryOp::new(*left_op, left_outer.span, (left_left, left_right))); + Some(right_ops) + }, + (None, None) => Some(vec![ + BinaryOp::new(*left_op, left_outer.span, (left_left, left_right)), + BinaryOp::new(*right_op, right_outer.span, (right_left, right_right)), + ]), + }, + _ => None, + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] +struct IdentLocation { + index: usize, +} + +impl Add for IdentLocation { + type Output = IdentLocation; + + fn add(self, other: Self) -> Self::Output { + Self { + index: self.index + other.index, + } + } +} + +impl AddAssign for IdentLocation { + fn add_assign(&mut self, other: Self) { + *self = *self + other + } +} + +#[derive(Clone, Copy, Debug)] +enum IdentDifference { + NoDifference, + Single(IdentLocation), + Double(IdentLocation, IdentLocation), + Multiple, + NonIdent, +} + +impl Add for IdentDifference { + type Output = IdentDifference; + + fn add(self, other: Self) -> Self::Output { + match (self, other) { + (Self::NoDifference, output) | (output, Self::NoDifference) => output, + (Self::Multiple, _) + | (_, Self::Multiple) + | (Self::Double(_, _), Self::Single(_)) + | (Self::Single(_) | Self::Double(_, _), Self::Double(_, _)) => Self::Multiple, + (Self::NonIdent, _) | (_, Self::NonIdent) => Self::NonIdent, + (Self::Single(il1), Self::Single(il2)) => Self::Double(il1, il2), + } + } +} + +impl AddAssign for IdentDifference { + fn add_assign(&mut self, other: Self) { + *self = *self + other + } +} + +impl IdentDifference { + /// Returns true if learning about more differences will not change the value + /// of this `IdentDifference`, and false otherwise. + fn is_complete(&self) -> bool { + match self { + Self::NoDifference | Self::Single(_) | Self::Double(_, _) => false, + Self::Multiple | Self::NonIdent => true, + } + } +} + +fn ident_difference_expr(left: &Expr, right: &Expr) -> IdentDifference { + ident_difference_expr_with_base_location(left, right, IdentLocation::default()).0 +} + +fn ident_difference_expr_with_base_location( + left: &Expr, + right: &Expr, + mut base: IdentLocation, +) -> (IdentDifference, IdentLocation) { + // Ideally, this function should not use IdentIter because it should return + // early if the expressions have any non-ident differences. We want that early + // return because if without that restriction the lint would lead to false + // positives. + // + // But, we cannot (easily?) use a `rustc_ast::visit::Visitor`, since we need + // the two expressions to be walked in lockstep. And without a `Visitor`, we'd + // have to do all the AST traversal ourselves, which is a lot of work, since to + // do it properly we'd need to be able to handle more or less every possible + // AST node since `Item`s can be written inside `Expr`s. + // + // In practice, it seems likely that expressions, above a certain size, that + // happen to use the exact same idents in the exact same order, and which are + // not structured the same, would be rare. Therefore it seems likely that if + // we do only the first layer of matching ourselves and eventually fallback on + // IdentIter, then the output of this function will be almost always be correct + // in practice. + // + // If it turns out that problematic cases are more prelavent than we assume, + // then we should be able to change this function to do the correct traversal, + // without needing to change the rest of the code. + + #![allow(clippy::enum_glob_use)] + use ExprKind::*; + + match ( + &strip_non_ident_wrappers(left).kind, + &strip_non_ident_wrappers(right).kind, + ) { + (Yield(_), Yield(_)) + | (Try(_), Try(_)) + | (Paren(_), Paren(_)) + | (Repeat(_, _), Repeat(_, _)) + | (Struct(_, _, _), Struct(_, _, _)) + | (MacCall(_), MacCall(_)) + | (LlvmInlineAsm(_), LlvmInlineAsm(_)) + | (InlineAsm(_), InlineAsm(_)) + | (Ret(_), Ret(_)) + | (Continue(_), Continue(_)) + | (Break(_, _), Break(_, _)) + | (AddrOf(_, _, _), AddrOf(_, _, _)) + | (Path(_, _), Path(_, _)) + | (Range(_, _, _), Range(_, _, _)) + | (Index(_, _), Index(_, _)) + | (Field(_, _), Field(_, _)) + | (AssignOp(_, _, _), AssignOp(_, _, _)) + | (Assign(_, _, _), Assign(_, _, _)) + | (TryBlock(_), TryBlock(_)) + | (Await(_), Await(_)) + | (Async(_, _, _), Async(_, _, _)) + | (Block(_, _), Block(_, _)) + | (Closure(_, _, _, _, _, _), Closure(_, _, _, _, _, _)) + | (Match(_, _), Match(_, _)) + | (Loop(_, _), Loop(_, _)) + | (ForLoop(_, _, _, _), ForLoop(_, _, _, _)) + | (While(_, _, _), While(_, _, _)) + | (If(_, _, _), If(_, _, _)) + | (Let(_, _), Let(_, _)) + | (Type(_, _), Type(_, _)) + | (Cast(_, _), Cast(_, _)) + | (Lit(_), Lit(_)) + | (Unary(_, _), Unary(_, _)) + | (Binary(_, _, _), Binary(_, _, _)) + | (Tup(_), Tup(_)) + | (MethodCall(_, _, _), MethodCall(_, _, _)) + | (Call(_, _), Call(_, _)) + | (ConstBlock(_), ConstBlock(_)) + | (Array(_), Array(_)) + | (Box(_), Box(_)) => { + // keep going + }, + _ => { + return (IdentDifference::NonIdent, base); + }, + } + + let mut difference = IdentDifference::NoDifference; + + for (left_attr, right_attr) in left.attrs.iter().zip(right.attrs.iter()) { + let (new_difference, new_base) = + ident_difference_via_ident_iter_with_base_location(left_attr, right_attr, base); + base = new_base; + difference += new_difference; + if difference.is_complete() { + return (difference, base); + } + } + + let (new_difference, new_base) = ident_difference_via_ident_iter_with_base_location(left, right, base); + base = new_base; + difference += new_difference; + + (difference, base) +} + +fn ident_difference_via_ident_iter_with_base_location>( + left: Iterable, + right: Iterable, + mut base: IdentLocation, +) -> (IdentDifference, IdentLocation) { + // See the note in `ident_difference_expr_with_base_location` about `IdentIter` + let mut difference = IdentDifference::NoDifference; + + let mut left_iterator = left.into(); + let mut right_iterator = right.into(); + + loop { + match (left_iterator.next(), right_iterator.next()) { + (Some(left_ident), Some(right_ident)) => { + if !eq_id(left_ident, right_ident) { + difference += IdentDifference::Single(base); + if difference.is_complete() { + return (difference, base); + } + } + }, + (Some(_), None) | (None, Some(_)) => { + return (IdentDifference::NonIdent, base); + }, + (None, None) => { + return (difference, base); + }, + } + base += IdentLocation { index: 1 }; + } +} + +fn get_ident(expr: &Expr, location: IdentLocation) -> Option { + IdentIter::from(expr).nth(location.index) +} + +fn suggestion_with_swapped_ident( + cx: &EarlyContext<'_>, + expr: &Expr, + location: IdentLocation, + new_ident: Ident, + applicability: &mut Applicability, +) -> Option { + get_ident(expr, location).and_then(|current_ident| { + if eq_id(current_ident, new_ident) { + // We never want to suggest a non-change + return None; + } + + Some(format!( + "{}{}{}", + snippet_with_applicability(cx, expr.span.with_hi(current_ident.span.lo()), "..", applicability), + new_ident.to_string(), + snippet_with_applicability(cx, expr.span.with_lo(current_ident.span.hi()), "..", applicability), + )) + }) +} + +fn skip_index(iter: Iter, index: usize) -> impl Iterator +where + Iter: Iterator, +{ + iter.enumerate() + .filter_map(move |(i, a)| if i == index { None } else { Some(a) }) +} diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index d4acf8df46d..daff5f81e8c 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -168,8 +168,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { if_chain! { if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; if !in_macro(bound_predicate.span); - if let TyKind::Path(ref path) = bound_predicate.bounded_ty.kind; - if let QPath::Resolved(_, Path { ref segments, .. }) = path; + if let TyKind::Path(QPath::Resolved(_, Path { ref segments, .. })) = bound_predicate.bounded_ty.kind; if let Some(segment) = segments.first(); if let Some(trait_resolutions_direct) = map.get(&segment.ident); then { diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs index d60306336c6..6b171a0fa1a 100644 --- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs @@ -48,8 +48,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Path(ref _qpath) = args[0].kind; let x = const_eval_context.expr(&args[0]); - if let Some(constant) = x; - if let Constant::RawPtr(0) = constant; + if let Some(Constant::RawPtr(0)) = x; then { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG) } diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs index f0e10e374e1..74ba53e6a9a 100644 --- a/src/tools/clippy/clippy_lints/src/types.rs +++ b/src/tools/clippy/clippy_lints/src/types.rs @@ -8,6 +8,7 @@ use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{ BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId, @@ -737,8 +738,7 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool { fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option> { if_chain! { if let Some(did) = qpath_res(cx, qpath, id).opt_def_id(); - if let Some(node) = cx.tcx.hir().get_if_local(did); - if let Node::GenericParam(generic_param) = node; + if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; if synthetic == Some(SyntheticTyParamKind::ImplTrait); then { @@ -1469,8 +1469,7 @@ fn check_loss_of_sign(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast // don't lint for positive constants let const_val = constant(cx, &cx.typeck_results(), op); if_chain! { - if let Some((const_val, _)) = const_val; - if let Constant::Int(n) = const_val; + if let Some((Constant::Int(n), _)) = const_val; if let ty::Int(ity) = *cast_from.kind(); if sext(cx.tcx, n, ity) >= 0; then { @@ -1632,7 +1631,14 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } - if let ExprKind::Cast(ref ex, _) = expr.kind { + if let ExprKind::Cast(ref ex, cast_to) = expr.kind { + if let TyKind::Path(QPath::Resolved(_, path)) = cast_to.kind { + if let Res::Def(_, def_id) = path.res { + if cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr) { + return; + } + } + } let (cast_from, cast_to) = (cx.typeck_results().expr_ty(ex), cx.typeck_results().expr_ty(expr)); lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to); if let Some(lit) = get_numeric_literal(ex) { @@ -1711,7 +1717,7 @@ fn show_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &st expr.span, &format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to), "try", - format!("{}_{}", literal_str, cast_to), + format!("{}_{}", literal_str.trim_end_matches('.'), cast_to), Applicability::MachineApplicable, ); } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 25ecc7a82f1..5d801511a0b 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -1,5 +1,5 @@ use crate::utils::{ - in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then, + contains_return, in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then, visitors::find_all_ret_expressions, }; use if_chain::if_chain; @@ -95,6 +95,7 @@ fn check_fn( if let ExprKind::Path(ref qpath) = func.kind; if match_qpath(qpath, path); if args.len() == 1; + if !contains_return(&args[0]); then { suggs.push((ret_expr.span, snippet(cx, args[0].span.source_callsite(), "..").to_string())); true @@ -134,7 +135,7 @@ fn check_fn( diag.multipart_suggestion( "...and change the returning expressions", suggs, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs index fcf7a4b1367..31b4e25411b 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs @@ -10,6 +10,17 @@ use rustc_span::symbol::Ident; use std::mem; +pub mod ident_iter; +pub use ident_iter::IdentIter; + +pub fn is_useless_with_eq_exprs(kind: BinOpKind) -> bool { + use BinOpKind::*; + matches!( + kind, + Sub | Div | Eq | Lt | Le | Gt | Ge | Ne | And | Or | BitXor | BitAnd | BitOr + ) +} + /// Checks if each element in the first slice is contained within the latter as per `eq_fn`. pub fn unordered_over(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { left.len() == right.len() && left.iter().all(|l| right.iter().any(|r| eq_fn(l, r))) diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs new file mode 100644 index 00000000000..eefcbabd835 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs @@ -0,0 +1,45 @@ +use core::iter::FusedIterator; +use rustc_ast::visit::{walk_attribute, walk_expr, Visitor}; +use rustc_ast::{Attribute, Expr}; +use rustc_span::symbol::Ident; + +pub struct IdentIter(std::vec::IntoIter); + +impl Iterator for IdentIter { + type Item = Ident; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl FusedIterator for IdentIter {} + +impl From<&Expr> for IdentIter { + fn from(expr: &Expr) -> Self { + let mut visitor = IdentCollector::default(); + + walk_expr(&mut visitor, expr); + + IdentIter(visitor.0.into_iter()) + } +} + +impl From<&Attribute> for IdentIter { + fn from(attr: &Attribute) -> Self { + let mut visitor = IdentCollector::default(); + + walk_attribute(&mut visitor, attr); + + IdentIter(visitor.0.into_iter()) + } +} + +#[derive(Default)] +struct IdentCollector(Vec); + +impl Visitor<'_> for IdentCollector { + fn visit_ident(&mut self, ident: Ident) { + self.0.push(ident); + } +} diff --git a/src/tools/clippy/clippy_lints/src/utils/attrs.rs b/src/tools/clippy/clippy_lints/src/utils/attrs.rs index e6d41341a55..24052a243af 100644 --- a/src/tools/clippy/clippy_lints/src/utils/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/utils/attrs.rs @@ -21,6 +21,7 @@ pub enum DeprecationStatus { DeprecationStatus::Replaced("cognitive_complexity"), ), ("dump", DeprecationStatus::None), + ("msrv", DeprecationStatus::None), ]; pub struct LimitStack { @@ -123,6 +124,24 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' } } +pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option { + let mut unique_attr = None; + for attr in get_attr(sess, attrs, name) { + match attr.style { + ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()), + ast::AttrStyle::Inner => { + sess.struct_span_err(attr.span, &format!("`{}` is defined multiple times", name)) + .span_note(unique_attr.as_ref().unwrap().span, "first definition found here") + .emit(); + }, + ast::AttrStyle::Outer => { + sess.span_err(attr.span, &format!("`{}` cannot be an outer attribute", name)); + }, + } + } + unique_attr +} + /// Return true if the attributes contain any of `proc_macro`, /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 0ac8fff69f0..6403ff6dad1 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -106,6 +106,8 @@ fn $config() -> $Ty { pub use self::helpers::Conf; define_Conf! { + /// Lint: MANUAL_NON_EXHAUSTIVE, MANUAL_STRIP, OPTION_AS_REF_DEREF, MATCH_LIKE_MATCHES_MACRO. The minimum rust version that the project supports + (msrv, "msrv": Option, None), /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses (blacklisted_names, "blacklisted_names": Vec, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have @@ -168,6 +170,8 @@ fn $config() -> $Ty { (warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false), /// Lint: DISALLOWED_METHOD. The list of blacklisted methods to lint about. NB: `bar` is not here since it has legitimate uses (disallowed_methods, "disallowed_methods": Vec, Vec::::new()), + /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators. + (unreadable_literal_lint_fractions, "unreadable_literal_lint_fractions": bool, true), } impl Default for Conf { diff --git a/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs b/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs index 0a58231558e..a7a6b5855b7 100644 --- a/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs +++ b/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs @@ -186,7 +186,9 @@ pub fn span_lint_hir_and_then( /// | /// = note: `-D fold-any` implied by `-D warnings` /// ``` -#[allow(clippy::collapsible_span_lint_calls)] + +#[allow(clippy::unknown_clippy_lints)] +#[cfg_attr(feature = "internal-lints", allow(clippy::collapsible_span_lint_calls))] pub fn span_lint_and_sugg<'a, T: LintContext>( cx: &'a T, lint: &'static Lint, diff --git a/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs index 6d7c5058b4f..01ffac5b559 100644 --- a/src/tools/clippy/clippy_lints/src/utils/higher.rs +++ b/src/tools/clippy/clippy_lints/src/utils/higher.rs @@ -162,8 +162,7 @@ pub fn while_loop<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx hir::Expr< if let hir::Block { expr: Some(expr), .. } = &**block; if let hir::ExprKind::Match(cond, arms, hir::MatchSource::WhileDesugar) = &expr.kind; if let hir::ExprKind::DropTemps(cond) = &cond.kind; - if let [arm, ..] = &arms[..]; - if let hir::Arm { body, .. } = arm; + if let [hir::Arm { body, .. }, ..] = &arms[..]; then { return Some((cond, body)); } diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs index e4ad105c351..d942d4e12b1 100644 --- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs @@ -81,7 +81,7 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { } } - match (&left.kind, &right.kind) { + match (&reduce_exprkind(&left.kind), &reduce_exprkind(&right.kind)) { (&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => { lb == rb && l_mut == r_mut && self.eq_expr(le, re) }, @@ -306,6 +306,32 @@ fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) - } } +/// Some simple reductions like `{ return }` => `return` +fn reduce_exprkind<'hir>(kind: &'hir ExprKind<'hir>) -> &ExprKind<'hir> { + if let ExprKind::Block(block, _) = kind { + match (block.stmts, block.expr) { + // `{}` => `()` + ([], None) => &ExprKind::Tup(&[]), + ([], Some(expr)) => match expr.kind { + // `{ return .. }` => `return ..` + ExprKind::Ret(..) => &expr.kind, + _ => kind, + }, + ([stmt], None) => match stmt.kind { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => match expr.kind { + // `{ return ..; }` => `return ..` + ExprKind::Ret(..) => &expr.kind, + _ => kind, + }, + _ => kind, + }, + _ => kind, + } + } else { + kind + } +} + fn swap_binop<'a>( binop: BinOpKind, lhs: &'a Expr<'a>, @@ -491,7 +517,7 @@ pub fn hash_expr(&mut self, e: &Expr<'_>) { } } asm.options.hash(&mut self.s); - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { InlineAsmOperand::In { reg, expr } => { reg.hash(&mut self.s); diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 8f0ef9150d4..323d8745538 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -293,7 +293,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}template: {}", ind, InlineAsmTemplatePiece::to_string(asm.template)); println!("{}options: {:?}", ind, asm.options); println!("{}operands:", ind); - for op in asm.operands { + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::InOut { expr, .. } diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index e9c71e23a67..3a6b64c90e8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -14,6 +14,7 @@ pub mod higher; mod hir_utils; pub mod inspector; +#[cfg(feature = "internal-lints")] pub mod internal_lints; pub mod numeric_literal; pub mod paths; @@ -51,6 +52,8 @@ use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable}; +use rustc_semver::RustcVersion; +use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::sym as rustc_sym; @@ -62,6 +65,49 @@ use crate::consts::{constant, Constant}; +pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { + if let Ok(version) = RustcVersion::parse(msrv) { + return Some(version); + } else if let Some(sess) = sess { + if let Some(span) = span { + sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv)); + } + } + None +} + +pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool { + msrv.map_or(true, |msrv| msrv.meets(*lint_msrv)) +} + +macro_rules! extract_msrv_attr { + (LateContext) => { + extract_msrv_attr!(@LateContext, ()); + }; + (EarlyContext) => { + extract_msrv_attr!(@EarlyContext); + }; + (@$context:ident$(, $call:tt)?) => { + fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) { + use $crate::utils::get_unique_inner_attr; + match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") { + Some(msrv_attr) => { + if let Some(msrv) = msrv_attr.value_str() { + self.msrv = $crate::utils::parse_msrv( + &msrv.to_string(), + Some(cx.sess$($call)?), + Some(msrv_attr.span), + ); + } else { + cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute"); + } + }, + _ => (), + } + } + }; +} + /// Returns `true` if the two spans come from differing expansions (i.e., one is /// from a macro and one isn't). #[must_use] @@ -527,6 +573,36 @@ pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool { cn.result } +/// Returns `true` if `expr` contains a return expression +pub fn contains_return(expr: &hir::Expr<'_>) -> bool { + struct RetCallFinder { + found: bool, + } + + impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + if self.found { + return; + } + if let hir::ExprKind::Ret(..) = &expr.kind { + self.found = true; + } else { + hir::intravisit::walk_expr(self, expr); + } + } + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + } + + let mut visitor = RetCallFinder { found: false }; + visitor.visit_expr(expr); + visitor.found +} + /// Converts a span to a code snippet if available, otherwise use default. /// /// This is useful if you want to provide suggestions for your lint or more generally, if you want diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index 137f5d18b66..6fdc7b4587f 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -20,6 +20,8 @@ pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; +pub const COPY: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"]; +pub const COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; @@ -31,6 +33,7 @@ pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; +#[cfg(feature = "internal-lints")] pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; @@ -58,9 +61,13 @@ pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; +pub const IPADDR_V4: [&str; 4] = ["std", "net", "IpAddr", "V4"]; +pub const IPADDR_V6: [&str; 4] = ["std", "net", "IpAddr", "V6"]; pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"]; +#[cfg(feature = "internal-lints")] pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; +#[cfg(feature = "internal-lints")] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; @@ -68,6 +75,8 @@ pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"]; pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; +pub const MEM_SIZE_OF: [&str; 3] = ["core", "mem", "size_of"]; +pub const MEM_SIZE_OF_VAL: [&str; 3] = ["core", "mem", "size_of_val"]; pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"]; pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OPS_MODULE: [&str; 2] = ["core", "ops"]; @@ -90,9 +99,14 @@ pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; +pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"]; +pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"]; pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"]; +pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"]; +pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"]; +pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; @@ -114,6 +128,8 @@ pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; +pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; +pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; @@ -129,6 +145,7 @@ pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"]; pub const STR_LEN: [&str; 4] = ["core", "str", "", "len"]; pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "", "starts_with"]; +#[cfg(feature = "internal-lints")] pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"]; pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"]; @@ -146,3 +163,4 @@ pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; +pub const WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"]; diff --git a/src/tools/clippy/clippy_lints/src/utils/visitors.rs b/src/tools/clippy/clippy_lints/src/utils/visitors.rs index b0837b6c43e..28b3e79d7a6 100644 --- a/src/tools/clippy/clippy_lints/src/utils/visitors.rs +++ b/src/tools/clippy/clippy_lints/src/utils/visitors.rs @@ -1,5 +1,7 @@ use rustc_hir as hir; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::def::Res; +use rustc_hir::intravisit::{self, walk_expr, NestedVisitorMap, Visitor}; +use rustc_hir::{Arm, Expr, ExprKind, HirId, QPath, Stmt}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; @@ -123,3 +125,54 @@ fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) { !ret_finder.failed } } + +pub struct LocalUsedVisitor { + pub local_hir_id: HirId, + pub used: bool, +} + +impl LocalUsedVisitor { + pub fn new(local_hir_id: HirId) -> Self { + Self { + local_hir_id, + used: false, + } + } + + fn check(&mut self, t: T, visit: fn(&mut Self, T)) -> bool { + visit(self, t); + std::mem::replace(&mut self.used, false) + } + + pub fn check_arm(&mut self, arm: &Arm<'_>) -> bool { + self.check(arm, Self::visit_arm) + } + + pub fn check_expr(&mut self, expr: &Expr<'_>) -> bool { + self.check(expr, Self::visit_expr) + } + + pub fn check_stmt(&mut self, stmt: &Stmt<'_>) -> bool { + self.check(stmt, Self::visit_stmt) + } +} + +impl<'v> Visitor<'v> for LocalUsedVisitor { + type Map = Map<'v>; + + fn visit_expr(&mut self, expr: &'v Expr<'v>) { + if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind { + if let Res::Local(id) = path.res { + if id == self.local_hir_id { + self.used = true; + return; + } + } + } + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } +} diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 0e8f7683103..ec3af94b9ca 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -12,6 +12,9 @@ mod cargo; +// whether to run internal tests or not +const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal-lints"); + fn host_lib() -> PathBuf { option_env!("HOST_LIBS").map_or(cargo::CARGO_TARGET_DIR.join(env!("PROFILE")), PathBuf::from) } @@ -96,6 +99,16 @@ fn run_mode(cfg: &mut compiletest::Config) { compiletest::run_tests(&cfg); } +fn run_internal_tests(cfg: &mut compiletest::Config) { + // only run internal tests with the internal-tests feature + if !RUN_INTERNAL_TESTS { + return; + } + cfg.mode = TestMode::Ui; + cfg.src_base = Path::new("tests").join("ui-internal"); + compiletest::run_tests(&cfg); +} + fn run_ui_toml(config: &mut compiletest::Config) { fn run_tests(config: &compiletest::Config, mut tests: Vec) -> Result { let mut result = true; @@ -199,7 +212,6 @@ fn run_tests( Some("main.rs") => {}, _ => continue, } - let paths = compiletest::common::TestPaths { file: file_path, base: config.src_base.clone(), @@ -253,4 +265,5 @@ fn compile_test() { run_mode(&mut config); run_ui_toml(&mut config); run_ui_cargo(&mut config); + run_internal_tests(&mut config); } diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs index 48e0478f169..a6163a83d76 100644 --- a/src/tools/clippy/tests/dogfood.rs +++ b/src/tools/clippy/tests/dogfood.rs @@ -18,7 +18,8 @@ fn dogfood_clippy() { } let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let output = Command::new(&*CLIPPY_PATH) + let mut command = Command::new(&*CLIPPY_PATH); + command .current_dir(root_dir) .env("CLIPPY_DOGFOOD", "1") .env("CARGO_INCREMENTAL", "0") @@ -27,11 +28,16 @@ fn dogfood_clippy() { .arg("--all-features") .arg("--") .args(&["-D", "clippy::all"]) - .args(&["-D", "clippy::internal"]) .args(&["-D", "clippy::pedantic"]) - .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir - .output() - .unwrap(); + .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir + + // internal lints only exist if we build with the internal-lints feature + if cfg!(feature = "internal-lints") { + command.args(&["-D", "clippy::internal"]); + } + + let output = command.output().unwrap(); + println!("status: {}", output.status); println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); 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 new file mode 100644 index 00000000000..e588c23345e --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -0,0 +1,91 @@ +// run-rustfix +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_errors; +extern crate rustc_lint; +extern crate rustc_session; +extern crate rustc_span; + +use rustc_ast::ast::Expr; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; + +#[allow(unused_variables)] +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) +where + F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), +{ +} + +#[allow(unused_variables)] +fn span_lint_and_help<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + option_span: Option, + help: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_note<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + note_span: Option, + note: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_sugg<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + sp: Span, + msg: &str, + help: &str, + sugg: String, + applicability: Applicability, +) { +} + +declare_tool_lint! { + pub clippy::TEST_LINT, + Warn, + "", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl EarlyLintPass for Pass { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + let lint_msg = "lint message"; + let help_msg = "help message"; + let note_msg = "note message"; + let sugg = "new_call()"; + let predicate = true; + + span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg); + + // This expr shouldn't trigger this lint. + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.note(note_msg); + if predicate { + db.note(note_msg); + } + }) + } +} + +fn main() {} 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 new file mode 100644 index 00000000000..d5dd3bb562b --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -0,0 +1,101 @@ +// run-rustfix +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_errors; +extern crate rustc_lint; +extern crate rustc_session; +extern crate rustc_span; + +use rustc_ast::ast::Expr; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; + +#[allow(unused_variables)] +pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) +where + F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), +{ +} + +#[allow(unused_variables)] +fn span_lint_and_help<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + option_span: Option, + help: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_note<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + note_span: Option, + note: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_sugg<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + sp: Span, + msg: &str, + help: &str, + sugg: String, + applicability: Applicability, +) { +} + +declare_tool_lint! { + pub clippy::TEST_LINT, + Warn, + "", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl EarlyLintPass for Pass { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + let lint_msg = "lint message"; + let help_msg = "help message"; + let note_msg = "note message"; + let sugg = "new_call()"; + let predicate = true; + + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.span_help(expr.span, help_msg); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.help(help_msg); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.span_note(expr.span, note_msg); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.note(note_msg); + }); + + // This expr shouldn't trigger this lint. + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.note(note_msg); + if predicate { + db.note(note_msg); + } + }) + } +} + +fn main() {} 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 new file mode 100644 index 00000000000..874d4a9f255 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -0,0 +1,49 @@ +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:75:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)` + | +note: the lint level is defined here + --> $DIR/collapsible_span_lint_calls.rs:2:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` + +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:78:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.span_help(expr.span, help_msg); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` + +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:81:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.help(help_msg); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` + +error: this call is collspible + --> $DIR/collapsible_span_lint_calls.rs:84:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.span_note(expr.span, note_msg); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` + +error: this call is collspible + --> $DIR/collapsible_span_lint_calls.rs:87:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +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 + diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs new file mode 100644 index 00000000000..5b30c9d5721 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs @@ -0,0 +1,10 @@ +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" +// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs" +// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" + +#![deny(clippy::internal)] + +fn it_looks_like_you_are_trying_to_kill_clippy() {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr new file mode 100644 index 00000000000..a1b8e2ee162 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr @@ -0,0 +1,13 @@ +thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new + +note: Clippy version: foo + +query stack during panic: +end of query stack diff --git a/src/tools/clippy/tests/ui-internal/default_lint.rs b/src/tools/clippy/tests/ui-internal/default_lint.rs new file mode 100644 index 00000000000..053faae02ce --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/default_lint.rs @@ -0,0 +1,27 @@ +#![deny(clippy::internal)] +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +extern crate rustc_lint; + +declare_tool_lint! { + pub clippy::TEST_LINT, + Warn, + "", + report_in_external_macro: true +} + +declare_tool_lint! { + pub clippy::TEST_LINT_DEFAULT, + Warn, + "default lint description", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [TEST_LINT]); +declare_lint_pass!(Pass2 => [TEST_LINT_DEFAULT]); + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr new file mode 100644 index 00000000000..5c5836a7d29 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/default_lint.stderr @@ -0,0 +1,21 @@ +error: the lint `TEST_LINT_DEFAULT` has the default lint description + --> $DIR/default_lint.rs:17:1 + | +LL | / declare_tool_lint! { +LL | | pub clippy::TEST_LINT_DEFAULT, +LL | | Warn, +LL | | "default lint description", +LL | | report_in_external_macro: true +LL | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/default_lint.rs:1:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.rs b/src/tools/clippy/tests/ui-internal/invalid_paths.rs new file mode 100644 index 00000000000..01e28ae5e9d --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/invalid_paths.rs @@ -0,0 +1,23 @@ +#![warn(clippy::internal)] + +mod paths { + // Good path + pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; + + // Path to method on inherent impl of a primitive type + pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; + + // Path to method on inherent impl + pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; + + // Path with empty segment + pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; + + // Path with bad crate + pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; + + // Path with bad module + pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr new file mode 100644 index 00000000000..bd69d661b71 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr @@ -0,0 +1,16 @@ +error: invalid path + --> $DIR/invalid_paths.rs:17:5 + | +LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::clippy-lints-internal` implied by `-D warnings` + +error: invalid path + --> $DIR/invalid_paths.rs:20:5 + | +LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs new file mode 100644 index 00000000000..beaef79a340 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs @@ -0,0 +1,44 @@ +#![deny(clippy::internal)] +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +extern crate rustc_lint; +use rustc_lint::LintPass; + +declare_tool_lint! { + pub clippy::TEST_LINT, + Warn, + "", + report_in_external_macro: true +} + +declare_tool_lint! { + pub clippy::TEST_LINT_REGISTERED, + Warn, + "", + report_in_external_macro: true +} + +declare_tool_lint! { + pub clippy::TEST_LINT_REGISTERED_ONLY_IMPL, + Warn, + "", + report_in_external_macro: true +} + +pub struct Pass; +impl LintPass for Pass { + fn name(&self) -> &'static str { + "TEST_LINT" + } +} + +declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]); + +pub struct Pass3; +impl_lint_pass!(Pass3 => [TEST_LINT_REGISTERED_ONLY_IMPL]); + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr new file mode 100644 index 00000000000..1257dae96d7 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr @@ -0,0 +1,21 @@ +error: the lint `TEST_LINT` is not added to any `LintPass` + --> $DIR/lint_without_lint_pass.rs:11:1 + | +LL | / declare_tool_lint! { +LL | | pub clippy::TEST_LINT, +LL | | Warn, +LL | | "", +LL | | report_in_external_macro: true +LL | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/lint_without_lint_pass.rs:1:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs new file mode 100644 index 00000000000..fe950b0aa7c --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs @@ -0,0 +1,50 @@ +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +use rustc_hir::Expr; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; + +mod paths { + pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; +} + +mod utils { + use super::*; + + pub fn match_type(_cx: &LateContext<'_>, _ty: Ty<'_>, _path: &[&str]) -> bool { + false + } +} + +use utils::match_type; + +declare_lint! { + pub TEST_LINT, + Warn, + "" +} + +declare_lint_pass!(Pass => [TEST_LINT]); + +static OPTION: [&str; 3] = ["core", "option", "Option"]; + +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) { + let ty = cx.typeck_results().expr_ty(expr); + + let _ = match_type(cx, ty, &paths::VEC); + let _ = match_type(cx, ty, &OPTION); + let _ = match_type(cx, ty, &["core", "result", "Result"]); + + let rc_path = &["alloc", "rc", "Rc"]; + let _ = utils::match_type(cx, ty, rc_path); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr new file mode 100644 index 00000000000..82465dbaf6e --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr @@ -0,0 +1,33 @@ +error: usage of `utils::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:41:17 + | +LL | let _ = match_type(cx, ty, &paths::VEC); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::vec_type)` + | +note: the lint level is defined here + --> $DIR/match_type_on_diag_item.rs:1:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]` + +error: usage of `utils::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:42:17 + | +LL | let _ = match_type(cx, ty, &OPTION); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::option_type)` + +error: usage of `utils::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:43:17 + | +LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::result_type)` + +error: usage of `utils::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:46:17 + | +LL | let _ = utils::match_type(cx, ty, rc_path); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::Rc)` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed new file mode 100644 index 00000000000..b0b3498f057 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed @@ -0,0 +1,28 @@ +// run-rustfix + +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +use rustc_hir::Expr; +use rustc_lint::{LateContext, LateLintPass}; + +declare_lint! { + pub TEST_LINT, + Warn, + "" +} + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { + let _ = expr.span.ctxt().outer_expn_data(); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs new file mode 100644 index 00000000000..55a3fed00d0 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs @@ -0,0 +1,28 @@ +// run-rustfix + +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +use rustc_hir::Expr; +use rustc_lint::{LateContext, LateLintPass}; + +declare_lint! { + pub TEST_LINT, + Warn, + "" +} + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { + let _ = expr.span.ctxt().outer_expn().expn_data(); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr new file mode 100644 index 00000000000..56b6ce1f78e --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr @@ -0,0 +1,15 @@ +error: usage of `outer_expn().expn_data()` + --> $DIR/outer_expn_data.rs:24:34 + | +LL | let _ = expr.span.ctxt().outer_expn().expn_data(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()` + | +note: the lint level is defined here + --> $DIR/outer_expn_data.rs:3:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml new file mode 100644 index 00000000000..088b12b2dac --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml @@ -0,0 +1 @@ +msrv = "invalid.version" diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs new file mode 100644 index 00000000000..2ebf28645e5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs @@ -0,0 +1,3 @@ +#![allow(clippy::redundant_clone)] + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr new file mode 100644 index 00000000000..e9d8fd2e0f5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file. `invalid.version` is not a valid Rust version + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml new file mode 100644 index 00000000000..6feaf7d5c0c --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml @@ -0,0 +1 @@ +unreadable-literal-lint-fractions = false \ No newline at end of file diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs new file mode 100644 index 00000000000..9377eb69b23 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs @@ -0,0 +1,22 @@ +#[deny(clippy::unreadable_literal)] + +fn allow_inconsistent_digit_grouping() { + #![allow(clippy::inconsistent_digit_grouping)] + let _pass1 = 100_200_300.123456789; +} + +fn main() { + allow_inconsistent_digit_grouping(); + + let _pass1 = 100_200_300.100_200_300; + let _pass2 = 1.123456789; + let _pass3 = 1.0; + let _pass4 = 10000.00001; + let _pass5 = 1.123456789e1; + + // due to clippy::inconsistent-digit-grouping + let _fail1 = 100_200_300.123456789; + + // fail due to the integer part + let _fail2 = 100200300.300200100; +} diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr new file mode 100644 index 00000000000..9119ef19a7b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr @@ -0,0 +1,10 @@ +error: digits grouped inconsistently by underscores + --> $DIR/test.rs:18:18 + | +LL | let _fail1 = 100_200_300.123456789; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789` + | + = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml b/src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml new file mode 100644 index 00000000000..8e17d8074c4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml @@ -0,0 +1 @@ +msrv = "1.0.0" diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs new file mode 100644 index 00000000000..bc41efa42a1 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -0,0 +1,68 @@ +#![allow(clippy::redundant_clone)] +#![warn(clippy::manual_non_exhaustive)] + +use std::ops::Deref; + +mod enums { + enum E { + A, + B, + #[doc(hidden)] + _C, + } + + // user forgot to remove the marker + #[non_exhaustive] + enum Ep { + A, + B, + #[doc(hidden)] + _C, + } +} + +fn option_as_ref_deref() { + let mut opt = Some(String::from("123")); + + let _ = opt.as_ref().map(String::as_str); + let _ = opt.as_ref().map(|x| x.as_str()); + let _ = opt.as_mut().map(String::as_mut_str); + let _ = opt.as_mut().map(|x| x.as_mut_str()); +} + +fn match_like_matches() { + let _y = match Some(5) { + Some(0) => true, + _ => false, + }; +} + +fn match_same_arms() { + match (1, 2, 3) { + (1, .., 3) => 42, + (.., 3) => 42, //~ ERROR match arms have same body + _ => 0, + }; +} + +fn match_same_arms2() { + let _ = match Some(42) { + Some(_) => 24, + None => 24, //~ ERROR match arms have same body + }; +} + +fn manual_strip_msrv() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } +} + +fn main() { + option_as_ref_deref(); + match_like_matches(); + match_same_arms(); + match_same_arms2(); + manual_strip_msrv(); +} diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index a58e7e918e2..7b3c476461d 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1 +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/as_conversions.rs b/src/tools/clippy/tests/ui/as_conversions.rs index e01ba0c64df..cd745feec6d 100644 --- a/src/tools/clippy/tests/ui/as_conversions.rs +++ b/src/tools/clippy/tests/ui/as_conversions.rs @@ -1,7 +1,19 @@ -#[warn(clippy::as_conversions)] +// aux-build:macro_rules.rs + +#![warn(clippy::as_conversions)] + +#[macro_use] +extern crate macro_rules; + +fn with_external_macro() { + as_conv_with_arg!(0u32 as u64); + as_conv!(); +} fn main() { let i = 0u32 as u64; let j = &i as *const u64 as *mut u64; + + with_external_macro(); } diff --git a/src/tools/clippy/tests/ui/as_conversions.stderr b/src/tools/clippy/tests/ui/as_conversions.stderr index 312d3a7460e..f5f75d3aee0 100644 --- a/src/tools/clippy/tests/ui/as_conversions.stderr +++ b/src/tools/clippy/tests/ui/as_conversions.stderr @@ -1,5 +1,5 @@ error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:4:13 + --> $DIR/as_conversions.rs:14:13 | LL | let i = 0u32 as u64; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let i = 0u32 as u64; = help: consider using a safe wrapper for this conversion error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:6:13 + --> $DIR/as_conversions.rs:16:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64; = help: consider using a safe wrapper for this conversion error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:6:13 + --> $DIR/as_conversions.rs:16:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs index 93303865e17..f985a15eda2 100644 --- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs +++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs @@ -70,3 +70,17 @@ macro_rules! ref_arg_function { fn fun_example(ref _x: usize) {} }; } + +#[macro_export] +macro_rules! as_conv_with_arg { + (0u32 as u64) => { + () + }; +} + +#[macro_export] +macro_rules! as_conv { + () => { + 0u32 as u64 + }; +} diff --git a/src/tools/clippy/tests/ui/collapsible_match.rs b/src/tools/clippy/tests/ui/collapsible_match.rs new file mode 100644 index 00000000000..a83e6c77b12 --- /dev/null +++ b/src/tools/clippy/tests/ui/collapsible_match.rs @@ -0,0 +1,239 @@ +#![warn(clippy::collapsible_match)] +#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)] + +fn lint_cases(opt_opt: Option>, res_opt: Result, String>) { + // match without block + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + _ => return, + }, + _ => return, + } + + // match with block + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + _ => return, + }, + _ => return, + } + + // if let, if let + if let Ok(val) = res_opt { + if let Some(n) = val { + take(n); + } + } + + // if let else, if let else + if let Ok(val) = res_opt { + if let Some(n) = val { + take(n); + } else { + return; + } + } else { + return; + } + + // if let, match + if let Ok(val) = res_opt { + match val { + Some(n) => foo(n), + _ => (), + } + } + + // match, if let + match res_opt { + Ok(val) => { + if let Some(n) = val { + take(n); + } + }, + _ => {}, + } + + // if let else, match + if let Ok(val) = res_opt { + match val { + Some(n) => foo(n), + _ => return, + } + } else { + return; + } + + // match, if let else + match res_opt { + Ok(val) => { + if let Some(n) = val { + take(n); + } else { + return; + } + }, + _ => return, + } + + // None in inner match same as outer wild branch + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + None => return, + }, + _ => return, + } + + // None in outer match same as inner wild branch + match opt_opt { + Some(val) => match val { + Some(n) => foo(n), + _ => return, + }, + None => return, + } +} + +fn negative_cases(res_opt: Result, String>, res_res: Result, String>) { + // no wild pattern in outer match + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + _ => return, + }, + Err(_) => return, + } + + // inner branch is not wild or None + match res_res { + Ok(val) => match val { + Ok(n) => foo(n), + Err(_) => return, + }, + _ => return, + } + + // statement before inner match + match res_opt { + Ok(val) => { + "hi buddy"; + match val { + Some(n) => foo(n), + _ => return, + } + }, + _ => return, + } + + // statement after inner match + match res_opt { + Ok(val) => { + match val { + Some(n) => foo(n), + _ => return, + } + "hi buddy"; + }, + _ => return, + } + + // wild branches do not match + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + _ => { + "sup"; + return; + }, + }, + _ => return, + } + + // binding used in if guard + match res_opt { + Ok(val) if val.is_some() => match val { + Some(n) => foo(n), + _ => return, + }, + _ => return, + } + + // binding used in inner match body + match res_opt { + Ok(val) => match val { + Some(_) => take(val), + _ => return, + }, + _ => return, + } + + // if guard on inner match + { + match res_opt { + Ok(val) => match val { + Some(n) if make() => foo(n), + _ => return, + }, + _ => return, + } + match res_opt { + Ok(val) => match val { + _ => make(), + _ if make() => return, + }, + _ => return, + } + } + + // differing macro contexts + { + macro_rules! mac { + ($val:ident) => { + match $val { + Some(n) => foo(n), + _ => return, + } + }; + } + match res_opt { + Ok(val) => mac!(val), + _ => return, + } + } + + // OR pattern + enum E { + A(T), + B(T), + C(T), + }; + match make::>>() { + E::A(val) | E::B(val) => match val { + Some(n) => foo(n), + _ => return, + }, + _ => return, + } + match make::>>() { + Some(val) => match val { + E::A(val) | E::B(val) => foo(val), + _ => return, + }, + _ => return, + } +} + +fn make() -> T { + unimplemented!() +} + +fn foo(t: T) -> U { + unimplemented!() +} + +fn take(t: T) {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr new file mode 100644 index 00000000000..63ac6a1613d --- /dev/null +++ b/src/tools/clippy/tests/ui/collapsible_match.stderr @@ -0,0 +1,179 @@ +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:7:20 + | +LL | Ok(val) => match val { + | ____________________^ +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | }, + | |_________^ + | + = note: `-D clippy::collapsible-match` implied by `-D warnings` +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:7:12 + | +LL | Ok(val) => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:16:20 + | +LL | Ok(val) => match val { + | ____________________^ +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | }, + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:16:12 + | +LL | Ok(val) => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:25:9 + | +LL | / if let Some(n) = val { +LL | | take(n); +LL | | } + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:24:15 + | +LL | if let Ok(val) = res_opt { + | ^^^ Replace this binding +LL | if let Some(n) = val { + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:32:9 + | +LL | / if let Some(n) = val { +LL | | take(n); +LL | | } else { +LL | | return; +LL | | } + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:31:15 + | +LL | if let Ok(val) = res_opt { + | ^^^ Replace this binding +LL | if let Some(n) = val { + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:43:9 + | +LL | / match val { +LL | | Some(n) => foo(n), +LL | | _ => (), +LL | | } + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:42:15 + | +LL | if let Ok(val) = res_opt { + | ^^^ Replace this binding +LL | match val { +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:52:13 + | +LL | / if let Some(n) = val { +LL | | take(n); +LL | | } + | |_____________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:51:12 + | +LL | Ok(val) => { + | ^^^ Replace this binding +LL | if let Some(n) = val { + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:61:9 + | +LL | / match val { +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | } + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:60:15 + | +LL | if let Ok(val) = res_opt { + | ^^^ Replace this binding +LL | match val { +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:72:13 + | +LL | / if let Some(n) = val { +LL | | take(n); +LL | | } else { +LL | | return; +LL | | } + | |_____________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:71:12 + | +LL | Ok(val) => { + | ^^^ Replace this binding +LL | if let Some(n) = val { + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:83:20 + | +LL | Ok(val) => match val { + | ____________________^ +LL | | Some(n) => foo(n), +LL | | None => return, +LL | | }, + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:83:12 + | +LL | Ok(val) => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match.rs:92:22 + | +LL | Some(val) => match val { + | ______________________^ +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | }, + | |_________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match.rs:92:14 + | +LL | Some(val) => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: aborting due to 10 previous errors + diff --git a/src/tools/clippy/tests/ui/collapsible_match2.rs b/src/tools/clippy/tests/ui/collapsible_match2.rs new file mode 100644 index 00000000000..d571ac4ab69 --- /dev/null +++ b/src/tools/clippy/tests/ui/collapsible_match2.rs @@ -0,0 +1,53 @@ +#![warn(clippy::collapsible_match)] +#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)] + +fn lint_cases(opt_opt: Option>, res_opt: Result, String>) { + // if guards on outer match + { + match res_opt { + Ok(val) if make() => match val { + Some(n) => foo(n), + _ => return, + }, + _ => return, + } + match res_opt { + Ok(val) => match val { + Some(n) => foo(n), + _ => return, + }, + _ if make() => return, + _ => return, + } + } + + // macro + { + macro_rules! mac { + ($outer:expr => $pat:pat, $e:expr => $inner_pat:pat, $then:expr) => { + match $outer { + $pat => match $e { + $inner_pat => $then, + _ => return, + }, + _ => return, + } + }; + } + // Lint this since the patterns are not defined by the macro. + // Allows the lint to work on if_chain! for example. + // Fixing the lint requires knowledge of the specific macro, but we optimistically assume that + // there is still a better way to write this. + mac!(res_opt => Ok(val), val => Some(n), foo(n)); + } +} + +fn make() -> T { + unimplemented!() +} + +fn foo(t: T) -> U { + unimplemented!() +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/collapsible_match2.stderr b/src/tools/clippy/tests/ui/collapsible_match2.stderr new file mode 100644 index 00000000000..490d82d12cd --- /dev/null +++ b/src/tools/clippy/tests/ui/collapsible_match2.stderr @@ -0,0 +1,61 @@ +error: Unnecessary nested match + --> $DIR/collapsible_match2.rs:8:34 + | +LL | Ok(val) if make() => match val { + | __________________________________^ +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | }, + | |_____________^ + | + = note: `-D clippy::collapsible-match` implied by `-D warnings` +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match2.rs:8:16 + | +LL | Ok(val) if make() => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match2.rs:15:24 + | +LL | Ok(val) => match val { + | ________________________^ +LL | | Some(n) => foo(n), +LL | | _ => return, +LL | | }, + | |_____________^ + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match2.rs:15:16 + | +LL | Ok(val) => match val { + | ^^^ Replace this binding +LL | Some(n) => foo(n), + | ^^^^^^^ with this pattern + +error: Unnecessary nested match + --> $DIR/collapsible_match2.rs:29:29 + | +LL | $pat => match $e { + | _____________________________^ +LL | | $inner_pat => $then, +LL | | _ => return, +LL | | }, + | |_____________________^ +... +LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); + | ------------------------------------------------- in this macro invocation + | +help: The outer pattern can be modified to include the inner pattern. + --> $DIR/collapsible_match2.rs:41:28 + | +LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); + | ^^^ ^^^^^^^ with this pattern + | | + | Replace this binding + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed deleted file mode 100644 index e588c23345e..00000000000 --- a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed +++ /dev/null @@ -1,91 +0,0 @@ -// run-rustfix -#![deny(clippy::internal)] -#![feature(rustc_private)] - -extern crate rustc_ast; -extern crate rustc_errors; -extern crate rustc_lint; -extern crate rustc_session; -extern crate rustc_span; - -use rustc_ast::ast::Expr; -use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -#[allow(unused_variables)] -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) -where - F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), -{ -} - -#[allow(unused_variables)] -fn span_lint_and_help<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - option_span: Option, - help: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_note<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - note_span: Option, - note: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_sugg<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - sp: Span, - msg: &str, - help: &str, - sugg: String, - applicability: Applicability, -) { -} - -declare_tool_lint! { - pub clippy::TEST_LINT, - Warn, - "", - report_in_external_macro: true -} - -declare_lint_pass!(Pass => [TEST_LINT]); - -impl EarlyLintPass for Pass { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - let lint_msg = "lint message"; - let help_msg = "help message"; - let note_msg = "note message"; - let sugg = "new_call()"; - let predicate = true; - - span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable); - span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg); - span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg); - span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg); - span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg); - - // This expr shouldn't trigger this lint. - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.note(note_msg); - if predicate { - db.note(note_msg); - } - }) - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs deleted file mode 100644 index d5dd3bb562b..00000000000 --- a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs +++ /dev/null @@ -1,101 +0,0 @@ -// run-rustfix -#![deny(clippy::internal)] -#![feature(rustc_private)] - -extern crate rustc_ast; -extern crate rustc_errors; -extern crate rustc_lint; -extern crate rustc_session; -extern crate rustc_span; - -use rustc_ast::ast::Expr; -use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -#[allow(unused_variables)] -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) -where - F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), -{ -} - -#[allow(unused_variables)] -fn span_lint_and_help<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - option_span: Option, - help: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_note<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - note_span: Option, - note: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_sugg<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - sp: Span, - msg: &str, - help: &str, - sugg: String, - applicability: Applicability, -) { -} - -declare_tool_lint! { - pub clippy::TEST_LINT, - Warn, - "", - report_in_external_macro: true -} - -declare_lint_pass!(Pass => [TEST_LINT]); - -impl EarlyLintPass for Pass { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { - let lint_msg = "lint message"; - let help_msg = "help message"; - let note_msg = "note message"; - let sugg = "new_call()"; - let predicate = true; - - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.span_help(expr.span, help_msg); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.help(help_msg); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.span_note(expr.span, note_msg); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.note(note_msg); - }); - - // This expr shouldn't trigger this lint. - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.note(note_msg); - if predicate { - db.note(note_msg); - } - }) - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr deleted file mode 100644 index 874d4a9f255..00000000000 --- a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:75:9 - | -LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { -LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); -LL | | }); - | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)` - | -note: the lint level is defined here - --> $DIR/collapsible_span_lint_calls.rs:2:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` - -error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:78:9 - | -LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { -LL | | db.span_help(expr.span, help_msg); -LL | | }); - | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` - -error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:81:9 - | -LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { -LL | | db.help(help_msg); -LL | | }); - | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` - -error: this call is collspible - --> $DIR/collapsible_span_lint_calls.rs:84:9 - | -LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { -LL | | db.span_note(expr.span, note_msg); -LL | | }); - | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` - -error: this call is collspible - --> $DIR/collapsible_span_lint_calls.rs:87:9 - | -LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { -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 - diff --git a/src/tools/clippy/tests/ui/custom_ice_message.rs b/src/tools/clippy/tests/ui/custom_ice_message.rs deleted file mode 100644 index 5b30c9d5721..00000000000 --- a/src/tools/clippy/tests/ui/custom_ice_message.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" -// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs" -// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" - -#![deny(clippy::internal)] - -fn it_looks_like_you_are_trying_to_kill_clippy() {} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/custom_ice_message.stderr b/src/tools/clippy/tests/ui/custom_ice_message.stderr deleted file mode 100644 index a1b8e2ee162..00000000000 --- a/src/tools/clippy/tests/ui/custom_ice_message.stderr +++ /dev/null @@ -1,13 +0,0 @@ -thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new - -note: Clippy version: foo - -query stack during panic: -end of query stack diff --git a/src/tools/clippy/tests/ui/default_lint.rs b/src/tools/clippy/tests/ui/default_lint.rs deleted file mode 100644 index 053faae02ce..00000000000 --- a/src/tools/clippy/tests/ui/default_lint.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![deny(clippy::internal)] -#![feature(rustc_private)] - -#[macro_use] -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -extern crate rustc_lint; - -declare_tool_lint! { - pub clippy::TEST_LINT, - Warn, - "", - report_in_external_macro: true -} - -declare_tool_lint! { - pub clippy::TEST_LINT_DEFAULT, - Warn, - "default lint description", - report_in_external_macro: true -} - -declare_lint_pass!(Pass => [TEST_LINT]); -declare_lint_pass!(Pass2 => [TEST_LINT_DEFAULT]); - -fn main() {} diff --git a/src/tools/clippy/tests/ui/default_lint.stderr b/src/tools/clippy/tests/ui/default_lint.stderr deleted file mode 100644 index 5c5836a7d29..00000000000 --- a/src/tools/clippy/tests/ui/default_lint.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: the lint `TEST_LINT_DEFAULT` has the default lint description - --> $DIR/default_lint.rs:17:1 - | -LL | / declare_tool_lint! { -LL | | pub clippy::TEST_LINT_DEFAULT, -LL | | Warn, -LL | | "default lint description", -LL | | report_in_external_macro: true -LL | | } - | |_^ - | -note: the lint level is defined here - --> $DIR/default_lint.rs:1:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index 4cbc5630d75..e1ee8dbca2c 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -1,5 +1,3 @@ -#[warn(clippy::str_to_string)] -#[warn(clippy::string_to_string)] #[warn(clippy::unstable_as_slice)] #[warn(clippy::unstable_as_mut_slice)] #[warn(clippy::misaligned_transmute)] diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index a348d01d734..edbb891afe0 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -1,88 +1,76 @@ -error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:1:8 - | -LL | #[warn(clippy::str_to_string)] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D renamed-and-removed-lints` implied by `-D warnings` - -error: lint `clippy::string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated.rs:2:8 - | -LL | #[warn(clippy::string_to_string)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:3:8 + --> $DIR/deprecated.rs:1:8 | LL | #[warn(clippy::unstable_as_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` - --> $DIR/deprecated.rs:4:8 + --> $DIR/deprecated.rs:2:8 | LL | #[warn(clippy::unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` - --> $DIR/deprecated.rs:5:8 + --> $DIR/deprecated.rs:3:8 | LL | #[warn(clippy::misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::unused_collect` has been removed: ``collect` has been marked as #[must_use] in rustc and that covers all cases of this lint` - --> $DIR/deprecated.rs:6:8 + --> $DIR/deprecated.rs:4:8 | LL | #[warn(clippy::unused_collect)] | ^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::invalid_ref` has been removed: `superseded by rustc lint `invalid_value`` - --> $DIR/deprecated.rs:7:8 + --> $DIR/deprecated.rs:5:8 | LL | #[warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ error: lint `clippy::into_iter_on_array` has been removed: `this lint has been uplifted to rustc and is now called `array_into_iter`` - --> $DIR/deprecated.rs:8:8 + --> $DIR/deprecated.rs:6:8 | LL | #[warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::unused_label` has been removed: `this lint has been uplifted to rustc and is now called `unused_labels`` - --> $DIR/deprecated.rs:9:8 + --> $DIR/deprecated.rs:7:8 | LL | #[warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::regex_macro` has been removed: `the regex! macro has been removed from the regex crate in 2018` - --> $DIR/deprecated.rs:10:8 + --> $DIR/deprecated.rs:8:8 | LL | #[warn(clippy::regex_macro)] | ^^^^^^^^^^^^^^^^^^^ error: lint `clippy::drop_bounds` has been removed: `this lint has been uplifted to rustc and is now called `drop_bounds`` - --> $DIR/deprecated.rs:11:8 + --> $DIR/deprecated.rs:9:8 | LL | #[warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ error: lint `clippy::temporary_cstring_as_ptr` has been removed: `this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr`` - --> $DIR/deprecated.rs:12:8 + --> $DIR/deprecated.rs:10:8 | LL | #[warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::panic_params` has been removed: `this lint has been uplifted to rustc and is now called `panic_fmt`` - --> $DIR/deprecated.rs:13:8 + --> $DIR/deprecated.rs:11:8 | LL | #[warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` +error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` --> $DIR/deprecated.rs:1:8 | -LL | #[warn(clippy::str_to_string)] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[warn(clippy::unstable_as_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/deprecated_old.rs b/src/tools/clippy/tests/ui/deprecated_old.rs index 2e5c5b7ead1..e89dca4fcfd 100644 --- a/src/tools/clippy/tests/ui/deprecated_old.rs +++ b/src/tools/clippy/tests/ui/deprecated_old.rs @@ -1,5 +1,3 @@ -#[warn(str_to_string)] -#[warn(string_to_string)] #[warn(unstable_as_slice)] #[warn(unstable_as_mut_slice)] #[warn(misaligned_transmute)] diff --git a/src/tools/clippy/tests/ui/deprecated_old.stderr b/src/tools/clippy/tests/ui/deprecated_old.stderr index ff3e9e8fcf3..2fe1facf0c7 100644 --- a/src/tools/clippy/tests/ui/deprecated_old.stderr +++ b/src/tools/clippy/tests/ui/deprecated_old.stderr @@ -1,40 +1,28 @@ -error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated_old.rs:1:8 - | -LL | #[warn(str_to_string)] - | ^^^^^^^^^^^^^ - | - = note: `-D renamed-and-removed-lints` implied by `-D warnings` - -error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon` - --> $DIR/deprecated_old.rs:2:8 - | -LL | #[warn(string_to_string)] - | ^^^^^^^^^^^^^^^^ - error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` - --> $DIR/deprecated_old.rs:3:8 + --> $DIR/deprecated_old.rs:1:8 | LL | #[warn(unstable_as_slice)] | ^^^^^^^^^^^^^^^^^ + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7` - --> $DIR/deprecated_old.rs:4:8 + --> $DIR/deprecated_old.rs:2:8 | LL | #[warn(unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^ error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr` - --> $DIR/deprecated_old.rs:5:8 + --> $DIR/deprecated_old.rs:3:8 | LL | #[warn(misaligned_transmute)] | ^^^^^^^^^^^^^^^^^^^^ -error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` +error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7` --> $DIR/deprecated_old.rs:1:8 | -LL | #[warn(str_to_string)] - | ^^^^^^^^^^^^^ +LL | #[warn(unstable_as_slice)] + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/eq_op.rs b/src/tools/clippy/tests/ui/eq_op.rs index 4e09d19ea21..7ab23320db6 100644 --- a/src/tools/clippy/tests/ui/eq_op.rs +++ b/src/tools/clippy/tests/ui/eq_op.rs @@ -86,3 +86,12 @@ fn check_ignore_macro() { // checks if the lint ignores macros with `!` operator !bool_macro!(1) && !bool_macro!(""); } + +struct Nested { + inner: ((i32,), (i32,), (i32,)), +} + +fn check_nested(n1: &Nested, n2: &Nested) -> bool { + // `n2.inner.0.0` mistyped as `n1.inner.0.0` + (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 +} diff --git a/src/tools/clippy/tests/ui/eq_op.stderr b/src/tools/clippy/tests/ui/eq_op.stderr index ad81b35a766..8ef658af8df 100644 --- a/src/tools/clippy/tests/ui/eq_op.stderr +++ b/src/tools/clippy/tests/ui/eq_op.stderr @@ -162,5 +162,13 @@ error: equal expressions as operands to `/` LL | const D: u32 = A / A; | ^^^^^ -error: aborting due to 27 previous errors +error: equal expressions as operands to `==` + --> $DIR/eq_op.rs:96:5 + | +LL | (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(clippy::eq_op)]` on by default + +error: aborting due to 28 previous errors diff --git a/src/tools/clippy/tests/ui/invalid_paths.rs b/src/tools/clippy/tests/ui/invalid_paths.rs deleted file mode 100644 index 01e28ae5e9d..00000000000 --- a/src/tools/clippy/tests/ui/invalid_paths.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![warn(clippy::internal)] - -mod paths { - // Good path - pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; - - // Path to method on inherent impl of a primitive type - pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; - - // Path to method on inherent impl - pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; - - // Path with empty segment - pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; - - // Path with bad crate - pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; - - // Path with bad module - pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/invalid_paths.stderr b/src/tools/clippy/tests/ui/invalid_paths.stderr deleted file mode 100644 index bd69d661b71..00000000000 --- a/src/tools/clippy/tests/ui/invalid_paths.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: invalid path - --> $DIR/invalid_paths.rs:17:5 - | -LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::clippy-lints-internal` implied by `-D warnings` - -error: invalid path - --> $DIR/invalid_paths.rs:20:5 - | -LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/tools/clippy/tests/ui/item_after_statement.rs b/src/tools/clippy/tests/ui/item_after_statement.rs index 377e58e4417..d439ca1e4e1 100644 --- a/src/tools/clippy/tests/ui/item_after_statement.rs +++ b/src/tools/clippy/tests/ui/item_after_statement.rs @@ -37,3 +37,16 @@ fn say_something() { b!(); println!("{}", a); } + +fn semicolon() { + struct S { + a: u32, + }; + impl S { + fn new(a: u32) -> Self { + Self { a } + } + } + + let _ = S::new(3); +} diff --git a/src/tools/clippy/tests/ui/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui/lint_without_lint_pass.rs deleted file mode 100644 index beaef79a340..00000000000 --- a/src/tools/clippy/tests/ui/lint_without_lint_pass.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![deny(clippy::internal)] -#![feature(rustc_private)] - -#[macro_use] -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -extern crate rustc_lint; -use rustc_lint::LintPass; - -declare_tool_lint! { - pub clippy::TEST_LINT, - Warn, - "", - report_in_external_macro: true -} - -declare_tool_lint! { - pub clippy::TEST_LINT_REGISTERED, - Warn, - "", - report_in_external_macro: true -} - -declare_tool_lint! { - pub clippy::TEST_LINT_REGISTERED_ONLY_IMPL, - Warn, - "", - report_in_external_macro: true -} - -pub struct Pass; -impl LintPass for Pass { - fn name(&self) -> &'static str { - "TEST_LINT" - } -} - -declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]); - -pub struct Pass3; -impl_lint_pass!(Pass3 => [TEST_LINT_REGISTERED_ONLY_IMPL]); - -fn main() {} diff --git a/src/tools/clippy/tests/ui/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui/lint_without_lint_pass.stderr deleted file mode 100644 index 1257dae96d7..00000000000 --- a/src/tools/clippy/tests/ui/lint_without_lint_pass.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: the lint `TEST_LINT` is not added to any `LintPass` - --> $DIR/lint_without_lint_pass.rs:11:1 - | -LL | / declare_tool_lint! { -LL | | pub clippy::TEST_LINT, -LL | | Warn, -LL | | "", -LL | | report_in_external_macro: true -LL | | } - | |_^ - | -note: the lint level is defined here - --> $DIR/lint_without_lint_pass.rs:1:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - diff --git a/src/tools/clippy/tests/ui/map_err.rs b/src/tools/clippy/tests/ui/map_err.rs index 05b9949f102..00e037843f8 100644 --- a/src/tools/clippy/tests/ui/map_err.rs +++ b/src/tools/clippy/tests/ui/map_err.rs @@ -22,5 +22,9 @@ fn main() -> Result<(), Errors> { println!("{:?}", x.map_err(|_| Errors::Ignored)); + // Should not warn you because you explicitly ignore the parameter + // using a named wildcard value + println!("{:?}", x.map_err(|_foo| Errors::Ignored)); + Ok(()) } diff --git a/src/tools/clippy/tests/ui/map_err.stderr b/src/tools/clippy/tests/ui/map_err.stderr index 390d7ce2e4e..8ee2941790d 100644 --- a/src/tools/clippy/tests/ui/map_err.stderr +++ b/src/tools/clippy/tests/ui/map_err.stderr @@ -1,11 +1,11 @@ -error: `map_err(|_|...` ignores the original error +error: `map_err(|_|...` wildcard pattern discards the original error --> $DIR/map_err.rs:23:32 | LL | println!("{:?}", x.map_err(|_| Errors::Ignored)); | ^^^ | = note: `-D clippy::map-err-ignore` implied by `-D warnings` - = help: Consider wrapping the error in an enum variant + = help: Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`) error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui/match_type_on_diag_item.rs deleted file mode 100644 index fe950b0aa7c..00000000000 --- a/src/tools/clippy/tests/ui/match_type_on_diag_item.rs +++ /dev/null @@ -1,50 +0,0 @@ -#![deny(clippy::internal)] -#![feature(rustc_private)] - -extern crate rustc_hir; -extern crate rustc_lint; -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -use rustc_hir::Expr; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; - -mod paths { - pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; -} - -mod utils { - use super::*; - - pub fn match_type(_cx: &LateContext<'_>, _ty: Ty<'_>, _path: &[&str]) -> bool { - false - } -} - -use utils::match_type; - -declare_lint! { - pub TEST_LINT, - Warn, - "" -} - -declare_lint_pass!(Pass => [TEST_LINT]); - -static OPTION: [&str; 3] = ["core", "option", "Option"]; - -impl<'tcx> LateLintPass<'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) { - let ty = cx.typeck_results().expr_ty(expr); - - let _ = match_type(cx, ty, &paths::VEC); - let _ = match_type(cx, ty, &OPTION); - let _ = match_type(cx, ty, &["core", "result", "Result"]); - - let rc_path = &["alloc", "rc", "Rc"]; - let _ = utils::match_type(cx, ty, rc_path); - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui/match_type_on_diag_item.stderr deleted file mode 100644 index 82465dbaf6e..00000000000 --- a/src/tools/clippy/tests/ui/match_type_on_diag_item.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:41:17 - | -LL | let _ = match_type(cx, ty, &paths::VEC); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::vec_type)` - | -note: the lint level is defined here - --> $DIR/match_type_on_diag_item.rs:1:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]` - -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:42:17 - | -LL | let _ = match_type(cx, ty, &OPTION); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::option_type)` - -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:43:17 - | -LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::result_type)` - -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:46:17 - | -LL | let _ = utils::match_type(cx, ty, rc_path); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::Rc)` - -error: aborting due to 4 previous errors - diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs new file mode 100644 index 00000000000..1026cc40d3b --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs @@ -0,0 +1,87 @@ +#![allow(clippy::redundant_clone)] +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.0.0"] + +use std::ops::Deref; + +fn option_as_ref_deref() { + let mut opt = Some(String::from("123")); + + let _ = opt.as_ref().map(String::as_str); + let _ = opt.as_ref().map(|x| x.as_str()); + let _ = opt.as_mut().map(String::as_mut_str); + let _ = opt.as_mut().map(|x| x.as_mut_str()); +} + +fn match_like_matches() { + let _y = match Some(5) { + Some(0) => true, + _ => false, + }; +} + +fn match_same_arms() { + match (1, 2, 3) { + (1, .., 3) => 42, + (.., 3) => 42, //~ ERROR match arms have same body + _ => 0, + }; +} + +fn match_same_arms2() { + let _ = match Some(42) { + Some(_) => 24, + None => 24, //~ ERROR match arms have same body + }; +} + +pub fn manual_strip_msrv() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } +} + +fn main() { + option_as_ref_deref(); + match_like_matches(); + match_same_arms(); + match_same_arms2(); + manual_strip_msrv(); +} + +mod meets_msrv { + #![feature(custom_inner_attributes)] + #![clippy::msrv = "1.45.0"] + + fn main() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } + } +} + +mod just_under_msrv { + #![feature(custom_inner_attributes)] + #![clippy::msrv = "1.46.0"] + + fn main() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } + } +} + +mod just_above_msrv { + #![feature(custom_inner_attributes)] + #![clippy::msrv = "1.44.0"] + + fn main() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } + } +} diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr new file mode 100644 index 00000000000..3e1af046e7a --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr @@ -0,0 +1,37 @@ +error: stripping a prefix manually + --> $DIR/min_rust_version_attr.rs:60:24 + | +LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::manual-strip` implied by `-D warnings` +note: the prefix was tested here + --> $DIR/min_rust_version_attr.rs:59:9 + | +LL | if s.starts_with("hello, ") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_prefix` method + | +LL | if let Some() = s.strip_prefix("hello, ") { +LL | assert_eq!(.to_uppercase(), "WORLD!"); + | + +error: stripping a prefix manually + --> $DIR/min_rust_version_attr.rs:72:24 + | +LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the prefix was tested here + --> $DIR/min_rust_version_attr.rs:71:9 + | +LL | if s.starts_with("hello, ") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_prefix` method + | +LL | if let Some() = s.strip_prefix("hello, ") { +LL | assert_eq!(.to_uppercase(), "WORLD!"); + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs new file mode 100644 index 00000000000..f20841891a7 --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs @@ -0,0 +1,4 @@ +#![feature(custom_inner_attributes)] +#![clippy::msrv = "invalid.version"] + +fn main() {} diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr new file mode 100644 index 00000000000..6ff88ca56f8 --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr @@ -0,0 +1,8 @@ +error: `invalid.version` is not a valid Rust version + --> $DIR/min_rust_version_invalid_attr.rs:2:1 + | +LL | #![clippy::msrv = "invalid.version"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs new file mode 100644 index 00000000000..e882d5ccf91 --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs @@ -0,0 +1,11 @@ +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.40"] +#![clippy::msrv = "=1.35.0"] +#![clippy::msrv = "1.10.1"] + +mod foo { + #![clippy::msrv = "1"] + #![clippy::msrv = "1.0.0"] +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr new file mode 100644 index 00000000000..e3ff6605cde --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr @@ -0,0 +1,38 @@ +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_multiple_inner_attr.rs:3:1 + | +LL | #![clippy::msrv = "=1.35.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1 + | +LL | #![clippy::msrv = "1.40"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_multiple_inner_attr.rs:4:1 + | +LL | #![clippy::msrv = "1.10.1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1 + | +LL | #![clippy::msrv = "1.40"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_multiple_inner_attr.rs:8:5 + | +LL | #![clippy::msrv = "1.0.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_multiple_inner_attr.rs:7:5 + | +LL | #![clippy::msrv = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs b/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs new file mode 100644 index 00000000000..98fffe1e351 --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs @@ -0,0 +1,14 @@ +#![allow(clippy::redundant_clone)] +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.0"] + +fn manual_strip_msrv() { + let s = "hello, world!"; + if s.starts_with("hello, ") { + assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); + } +} + +fn main() { + manual_strip_msrv() +} diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs new file mode 100644 index 00000000000..551948bd72e --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs @@ -0,0 +1,4 @@ +#![feature(custom_inner_attributes)] + +#[clippy::msrv = "invalid.version"] +fn main() {} diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr new file mode 100644 index 00000000000..579ee7a87d2 --- /dev/null +++ b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr @@ -0,0 +1,8 @@ +error: `msrv` cannot be an outer attribute + --> $DIR/min_rust_version_outer_attr.rs:3:1 + | +LL | #[clippy::msrv = "invalid.version"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/modulo_one.rs b/src/tools/clippy/tests/ui/modulo_one.rs index cc8c8e7cdae..678a312f66e 100644 --- a/src/tools/clippy/tests/ui/modulo_one.rs +++ b/src/tools/clippy/tests/ui/modulo_one.rs @@ -2,13 +2,22 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation)] static STATIC_ONE: usize = 2 - 1; +static STATIC_NEG_ONE: i64 = 1 - 2; fn main() { 10 % 1; + 10 % -1; 10 % 2; + i32::MIN % (-1); // also caught by rustc const ONE: u32 = 1 * 1; + const NEG_ONE: i64 = 1 - 2; + const INT_MIN: i64 = i64::MIN; 2 % ONE; - 5 % STATIC_ONE; + 5 % STATIC_ONE; // NOT caught by lint + 2 % NEG_ONE; + 5 % STATIC_NEG_ONE; // NOT caught by lint + INT_MIN % NEG_ONE; // also caught by rustc + INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc } diff --git a/src/tools/clippy/tests/ui/modulo_one.stderr b/src/tools/clippy/tests/ui/modulo_one.stderr index 6bee68360b6..2b2c6997338 100644 --- a/src/tools/clippy/tests/ui/modulo_one.stderr +++ b/src/tools/clippy/tests/ui/modulo_one.stderr @@ -1,13 +1,45 @@ +error: this arithmetic operation will overflow + --> $DIR/modulo_one.rs:11:5 + | +LL | i32::MIN % (-1); // also caught by rustc + | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/modulo_one.rs:21:5 + | +LL | INT_MIN % NEG_ONE; // also caught by rustc + | ^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/modulo_one.rs:22:5 + | +LL | INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc + | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + error: any number modulo 1 will be 0 - --> $DIR/modulo_one.rs:7:5 + --> $DIR/modulo_one.rs:8:5 | LL | 10 % 1; | ^^^^^^ | = note: `-D clippy::modulo-one` implied by `-D warnings` +error: any number modulo -1 will panic/overflow or result in 0 + --> $DIR/modulo_one.rs:9:5 + | +LL | 10 % -1; + | ^^^^^^^ + +error: any number modulo -1 will panic/overflow or result in 0 + --> $DIR/modulo_one.rs:11:5 + | +LL | i32::MIN % (-1); // also caught by rustc + | ^^^^^^^^^^^^^^^ + error: the operation is ineffective. Consider reducing it to `1` - --> $DIR/modulo_one.rs:10:22 + --> $DIR/modulo_one.rs:13:22 | LL | const ONE: u32 = 1 * 1; | ^^^^^ @@ -15,16 +47,28 @@ LL | const ONE: u32 = 1 * 1; = note: `-D clippy::identity-op` implied by `-D warnings` error: the operation is ineffective. Consider reducing it to `1` - --> $DIR/modulo_one.rs:10:22 + --> $DIR/modulo_one.rs:13:22 | LL | const ONE: u32 = 1 * 1; | ^^^^^ error: any number modulo 1 will be 0 - --> $DIR/modulo_one.rs:12:5 + --> $DIR/modulo_one.rs:17:5 | LL | 2 % ONE; | ^^^^^^^ -error: aborting due to 4 previous errors +error: any number modulo -1 will panic/overflow or result in 0 + --> $DIR/modulo_one.rs:19:5 + | +LL | 2 % NEG_ONE; + | ^^^^^^^^^^^ + +error: any number modulo -1 will panic/overflow or result in 0 + --> $DIR/modulo_one.rs:21:5 + | +LL | INT_MIN % NEG_ONE; // also caught by rustc + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs index 4f6e5357727..0918a6868ab 100644 --- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs +++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs @@ -22,4 +22,24 @@ fn main() { let sample = vec![a.clone(), "b".to_string(), "c".to_string()]; let non_copy_contains = sample.into_iter().collect::>(); non_copy_contains.contains(&a); + + // Fix #5991 + let vec_a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let vec_b = vec_a.iter().collect::>(); + if vec_b.len() > 3 {} + let other_vec = vec![1, 3, 12, 4, 16, 2]; + let we_got_the_same_numbers = other_vec.iter().filter(|item| vec_b.contains(item)).collect::>(); + + // Fix #6297 + let sample = [1; 5]; + let multiple_indirect = sample.iter().collect::>(); + let sample2 = vec![2, 3]; + if multiple_indirect.is_empty() { + // do something + } else { + let found = sample2 + .iter() + .filter(|i| multiple_indirect.iter().any(|s| **s % **i == 0)) + .collect::>(); + } } diff --git a/src/tools/clippy/tests/ui/outer_expn_data.fixed b/src/tools/clippy/tests/ui/outer_expn_data.fixed deleted file mode 100644 index b0b3498f057..00000000000 --- a/src/tools/clippy/tests/ui/outer_expn_data.fixed +++ /dev/null @@ -1,28 +0,0 @@ -// run-rustfix - -#![deny(clippy::internal)] -#![feature(rustc_private)] - -extern crate rustc_hir; -extern crate rustc_lint; -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -use rustc_hir::Expr; -use rustc_lint::{LateContext, LateLintPass}; - -declare_lint! { - pub TEST_LINT, - Warn, - "" -} - -declare_lint_pass!(Pass => [TEST_LINT]); - -impl<'tcx> LateLintPass<'tcx> for Pass { - fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { - let _ = expr.span.ctxt().outer_expn_data(); - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/outer_expn_data.rs b/src/tools/clippy/tests/ui/outer_expn_data.rs deleted file mode 100644 index 55a3fed00d0..00000000000 --- a/src/tools/clippy/tests/ui/outer_expn_data.rs +++ /dev/null @@ -1,28 +0,0 @@ -// run-rustfix - -#![deny(clippy::internal)] -#![feature(rustc_private)] - -extern crate rustc_hir; -extern crate rustc_lint; -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -use rustc_hir::Expr; -use rustc_lint::{LateContext, LateLintPass}; - -declare_lint! { - pub TEST_LINT, - Warn, - "" -} - -declare_lint_pass!(Pass => [TEST_LINT]); - -impl<'tcx> LateLintPass<'tcx> for Pass { - fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { - let _ = expr.span.ctxt().outer_expn().expn_data(); - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/outer_expn_data.stderr b/src/tools/clippy/tests/ui/outer_expn_data.stderr deleted file mode 100644 index 56b6ce1f78e..00000000000 --- a/src/tools/clippy/tests/ui/outer_expn_data.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: usage of `outer_expn().expn_data()` - --> $DIR/outer_expn_data.rs:24:34 - | -LL | let _ = expr.span.ctxt().outer_expn().expn_data(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()` - | -note: the lint level is defined here - --> $DIR/outer_expn_data.rs:3:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]` - -error: aborting due to previous error - diff --git a/src/tools/clippy/tests/ui/panicking_macros.stderr b/src/tools/clippy/tests/ui/panicking_macros.stderr index 83234c0ed92..6028323a3c8 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.stderr +++ b/src/tools/clippy/tests/ui/panicking_macros.stderr @@ -62,7 +62,7 @@ error: `unimplemented` should not be present in production code LL | unimplemented!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `unreachable` should not be present in production code +error: usage of the `unreachable!` macro --> $DIR/panicking_macros.rs:32:5 | LL | unreachable!(); @@ -70,7 +70,7 @@ LL | unreachable!(); | = note: `-D clippy::unreachable` implied by `-D warnings` -error: `unreachable` should not be present in production code +error: usage of the `unreachable!` macro --> $DIR/panicking_macros.rs:33:5 | LL | unreachable!("message"); @@ -78,7 +78,7 @@ LL | unreachable!("message"); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: `unreachable` should not be present in production code +error: usage of the `unreachable!` macro --> $DIR/panicking_macros.rs:34:5 | LL | unreachable!("{} {}", "panic with", "multiple arguments"); @@ -102,7 +102,7 @@ error: `unimplemented` should not be present in production code LL | unimplemented!(); | ^^^^^^^^^^^^^^^^^ -error: `unreachable` should not be present in production code +error: usage of the `unreachable!` macro --> $DIR/panicking_macros.rs:43:5 | LL | unreachable!(); diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching.fixed deleted file mode 100644 index aa20512296a..00000000000 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching.fixed +++ /dev/null @@ -1,110 +0,0 @@ -// run-rustfix - -#![warn(clippy::all)] -#![warn(clippy::redundant_pattern_matching)] -#![allow( - clippy::unit_arg, - unused_must_use, - clippy::needless_bool, - clippy::match_like_matches_macro, - clippy::unnecessary_wraps, - deprecated -)] - -fn main() { - let result: Result = Err(5); - if result.is_ok() {} - - if Ok::(42).is_ok() {} - - if Err::(42).is_err() {} - - while Ok::(10).is_ok() {} - - while Ok::(10).is_err() {} - - if Ok::(42).is_ok() {} - - if Err::(42).is_err() {} - - if let Ok(x) = Ok::(42) { - println!("{}", x); - } - - Ok::(42).is_ok(); - - Ok::(42).is_err(); - - Err::(42).is_err(); - - Err::(42).is_ok(); - - let _ = if Ok::(4).is_ok() { true } else { false }; - - issue5504(); - issue6067(); - issue6065(); - - let _ = if gen_res().is_ok() { - 1 - } else if gen_res().is_err() { - 2 - } else { - 3 - }; -} - -fn gen_res() -> Result<(), ()> { - Ok(()) -} - -macro_rules! m { - () => { - Some(42u32) - }; -} - -fn issue5504() { - fn result_opt() -> Result, i32> { - Err(42) - } - - fn try_result_opt() -> Result { - while r#try!(result_opt()).is_some() {} - if r#try!(result_opt()).is_some() {} - Ok(42) - } - - try_result_opt(); - - if m!().is_some() {} - while m!().is_some() {} -} - -fn issue6065() { - macro_rules! if_let_in_macro { - ($pat:pat, $x:expr) => { - if let Some($pat) = $x {} - }; - } - - // shouldn't be linted - if_let_in_macro!(_, Some(42)); -} - -// Methods that are unstable const should not be suggested within a const context, see issue #5697. -// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const, -// so the following should be linted. -const fn issue6067() { - if Ok::(42).is_ok() {} - - if Err::(42).is_err() {} - - while Ok::(10).is_ok() {} - - while Ok::(10).is_err() {} - - Ok::(42).is_ok(); - - Err::(42).is_err(); -} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching.rs deleted file mode 100644 index d76f9c288ff..00000000000 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching.rs +++ /dev/null @@ -1,128 +0,0 @@ -// run-rustfix - -#![warn(clippy::all)] -#![warn(clippy::redundant_pattern_matching)] -#![allow( - clippy::unit_arg, - unused_must_use, - clippy::needless_bool, - clippy::match_like_matches_macro, - clippy::unnecessary_wraps, - deprecated -)] - -fn main() { - let result: Result = Err(5); - if let Ok(_) = &result {} - - if let Ok(_) = Ok::(42) {} - - if let Err(_) = Err::(42) {} - - while let Ok(_) = Ok::(10) {} - - while let Err(_) = Ok::(10) {} - - if Ok::(42).is_ok() {} - - if Err::(42).is_err() {} - - if let Ok(x) = Ok::(42) { - println!("{}", x); - } - - match Ok::(42) { - Ok(_) => true, - Err(_) => false, - }; - - match Ok::(42) { - Ok(_) => false, - Err(_) => true, - }; - - match Err::(42) { - Ok(_) => false, - Err(_) => true, - }; - - match Err::(42) { - Ok(_) => true, - Err(_) => false, - }; - - let _ = if let Ok(_) = Ok::(4) { true } else { false }; - - issue5504(); - issue6067(); - issue6065(); - - let _ = if let Ok(_) = gen_res() { - 1 - } else if let Err(_) = gen_res() { - 2 - } else { - 3 - }; -} - -fn gen_res() -> Result<(), ()> { - Ok(()) -} - -macro_rules! m { - () => { - Some(42u32) - }; -} - -fn issue5504() { - fn result_opt() -> Result, i32> { - Err(42) - } - - fn try_result_opt() -> Result { - while let Some(_) = r#try!(result_opt()) {} - if let Some(_) = r#try!(result_opt()) {} - Ok(42) - } - - try_result_opt(); - - if let Some(_) = m!() {} - while let Some(_) = m!() {} -} - -fn issue6065() { - macro_rules! if_let_in_macro { - ($pat:pat, $x:expr) => { - if let Some($pat) = $x {} - }; - } - - // shouldn't be linted - if_let_in_macro!(_, Some(42)); -} - -// Methods that are unstable const should not be suggested within a const context, see issue #5697. -// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const, -// so the following should be linted. -const fn issue6067() { - if let Ok(_) = Ok::(42) {} - - if let Err(_) = Err::(42) {} - - while let Ok(_) = Ok::(10) {} - - while let Err(_) = Ok::(10) {} - - match Ok::(42) { - Ok(_) => true, - Err(_) => false, - }; - - match Err::(42) { - Ok(_) => false, - Err(_) => true, - }; -} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching.stderr deleted file mode 100644 index aeb309f5ba1..00000000000 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching.stderr +++ /dev/null @@ -1,154 +0,0 @@ -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:16:12 - | -LL | if let Ok(_) = &result {} - | -------^^^^^---------- help: try this: `if result.is_ok()` - | - = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:18:12 - | -LL | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:20:12 - | -LL | if let Err(_) = Err::(42) {} - | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:22:15 - | -LL | while let Ok(_) = Ok::(10) {} - | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:24:15 - | -LL | while let Err(_) = Ok::(10) {} - | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:34:5 - | -LL | / match Ok::(42) { -LL | | Ok(_) => true, -LL | | Err(_) => false, -LL | | }; - | |_____^ help: try this: `Ok::(42).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:39:5 - | -LL | / match Ok::(42) { -LL | | Ok(_) => false, -LL | | Err(_) => true, -LL | | }; - | |_____^ help: try this: `Ok::(42).is_err()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:44:5 - | -LL | / match Err::(42) { -LL | | Ok(_) => false, -LL | | Err(_) => true, -LL | | }; - | |_____^ help: try this: `Err::(42).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:49:5 - | -LL | / match Err::(42) { -LL | | Ok(_) => true, -LL | | Err(_) => false, -LL | | }; - | |_____^ help: try this: `Err::(42).is_ok()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:54:20 - | -LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; - | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:60:20 - | -LL | let _ = if let Ok(_) = gen_res() { - | -------^^^^^------------ help: try this: `if gen_res().is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:62:19 - | -LL | } else if let Err(_) = gen_res() { - | -------^^^^^^------------ help: try this: `if gen_res().is_err()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:85:19 - | -LL | while let Some(_) = r#try!(result_opt()) {} - | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:86:16 - | -LL | if let Some(_) = r#try!(result_opt()) {} - | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:92:12 - | -LL | if let Some(_) = m!() {} - | -------^^^^^^^------- help: try this: `if m!().is_some()` - -error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching.rs:93:15 - | -LL | while let Some(_) = m!() {} - | ----------^^^^^^^------- help: try this: `while m!().is_some()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:111:12 - | -LL | if let Ok(_) = Ok::(42) {} - | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:113:12 - | -LL | if let Err(_) = Err::(42) {} - | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:115:15 - | -LL | while let Ok(_) = Ok::(10) {} - | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:117:15 - | -LL | while let Err(_) = Ok::(10) {} - | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` - -error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching.rs:119:5 - | -LL | / match Ok::(42) { -LL | | Ok(_) => true, -LL | | Err(_) => false, -LL | | }; - | |_____^ help: try this: `Ok::(42).is_ok()` - -error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching.rs:124:5 - | -LL | / match Err::(42) { -LL | | Ok(_) => false, -LL | | Err(_) => true, -LL | | }; - | |_____^ help: try this: `Err::(42).is_err()` - -error: aborting due to 22 previous errors - diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed new file mode 100644 index 00000000000..acc8de5f41e --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] + +use std::net::{ + IpAddr::{self, V4, V6}, + Ipv4Addr, Ipv6Addr, +}; + +fn main() { + let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); + if ipaddr.is_ipv4() {} + + if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + while V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + while V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + if let V4(ipaddr) = V4(Ipv4Addr::LOCALHOST) { + println!("{}", ipaddr); + } + + V4(Ipv4Addr::LOCALHOST).is_ipv4(); + + V4(Ipv4Addr::LOCALHOST).is_ipv6(); + + V6(Ipv6Addr::LOCALHOST).is_ipv6(); + + V6(Ipv6Addr::LOCALHOST).is_ipv4(); + + let _ = if V4(Ipv4Addr::LOCALHOST).is_ipv4() { + true + } else { + false + }; + + ipaddr_const(); + + let _ = if gen_ipaddr().is_ipv4() { + 1 + } else if gen_ipaddr().is_ipv6() { + 2 + } else { + 3 + }; +} + +fn gen_ipaddr() -> IpAddr { + V4(Ipv4Addr::LOCALHOST) +} + +const fn ipaddr_const() { + if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + while V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + while V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + V4(Ipv4Addr::LOCALHOST).is_ipv4(); + + V6(Ipv6Addr::LOCALHOST).is_ipv6(); +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs new file mode 100644 index 00000000000..678d91ce93a --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -0,0 +1,91 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] + +use std::net::{ + IpAddr::{self, V4, V6}, + Ipv4Addr, Ipv6Addr, +}; + +fn main() { + let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); + if let V4(_) = &ipaddr {} + + if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + + if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + + while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + + while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + + if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + + if let V4(ipaddr) = V4(Ipv4Addr::LOCALHOST) { + println!("{}", ipaddr); + } + + match V4(Ipv4Addr::LOCALHOST) { + V4(_) => true, + V6(_) => false, + }; + + match V4(Ipv4Addr::LOCALHOST) { + V4(_) => false, + V6(_) => true, + }; + + match V6(Ipv6Addr::LOCALHOST) { + V4(_) => false, + V6(_) => true, + }; + + match V6(Ipv6Addr::LOCALHOST) { + V4(_) => true, + V6(_) => false, + }; + + let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { + true + } else { + false + }; + + ipaddr_const(); + + let _ = if let V4(_) = gen_ipaddr() { + 1 + } else if let V6(_) = gen_ipaddr() { + 2 + } else { + 3 + }; +} + +fn gen_ipaddr() -> IpAddr { + V4(Ipv4Addr::LOCALHOST) +} + +const fn ipaddr_const() { + if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + + if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + + while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + + while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + + match V4(Ipv4Addr::LOCALHOST) { + V4(_) => true, + V6(_) => false, + }; + + match V6(Ipv6Addr::LOCALHOST) { + V4(_) => false, + V6(_) => true, + }; +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr new file mode 100644 index 00000000000..caf458cd862 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -0,0 +1,130 @@ +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:14:12 + | +LL | if let V4(_) = &ipaddr {} + | -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:16:12 + | +LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 + | +LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:20:15 + | +LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:22:15 + | +LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:32:5 + | +LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | V4(_) => true, +LL | | V6(_) => false, +LL | | }; + | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:37:5 + | +LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | V4(_) => false, +LL | | V6(_) => true, +LL | | }; + | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:42:5 + | +LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | V4(_) => false, +LL | | V6(_) => true, +LL | | }; + | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:47:5 + | +LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | V4(_) => true, +LL | | V6(_) => false, +LL | | }; + | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:52:20 + | +LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { + | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:60:20 + | +LL | let _ = if let V4(_) = gen_ipaddr() { + | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:62:19 + | +LL | } else if let V6(_) = gen_ipaddr() { + | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:74:12 + | +LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:76:12 + | +LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:78:15 + | +LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:80:15 + | +LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:82:5 + | +LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | V4(_) => true, +LL | | V6(_) => false, +LL | | }; + | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:87:5 + | +LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | V4(_) => false, +LL | | V6(_) => true, +LL | | }; + | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed index 499b975b2bb..66f580a0a68 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed @@ -2,13 +2,7 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow( - clippy::unit_arg, - unused_must_use, - clippy::needless_bool, - clippy::match_like_matches_macro, - deprecated -)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] fn main() { if None::<()>.is_none() {} @@ -43,8 +37,7 @@ fn main() { let _ = None::<()>.is_none(); let opt = Some(false); - let x = if opt.is_some() { true } else { false }; - takes_bool(x); + let _ = if opt.is_some() { true } else { false }; issue6067(); @@ -61,8 +54,6 @@ fn gen_opt() -> Option<()> { None } -fn takes_bool(_: bool) {} - fn foo() {} fn bar() {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs index 2a98435e790..f18b27b8b95 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs @@ -2,13 +2,7 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow( - clippy::unit_arg, - unused_must_use, - clippy::needless_bool, - clippy::match_like_matches_macro, - deprecated -)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] fn main() { if let None = None::<()> {} @@ -52,8 +46,7 @@ fn main() { }; let opt = Some(false); - let x = if let Some(_) = opt { true } else { false }; - takes_bool(x); + let _ = if let Some(_) = opt { true } else { false }; issue6067(); @@ -70,8 +63,6 @@ fn gen_opt() -> Option<()> { None } -fn takes_bool(_: bool) {} - fn foo() {} fn bar() {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr index eebb3448491..58482a0ab70 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:14:12 + --> $DIR/redundant_pattern_matching_option.rs:8:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` @@ -7,43 +7,43 @@ LL | if let None = None::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:16:12 + --> $DIR/redundant_pattern_matching_option.rs:10:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:18:12 + --> $DIR/redundant_pattern_matching_option.rs:12:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:24:15 + --> $DIR/redundant_pattern_matching_option.rs:18:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:26:15 + --> $DIR/redundant_pattern_matching_option.rs:20:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:28:15 + --> $DIR/redundant_pattern_matching_option.rs:22:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:31:15 + --> $DIR/redundant_pattern_matching_option.rs:25:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:39:5 + --> $DIR/redundant_pattern_matching_option.rs:33:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:44:5 + --> $DIR/redundant_pattern_matching_option.rs:38:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:49:13 + --> $DIR/redundant_pattern_matching_option.rs:43:13 | LL | let _ = match None::<()> { | _____________^ @@ -71,49 +71,49 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:55:20 + --> $DIR/redundant_pattern_matching_option.rs:49:20 | -LL | let x = if let Some(_) = opt { true } else { false }; +LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:60:20 + --> $DIR/redundant_pattern_matching_option.rs:53:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:62:19 + --> $DIR/redundant_pattern_matching_option.rs:55:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:83:12 + --> $DIR/redundant_pattern_matching_option.rs:74:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:85:12 + --> $DIR/redundant_pattern_matching_option.rs:76:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:87:15 + --> $DIR/redundant_pattern_matching_option.rs:78:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:89:15 + --> $DIR/redundant_pattern_matching_option.rs:80:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:91:5 + --> $DIR/redundant_pattern_matching_option.rs:82:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -122,7 +122,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:96:5 + --> $DIR/redundant_pattern_matching_option.rs:87:5 | LL | / match None::<()> { LL | | Some(_) => false, diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed new file mode 100644 index 00000000000..465aa80dac2 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed @@ -0,0 +1,70 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] + +use std::task::Poll::{self, Pending, Ready}; + +fn main() { + if Pending::<()>.is_pending() {} + + if Ready(42).is_ready() {} + + if Ready(42).is_ready() { + foo(); + } else { + bar(); + } + + while Ready(42).is_ready() {} + + while Ready(42).is_pending() {} + + while Pending::<()>.is_pending() {} + + if Pending::.is_pending() {} + + if Ready(42).is_ready() {} + + Ready(42).is_ready(); + + Pending::<()>.is_pending(); + + let _ = Pending::<()>.is_pending(); + + let poll = Ready(false); + let _ = if poll.is_ready() { true } else { false }; + + poll_const(); + + let _ = if gen_poll().is_ready() { + 1 + } else if gen_poll().is_pending() { + 2 + } else { + 3 + }; +} + +fn gen_poll() -> Poll<()> { + Pending +} + +fn foo() {} + +fn bar() {} + +const fn poll_const() { + if Ready(42).is_ready() {} + + if Pending::<()>.is_pending() {} + + while Ready(42).is_ready() {} + + while Pending::<()>.is_pending() {} + + Ready(42).is_ready(); + + Pending::<()>.is_pending(); +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs new file mode 100644 index 00000000000..7891ff353b1 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs @@ -0,0 +1,85 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] + +use std::task::Poll::{self, Pending, Ready}; + +fn main() { + if let Pending = Pending::<()> {} + + if let Ready(_) = Ready(42) {} + + if let Ready(_) = Ready(42) { + foo(); + } else { + bar(); + } + + while let Ready(_) = Ready(42) {} + + while let Pending = Ready(42) {} + + while let Pending = Pending::<()> {} + + if Pending::.is_pending() {} + + if Ready(42).is_ready() {} + + match Ready(42) { + Ready(_) => true, + Pending => false, + }; + + match Pending::<()> { + Ready(_) => false, + Pending => true, + }; + + let _ = match Pending::<()> { + Ready(_) => false, + Pending => true, + }; + + let poll = Ready(false); + let _ = if let Ready(_) = poll { true } else { false }; + + poll_const(); + + let _ = if let Ready(_) = gen_poll() { + 1 + } else if let Pending = gen_poll() { + 2 + } else { + 3 + }; +} + +fn gen_poll() -> Poll<()> { + Pending +} + +fn foo() {} + +fn bar() {} + +const fn poll_const() { + if let Ready(_) = Ready(42) {} + + if let Pending = Pending::<()> {} + + while let Ready(_) = Ready(42) {} + + while let Pending = Pending::<()> {} + + match Ready(42) { + Ready(_) => true, + Pending => false, + }; + + match Pending::<()> { + Ready(_) => false, + Pending => true, + }; +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr new file mode 100644 index 00000000000..5ffc6c47c90 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr @@ -0,0 +1,128 @@ +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:10:12 + | +LL | if let Pending = Pending::<()> {} + | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:12:12 + | +LL | if let Ready(_) = Ready(42) {} + | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:14:12 + | +LL | if let Ready(_) = Ready(42) { + | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:20:15 + | +LL | while let Ready(_) = Ready(42) {} + | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:22:15 + | +LL | while let Pending = Ready(42) {} + | ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:24:15 + | +LL | while let Pending = Pending::<()> {} + | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:30:5 + | +LL | / match Ready(42) { +LL | | Ready(_) => true, +LL | | Pending => false, +LL | | }; + | |_____^ help: try this: `Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:35:5 + | +LL | / match Pending::<()> { +LL | | Ready(_) => false, +LL | | Pending => true, +LL | | }; + | |_____^ help: try this: `Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:40:13 + | +LL | let _ = match Pending::<()> { + | _____________^ +LL | | Ready(_) => false, +LL | | Pending => true, +LL | | }; + | |_____^ help: try this: `Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:46:20 + | +LL | let _ = if let Ready(_) = poll { true } else { false }; + | -------^^^^^^^^------- help: try this: `if poll.is_ready()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:50:20 + | +LL | let _ = if let Ready(_) = gen_poll() { + | -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:52:19 + | +LL | } else if let Pending = gen_poll() { + | -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:68:12 + | +LL | if let Ready(_) = Ready(42) {} + | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:70:12 + | +LL | if let Pending = Pending::<()> {} + | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:72:15 + | +LL | while let Ready(_) = Ready(42) {} + | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:74:15 + | +LL | while let Pending = Pending::<()> {} + | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:76:5 + | +LL | / match Ready(42) { +LL | | Ready(_) => true, +LL | | Pending => false, +LL | | }; + | |_____^ help: try this: `Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:81:5 + | +LL | / match Pending::<()> { +LL | | Ready(_) => false, +LL | | Pending => true, +LL | | }; + | |_____^ help: try this: `Pending::<()>.is_pending()` + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed new file mode 100644 index 00000000000..e94c5704b48 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed @@ -0,0 +1,109 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::unnecessary_wraps, + deprecated +)] + +fn main() { + let result: Result = Err(5); + if result.is_ok() {} + + if Ok::(42).is_ok() {} + + if Err::(42).is_err() {} + + while Ok::(10).is_ok() {} + + while Ok::(10).is_err() {} + + if Ok::(42).is_ok() {} + + if Err::(42).is_err() {} + + if let Ok(x) = Ok::(42) { + println!("{}", x); + } + + Ok::(42).is_ok(); + + Ok::(42).is_err(); + + Err::(42).is_err(); + + Err::(42).is_ok(); + + let _ = if Ok::(4).is_ok() { true } else { false }; + + issue5504(); + issue6067(); + issue6065(); + + let _ = if gen_res().is_ok() { + 1 + } else if gen_res().is_err() { + 2 + } else { + 3 + }; +} + +fn gen_res() -> Result<(), ()> { + Ok(()) +} + +macro_rules! m { + () => { + Some(42u32) + }; +} + +fn issue5504() { + fn result_opt() -> Result, i32> { + Err(42) + } + + fn try_result_opt() -> Result { + while r#try!(result_opt()).is_some() {} + if r#try!(result_opt()).is_some() {} + Ok(42) + } + + try_result_opt(); + + if m!().is_some() {} + while m!().is_some() {} +} + +fn issue6065() { + macro_rules! if_let_in_macro { + ($pat:pat, $x:expr) => { + if let Some($pat) = $x {} + }; + } + + // shouldn't be linted + if_let_in_macro!(_, Some(42)); +} + +// Methods that are unstable const should not be suggested within a const context, see issue #5697. +// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const, +// so the following should be linted. +const fn issue6067() { + if Ok::(42).is_ok() {} + + if Err::(42).is_err() {} + + while Ok::(10).is_ok() {} + + while Ok::(10).is_err() {} + + Ok::(42).is_ok(); + + Err::(42).is_err(); +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs new file mode 100644 index 00000000000..5d175294232 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs @@ -0,0 +1,127 @@ +// run-rustfix + +#![warn(clippy::all)] +#![warn(clippy::redundant_pattern_matching)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::unnecessary_wraps, + deprecated +)] + +fn main() { + let result: Result = Err(5); + if let Ok(_) = &result {} + + if let Ok(_) = Ok::(42) {} + + if let Err(_) = Err::(42) {} + + while let Ok(_) = Ok::(10) {} + + while let Err(_) = Ok::(10) {} + + if Ok::(42).is_ok() {} + + if Err::(42).is_err() {} + + if let Ok(x) = Ok::(42) { + println!("{}", x); + } + + match Ok::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Ok::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => false, + Err(_) => true, + }; + + match Err::(42) { + Ok(_) => true, + Err(_) => false, + }; + + let _ = if let Ok(_) = Ok::(4) { true } else { false }; + + issue5504(); + issue6067(); + issue6065(); + + let _ = if let Ok(_) = gen_res() { + 1 + } else if let Err(_) = gen_res() { + 2 + } else { + 3 + }; +} + +fn gen_res() -> Result<(), ()> { + Ok(()) +} + +macro_rules! m { + () => { + Some(42u32) + }; +} + +fn issue5504() { + fn result_opt() -> Result, i32> { + Err(42) + } + + fn try_result_opt() -> Result { + while let Some(_) = r#try!(result_opt()) {} + if let Some(_) = r#try!(result_opt()) {} + Ok(42) + } + + try_result_opt(); + + if let Some(_) = m!() {} + while let Some(_) = m!() {} +} + +fn issue6065() { + macro_rules! if_let_in_macro { + ($pat:pat, $x:expr) => { + if let Some($pat) = $x {} + }; + } + + // shouldn't be linted + if_let_in_macro!(_, Some(42)); +} + +// Methods that are unstable const should not be suggested within a const context, see issue #5697. +// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const, +// so the following should be linted. +const fn issue6067() { + if let Ok(_) = Ok::(42) {} + + if let Err(_) = Err::(42) {} + + while let Ok(_) = Ok::(10) {} + + while let Err(_) = Ok::(10) {} + + match Ok::(42) { + Ok(_) => true, + Err(_) => false, + }; + + match Err::(42) { + Ok(_) => false, + Err(_) => true, + }; +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr new file mode 100644 index 00000000000..d6a46babb77 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr @@ -0,0 +1,154 @@ +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:15:12 + | +LL | if let Ok(_) = &result {} + | -------^^^^^---------- help: try this: `if result.is_ok()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:17:12 + | +LL | if let Ok(_) = Ok::(42) {} + | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:19:12 + | +LL | if let Err(_) = Err::(42) {} + | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:21:15 + | +LL | while let Ok(_) = Ok::(10) {} + | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:23:15 + | +LL | while let Err(_) = Ok::(10) {} + | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:33:5 + | +LL | / match Ok::(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; + | |_____^ help: try this: `Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:38:5 + | +LL | / match Ok::(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; + | |_____^ help: try this: `Ok::(42).is_err()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:43:5 + | +LL | / match Err::(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; + | |_____^ help: try this: `Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:48:5 + | +LL | / match Err::(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; + | |_____^ help: try this: `Err::(42).is_ok()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:53:20 + | +LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; + | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:59:20 + | +LL | let _ = if let Ok(_) = gen_res() { + | -------^^^^^------------ help: try this: `if gen_res().is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:61:19 + | +LL | } else if let Err(_) = gen_res() { + | -------^^^^^^------------ help: try this: `if gen_res().is_err()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_result.rs:84:19 + | +LL | while let Some(_) = r#try!(result_opt()) {} + | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_result.rs:85:16 + | +LL | if let Some(_) = r#try!(result_opt()) {} + | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_result.rs:91:12 + | +LL | if let Some(_) = m!() {} + | -------^^^^^^^------- help: try this: `if m!().is_some()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_result.rs:92:15 + | +LL | while let Some(_) = m!() {} + | ----------^^^^^^^------- help: try this: `while m!().is_some()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:110:12 + | +LL | if let Ok(_) = Ok::(42) {} + | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:112:12 + | +LL | if let Err(_) = Err::(42) {} + | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:114:15 + | +LL | while let Ok(_) = Ok::(10) {} + | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:116:15 + | +LL | while let Err(_) = Ok::(10) {} + | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:118:5 + | +LL | / match Ok::(42) { +LL | | Ok(_) => true, +LL | | Err(_) => false, +LL | | }; + | |_____^ help: try this: `Ok::(42).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:123:5 + | +LL | / match Err::(42) { +LL | | Ok(_) => false, +LL | | Err(_) => true, +LL | | }; + | |_____^ help: try this: `Err::(42).is_err()` + +error: aborting due to 22 previous errors + diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count.rs b/src/tools/clippy/tests/ui/size_of_in_element_count.rs new file mode 100644 index 00000000000..b13e390705a --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_in_element_count.rs @@ -0,0 +1,61 @@ +#![warn(clippy::size_of_in_element_count)] +#![allow(clippy::ptr_offset_with_cast)] + +use std::mem::{size_of, size_of_val}; +use std::ptr::{ + copy, copy_nonoverlapping, slice_from_raw_parts, slice_from_raw_parts_mut, swap_nonoverlapping, write_bytes, +}; +use std::slice::{from_raw_parts, from_raw_parts_mut}; + +fn main() { + const SIZE: usize = 128; + const HALF_SIZE: usize = SIZE / 2; + const DOUBLE_SIZE: usize = SIZE * 2; + let mut x = [2u8; SIZE]; + let mut y = [2u8; SIZE]; + + // Count is size_of (Should trigger the lint) + unsafe { copy_nonoverlapping::(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; + unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; + + unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::()) }; + unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::()) }; + unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::()) }; + unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::()) }; + + unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; + unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; + + unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::() * SIZE) }; + unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::() * SIZE) }; + + unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::() * SIZE) }; + + slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE); + slice_from_raw_parts(y.as_ptr(), size_of::() * SIZE); + + unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE) }; + unsafe { from_raw_parts(y.as_ptr(), size_of::() * SIZE) }; + + unsafe { y.as_mut_ptr().sub(size_of::()) }; + y.as_ptr().wrapping_sub(size_of::()); + unsafe { y.as_ptr().add(size_of::()) }; + y.as_mut_ptr().wrapping_add(size_of::()); + unsafe { y.as_ptr().offset(size_of::() as isize) }; + y.as_mut_ptr().wrapping_offset(size_of::() as isize); + + // Count expression involving multiplication of size_of (Should trigger the lint) + unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::() * SIZE) }; + + // Count expression involving nested multiplications of size_of (Should trigger the lint) + unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) }; + + // Count expression involving divisions of size_of (Should trigger the lint) + unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::() / 2) }; + + // No size_of calls (Should not trigger the lint) + unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) }; + + // Different types for pointee and size_of (Should not trigger the lint) + unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::() / 2 * SIZE) }; +} diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count.stderr new file mode 100644 index 00000000000..8cf3612abda --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_in_element_count.stderr @@ -0,0 +1,195 @@ +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:18:68 + | +LL | unsafe { copy_nonoverlapping::(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = note: `-D clippy::size-of-in-element-count` implied by `-D warnings` + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:19:62 + | +LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; + | ^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:21:49 + | +LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:22:64 + | +LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:23:51 + | +LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:24:66 + | +LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:26:47 + | +LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:27:47 + | +LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; + | ^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:29:46 + | +LL | unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:30:47 + | +LL | unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:32:66 + | +LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:34:46 + | +LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:35:38 + | +LL | slice_from_raw_parts(y.as_ptr(), size_of::() * SIZE); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:37:49 + | +LL | unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:38:41 + | +LL | unsafe { from_raw_parts(y.as_ptr(), size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:40:33 + | +LL | unsafe { y.as_mut_ptr().sub(size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:41:29 + | +LL | y.as_ptr().wrapping_sub(size_of::()); + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:42:29 + | +LL | unsafe { y.as_ptr().add(size_of::()) }; + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:43:33 + | +LL | y.as_mut_ptr().wrapping_add(size_of::()); + | ^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:44:32 + | +LL | unsafe { y.as_ptr().offset(size_of::() as isize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:45:36 + | +LL | y.as_mut_ptr().wrapping_offset(size_of::() as isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:48:62 + | +LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::() * SIZE) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:51:62 + | +LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: found a count of bytes instead of a count of elements of `T` + --> $DIR/size_of_in_element_count.rs:54:47 + | +LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::() / 2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type + +error: aborting due to 24 previous errors + diff --git a/src/tools/clippy/tests/ui/str_to_string.rs b/src/tools/clippy/tests/ui/str_to_string.rs new file mode 100644 index 00000000000..08f73402518 --- /dev/null +++ b/src/tools/clippy/tests/ui/str_to_string.rs @@ -0,0 +1,7 @@ +#![warn(clippy::str_to_string)] + +fn main() { + let hello = "hello world".to_string(); + let msg = &hello[..]; + msg.to_string(); +} diff --git a/src/tools/clippy/tests/ui/str_to_string.stderr b/src/tools/clippy/tests/ui/str_to_string.stderr new file mode 100644 index 00000000000..b1f73eda5d2 --- /dev/null +++ b/src/tools/clippy/tests/ui/str_to_string.stderr @@ -0,0 +1,19 @@ +error: `to_string()` called on a `&str` + --> $DIR/str_to_string.rs:4:17 + | +LL | let hello = "hello world".to_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::str-to-string` implied by `-D warnings` + = help: consider using `.to_owned()` + +error: `to_string()` called on a `&str` + --> $DIR/str_to_string.rs:6:5 + | +LL | msg.to_string(); + | ^^^^^^^^^^^^^^^ + | + = help: consider using `.to_owned()` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/string_to_string.rs b/src/tools/clippy/tests/ui/string_to_string.rs new file mode 100644 index 00000000000..4c66855f709 --- /dev/null +++ b/src/tools/clippy/tests/ui/string_to_string.rs @@ -0,0 +1,7 @@ +#![warn(clippy::string_to_string)] +#![allow(clippy::redundant_clone)] + +fn main() { + let mut message = String::from("Hello"); + let mut v = message.to_string(); +} diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr new file mode 100644 index 00000000000..1ebd17999bd --- /dev/null +++ b/src/tools/clippy/tests/ui/string_to_string.stderr @@ -0,0 +1,11 @@ +error: `to_string()` called on a `String` + --> $DIR/string_to_string.rs:6:17 + | +LL | let mut v = message.to_string(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::string-to-string` implied by `-D warnings` + = help: consider using `.clone()` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs new file mode 100644 index 00000000000..dd6f4ec7bd9 --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs @@ -0,0 +1,207 @@ +#![warn(clippy::suspicious_operation_groupings)] + +struct Vec3 { + x: f64, + y: f64, + z: f64, +} + +impl Eq for Vec3 {} + +impl PartialEq for Vec3 { + fn eq(&self, other: &Self) -> bool { + // This should trigger the lint because `self.x` is compared to `other.y` + self.x == other.y && self.y == other.y && self.z == other.z + } +} + +struct S { + a: i32, + b: i32, + c: i32, + d: i32, +} + +fn buggy_ab_cmp(s1: &S, s2: &S) -> bool { + // There's no `s1.b` + s1.a < s2.a && s1.a < s2.b +} + +struct SAOnly { + a: i32, +} + +impl S { + fn a(&self) -> i32 { + 0 + } +} + +fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SAOnly) -> bool { + // This is superficially similar to `buggy_ab_cmp`, but we should not suggest + // `s2.b` since that is invalid. + s1.a < s2.a && s1.a() < s1.b +} + +fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SAOnly) -> bool { + macro_rules! s1 { + () => { + S { + a: 1, + b: 1, + c: 1, + d: 1, + } + }; + } + + // This is superficially similar to `buggy_ab_cmp`, but we should not suggest + // `s2.b` since that is invalid. + s1.a < s2.a && s1!().a < s1.b +} + +fn do_not_give_bad_suggestions_for_this_incorrect_expr(s1: &S, s2: &SAOnly) -> bool { + // There's two `s1.b`, but we should not suggest `s2.b` since that is invalid + s1.a < s2.a && s1.b < s1.b +} + +fn permissable(s1: &S, s2: &S) -> bool { + // Something like this seems like it might actually be what is desired. + s1.a == s2.b +} + +fn non_boolean_operators(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d +} + +fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 { + // There's no `s2.b` + s1.a * s2.a + s1.b * s2.c + s1.c * s2.c +} + +fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 { + // There's no `s1.b` + s1.a * s2.a + s2.b * s2.b + s1.c * s2.c +} + +fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 { + // There's no `s2.b` + s1.a * s2.a + s1.b * s1.b + s1.c * s2.c +} + +fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 { + // There's no `s2.a` + s1.a * s1.a + s1.b * s2.b + s1.c * s2.c +} + +fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + s1.a * s2.a + s1.b * s2.b + s1.c * s1.c +} + +fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) { + ( + s1.b * s2.c - s1.c * s2.b, + s1.c * s2.a - s1.a * s2.c, + s1.a * s2.b - s1.b * s2.a, + ) +} + +fn outer_parens_simple(s1: &S, s2: &S) -> i32 { + // There's no `s2.b` + (s1.a * s2.a + s1.b * s1.b) +} + +fn outer_parens(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) +} + +fn inner_parens(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) +} + +fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) +} + +fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) +} + +fn all_parens_left_tree(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) +} + +fn all_parens_right_tree(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) +} + +fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 { + // There's no `s1.b` + (s1.a * s2.a + s2.b * s2.b) / 2 +} + +fn inside_function_call(s1: &S, s2: &S) -> i32 { + // There's no `s1.b` + i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) +} + +fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool { + // There's no `s1.c` + s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d +} + +fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool { + // There's no `s1.c` + s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d +} + +struct Nested { + inner: ((i32,), (i32,), (i32,)), +} + +fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool { + // There's no `n2.inner.2.0` + (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 +} + +// `eq_op` should catch this one. +fn changed_initial_ident(n1: &Nested, n2: &Nested) -> bool { + // There's no `n2.inner.0.0` + (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 +} + +fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool { + if strict { + s1.a < s2.a && s1.b < s2.b + } else { + // There's no `s1.b` in this subexpression + s1.a <= s2.a && s1.a <= s2.b + } +} + +fn inside_an_if_statement(s1: &S, s2: &S) { + // There's no `s1.b` + if s1.a < s2.a && s1.a < s2.b { + s1.c = s2.c; + } +} + +fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 { + // There's no `s2.c` + -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) +} + +fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 { + // There's no `s1.b` + -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr new file mode 100644 index 00000000000..ce7108217f1 --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr @@ -0,0 +1,166 @@ +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:14:9 + | +LL | self.x == other.y && self.y == other.y && self.z == other.z + | ^^^^^^^^^^^^^^^^^ help: I think you meant: `self.x == other.x` + | + = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:14:9 + | +LL | self.x == other.y && self.y == other.y && self.z == other.z + | ^^^^^^^^^^^^^^^^^ help: I think you meant: `self.x == other.x` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:27:20 + | +LL | s1.a < s2.a && s1.a < s2.b + | ^^^^^^^^^^^ help: I think you meant: `s1.b < s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:75:33 + | +LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:80:19 + | +LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:80:19 + | +LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:85:19 + | +LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:90:19 + | +LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:95:5 + | +LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c + | ^^^^^^^^^^^ help: I think you meant: `s1.a * s2.a` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:100:33 + | +LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:113:20 + | +LL | (s1.a * s2.a + s1.b * s1.b) + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:118:34 + | +LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:123:38 + | +LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:128:39 + | +LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:133:42 + | +LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:133:42 + | +LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:138:40 + | +LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:143:40 + | +LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) + | ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:148:20 + | +LL | (s1.a * s2.a + s2.b * s2.b) / 2 + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:153:35 + | +LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) + | ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:158:29 + | +LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d + | ^^^^^^^^^^^^ help: I think you meant: `s1.c == s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:163:17 + | +LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d + | ^^^^^^^^^^^^ help: I think you meant: `s1.c == s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:172:77 + | +LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: I think you meant: `(n1.inner.2).0 == (n2.inner.2).0` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:186:25 + | +LL | s1.a <= s2.a && s1.a <= s2.b + | ^^^^^^^^^^^^ help: I think you meant: `s1.b <= s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:192:23 + | +LL | if s1.a < s2.a && s1.a < s2.b { + | ^^^^^^^^^^^ help: I think you meant: `s1.b < s2.b` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:199:48 + | +LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) + | ^^^^^^^^^^^^^ help: I think you meant: `-s1.c * -s2.c` + +error: This sequence of operators looks suspiciously like a bug. + --> $DIR/suspicious_operation_groupings.rs:204:27 + | +LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) + | ^^^^^^^^^^^^^ help: I think you meant: `-s1.b < -s2.b` + +error: aborting due to 27 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index df9b227eeb3..e8f2fb46665 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -20,4 +20,7 @@ pub fn $a() -> $b { foo!(a, i32); foo!(b, f32); foo!(c, f64); + + // do not lint cast to cfg-dependant type + 1 as std::os::raw::c_char; } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed index 350da4965d1..7fbce58a82f 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed @@ -11,6 +11,8 @@ fn main() { let _ = -100_f32; let _ = -100_f64; let _ = -100_f64; + 100_f32; + 100_f64; // Should not trigger #[rustfmt::skip] let v = vec!(1); diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs index ad2fb2e6289..a71363ea4d2 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs @@ -11,6 +11,8 @@ fn main() { let _ = -100 as f32; let _ = -100 as f64; let _ = -100_i32 as f64; + 100. as f32; + 100. as f64; // Should not trigger #[rustfmt::skip] let v = vec!(1); diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.stderr b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.stderr index 5a210fc8909..3695a8f819c 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.stderr @@ -36,59 +36,71 @@ error: casting integer literal to `f64` is unnecessary LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` +error: casting float literal to `f32` is unnecessary + --> $DIR/unnecessary_cast_fixable.rs:14:5 + | +LL | 100. as f32; + | ^^^^^^^^^^^ help: try: `100_f32` + +error: casting float literal to `f64` is unnecessary + --> $DIR/unnecessary_cast_fixable.rs:15:5 + | +LL | 100. as f64; + | ^^^^^^^^^^^ help: try: `100_f64` + error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:25:5 + --> $DIR/unnecessary_cast_fixable.rs:27:5 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:26:5 + --> $DIR/unnecessary_cast_fixable.rs:28:5 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:27:5 + --> $DIR/unnecessary_cast_fixable.rs:29:5 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:28:5 + --> $DIR/unnecessary_cast_fixable.rs:30:5 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:29:5 + --> $DIR/unnecessary_cast_fixable.rs:31:5 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:31:5 + --> $DIR/unnecessary_cast_fixable.rs:33:5 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:32:5 + --> $DIR/unnecessary_cast_fixable.rs:34:5 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:36:13 + --> $DIR/unnecessary_cast_fixable.rs:38:13 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast_fixable.rs:37:13 + --> $DIR/unnecessary_cast_fixable.rs:39:13 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` -error: aborting due to 15 previous errors +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.rs b/src/tools/clippy/tests/ui/unnecessary_wraps.rs index a53dec8f91a..a4570098d71 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.rs +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.rs @@ -109,6 +109,13 @@ fn func13() -> Option { } } +fn issue_6384(s: &str) -> Option<&str> { + Some(match s { + "a" => "A", + _ => return None, + }) +} + fn main() { // method calls are not linted func1(true, true); diff --git a/src/tools/clippy/tests/ui/unreadable_literal.fixed b/src/tools/clippy/tests/ui/unreadable_literal.fixed index 4043d53299f..c2e38037add 100644 --- a/src/tools/clippy/tests/ui/unreadable_literal.fixed +++ b/src/tools/clippy/tests/ui/unreadable_literal.fixed @@ -10,6 +10,14 @@ macro_rules! foo { }; } +struct Bar(f32); + +macro_rules! bar { + () => { + Bar(100200300400.100200300400500) + }; +} + fn main() { let _good = ( 0b1011_i64, @@ -26,10 +34,12 @@ fn main() { let _good_sci = 1.1234e1; let _bad_sci = 1.123_456e1; - let _fail9 = 0x00ab_cdef; - let _fail10: u32 = 0xBAFE_BAFE; - let _fail11 = 0x0abc_deff; - let _fail12: i128 = 0x00ab_cabc_abca_bcab_cabc; + let _fail1 = 0x00ab_cdef; + let _fail2: u32 = 0xBAFE_BAFE; + let _fail3 = 0x0abc_deff; + let _fail4: i128 = 0x00ab_cabc_abca_bcab_cabc; + let _fail5 = 1.100_300_400; let _ = foo!(); + let _ = bar!(); } diff --git a/src/tools/clippy/tests/ui/unreadable_literal.rs b/src/tools/clippy/tests/ui/unreadable_literal.rs index e658a5f28c9..8296945b25e 100644 --- a/src/tools/clippy/tests/ui/unreadable_literal.rs +++ b/src/tools/clippy/tests/ui/unreadable_literal.rs @@ -10,6 +10,14 @@ macro_rules! foo { }; } +struct Bar(f32); + +macro_rules! bar { + () => { + Bar(100200300400.100200300400500) + }; +} + fn main() { let _good = ( 0b1011_i64, @@ -26,10 +34,12 @@ fn main() { let _good_sci = 1.1234e1; let _bad_sci = 1.123456e1; - let _fail9 = 0xabcdef; - let _fail10: u32 = 0xBAFEBAFE; - let _fail11 = 0xabcdeff; - let _fail12: i128 = 0xabcabcabcabcabcabc; + let _fail1 = 0xabcdef; + let _fail2: u32 = 0xBAFEBAFE; + let _fail3 = 0xabcdeff; + let _fail4: i128 = 0xabcabcabcabcabcabc; + let _fail5 = 1.100300400; let _ = foo!(); + let _ = bar!(); } diff --git a/src/tools/clippy/tests/ui/unreadable_literal.stderr b/src/tools/clippy/tests/ui/unreadable_literal.stderr index 8645cabeabb..8436aac17ac 100644 --- a/src/tools/clippy/tests/ui/unreadable_literal.stderr +++ b/src/tools/clippy/tests/ui/unreadable_literal.stderr @@ -1,5 +1,5 @@ error: digits of hex or binary literal not grouped by four - --> $DIR/unreadable_literal.rs:17:9 + --> $DIR/unreadable_literal.rs:25:9 | LL | 0x1_234_567, | ^^^^^^^^^^^ help: consider: `0x0123_4567` @@ -7,7 +7,7 @@ LL | 0x1_234_567, = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:17 + --> $DIR/unreadable_literal.rs:33:17 | LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -15,52 +15,58 @@ LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:31 + --> $DIR/unreadable_literal.rs:33:31 | LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:49 + --> $DIR/unreadable_literal.rs:33:49 | LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:61 + --> $DIR/unreadable_literal.rs:33:61 | LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:27:20 + --> $DIR/unreadable_literal.rs:35:20 | LL | let _bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:29:18 + --> $DIR/unreadable_literal.rs:37:18 | -LL | let _fail9 = 0xabcdef; +LL | let _fail1 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:30:24 + --> $DIR/unreadable_literal.rs:38:23 | -LL | let _fail10: u32 = 0xBAFEBAFE; - | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` +LL | let _fail2: u32 = 0xBAFEBAFE; + | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:31:19 + --> $DIR/unreadable_literal.rs:39:18 | -LL | let _fail11 = 0xabcdeff; - | ^^^^^^^^^ help: consider: `0x0abc_deff` +LL | let _fail3 = 0xabcdeff; + | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:32:25 + --> $DIR/unreadable_literal.rs:40:24 | -LL | let _fail12: i128 = 0xabcabcabcabcabcabc; - | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` +LL | let _fail4: i128 = 0xabcabcabcabcabcabc; + | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` -error: aborting due to 10 previous errors +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:41:18 + | +LL | let _fail5 = 1.100300400; + | ^^^^^^^^^^^ help: consider: `1.100_300_400` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed index b1e5742b785..c266f684a36 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed @@ -7,7 +7,8 @@ dead_code, clippy::single_match, clippy::wildcard_in_or_patterns, - clippy::unnested_or_patterns, clippy::diverging_sub_expression + clippy::unnested_or_patterns, + clippy::diverging_sub_expression )] use std::io::ErrorKind; diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs index cd3ec3ea8d2..2dbf726d5d0 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs @@ -7,7 +7,8 @@ dead_code, clippy::single_match, clippy::wildcard_in_or_patterns, - clippy::unnested_or_patterns, clippy::diverging_sub_expression + clippy::unnested_or_patterns, + clippy::diverging_sub_expression )] use std::io::ErrorKind; diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr index e03b3be43ed..0da2b68ba0b 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr @@ -1,5 +1,5 @@ error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:38:9 + --> $DIR/wildcard_enum_match_arm.rs:39:9 | LL | _ => eprintln!("Not red"), | ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` @@ -11,25 +11,25 @@ LL | #![deny(clippy::wildcard_enum_match_arm)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:42:9 + --> $DIR/wildcard_enum_match_arm.rs:43:9 | LL | _not_red => eprintln!("Not red"), | ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:46:9 + --> $DIR/wildcard_enum_match_arm.rs:47:9 | LL | not_red => format!("{:?}", not_red), | ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` error: wildcard match will miss any future added variants - --> $DIR/wildcard_enum_match_arm.rs:62:9 + --> $DIR/wildcard_enum_match_arm.rs:63:9 | LL | _ => "No red", | ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` error: match on non-exhaustive enum doesn't explicitly match all known variants - --> $DIR/wildcard_enum_match_arm.rs:79:9 + --> $DIR/wildcard_enum_match_arm.rs:80:9 | LL | _ => {}, | ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _` diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 7586f5aa3b5..0d4a755551a 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -28,7 +28,7 @@ MAINTAINERS = { 'rls': {'Xanewok'}, 'rustfmt': {'topecongiro', 'calebcartwright'}, 'book': {'carols10cents', 'steveklabnik'}, - 'nomicon': {'frewsxcv', 'Gankra'}, + 'nomicon': {'frewsxcv', 'Gankra', 'JohnTitor'}, 'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'}, 'rust-by-example': {'steveklabnik', 'marioidival'}, 'embedded-book': {'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof'}, diff --git a/src/tools/rls b/src/tools/rls index dab1468d6ae..2cf84baa5e3 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit dab1468d6aeed0e49f7d0569c1d2128b5a7751e0 +Subproject commit 2cf84baa5e3c55ac02f42919e67440acb5417125 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 337d65e4da4..11b175f9e80 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -64,6 +64,7 @@ features = [ byteorder = { version = "1", features = ['default', 'std'] } curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } crossbeam-utils = { version = "0.7.2", features = ["nightly"] } +libc = { version = "0.2.79", features = ["align"] } proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } serde = { version = "1.0.82", features = ['derive'] } diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 580d826e9b0..70ce18255f4 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 580d826e9b0f407a2d4b36696cda2f0fa8d7ddaa +Subproject commit 70ce18255f429caf0d75ecfed8c1464535ee779b