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

Spurious unreachable_patterns with macro #80501

Closed
lnicola opened this issue Dec 30, 2020 · 11 comments · Fixed by #80632
Closed

Spurious unreachable_patterns with macro #80501

lnicola opened this issue Dec 30, 2020 · 11 comments · Fixed by #80632
Assignees
Labels
A-exhaustiveness-checking Relating to exhaustiveness / usefulness checking of patterns A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Milestone

Comments

@lnicola
Copy link
Member

lnicola commented Dec 30, 2020

Code

I tried this code:

pub enum TypeCtor {
    Bool,
    Slice,
    Array,
}

pub struct ApplicationTy {
    pub ctor: TypeCtor,
    pub parameters: (),
}

pub enum Ty {
    Apply(ApplicationTy),
}

macro_rules! ty_app {
    ($ctor:pat, $param:pat) => {
        crate::Ty::Apply(crate::ApplicationTy {
            ctor: $ctor,
            parameters: $param,
        })
    };
    ($ctor:pat) => {
        ty_app!($ctor, _)
    };
}

fn _foo(ty: Ty) {
    match ty {
        ty_app!(TypeCtor::Array, _st) | ty_app!(TypeCtor::Slice, _st) => {}
        _ => {}
    }

    // same as above, with the macro expanded
    match ty {
        Ty::Apply(crate::ApplicationTy {
            ctor: TypeCtor::Array,
            parameters: _st,
        })
        | Ty::Apply(crate::ApplicationTy {
            ctor: TypeCtor::Slice,
            parameters: _st,
        }) => {}
        _ => {}
    }
}

fn main() {}

I expected to see this happen: code should build fine

Instead, this happened: unreachable pattern in the first, but not on the second match

warning: unreachable pattern
  --> src/main.rs:18:9
   |
18 | /         crate::Ty::Apply(crate::ApplicationTy {
19 | |             ctor: $ctor,
20 | |             parameters: $param,
21 | |         })
   | |__________^
...
30 |           ty_app!(TypeCtor::Array, _st) | ty_app!(TypeCtor::Slice, _st) => {}
   |                                           ----------------------------- in this macro invocation
   |
   = note: `#[warn(unreachable_patterns)]` on by default
   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: 1 warning emitted

Version it worked on

It most recently worked on:

rustc 1.48.0 (7eac88abb 2020-11-16)
binary: rustc
commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
commit-date: 2020-11-16
host: x86_64-unknown-linux-gnu
release: 1.48.0
LLVM version: 11.0

Version with regression

rustc 1.50.0-beta.1 (05b602367 2020-12-29)
binary: rustc
commit-hash: 05b6023675d77979637b04a350c85903fbf59257
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.50.0-beta.1

@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged

@rustbot rustbot added regression-from-stable-to-beta Performance or correctness regression from stable to beta. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Dec 30, 2020
@SNCPlay42
Copy link
Contributor

searched nightlies: from nightly-2020-12-09 to nightly-2020-12-29
regressed nightly: nightly-2020-12-20
searched commits: from f745834 to 1f5bc17
regressed commit: 1f5bc17

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --preserve --start=2020-12-09 --end=2020-12-29 -- check 

@lqd
Copy link
Member

lqd commented Dec 30, 2020

cc @Nadrieril

lnicola added a commit to lnicola/rust-analyzer that referenced this issue Dec 30, 2020
bors bot added a commit to rust-lang/rust-analyzer that referenced this issue Dec 30, 2020
7090: Allow spurious warning from rust-lang/rust#80501 r=lnicola a=lnicola

bors r+

Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
@jonas-schievink jonas-schievink added A-exhaustiveness-checking Relating to exhaustiveness / usefulness checking of patterns A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 30, 2020
@apiraino
Copy link
Contributor

Assigning P-medium as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@apiraino apiraino added P-medium Medium priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Dec 30, 2020
@jyn514
Copy link
Member

jyn514 commented Dec 30, 2020

Slightly minimized:

pub enum TypeCtor {
    Slice,
    Array,
}

pub struct ApplicationTy(TypeCtor);

macro_rules! ty_app {
    ($ctor:pat) => {
        ApplicationTy($ctor)
    };
}

fn _foo(ty: ApplicationTy) -> usize {
    return match ty {
        ty_app!(TypeCtor::Array) | ty_app!(TypeCtor::Slice) => 1,
    };

    // same as above, with the macro expanded
    match ty {
        crate::ApplicationTy(TypeCtor::Array)
        | crate::ApplicationTy(TypeCtor::Slice) => {}
    }
}

fn main() {}

If you remove ApplicationTy it stops giving the warning for some reason.

@Nadrieril
Copy link
Member

Nadrieril commented Dec 31, 2020

Oh boy, this is annoying. I had found a clever scheme in #80104 to deal with unreachable sub-patterns, but it relies on the assumption that the different alternatives in an or-pattern will have different spans.
Here both alternatives get given the span of ApplicationTy in the macro def, which breaks my clever idea :(. I'll have to think of a new idea that doesn't rely on spans...

@Nadrieril Nadrieril self-assigned this Dec 31, 2020
@jyn514
Copy link
Member

jyn514 commented Dec 31, 2020

@Nadrieril I think if you call source_callsite it will point to the pattern in the match instead.

@Nadrieril
Copy link
Member

@jyn514 Sounds interesting! I'm not entirely sure it does what I want. What would source_callsite return if I called it on the span of 1 below? I would want to get the same span of 1, but I suspect it would return the span of the foo!() invocation.

macro_rules! foo {
    () => {
        (0 | 1)
    };
}

fn main() {
	match 0 {
		foo!() -> {}
	}
}

@jyn514
Copy link
Member

jyn514 commented Dec 31, 2020

Yup, that's right. My idea probably wouldn't work then, sorry.

@Nadrieril
Copy link
Member

Nadrieril commented Dec 31, 2020

That gave me the idea for this cursed thing, where several different patterns really do have the same span. Unless I can distinguish a same span across different macro expansion paths, I don't think I can salvage my clever idea.

@Mark-Simulacrum Mark-Simulacrum added this to the 1.50.0 milestone Jan 14, 2021
ivan770 pushed a commit to ivan770/rust-analyzer that referenced this issue Jan 22, 2021
@Mark-Simulacrum
Copy link
Member

@Nadrieril I did some experimentation, but wanted to confirm with you that we believe this one (unlike a previous similar sounding issue) is not a soundness bug, as we cannot actually remove the claimed-unreachable pattern in any case, right?

@Nadrieril
Copy link
Member

@Mark-Simulacrum Agreed, this is not a soundness bug. The soundness-relevant code is independent of those Span shenanigans.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-exhaustiveness-checking Relating to exhaustiveness / usefulness checking of patterns A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants