Deny-by-default lints

These lints are all set to the 'deny' level by default.

ambiguous-associated-items

The ambiguous_associated_items lint detects ambiguity between associated items and enum variants.

Example


#![allow(unused)]
fn main() {
enum E {
    V
}

trait Tr {
    type V;
    fn foo() -> Self::V;
}

impl Tr for E {
    type V = u8;
    // `Self::V` is ambiguous because it may refer to the associated type or
    // the enum variant.
    fn foo() -> Self::V { 0 }
}
}

This will produce:

error: ambiguous associated item
  --> lint_example.rs:15:17
   |
15 |     fn foo() -> Self::V { 0 }
   |                 ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V`
   |
   = note: `#[deny(ambiguous_associated_items)]` 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
note: `V` could refer to the variant defined here
  --> lint_example.rs:3:5
   |
3  |     V
   |     ^
note: `V` could also refer to the associated type defined here
  --> lint_example.rs:7:5
   |
7  |     type V;
   |     ^^^^^^^

Explanation

Previous versions of Rust did not allow accessing enum variants through type aliases. When this ability was added (see RFC 2338), this introduced some situations where it can be ambiguous what a type was referring to.

To fix this ambiguity, you should use a qualified path to explicitly state which type to use. For example, in the above example the function can be written as fn f() -> <Self as Tr>::V { 0 } to specifically refer to the associated type.

This is a future-incompatible lint to transition this to a hard error in the future. See issue #57644 for more details.

arithmetic-overflow

The arithmetic_overflow lint detects that an arithmetic operation will overflow.

Example


#![allow(unused)]
fn main() {
1_i32 << 32;
}

This will produce:

error: this arithmetic operation will overflow
 --> lint_example.rs:2:1
  |
2 | 1_i32 << 32;
  | ^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
  |
  = note: `#[deny(arithmetic_overflow)]` on by default

Explanation

It is very likely a mistake to perform an arithmetic operation that overflows its value. If the compiler is able to detect these kinds of overflows at compile-time, it will trigger this lint. Consider adjusting the expression to avoid overflow, or use a data type that will not overflow.

conflicting-repr-hints

The conflicting_repr_hints lint detects repr attributes with conflicting hints.

Example


#![allow(unused)]
fn main() {
#[repr(u32, u64)]
enum Foo {
    Variant1,
}
}

This will produce:

error[E0566]: conflicting representation hints
 --> lint_example.rs:2:8
  |
2 | #[repr(u32, u64)]
  |        ^^^  ^^^
  |
  = note: `#[deny(conflicting_repr_hints)]` 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 #68585 <https://github.com/rust-lang/rust/issues/68585>

Explanation

The compiler incorrectly accepted these conflicting representations in the past. This is a future-incompatible lint to transition this to a hard error in the future. See issue #68585 for more details.

To correct the issue, remove one of the conflicting hints.

const-err

The const_err lint detects an erroneous expression while doing constant evaluation.

Example


#![allow(unused)]
#![allow(unconditional_panic)]
fn main() {
let x: &'static i32 = &(1 / 0);
}

This will produce:

error: reaching this expression at runtime will panic or abort
 --> lint_example.rs:3:24
  |
3 | let x: &'static i32 = &(1 / 0);
  |                       -^^^^^^^
  |                        |
  |                        dividing by zero
  |
  = note: `#[deny(const_err)]` on by default

Explanation

This lint detects code that is very likely incorrect. If this lint is allowed, then the code will not be evaluated at compile-time, and instead continue to generate code to evaluate at runtime, which may panic during runtime.

Note that this lint may trigger in either inside or outside of a const context. Outside of a const context, the compiler can sometimes evaluate an expression at compile-time in order to generate more efficient code. As the compiler becomes better at doing this, it needs to decide what to do when it encounters code that it knows for certain will panic or is otherwise incorrect. Making this a hard error would prevent existing code that exhibited this behavior from compiling, breaking backwards-compatibility. However, this is almost certainly incorrect code, so this is a deny-by-default lint. For more details, see RFC 1229 and issue #28238.

Note that there are several other more specific lints associated with compile-time evaluation, such as arithmetic_overflow, unconditional_panic.

ill-formed-attribute-input

The ill_formed_attribute_input lint detects ill-formed attribute inputs that were previously accepted and used in practice.

Example


#![allow(unused)]
fn main() {
#[inline = "this is not valid"]
fn foo() {}
}

This will produce:

error: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
 --> lint_example.rs:2:1
  |
2 | #[inline = "this is not valid"]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(ill_formed_attribute_input)]` 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 #57571 <https://github.com/rust-lang/rust/issues/57571>

Explanation

Previously, inputs for many built-in attributes weren't validated and nonsensical attribute inputs were accepted. After validation was added, it was determined that some existing projects made use of these invalid forms. This is a future-incompatible lint to transition this to a hard error in the future. See issue #57571 for more details.

Check the attribute reference for details on the valid inputs for attributes.

incomplete-include

The incomplete_include lint detects the use of the include! macro with a file that contains more than one expression.

Example

fn main() {
    include!("foo.txt");
}

where the file foo.txt contains:

println!("hi!");

produces:

error: include macro expected single expression in source
 --> foo.txt:1:14
  |
1 | println!("1");
  |              ^
  |
  = note: `#[deny(incomplete_include)]` on by default

Explanation

The include! macro is currently only intended to be used to include a single expression or multiple items. Historically it would ignore any contents after the first expression, but that can be confusing. In the example above, the println! expression ends just before the semicolon, making the semicolon "extra" information that is ignored. Perhaps even more surprising, if the included file had multiple print statements, the subsequent ones would be ignored!

One workaround is to place the contents in braces to create a block expression. Also consider alternatives, like using functions to encapsulate the expressions, or use proc-macros.

This is a lint instead of a hard error because existing projects were found to hit this error. To be cautious, it is a lint for now. The future semantics of the include! macro are also uncertain, see issue #35560.

invalid-type-param-default

The invalid_type_param_default lint detects type parameter defaults erroneously allowed in an invalid location.

Example


#![allow(unused)]
fn main() {
fn foo<T=i32>(t: T) {}
}

This will produce:

error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
 --> lint_example.rs:2:8
  |
2 | fn foo<T=i32>(t: T) {}
  |        ^
  |
  = note: `#[deny(invalid_type_param_default)]` 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 #36887 <https://github.com/rust-lang/rust/issues/36887>

Explanation

Default type parameters were only intended to be allowed in certain situations, but historically the compiler allowed them everywhere. This is a future-incompatible lint to transition this to a hard error in the future. See issue #36887 for more details.

macro-expanded-macro-exports-accessed-by-absolute-paths

The macro_expanded_macro_exports_accessed_by_absolute_paths lint detects macro-expanded macro_export macros from the current crate that cannot be referred to by absolute paths.

Example

macro_rules! define_exported {
    () => {
        #[macro_export]
        macro_rules! exported {
            () => {};
        }
    };
}

define_exported!();

fn main() {
    crate::exported!();
}

This will produce:

error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
  --> lint_example.rs:13:5
   |
13 |     crate::exported!();
   |     ^^^^^^^^^^^^^^^
   |
   = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` 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 #52234 <https://github.com/rust-lang/rust/issues/52234>
note: the macro is defined here
  --> lint_example.rs:4:9
   |
4  | /         macro_rules! exported {
5  | |             () => {};
6  | |         }
   | |_________^
...
10 |   define_exported!();
   |   ------------------- in this macro invocation
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Explanation

The intent is that all macros marked with the #[macro_export] attribute are made available in the root of the crate. However, when a macro_rules! definition is generated by another macro, the macro expansion is unable to uphold this rule. This is a future-incompatible lint to transition this to a hard error in the future. See issue #53495 for more details.

mutable-transmutes

The mutable_transmutes lint catches transmuting from &T to &mut T because it is undefined behavior.

Example


#![allow(unused)]
fn main() {
unsafe {
    let y = std::mem::transmute::<&i32, &mut i32>(&5);
}
}

This will produce:

error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
 --> lint_example.rs:3:13
  |
3 |     let y = std::mem::transmute::<&i32, &mut i32>(&5);
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(mutable_transmutes)]` on by default

Explanation

Certain assumptions are made about aliasing of data, and this transmute violates those assumptions. Consider using UnsafeCell instead.

no-mangle-const-items

The no_mangle_const_items lint detects any const items with the no_mangle attribute.

Example


#![allow(unused)]
fn main() {
#[no_mangle]
const FOO: i32 = 5;
}

This will produce:

error: const items should never be `#[no_mangle]`
 --> lint_example.rs:3:1
  |
3 | const FOO: i32 = 5;
  | -----^^^^^^^^^^^^^^
  | |
  | help: try a static value: `pub static`
  |
  = note: `#[deny(no_mangle_const_items)]` on by default

Explanation

Constants do not have their symbols exported, and therefore, this probably means you meant to use a static, not a const.

order-dependent-trait-objects

The order_dependent_trait_objects lint detects a trait coherency violation that would allow creating two trait impls for the same dynamic trait object involving marker traits.

Example


#![allow(unused)]
fn main() {
pub trait Trait {}

impl Trait for dyn Send + Sync { }
impl Trait for dyn Sync + Send { }
}

This will produce:

error: conflicting implementations of trait `main::Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
 --> lint_example.rs:5:1
  |
4 | impl Trait for dyn Send + Sync { }
  | ------------------------------ first implementation here
5 | impl Trait for dyn Sync + Send { }
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
  |
  = note: `#[deny(order_dependent_trait_objects)]` 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 #56484 <https://github.com/rust-lang/rust/issues/56484>

Explanation

A previous bug caused the compiler to interpret traits with different orders (such as Send + Sync and Sync + Send) as distinct types when they were intended to be treated the same. This allowed code to define separate trait implementations when there should be a coherence error. This is a future-incompatible lint to transition this to a hard error in the future. See issue #56484 for more details.

overflowing-literals

The overflowing_literals lint detects literal out of range for its type.

Example


#![allow(unused)]
fn main() {
let x: u8 = 1000;
}

