Deny-by-default lints - The rustc book

# Deny-by-default lints

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

- `ambiguous_associated_items`
- `arithmetic_overflow`
- `conflicting_repr_hints`
- `const_err`
- `ill_formed_attribute_input`
- `incomplete_include`
- `invalid_type_param_default`
- `macro_expanded_macro_exports_accessed_by_absolute_paths`
- `missing_fragment_specifier`
- `mutable_transmutes`
- `no_mangle_const_items`
- `order_dependent_trait_objects`
- `overflowing_literals`
- `patterns_in_fns_without_body`
- `pub_use_of_private_extern_crate`
- `soft_unstable`
- `unconditional_panic`
- `unknown_crate_types`
- `useless_deprecated`

## 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.

## missing-fragment-specifier

The `missing_fragment_specifier` lint is issued when an unused pattern in a `macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not followed by a fragment specifier (e.g. `:expr`).

This warning can always be fixed by removing the unused pattern in the `macro_rules!` macro definition.

### Example

    macro_rules! foo {
       () => {};
       ($name) => { };
    }

    fn main() {
       foo!();
    }

This will produce:

    error: missing fragment specifier
     --> lint_example.rs:3:5
      |
    3 |    ($name) => { };
      |     ^^^^^
      |
      = note: `#[deny(missing_fragment_specifier)]` 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 #40107 <https://github.com/rust-lang/rust/issues/40107>

### Explanation

To fix this, remove the unused pattern from the `macro_rules!` macro definition:

    macro_rules! foo {
        () => {};
    }
    fn main() {
        foo!();
    }

## 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.