"quine-mc_cluskey",
"quote",
"regex-syntax",
+ "rustc-semver",
"semver 0.11.0",
"serde",
"smallvec 1.4.2",
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"
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
[[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",
"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",
[[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",
"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"
dependencies = [
"byteorder",
"crossbeam-utils 0.7.2",
+ "libc",
"proc-macro2",
"quote",
"serde",
version = "0.0.0"
dependencies = [
"cfg-if 0.1.10",
- "md-5 0.9.1",
+ "md-5",
"rustc_arena",
"rustc_data_structures",
"rustc_index",
[[package]]
name = "rustfmt-nightly"
-version = "1.4.27"
+version = "1.4.29"
dependencies = [
"annotate-snippets 0.6.1",
"anyhow",
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
}
};
- Some(op)
+ Some((op, *op_sp))
})
.collect();
} = *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, .. }
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.
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!(),
-A method was implemented on a primitive type.
+A method or constant was implemented on a primitive type.
Erroneous code example:
// `#[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:
```
// 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>,
#[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],
}
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, .. }
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));
}
let canon_value = Canonical {
max_universe: ty::UniverseIndex::ROOT,
variables: List::empty(),
- value: value.clone(),
+ value,
};
return canon_value;
}
"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 <https://github.com/rust-lang/rust/issues/32408>",
+ edition: None,
+ };
+}
+
declare_tool_lint! {
pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
Deny,
UNINHABITED_STATIC,
FUNCTION_ITEM_REFERENCES,
USELESS_DEPRECATED,
+ UNSUPPORTED_NAKED_FUNCTIONS,
]
}
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));
pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>;
-/// 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<const N: usize>(&self) -> usize { N }
+/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] }
+/// // ^ const parameter
/// }
/// struct B;
/// impl B {
-/// fn foo<const N: u8>(&self) -> usize { 42 }
+/// fn foo<const M: u8>(&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)]
///
/// 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<DefId>,
}
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<Self::BreakTy> {
if !c.needs_subst() {
}
match c.val {
- ty::ConstKind::Param(..) => ControlFlow::BREAK,
+ ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
_ => c.super_visit_with(self),
}
}
}
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) => {
}
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(())
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() }
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(),
}
}
}
}
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);
};
// 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 { .. }
// 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, .. }
}
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 {
+//! 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(
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) => {}
}
}
-/// 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<Self::Map> {
.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<Span> = 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<Self::Map> {
+ 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);
+ }
+}
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 {
// 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,
/// 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<Ty<'tcx>>;
-
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- 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<Self::BreakTy> {
- 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;
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
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;
}
}
+ #[derive(Debug)]
+ struct ProhibitOpaqueVisitor<'tcx> {
+ 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<Self::BreakTy> {
+ 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,
..
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
if snippet == "Self" {
- if let Some(ty) = ty {
- err.span_suggestion(
- span,
- "consider spelling out the type instead",
- format!("{:?}", ty),
- Applicability::MaybeIncorrect,
- );
- }
+ err.span_suggestion(
+ span,
+ "consider spelling out the type instead",
+ format!("{:?}", ty),
+ Applicability::MaybeIncorrect,
+ );
}
}
err.emit();
}
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);
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,
};
"bool",
"bool",
item.span,
+ assoc_items,
);
}
ty::Char => {
"char",
"char",
item.span,
+ assoc_items,
);
}
ty::Str => {
"str",
"str",
item.span,
+ assoc_items,
);
}
ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
"slice_u8",
"[u8]",
item.span,
+ assoc_items,
);
}
ty::Slice(_) => {
"slice",
"[T]",
item.span,
+ assoc_items,
);
}
ty::Array(_, _) => {
"array",
"[T; N]",
item.span,
+ assoc_items,
);
}
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
"const_slice_ptr",
"*const [T]",
item.span,
+ assoc_items,
);
}
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
"mut_slice_ptr",
"*mut [T]",
item.span,
+ assoc_items,
);
}
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
"const_ptr",
"*const T",
item.span,
+ assoc_items,
);
}
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
"mut_ptr",
"*mut T",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::I8) => {
"i8",
"i8",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::I16) => {
"i16",
"i16",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::I32) => {
"i32",
"i32",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::I64) => {
"i64",
"i64",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::I128) => {
"i128",
"i128",
item.span,
+ assoc_items,
);
}
ty::Int(ast::IntTy::Isize) => {
"isize",
"isize",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::U8) => {
"u8",
"u8",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::U16) => {
"u16",
"u16",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::U32) => {
"u32",
"u32",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::U64) => {
"u64",
"u64",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::U128) => {
"u128",
"u128",
item.span,
+ assoc_items,
);
}
ty::Uint(ast::UintTy::Usize) => {
"usize",
"usize",
item.span,
+ assoc_items,
);
}
ty::Float(ast::FloatTy::F32) => {
"f32",
"f32",
item.span,
+ assoc_items,
);
}
ty::Float(ast::FloatTy::F64) => {
"f64",
"f64",
item.span,
+ assoc_items,
);
}
ty::Error(_) => {}
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() => {
// 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,
lang,
ty
)
- .span_help(span, "consider using a trait to implement these methods")
+ .help(&format!("consider using a trait{}", to_implement))
.emit();
}
}
}
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, .. }
ControlFlow::Break(x) => Some(x),
}
}
+
+ /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` 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<T, F>(self, f: F) -> ControlFlow<T, C>
+ where
+ F: FnOnce(B) -> T,
+ {
+ match self {
+ ControlFlow::Continue(x) => ControlFlow::Continue(x),
+ ControlFlow::Break(x) => ControlFlow::Break(f(x)),
+ }
+ }
}
impl<R: Try> ControlFlow<R, R::Ok> {
/// 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:
///
/// ```
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),
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,
}
}
// 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")
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<BufReader<Take<_>>>` type. Thus its result is only valid
(**self).drain_to(writer, limit)
}
+ fn taken(&mut self, bytes: u64) {
+ (**self).taken(bytes);
+ }
+
fn min_limit(&self) -> u64 {
(**self).min_limit()
}
Ok(bytes_drained)
}
+ fn taken(&mut self, bytes: u64) {
+ self.set_limit(self.limit() - bytes);
+ self.get_mut().taken(bytes);
+ }
+
fn min_limit(&self) -> u64 {
min(Take::limit(self), self.get_ref().min_limit())
}
Ok(bytes as u64 + inner_bytes)
}
+ fn taken(&mut self, bytes: u64) {
+ self.get_mut().taken(bytes);
+ }
+
fn min_limit(&self) -> u64 {
self.get_ref().min_limit()
}
}
pub(super) enum CopyResult {
- Ended(Result<u64>),
+ 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
///
// - 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() {
assert_eq!(written, 0);
CopyResult::Fallback(0)
}
- _ => CopyResult::Ended(Err(err)),
+ _ => CopyResult::Error(err, written),
};
}
}
}
- CopyResult::Ended(Ok(written))
+ CopyResult::Ended(written)
}
#[derive(PartialEq)]
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)
}
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))?;
);
match probe {
- CopyResult::Ended(Ok(1)) => {
+ CopyResult::Ended(1) => {
// splice works
}
_ => {
}
#[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<String, VarError>) -> Option<OsString> {
match var {
Ok(var) => Some(OsString::from(var)),
cfg_if::cfg_if! {
if #[cfg(unix)] {
- use std::path::PathBuf;
-
let oldhome = var_to_os_string(var("HOME"));
set_var("HOME", "/home/MountainView");
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"));
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,
} 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(())
/// 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,
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<String>,
/// 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.
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,
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,
pub end: (usize, usize),
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Deprecation {
pub since: Option<String>,
pub note: Option<String>,
}
#[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
}
#[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<GenericArg>, bindings: Vec<TypeBinding> },
}
#[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,
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<GenericBound>),
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,
}
#[serde(untagged)]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum ItemEnum {
ModuleItem(Module),
ExternCrateItem {
},
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Module {
pub is_crate: bool,
pub items: Vec<Id>,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Struct {
pub struct_type: StructType,
pub generics: Generics,
pub impls: Vec<Id>,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Enum {
pub generics: Generics,
pub variants_stripped: bool,
#[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<Type>),
}
#[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,
pub abi: String,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Method {
pub decl: FnDecl,
pub generics: Generics,
pub has_body: bool,
}
-#[derive(Clone, Debug, Default, Serialize, Deserialize)]
+#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct Generics {
pub params: Vec<GenericParamDef>,
pub where_predicates: Vec<WherePredicate>,
}
-#[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<GenericBound>, default: Option<Type> },
}
#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
RegionPredicate { lifetime: String, bounds: Vec<GenericBound> },
}
#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum GenericBound {
TraitBound {
#[serde(rename = "trait")]
}
#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum TraitBoundModifier {
None,
Maybe,
#[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 {
},
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct FunctionPointer {
pub is_unsafe: bool,
pub generic_params: Vec<GenericParamDef>,
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<Type>,
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,
pub implementors: Vec<Id>,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct TraitAlias {
pub generics: Generics,
pub params: Vec<GenericBound>,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Impl {
pub is_unsafe: bool,
pub generics: Generics,
}
#[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,
pub glob: bool,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ProcMacro {
pub kind: MacroKind,
pub helpers: Vec<String>,
}
#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum MacroKind {
/// A bang macro `foo!()`.
Bang,
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<GenericBound>,
pub generics: Generics,
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Static {
#[serde(rename = "type")]
pub type_: Type,
--- /dev/null
+{
+ "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
--- /dev/null
+// edition:2018
+pub mod l1 {
+ pub mod l3 {
+ pub struct L4;
+ }
+ pub use l3::L4;
+}
--- /dev/null
+#![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<T> {
+ cv_stack: T,
+}
+
+unsafe impl<T: Default> Send for Hasher<T> {}
+
+// @has foo/struct.Foo.html
+// @has - '//code' 'impl Send for Foo'
+pub struct Foo {
+ hasher: Hasher<[u8; 3]>,
+}
+++ /dev/null
-#![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<T> {
- cv_stack: T,
-}
-
-unsafe impl<T: Default> Send for Hasher<T> {}
-
-// @has foo/struct.Foo.html
-// @has - '//code' 'impl Send for Foo'
-pub struct Foo {
- hasher: Hasher<[u8; 3]>,
-}
--- /dev/null
+// 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<std::ptr::NonNull<u8>>,
+ //~^ 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>() -> 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));
+}
--- /dev/null
+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<std::ptr::NonNull<u8>>,
+ | ^^^^^^^^^^^^^^
+
+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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/32408>
+
+error: aborting due to 8 previous errors; 19 warnings emitted
+
+++ /dev/null
-// 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<std::ptr::NonNull<u8>>,
- //~^ 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
-}
+++ /dev/null
-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<std::ptr::NonNull<u8>>,
- | ^^^^^^^^^^^^^^
-
-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
-
+++ /dev/null
-#![crate_name = "Vec"]
-
-pub fn new(arg1: f32, arg2: ()) {}
+++ /dev/null
-pub struct S;
-
-impl S {
- pub fn external(&self) {}
-}
|
LL | foo::<_, {[1]}>();
| ^
+ |
+ = help: const arguments cannot yet be inferred with `_`
error[E0308]: mismatched types
--> $DIR/issue-62878.rs:11:15
--- /dev/null
+#![feature(min_const_generics)]
+fn foo<const N: usize, const K: usize>(data: [u32; N]) -> [u32; K] {
+ [0; K]
+}
+fn main() {
+ let a = foo::<_, 2>([0, 1, 2]);
+ //~^ ERROR type provided when a constant was expected
+}
--- /dev/null
+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`.
--- /dev/null
+#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
+ //~| ERROR cannot determine resolution for the derive macro `Copy`
+
+fn main() {}
--- /dev/null
+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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
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);
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
+++ /dev/null
-// 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() { }
+++ /dev/null
-// 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
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+#![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() {}
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]
| ^^^^^^^^
= 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]
| ^^^^^^^^
const _: () = {
fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
- //~^ 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
const _: () = {
fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
- //~^ ERROR: expected one of `>`, const, lifetime, or type, found `=`
+ //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `=`
};
fn main() {}
-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<dyn X< : 32 >>) {}
- | ^ 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
|
| 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<dyn X< = 32 >>) {}
- | ^ 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
+++ /dev/null
-// 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<T>() {}
-
-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::<A>(); //~ ERROR: cannot find type `A` in this scope
- foo::<C>(); //~ ERROR: cannot find type `C` in this scope
- foo::<D>(); //~ ERROR: cannot find type `D` in this scope
-}
-
-mod other {
- pub fn import() {}
-}
+++ /dev/null
-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::<A>();
- | ^
- |
-help: an enum with a similar name exists
- |
-LL | foo::<B>();
- | ^
-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::<C>();
- | ^
- |
-help: an enum with a similar name exists
- |
-LL | foo::<B>();
- | ^
-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::<D>();
- | ^
- |
-help: an enum with a similar name exists
- |
-LL | foo::<B>();
- | ^
-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`.
+++ /dev/null
-// 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() { }
+++ /dev/null
-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`.
+++ /dev/null
-// 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() { }
+++ /dev/null
-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`.
+++ /dev/null
-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();
-}
+++ /dev/null
-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`.
+++ /dev/null
-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();
-}
+++ /dev/null
-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`.
+++ /dev/null
-// error-pattern: unresolved
-use main::bar;
-
-fn main() { println!("foo"); }
+++ /dev/null
-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`.
+++ /dev/null
-// error-pattern: import
-
-
-mod a { pub use b::foo; }
-mod b { pub use a::foo; }
-
-fn main() { println!("loop"); }
+++ /dev/null
-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`.
--- /dev/null
+pub trait Foo {}
--- /dev/null
+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 {}
--- /dev/null
+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() {}
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() { }
--- /dev/null
+// 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<T>() {}
+
+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::<A>(); //~ ERROR: cannot find type `A` in this scope
+ foo::<C>(); //~ ERROR: cannot find type `C` in this scope
+ foo::<D>(); //~ ERROR: cannot find type `D` in this scope
+}
+
+mod other {
+ pub fn import() {}
+}
--- /dev/null
+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::<A>();
+ | ^
+ |
+help: an enum with a similar name exists
+ |
+LL | foo::<B>();
+ | ^
+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::<C>();
+ | ^
+ |
+help: an enum with a similar name exists
+ |
+LL | foo::<B>();
+ | ^
+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::<D>();
+ | ^
+ |
+help: an enum with a similar name exists
+ |
+LL | foo::<B>();
+ | ^
+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`.
--- /dev/null
+// 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(); }
-// 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();
+}
--- /dev/null
+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`.
--- /dev/null
+// run-pass
+
+use zed::bar;
+
+mod zed {
+ pub fn bar() { println!("bar"); }
+}
+
+pub fn main() { bar(); }
-// 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(); }
--- /dev/null
+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`.
--- /dev/null
+// 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(); }
-// 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"); }
--- /dev/null
+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`.
--- /dev/null
+// run-pass
+
+use zed::bar;
+
+mod zed {
+ pub fn bar() { println!("bar"); }
+}
+
+pub fn main() { let _zed = 42; bar(); }
-// 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"); }
--- /dev/null
+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`.
--- /dev/null
+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();
+}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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() {}
--- /dev/null
+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`.
--- /dev/null
+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() {}
--- /dev/null
+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`.
--- /dev/null
+#![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;
+}
--- /dev/null
+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`.
--- /dev/null
+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() {
+}
--- /dev/null
+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`.
--- /dev/null
+// compile-flags: --test
+
+#![allow(soft_unstable)]
+#![test] //~ ERROR cannot determine resolution for the attribute macro `test`
--- /dev/null
+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
+
--- /dev/null
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+use foo::{}; //~ ERROR unresolved import `foo`
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
+ //~^ no `f` in `m`
+
+mod m {}
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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`
+}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
+ //~^ no `Foo` in `bar`
+mod bar {
+ use Foo;
+}
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// aux-build:issue-36881-aux.rs
+
+fn main() {
+ extern crate issue_36881_aux;
+ use issue_36881_aux::Foo; //~ ERROR unresolved import
+}
--- /dev/null
+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`.
--- /dev/null
+fn main() {
+ extern crate libc; //~ ERROR use of unstable
+ use libc::*; //~ ERROR unresolved import
+}
--- /dev/null
+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 <https://github.com/rust-lang/rust/issues/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`.
--- /dev/null
+// 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`
+}
--- /dev/null
+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`.
--- /dev/null
+// 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`
+}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// run-rustfix
+
+extern crate std as other_std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
--- /dev/null
+// run-rustfix
+
+extern crate std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
--- /dev/null
+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`.
--- /dev/null
+pub const FOO: usize = *&0;
--- /dev/null
+pub const FOO: usize = *&0;
--- /dev/null
+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() {}
--- /dev/null
+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`.
--- /dev/null
+mod foo {
+ pub struct A;
+ pub struct B;
+}
+
+use foo::{A, A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+mod foo {
+ pub struct A;
+ pub struct B;
+}
+
+use foo::{A, B as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_b;
+use std as issue_45829_b;
+//~^ ERROR is defined multiple times
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+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() {}
--- /dev/null
+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`.
--- /dev/null
+use std::{collections::HashMap as A, sync::Arc as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+use core;
+use std as core;
+//~^ ERROR is defined multiple times
+
+fn main() {
+ 1 + 1;
+}
--- /dev/null
+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`.
--- /dev/null
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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() {
+}
--- /dev/null
+// 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() {}
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+use std::time::{foo, bar, buzz};
+//~^ ERROR unresolved imports
+use std::time::{abc, def};
+//~^ ERROR unresolved imports
+fn main(){
+ println!("Hello World!");
+}
--- /dev/null
+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`.
--- /dev/null
+// 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]
+}
--- /dev/null
+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`.
--- /dev/null
+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() {
+}
--- /dev/null
+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`.
--- /dev/null
+#[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() {}
--- /dev/null
+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`.
--- /dev/null
+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() {}
--- /dev/null
+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`.
+++ /dev/null
-pub trait Foo {}
+++ /dev/null
-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 {}
+++ /dev/null
-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() {}
+++ /dev/null
-#![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()));
-}
+++ /dev/null
-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();
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
type Type_3<T> = Box<T,,>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-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<T> = Box<T,,>;
- | ^ expected one of `>`, const, lifetime, or type
+ | ^ expected one of `>`, a const expression, lifetime, or type
error: aborting due to previous error
type Type_4<T> = 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, ()>;
-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<T> = 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
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 `,`
-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
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 `,`
-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
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 `,`
-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
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
+++ /dev/null
-#![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;
-}
+++ /dev/null
-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`.
+++ /dev/null
-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() {
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-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`.
+++ /dev/null
-// compile-flags: --test
-
-#![allow(soft_unstable)]
-#![test] //~ ERROR cannot determine resolution for the attribute macro `test`
+++ /dev/null
-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
-
+++ /dev/null
-// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
-
-use foo::{}; //~ ERROR unresolved import `foo`
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
- //~^ no `f` in `m`
-
-mod m {}
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
+++ /dev/null
-#![warn(unused)]
-#![deny(warnings)]
-use std::thread;
-//~^ ERROR: unused import
-fn main() {}
+++ /dev/null
-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
-
+++ /dev/null
-// 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`
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
- //~^ no `Foo` in `bar`
-mod bar {
- use Foo;
-}
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
- //~| ERROR cannot determine resolution for the derive macro `Copy`
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-// aux-build:issue-36881-aux.rs
-
-fn main() {
- extern crate issue_36881_aux;
- use issue_36881_aux::Foo; //~ ERROR unresolved import
-}
+++ /dev/null
-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`.
+++ /dev/null
-fn main() {
- extern crate libc; //~ ERROR use of unstable
- use libc::*; //~ ERROR unresolved import
-}
+++ /dev/null
-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 <https://github.com/rust-lang/rust/issues/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`.
+++ /dev/null
-// 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`
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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`
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// run-rustfix
-
-extern crate std as other_std;
-fn main() {}
-//~^^ ERROR the name `std` is defined multiple times [E0259]
+++ /dev/null
-// run-rustfix
-
-extern crate std;
-fn main() {}
-//~^^ ERROR the name `std` is defined multiple times [E0259]
+++ /dev/null
-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`.
+++ /dev/null
-pub const FOO: usize = *&0;
+++ /dev/null
-pub const FOO: usize = *&0;
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
+++ /dev/null
-mod foo {
- pub struct A;
- pub struct B;
-}
-
-use foo::{A, A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-mod foo {
- pub struct A;
- pub struct B;
-}
-
-use foo::{A, B as A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-// aux-build:issue-45829-b.rs
-
-extern crate issue_45829_b;
-use std as issue_45829_b;
-//~^ ERROR is defined multiple times
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
+++ /dev/null
-use std::{collections::HashMap as A, sync::Arc as A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-use core;
-use std as core;
-//~^ ERROR is defined multiple times
-
-fn main() {
- 1 + 1;
-}
+++ /dev/null
-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`.
+++ /dev/null
-#![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() {}
+++ /dev/null
-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
-
+++ /dev/null
-use self; //~ERROR `self` imports are only allowed within a { } list
-
-fn main() {}
+++ /dev/null
-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`.
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-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
-
+++ /dev/null
-// 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() {}
+++ /dev/null
-// 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() {}
+++ /dev/null
-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`.
+++ /dev/null
-use std::time::{foo, bar, buzz};
-//~^ ERROR unresolved imports
-use std::time::{abc, def};
-//~^ ERROR unresolved imports
-fn main(){
- println!("Hello World!");
-}
+++ /dev/null
-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`.
+++ /dev/null
-// check-pass
-
-struct T {}
-
-fn main() {}
+++ /dev/null
-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!");
-}
+++ /dev/null
-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`.
+++ /dev/null
-// 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]
-}
+++ /dev/null
-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`.
+++ /dev/null
-#![deny(unused_imports)]
-
-struct S;
-
-fn main() {
- use S; //~ ERROR the item `S` is imported redundantly
-
- let _s = S;
-}
+++ /dev/null
-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
-
+++ /dev/null
-// compile-flags: --edition=2018
-// run-pass
-
-macro_rules! regex {
- //~^ WARN unused macro definition
- () => {};
-}
-
-#[allow(dead_code)]
-use regex;
-//~^ WARN unused import
-
-fn main() {}
+++ /dev/null
-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
-
+++ /dev/null
-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() {
-}
+++ /dev/null
-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`.
+++ /dev/null
-#[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() {}
+++ /dev/null
-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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+// check-pass
+
+struct T {}
+
+fn main() {}
--- /dev/null
+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!");
+}
--- /dev/null
+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`.
type mut_box = Box<mut isize>;
-//~^ ERROR expected one of `>`, const, lifetime, or type, found keyword `mut`
+//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut`
-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<mut isize>;
- | ^^^ expected one of `>`, const, lifetime, or type
+ | ^^^ expected one of `>`, a const expression, lifetime, or type
error: aborting due to previous error
+++ /dev/null
-// run-pass
-// check that type parameters can't "shadow" qualified paths.
-
-fn check<Clone>(_c: Clone) {
- fn check2() {
- let _ = <() as std::clone::Clone>::clone(&());
- }
- check2();
-}
-
-fn main() { check(()); }
--- /dev/null
+#![crate_name = "Vec"]
+
+pub fn new(arg1: f32, arg2: ()) {}
--- /dev/null
+pub struct S;
+
+impl S {
+ pub fn external(&self) {}
+}
--- /dev/null
+// 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
+}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+// 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
+}
--- /dev/null
+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
+
--- /dev/null
+// run-pass
+// check that type parameters can't "shadow" qualified paths.
+
+fn check<Clone>(_c: Clone) {
+ fn check2() {
+ let _ = <() as std::clone::Clone>::clone(&());
+ }
+ check2();
+}
+
+fn main() { check(()); }
+++ /dev/null
-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() {}
+++ /dev/null
-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`.
-#![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() {}
| ^^^^^^^^^^^^^^^
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]
| ^^^^^^^^^^^^^^^
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
--- /dev/null
+#![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()));
+}
--- /dev/null
+// 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() {
+}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+#![warn(unused)]
+#![deny(warnings)]
+use std::thread;
+//~^ ERROR: unused import
+fn main() {}
--- /dev/null
+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
+
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
--- /dev/null
+#![deny(unused_imports)]
+
+struct S;
+
+fn main() {
+ use S; //~ ERROR the item `S` is imported redundantly
+
+ let _s = S;
+}
--- /dev/null
+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
+
--- /dev/null
+// compile-flags: --edition=2018
+// run-pass
+
+macro_rules! regex {
+ //~^ WARN unused macro definition
+ () => {};
+}
+
+#[allow(dead_code)]
+use regex;
+//~^ WARN unused import
+
+fn main() {}
--- /dev/null
+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
+
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
[`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
[`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
[`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
- [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)
[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
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]
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"]
```
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
```
```
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).
}
#[must_use]
-pub fn gen_register_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
- 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<Item = &'a Lint>,
+ usable_lints: impl Iterator<Item = &'a Lint>,
+) -> Vec<String> {
+ 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::<Vec<String>>();
- 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
"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;
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 <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
url = { version = "2.1.0", features = ["serde"] }
[features]
deny-warnings = []
+# build clippy with internal lints enabled, off by default
+internal-lints = []
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::{
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};
--- /dev/null
+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<Result<u64, String>>) {
+ /// let n = match opt {
+ /// Some(n) => match n {
+ /// Ok(n) => n,
+ /// _ => return,
+ /// }
+ /// None => return,
+ /// };
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// fn func(opt: Option<Result<u64, String>>) {
+ /// 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 <local> { .. }
+ 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
+ // ..<local>.. => match <local> { .. }
+ 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<Span> {
+ 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
+}
/// **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
// 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 {
"`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.
///
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};
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,
}
}
}
-
-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
- )
-}
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<T,E>.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;
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);
}
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
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 {
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;
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;
+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! {
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);
}
}
-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<Self::Map> {
- intravisit::NestedVisitorMap::None
- }
-}
-
fn check_assign<'tcx>(
cx: &LateContext<'tcx>,
decl: hir::HirId,
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);
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
-}
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;
mod checked_conversions;
mod cognitive_complexity;
mod collapsible_if;
+mod collapsible_match;
mod comparison_chain;
mod copies;
mod copy_iterator;
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;
"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",
// 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,
&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,
&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,
&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,
]);
// 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);
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);
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);
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());
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);
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);
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,
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::<FxHashSet<_>>();
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),
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),
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),
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),
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),
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),
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),
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),
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),
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),
"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",
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
/// ```
pub UNREADABLE_LITERAL,
pedantic,
- "long integer literal without underscores"
+ "long literal without underscores"
}
declare_clippy_lint! {
}
}
-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,
}
if let ExprKind::Lit(ref lit) = expr.kind {
- Self::check_lit(cx, lit)
+ self.check_lit(cx, lit)
}
}
}
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);
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,
/// 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<Item = &'a str>, radix: Radix) -> Result<Option<usize>, WarningType> {
+ fn get_group_size<'a>(
+ groups: impl Iterator<Item = &'a str>,
+ radix: Radix,
+ lint_unreadable: bool,
+ ) -> Result<Option<usize>, WarningType> {
let mut groups = groups.map(str::len);
let first = groups.next().expect("At least one group");
} else {
Ok(Some(second))
}
- } else if first > 5 {
+ } else if first > 5 && lint_unreadable {
Err(WarningType::UnreadableLiteral)
} else {
Ok(None)
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,
ExprKind::InlineAsm(ref asm) => asm
.operands
.iter()
- .map(|o| match o {
+ .map(|(o, _)| match o {
InlineAsmOperand::In { expr, .. }
| InlineAsmOperand::InOut { expr, .. }
| InlineAsmOperand::Const { expr }
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;
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);
}
}
}
-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<Self::Map> {
- NestedVisitorMap::None
- }
-}
-
struct VarVisitor<'a, 'tcx> {
/// context reference
cx: &'a LateContext<'tcx>,
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
};
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;
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(
}
}
+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<Self::Map> {
+ 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<Vec<IterFunction>> {
-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.
///
"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<RustcVersion>,
+}
+
+impl ManualNonExhaustive {
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> 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);
_ => {},
}
}
+
+ extract_msrv_attr!(EarlyContext);
}
fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
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;
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
"suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
}
-declare_lint_pass!(ManualStrip => [MANUAL_STRIP]);
+pub struct ManualStrip {
+ msrv: Option<RustcVersion>,
+}
+
+impl ManualStrip {
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> Self {
+ Self { msrv }
+ }
+}
+
+impl_lint_pass!(ManualStrip => [MANUAL_STRIP]);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
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;
}
}
}
+
+ extract_msrv_attr!(LateContext);
}
// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
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 {
/// }
/// ```
pub MAP_ERR_IGNORE,
- pedantic,
+ restriction,
"`map_err` should not ignore the original error"
}
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| ...`)",
);
}
}
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};
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};
}
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
/// **Example:**
///
/// ```rust
+ /// # use std::task::Poll;
+ /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
/// if let Ok(_) = Ok::<i32, i32>(42) {}
/// if let Err(_) = Err::<i32, i32>(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::<i32, i32>(42) {
/// Ok(_) => true,
/// Err(_) => false,
/// The more idiomatic use would be:
///
/// ```rust
+ /// # use std::task::Poll;
+ /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
/// if Ok::<i32, i32>(42).is_ok() {}
/// if Err::<i32, i32>(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::<i32, i32>(42).is_ok();
/// ```
pub REDUNDANT_PATTERN_MATCHING,
///
/// **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
#[derive(Default)]
pub struct Matches {
+ msrv: Option<RustcVersion>,
infallible_destructuring_match_linted: bool,
}
+impl Matches {
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> Self {
+ Self {
+ msrv,
+ ..Matches::default()
+ }
+ }
+}
+
impl_lint_pass!(Matches => [
SINGLE_MATCH,
MATCH_REF_PATS,
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) {
}
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);
}
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();
}
}
}
+
+ extract_msrv_attr!(LateContext);
}
#[rustfmt::skip]
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()));
}
}
}
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()
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)
"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;
}
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,
};
"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
}
"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
}
if_chain! {
if let hir::ExprKind::Call(func, args) = &expr.kind;
if args.is_empty();
- if let hir::ExprKind::Path(path) = &func.kind;
- if let hir::QPath::TypeRelative(_, segment) = path;
+ if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind;
then {
match &*segment.ident.as_str() {
"max_value" => return Some(MinMax::Max),
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};
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! {
"use `.collect()` instead of `::from_iter()`"
}
-declare_lint_pass!(Methods => [
+pub struct Methods {
+ msrv: Option<RustcVersion>,
+}
+
+impl Methods {
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> Self {
+ Self { msrv }
+ }
+}
+
+impl_lint_pass!(Methods => [
UNWRAP_USED,
EXPECT_USED,
SHOULD_IMPLEMENT_TRAIT,
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"),
}
}
}
+
+ extract_msrv_attr!(LateContext);
}
/// Checks for the `OR_FUN_CALL` lint.
);
}
+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>,
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]);
}
}
-// 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<Self::Map> {
- 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;
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! {
}
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.
///
/// ```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! {
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;
},
_ => {},
}
}
}
}
+
+fn check_binary(
+ cx: &LateContext<'a>,
+ expr: &Expr<'_>,
+ cmp: &rustc_span::source_map::Spanned<rustc_hir::BinOpKind>,
+ 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",
+ );
+ }
+ };
+ }
+}
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};
}
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)
}
/// ```
pub UNREACHABLE,
restriction,
- "`unreachable!` should not be present in production code"
+ "usage of the `unreachable!` macro"
}
declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
} 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");
}
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);
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>;
fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
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
--- /dev/null
+//! 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::<T>` or `size_of_val::<T>` 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::<u8>() * SIZE) };
+ /// ```
+ pub SIZE_OF_IN_ELEMENT_COUNT,
+ correctness,
+ "using `size_of::<T>` or `size_of_val::<T>` 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<Ty<'tcx>> {
+ 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
+ );
+ }
+ };
+ }
+}
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;
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! {
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;
}
}
}
+
+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()`",
+ );
+ }
+ }
+ }
+}
--- /dev/null
+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::<Vec<_>>());
+
+ 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<Ident>,
+ binop: &BinaryOp<'_>,
+ location: IdentLocation,
+ applicability: &mut Applicability,
+) -> Option<String> {
+ 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<Vec<BinaryOp<'_>>> {
+ append_opt_vecs(chained_binops(kind), if_statment_binops(kind))
+}
+
+fn if_statment_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> {
+ 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<A>(target_opt: Option<Vec<A>>, source_opt: Option<Vec<A>>) -> Option<Vec<A>> {
+ 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<Vec<BinaryOp<'_>>> {
+ 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<Vec<BinaryOp<'expr>>> {
+ 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<Iterable: Into<IdentIter>>(
+ 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<Ident> {
+ IdentIter::from(expr).nth(location.index)
+}
+
+fn suggestion_with_swapped_ident(
+ cx: &EarlyContext<'_>,
+ expr: &Expr,
+ location: IdentLocation,
+ new_ident: Ident,
+ applicability: &mut Applicability,
+) -> Option<String> {
+ 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<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
+where
+ Iter: Iterator<Item = A>,
+{
+ iter.enumerate()
+ .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
+}
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 {
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)
}
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,
fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option<GenericBounds<'tcx>> {
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 {
// 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 {
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) {
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,
);
}
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;
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
diag.multipart_suggestion(
"...and change the returning expressions",
suggs,
- Applicability::MachineApplicable,
+ Applicability::MaybeIncorrect,
);
},
);
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<X>(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)))
--- /dev/null
+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<Ident>);
+
+impl Iterator for IdentIter {
+ type Item = Ident;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<Ident>);
+
+impl Visitor<'_> for IdentCollector {
+ fn visit_ident(&mut self, ident: Ident) {
+ self.0.push(ident);
+ }
+}
DeprecationStatus::Replaced("cognitive_complexity"),
),
("dump", DeprecationStatus::None),
+ ("msrv", DeprecationStatus::None),
];
pub struct LimitStack {
}
}
+pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option<ast::Attribute> {
+ 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 {
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<String>, 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<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
/// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
(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<String>, Vec::<String>::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 {
/// |
/// = 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,
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));
}
}
}
- 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)
},
}
}
+/// 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>,
}
}
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);
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, .. }
pub mod higher;
mod hir_utils;
pub mod inspector;
+#[cfg(feature = "internal-lints")]
pub mod internal_lints;
pub mod numeric_literal;
pub mod paths;
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;
use crate::consts::{constant, Constant};
+pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
+ 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]
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<Self::Map> {
+ 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
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"];
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", "<impl f32>", "EPSILON"];
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"];
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"];
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"];
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", "<impl [T]>", "into_vec"];
pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl 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"];
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"];
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;
!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<T>(&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<Self::Map> {
+ NestedVisitorMap::None
+ }
+}
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)
}
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<tester::TestDescAndFn>) -> Result<bool, io::Error> {
let mut result = true;
Some("main.rs") => {},
_ => continue,
}
-
let paths = compiletest::common::TestPaths {
file: file_path,
base: config.src_base.clone(),
run_mode(&mut config);
run_ui_toml(&mut config);
run_ui_cargo(&mut config);
+ run_internal_tests(&mut config);
}
}
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")
.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));
--- /dev/null
+// 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<Span>,
+ 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<Span>,
+ 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() {}
--- /dev/null
+// 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<Span>,
+ 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<Span>,
+ 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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() {}
--- /dev/null
+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
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
--- /dev/null
+#![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", "<impl 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() {}
--- /dev/null
+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
+
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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() {}
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+msrv = "invalid.version"
--- /dev/null
+#![allow(clippy::redundant_clone)]
+
+fn main() {}
--- /dev/null
+error: error reading Clippy's configuration file. `invalid.version` is not a valid Rust version
+
+error: aborting due to previous error
+
--- /dev/null
+unreadable-literal-lint-fractions = false
\ No newline at end of file
--- /dev/null
+#[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;
+}
--- /dev/null
+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
+
--- /dev/null
+msrv = "1.0.0"
--- /dev/null
+#![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();
+}
-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
-#[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();
}
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;
| ^^^^^^^^^^^
= 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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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;
| ^^^^^^^^^^^^^^^^
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
+ };
+}
--- /dev/null
+#![warn(clippy::collapsible_match)]
+#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+
+fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, 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<Option<u32>, String>, res_res: Result<Result<u32, String>, 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<T> {
+ A(T),
+ B(T),
+ C(T),
+ };
+ match make::<E<Option<u32>>>() {
+ E::A(val) | E::B(val) => match val {
+ Some(n) => foo(n),
+ _ => return,
+ },
+ _ => return,
+ }
+ match make::<Option<E<u32>>>() {
+ Some(val) => match val {
+ E::A(val) | E::B(val) => foo(val),
+ _ => return,
+ },
+ _ => return,
+ }
+}
+
+fn make<T>() -> T {
+ unimplemented!()
+}
+
+fn foo<T, U>(t: T) -> U {
+ unimplemented!()
+}
+
+fn take<T>(t: T) {}
+
+fn main() {}
--- /dev/null
+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
+
--- /dev/null
+#![warn(clippy::collapsible_match)]
+#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+
+fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, 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>() -> T {
+ unimplemented!()
+}
+
+fn foo<T, U>(t: T) -> U {
+ unimplemented!()
+}
+
+fn main() {}
--- /dev/null
+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
+
+++ /dev/null
-// 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<Span>,
- 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<Span>,
- 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() {}
+++ /dev/null
-// 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<Span>,
- 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<Span>,
- 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() {}
+++ /dev/null
-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
-
+++ /dev/null
-// 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() {}
+++ /dev/null
-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
+++ /dev/null
-#![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() {}
+++ /dev/null
-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
-
-#[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)]
-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
-#[warn(str_to_string)]
-#[warn(string_to_string)]
#[warn(unstable_as_slice)]
#[warn(unstable_as_mut_slice)]
#[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`
- --> $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
// 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
+}
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
+++ /dev/null
-#![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", "<impl 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() {}
+++ /dev/null
-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
-
b!();
println!("{}", a);
}
+
+fn semicolon() {
+ struct S {
+ a: u32,
+ };
+ impl S {
+ fn new(a: u32) -> Self {
+ Self { a }
+ }
+ }
+
+ let _ = S::new(3);
+}
+++ /dev/null
-#![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() {}
+++ /dev/null
-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
-
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(())
}
-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
+++ /dev/null
-#![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() {}
+++ /dev/null
-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
-
--- /dev/null
+#![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!");
+ }
+ }
+}
--- /dev/null
+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(<stripped>) = s.strip_prefix("hello, ") {
+LL | assert_eq!(<stripped>.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(<stripped>) = s.strip_prefix("hello, ") {
+LL | assert_eq!(<stripped>.to_uppercase(), "WORLD!");
+ |
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "invalid.version"]
+
+fn main() {}
--- /dev/null
+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
+
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
--- /dev/null
+#![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()
+}
--- /dev/null
+#![feature(custom_inner_attributes)]
+
+#[clippy::msrv = "invalid.version"]
+fn main() {}
--- /dev/null
+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
+
#![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
}
+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;
| ^^^^^
= 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
let sample = vec![a.clone(), "b".to_string(), "c".to_string()];
let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
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::<Vec<_>>();
+ 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::<Vec<_>>();
+
+ // Fix #6297
+ let sample = [1; 5];
+ let multiple_indirect = sample.iter().collect::<Vec<_>>();
+ 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::<Vec<_>>();
+ }
}
+++ /dev/null
-// 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() {}
+++ /dev/null
-// 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() {}
+++ /dev/null
-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
-
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!();
|
= 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");
|
= 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");
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!();
+++ /dev/null
-// 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<usize, usize> = Err(5);
- if result.is_ok() {}
-
- if Ok::<i32, i32>(42).is_ok() {}
-
- if Err::<i32, i32>(42).is_err() {}
-
- while Ok::<i32, i32>(10).is_ok() {}
-
- while Ok::<i32, i32>(10).is_err() {}
-
- if Ok::<i32, i32>(42).is_ok() {}
-
- if Err::<i32, i32>(42).is_err() {}
-
- if let Ok(x) = Ok::<i32, i32>(42) {
- println!("{}", x);
- }
-
- Ok::<i32, i32>(42).is_ok();
-
- Ok::<i32, i32>(42).is_err();
-
- Err::<i32, i32>(42).is_err();
-
- Err::<i32, i32>(42).is_ok();
-
- let _ = if Ok::<usize, ()>(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<Option<i32>, i32> {
- Err(42)
- }
-
- fn try_result_opt() -> Result<i32, i32> {
- 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::<i32, i32>(42).is_ok() {}
-
- if Err::<i32, i32>(42).is_err() {}
-
- while Ok::<i32, i32>(10).is_ok() {}
-
- while Ok::<i32, i32>(10).is_err() {}
-
- Ok::<i32, i32>(42).is_ok();
-
- Err::<i32, i32>(42).is_err();
-}
+++ /dev/null
-// 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<usize, usize> = Err(5);
- if let Ok(_) = &result {}
-
- if let Ok(_) = Ok::<i32, i32>(42) {}
-
- if let Err(_) = Err::<i32, i32>(42) {}
-
- while let Ok(_) = Ok::<i32, i32>(10) {}
-
- while let Err(_) = Ok::<i32, i32>(10) {}
-
- if Ok::<i32, i32>(42).is_ok() {}
-
- if Err::<i32, i32>(42).is_err() {}
-
- if let Ok(x) = Ok::<i32, i32>(42) {
- println!("{}", x);
- }
-
- match Ok::<i32, i32>(42) {
- Ok(_) => true,
- Err(_) => false,
- };
-
- match Ok::<i32, i32>(42) {
- Ok(_) => false,
- Err(_) => true,
- };
-
- match Err::<i32, i32>(42) {
- Ok(_) => false,
- Err(_) => true,
- };
-
- match Err::<i32, i32>(42) {
- Ok(_) => true,
- Err(_) => false,
- };
-
- let _ = if let Ok(_) = Ok::<usize, ()>(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<Option<i32>, i32> {
- Err(42)
- }
-
- fn try_result_opt() -> Result<i32, i32> {
- 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::<i32, i32>(42) {}
-
- if let Err(_) = Err::<i32, i32>(42) {}
-
- while let Ok(_) = Ok::<i32, i32>(10) {}
-
- while let Err(_) = Ok::<i32, i32>(10) {}
-
- match Ok::<i32, i32>(42) {
- Ok(_) => true,
- Err(_) => false,
- };
-
- match Err::<i32, i32>(42) {
- Ok(_) => false,
- Err(_) => true,
- };
-}
+++ /dev/null
-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::<i32, i32>(42) {}
- | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:20:12
- |
-LL | if let Err(_) = Err::<i32, i32>(42) {}
- | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:22:15
- |
-LL | while let Ok(_) = Ok::<i32, i32>(10) {}
- | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:24:15
- |
-LL | while let Err(_) = Ok::<i32, i32>(10) {}
- | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:34:5
- |
-LL | / match Ok::<i32, i32>(42) {
-LL | | Ok(_) => true,
-LL | | Err(_) => false,
-LL | | };
- | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:39:5
- |
-LL | / match Ok::<i32, i32>(42) {
-LL | | Ok(_) => false,
-LL | | Err(_) => true,
-LL | | };
- | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:44:5
- |
-LL | / match Err::<i32, i32>(42) {
-LL | | Ok(_) => false,
-LL | | Err(_) => true,
-LL | | };
- | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:49:5
- |
-LL | / match Err::<i32, i32>(42) {
-LL | | Ok(_) => true,
-LL | | Err(_) => false,
-LL | | };
- | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:54:20
- |
-LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
- | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(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::<i32, i32>(42) {}
- | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:113:12
- |
-LL | if let Err(_) = Err::<i32, i32>(42) {}
- | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:115:15
- |
-LL | while let Ok(_) = Ok::<i32, i32>(10) {}
- | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:117:15
- |
-LL | while let Err(_) = Ok::<i32, i32>(10) {}
- | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching.rs:119:5
- |
-LL | / match Ok::<i32, i32>(42) {
-LL | | Ok(_) => true,
-LL | | Err(_) => false,
-LL | | };
- | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching.rs:124:5
- |
-LL | / match Err::<i32, i32>(42) {
-LL | | Ok(_) => false,
-LL | | Err(_) => true,
-LL | | };
- | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
-
-error: aborting due to 22 previous errors
-
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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,
+ };
+}
--- /dev/null
+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
+
#![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() {}
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();
None
}
-fn takes_bool(_: bool) {}
-
fn foo() {}
fn bar() {}
#![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::<()> {}
};
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();
None
}
-fn takes_bool(_: bool) {}
-
fn foo() {}
fn bar() {}
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()`
= 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,
| |_____^ 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,
| |_____^ 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::<()> {
| _____________^
| |_____^ 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,
| |_____^ 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,
--- /dev/null
+// 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::<i32>.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();
+}
--- /dev/null
+// 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::<i32>.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,
+ };
+}
--- /dev/null
+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
+
--- /dev/null
+// 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<usize, usize> = Err(5);
+ if result.is_ok() {}
+
+ if Ok::<i32, i32>(42).is_ok() {}
+
+ if Err::<i32, i32>(42).is_err() {}
+
+ while Ok::<i32, i32>(10).is_ok() {}
+
+ while Ok::<i32, i32>(10).is_err() {}
+
+ if Ok::<i32, i32>(42).is_ok() {}
+
+ if Err::<i32, i32>(42).is_err() {}
+
+ if let Ok(x) = Ok::<i32, i32>(42) {
+ println!("{}", x);
+ }
+
+ Ok::<i32, i32>(42).is_ok();
+
+ Ok::<i32, i32>(42).is_err();
+
+ Err::<i32, i32>(42).is_err();
+
+ Err::<i32, i32>(42).is_ok();
+
+ let _ = if Ok::<usize, ()>(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<Option<i32>, i32> {
+ Err(42)
+ }
+
+ fn try_result_opt() -> Result<i32, i32> {
+ 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::<i32, i32>(42).is_ok() {}
+
+ if Err::<i32, i32>(42).is_err() {}
+
+ while Ok::<i32, i32>(10).is_ok() {}
+
+ while Ok::<i32, i32>(10).is_err() {}
+
+ Ok::<i32, i32>(42).is_ok();
+
+ Err::<i32, i32>(42).is_err();
+}
--- /dev/null
+// 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<usize, usize> = Err(5);
+ if let Ok(_) = &result {}
+
+ if let Ok(_) = Ok::<i32, i32>(42) {}
+
+ if let Err(_) = Err::<i32, i32>(42) {}
+
+ while let Ok(_) = Ok::<i32, i32>(10) {}
+
+ while let Err(_) = Ok::<i32, i32>(10) {}
+
+ if Ok::<i32, i32>(42).is_ok() {}
+
+ if Err::<i32, i32>(42).is_err() {}
+
+ if let Ok(x) = Ok::<i32, i32>(42) {
+ println!("{}", x);
+ }
+
+ match Ok::<i32, i32>(42) {
+ Ok(_) => true,
+ Err(_) => false,
+ };
+
+ match Ok::<i32, i32>(42) {
+ Ok(_) => false,
+ Err(_) => true,
+ };
+
+ match Err::<i32, i32>(42) {
+ Ok(_) => false,
+ Err(_) => true,
+ };
+
+ match Err::<i32, i32>(42) {
+ Ok(_) => true,
+ Err(_) => false,
+ };
+
+ let _ = if let Ok(_) = Ok::<usize, ()>(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<Option<i32>, i32> {
+ Err(42)
+ }
+
+ fn try_result_opt() -> Result<i32, i32> {
+ 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::<i32, i32>(42) {}
+
+ if let Err(_) = Err::<i32, i32>(42) {}
+
+ while let Ok(_) = Ok::<i32, i32>(10) {}
+
+ while let Err(_) = Ok::<i32, i32>(10) {}
+
+ match Ok::<i32, i32>(42) {
+ Ok(_) => true,
+ Err(_) => false,
+ };
+
+ match Err::<i32, i32>(42) {
+ Ok(_) => false,
+ Err(_) => true,
+ };
+}
--- /dev/null
+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::<i32, i32>(42) {}
+ | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:19:12
+ |
+LL | if let Err(_) = Err::<i32, i32>(42) {}
+ | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:21:15
+ |
+LL | while let Ok(_) = Ok::<i32, i32>(10) {}
+ | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:23:15
+ |
+LL | while let Err(_) = Ok::<i32, i32>(10) {}
+ | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:33:5
+ |
+LL | / match Ok::<i32, i32>(42) {
+LL | | Ok(_) => true,
+LL | | Err(_) => false,
+LL | | };
+ | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:38:5
+ |
+LL | / match Ok::<i32, i32>(42) {
+LL | | Ok(_) => false,
+LL | | Err(_) => true,
+LL | | };
+ | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:43:5
+ |
+LL | / match Err::<i32, i32>(42) {
+LL | | Ok(_) => false,
+LL | | Err(_) => true,
+LL | | };
+ | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:48:5
+ |
+LL | / match Err::<i32, i32>(42) {
+LL | | Ok(_) => true,
+LL | | Err(_) => false,
+LL | | };
+ | |_____^ help: try this: `Err::<i32, i32>(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::<usize, ()>(4) { true } else { false };
+ | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(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::<i32, i32>(42) {}
+ | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:112:12
+ |
+LL | if let Err(_) = Err::<i32, i32>(42) {}
+ | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:114:15
+ |
+LL | while let Ok(_) = Ok::<i32, i32>(10) {}
+ | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:116:15
+ |
+LL | while let Err(_) = Ok::<i32, i32>(10) {}
+ | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:118:5
+ |
+LL | / match Ok::<i32, i32>(42) {
+LL | | Ok(_) => true,
+LL | | Err(_) => false,
+LL | | };
+ | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:123:5
+ |
+LL | / match Err::<i32, i32>(42) {
+LL | | Ok(_) => false,
+LL | | Err(_) => true,
+LL | | };
+ | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
+
+error: aborting due to 22 previous errors
+
--- /dev/null
+#![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::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+ 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::<u8>()) };
+ unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+ unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+ unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+
+ unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+ unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+
+ unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
+ unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
+
+ unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+
+ slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+ slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+
+ unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+ unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+
+ unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+ y.as_ptr().wrapping_sub(size_of::<u8>());
+ unsafe { y.as_ptr().add(size_of::<u8>()) };
+ y.as_mut_ptr().wrapping_add(size_of::<u8>());
+ unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+ y.as_mut_ptr().wrapping_offset(size_of::<u8>() 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::<u8>() * 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::<u8>() / 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::<u16>() / 2 * SIZE) };
+}
--- /dev/null
+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::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>() * 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::<u8>() * 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::<u8>() * 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::<u8>() * 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::<u8>() * 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::<u8>() * 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::<u8>() * 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>());
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>()) };
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>());
+ | ^^^^^^^^^^^^^^^
+ |
+ = 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::<u8>() 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::<u8>() 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::<u8>() * 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::<u8>() / 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
+
--- /dev/null
+#![warn(clippy::str_to_string)]
+
+fn main() {
+ let hello = "hello world".to_string();
+ let msg = &hello[..];
+ msg.to_string();
+}
--- /dev/null
+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
+
--- /dev/null
+#![warn(clippy::string_to_string)]
+#![allow(clippy::redundant_clone)]
+
+fn main() {
+ let mut message = String::from("Hello");
+ let mut v = message.to_string();
+}
--- /dev/null
+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
+
--- /dev/null
+#![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() {}
--- /dev/null
+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
+
foo!(a, i32);
foo!(b, f32);
foo!(c, f64);
+
+ // do not lint cast to cfg-dependant type
+ 1 as std::os::raw::c_char;
}
let _ = -100_f32;
let _ = -100_f64;
let _ = -100_f64;
+ 100_f32;
+ 100_f64;
// Should not trigger
#[rustfmt::skip]
let v = vec!(1);
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);
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
}
}
+fn issue_6384(s: &str) -> Option<&str> {
+ Some(match s {
+ "a" => "A",
+ _ => return None,
+ })
+}
+
fn main() {
// method calls are not linted
func1(true, true);
};
}
+struct Bar(f32);
+
+macro_rules! bar {
+ () => {
+ Bar(100200300400.100200300400500)
+ };
+}
+
fn main() {
let _good = (
0b1011_i64,
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!();
}
};
}
+struct Bar(f32);
+
+macro_rules! bar {
+ () => {
+ Bar(100200300400.100200300400500)
+ };
+}
+
fn main() {
let _good = (
0b1011_i64,
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!();
}
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`
= 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`
= 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
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;
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;
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`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 | _`
'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'},
-Subproject commit dab1468d6aeed0e49f7d0569c1d2128b5a7751e0
+Subproject commit 2cf84baa5e3c55ac02f42919e67440acb5417125
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'] }
-Subproject commit 580d826e9b0f407a2d4b36696cda2f0fa8d7ddaa
+Subproject commit 70ce18255f429caf0d75ecfed8c1464535ee779b