This will produce:

error: literal out of range for `u8`
 --> lint_example.rs:2:13
  |
2 | let x: u8 = 1000;
  |             ^^^^
  |
  = note: `#[deny(overflowing_literals)]` on by default
  = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255`

Explanation

It is usually a mistake to use a literal that overflows the type where it is used. Either use a literal that is within range, or change the type to be within the range of the literal.

patterns-in-fns-without-body

The patterns_in_fns_without_body lint detects mut identifier patterns as a parameter in functions without a body.

Example


#![allow(unused)]
fn main() {
trait Trait {
    fn foo(mut arg: u8);
}
}

This will produce:

error: patterns aren't allowed in functions without bodies
 --> lint_example.rs:3:12
  |
3 |     fn foo(mut arg: u8);
  |            ^^^^^^^
  |
  = note: `#[deny(patterns_in_fns_without_body)]` 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 #35203 <https://github.com/rust-lang/rust/issues/35203>

Explanation

To fix this, remove mut from the parameter in the trait definition; it can be used in the implementation. That is, the following is OK:


#![allow(unused)]
fn main() {
trait Trait {
    fn foo(arg: u8); // Removed `mut` here
}

impl Trait for i32 {
    fn foo(mut arg: u8) { // `mut` here is OK

    }
}
}

Trait definitions can define functions without a body to specify a function that implementors must define. The parameter names in the body-less functions are only allowed to be _ or an identifier for documentation purposes (only the type is relevant). Previous versions of the compiler erroneously allowed identifier patterns with the mut keyword, but this was not intended to be allowed. This is a future-incompatible lint to transition this to a hard error in the future. See issue #35203 for more details.

pub-use-of-private-extern-crate

The pub_use_of_private_extern_crate lint detects a specific situation of re-exporting a private extern crate.

Example


#![allow(unused)]
fn main() {
extern crate core;
pub use core as reexported_core;
}

This will produce:

error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
 --> lint_example.rs:3:9
  |
3 | pub use core as reexported_core;
  |         ^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(pub_use_of_private_extern_crate)]` 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 #34537 <https://github.com/rust-lang/rust/issues/34537>

Explanation

A public use declaration should not be used to publicly re-export a private extern crate. pub extern crate should be used instead.

This was historically allowed, but is not the intended behavior according to the visibility rules. This is a future-incompatible lint to transition this to a hard error in the future. See issue #34537 for more details.

soft-unstable

The soft_unstable lint detects unstable features that were unintentionally allowed on stable.

Example


#![allow(unused)]
fn main() {
#[cfg(test)]
extern crate test;

#[bench]
fn name(b: &mut test::Bencher) {
    b.iter(|| 123)
}
}

This will produce:

error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
 --> lint_example.rs:5:3
  |
5 | #[bench]
  |   ^^^^^
  |
  = note: `#[deny(soft_unstable)]` 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 #64266 <https://github.com/rust-lang/rust/issues/64266>

Explanation

The bench attribute was accidentally allowed to be specified on the stable release channel. Turning this to a hard error would have broken some projects. This lint allows those projects to continue to build correctly when --cap-lints is used, but otherwise signal an error that #[bench] should not be used on the stable channel. This is a future-incompatible lint to transition this to a hard error in the future. See issue #64266 for more details.

unconditional-panic

The unconditional_panic lint detects an operation that will cause a panic at runtime.

Example


#![allow(unused)]
fn main() {
#![allow(unused)]
let x = 1 / 0;
}

This will produce:

error: this operation will panic at runtime
 --> lint_example.rs:3:9
  |
3 | let x = 1 / 0;
  |         ^^^^^ attempt to divide `1_i32` by zero
  |
  = note: `#[deny(unconditional_panic)]` on by default

Explanation

This lint detects code that is very likely incorrect. When possible, the compiler will attempt to detect situations where code can be evaluated at compile-time to generate more efficient code. While evaluating such code, if it detects that the code will unconditionally panic, this usually indicates that it is doing something incorrectly. If this lint is allowed, then the code will not be evaluated at compile-time, and instead continue to generate code to evaluate at runtime, which may panic during runtime.

unknown-crate-types

The unknown_crate_types lint detects an unknown crate type found in a crate_type attribute.

Example

#![crate_type="lol"]
fn main() {}

This will produce:

error: invalid `crate_type` value
 --> lint_example.rs:1:15
  |
1 | #![crate_type="lol"]
  |               ^^^^^
  |
  = note: `#[deny(unknown_crate_types)]` on by default

Explanation

An unknown value give to the crate_type attribute is almost certainly a mistake.

useless-deprecated

The useless_deprecated lint detects deprecation attributes with no effect.

Example


#![allow(unused)]
fn main() {
struct X;

#[deprecated = "message"]
impl Default for X {
    fn default() -> Self {
        X
    }
}
}

This will produce:

error: this `#[deprecated]` annotation has no effect
 --> lint_example.rs:4:1
  |
4 | #[deprecated = "message"]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute
  |
  = note: `#[deny(useless_deprecated)]` on by default

Explanation

Deprecation attributes have no effect on trait implementations.