Skip to content

New lint: relative_path_in_macro_definition #14472

Open
@y86-dev

Description

@y86-dev

What it does

Check for relative paths (such as core::ops::BitOr) being used in macros.

When writing declarative macros, one should always refer to items using their absolute path (paths starting with :: or using $crate or be keywords such as Self). That is because users might declare a module with the same name as the first component of the path and thus change the meaning of the macro.

Advantage

This change prevents macros from changing their meaning depending on the context:

macro_rules! derive_bit_or {
   ($t:ident) => {
        impl core::ops::BitOr for $t {
            type Output = Self;
            fn bitor(self, rhs: Self) -> Self {
                Self(self.0 | rhs.0)
            }
        }
    }
}

mod bar {
    struct Bar(u32);
    derive_bit_or!(Bar);
    mod core {}
}

This code fails to compile, because the path core::ops::BitOr is relative and thus the custom core module defined in mod bar is used instead of the core crate.

Drawbacks

Increase verbosity and thus decrease readability of declarative macros.

Example

macro_rules! derive_bit_or {
   ($t:ident) => {
        impl core::ops::BitOr for $t {
            type Output = Self;
            fn bitor(self, rhs: Self) -> Self {
                Self(self.0 | rhs.0)
            }
        }
    }
}

Could be written as:

macro_rules! derive_bit_or {
   ($t:ident) => {
        impl ::core::ops::BitOr for $t {
            type Output = Self;
            fn bitor(self, rhs: Self) -> Self {
                Self(self.0 | rhs.0)
            }
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions