Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New correctness lint: uninhabited_reference #11851

Closed
pitaj opened this issue Nov 21, 2023 · 2 comments · Fixed by #11878
Closed

New correctness lint: uninhabited_reference #11851

pitaj opened this issue Nov 21, 2023 · 2 comments · Fixed by #11878
Labels
A-lint Area: New lints

Comments

@pitaj
Copy link
Contributor

pitaj commented Nov 21, 2023

What it does

This lint will trigger whenever using a reference to an uninhabited type, such as !, Infallible, or Void.

This should apply recursively, like when a struct has an uninhabited field. But care should be taken that this applies to an enum type only when all variants are uninhabited, such that &Result<(), !> does not trigger the lint.

Advantage

Creating a reference to an uninhabited type is a footgun at best and UB at worst, and can only be achieved via unsafe code. Essentially, it's never correct to have a reference to an uninhabited type.

Drawbacks

No response

Example

// This function shouldn't be possible to call
fn impossible(_thing: &Infallible) {}

fn foo(thing: &Infallible) {
    // But we call it here because somehow we have a reference
    impossible(thing);
}

Should be denied wholesale.

@pitaj pitaj added the A-lint Area: New lints label Nov 21, 2023
@Nadrieril
Copy link
Member

Nadrieril commented Nov 21, 2023

Creating a reference to an uninhabited type is UB and can only be achieved via unsafe code.

This is not fully true: it is not decided yet whether that is UB, see rust-lang/unsafe-code-guidelines#413. It is however unsafe to do so; in other words, a safe value of type &Void cannot exist. Dereferencing such a value is instant UB.

If I may add, the motivation for the OP lint is the unfortunate case of using *const Void to denote an extern type. Having a *const Void in safe code is fine. If a bindings library ever exposed a &Void to safe code however, that would be terribly unsound.

@RalfJung
Copy link
Member

To quote Jules Bertholet who put this very well on Zulip:

As soon as you have an &Uninhabited, you have broken a safety invariant; usually the size of the space between safety and validity invariant is treated as a private implementation detail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants