Fix suggestion span involving wrongly placed generic arg on enum variants
When the variant and the (wrongly placed) args are at separate source locations such as being in different macos or one in a macro and the other somwhere outside of it, the arg spans we computed spanned the entire distance between such locations and were hence invalid. .
This commit is contained in:
parent
6683f13fa1
commit
23a3b9e449
3 changed files with 356 additions and 3 deletions
|
@ -36,7 +36,7 @@ use rustc_middle::ty::{
|
|||
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::{sym, Span, DUMMY_SP};
|
||||
use rustc_span::{sym, BytePos, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::traits::wf::object_region_bounds;
|
||||
use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
|
||||
|
@ -1275,8 +1275,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
return;
|
||||
};
|
||||
// Get the span of the generics args *including* the leading `::`.
|
||||
let args_span =
|
||||
assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
|
||||
// We do so by stretching args.span_ext to the left by 2. Earlier
|
||||
// it was done based on the end of assoc segment but that sometimes
|
||||
// led to impossible spans and caused issues like #116473
|
||||
let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
|
||||
if tcx.generics_of(adt_def.did()).count() == 0 {
|
||||
// FIXME(estebank): we could also verify that the arguments being
|
||||
// work for the `enum`, instead of just looking if it takes *any*.
|
||||
|
|
96
tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs
Normal file
96
tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Regression test for ICE #116473.
|
||||
// The ICE occurs when arguments are specified on an enum variant
|
||||
// (which is illegal) and the variant and its preceding path are
|
||||
// located at different places such as in different macros or
|
||||
// different expansions of the same macro (i.e. when the macro
|
||||
// calls itself recursively)
|
||||
|
||||
enum Enum<T1, T2> { VariantA { _v1: T1, _v2: T2 }, VariantB }
|
||||
|
||||
type EnumUnit = Enum<(), ()>;
|
||||
|
||||
// Recursive macro call using a tt metavariable for variant
|
||||
macro_rules! recursive_tt {
|
||||
() => (recursive_tt!(VariantB));
|
||||
($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
// Recursive macro call using an ident metavariable for variant
|
||||
// (the behaviour is different for tt and ident)
|
||||
macro_rules! recursive_ident {
|
||||
() => (recursive_ident!(VariantB));
|
||||
($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
// Mested macro calls (i.e. one calling another) using a tt
|
||||
// metavariable for variant
|
||||
macro_rules! nested1_tt {
|
||||
() => (nested2_tt!(VariantB));
|
||||
}
|
||||
|
||||
macro_rules! nested2_tt {
|
||||
($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
// Mested macro calls using an ident metavariable for variant
|
||||
// (the behaviour is different for tt and ident)
|
||||
macro_rules! nested1_ident {
|
||||
() => (nested2_ident!(VariantB));
|
||||
}
|
||||
|
||||
macro_rules! nested2_ident {
|
||||
($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
// Mested macro calls when args are passed as metavariable
|
||||
// instead of the enum variant
|
||||
macro_rules! nested1_tt_args_in_first_macro {
|
||||
() => (nested2_tt_args_in_first_macro!(i32, u32));
|
||||
}
|
||||
|
||||
macro_rules! nested2_tt_args_in_first_macro {
|
||||
($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
= 5 { true } else { false });
|
||||
}
|
||||
|
||||
// Mested macro calls when args are passed as metavariable
|
||||
// instead of the enum variant
|
||||
macro_rules! nested1_ident_args_in_first_macro {
|
||||
() => (nested2_ident_args_in_first_macro!(i32, u32));
|
||||
}
|
||||
|
||||
macro_rules! nested2_ident_args_in_first_macro {
|
||||
($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
= 5 { true } else { false });
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Macro cases
|
||||
recursive_tt!();
|
||||
recursive_ident!();
|
||||
nested1_tt!();
|
||||
nested1_ident!();
|
||||
nested1_tt_args_in_first_macro!();
|
||||
nested1_ident_args_in_first_macro!();
|
||||
|
||||
// Regular, non-macro case
|
||||
if let EnumUnit::VariantB::<i32, u32> {} = 5 { true } else { false };
|
||||
//~^ ERROR type arguments are not allowed on this type
|
||||
//~| ERROR mismatched types
|
||||
}
|
255
tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr
Normal file
255
tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr
Normal file
|
@ -0,0 +1,255 @@
|
|||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:51
|
||||
|
|
||||
LL | ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| -------- ^^^ ^^^ type argument not allowed
|
||||
| |
|
||||
| not allowed on this type
|
||||
...
|
||||
LL | recursive_tt!();
|
||||
| ---------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
LL + ($variant:tt) => (if let EnumUnit::<i32, u32>::$variant {} = 5 { true } else { false });
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:30
|
||||
|
|
||||
LL | ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | recursive_tt!();
|
||||
| --------------- in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:54
|
||||
|
|
||||
LL | () => (recursive_ident!(VariantB));
|
||||
| -------- not allowed on this type
|
||||
LL | ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^ ^^^ type argument not allowed
|
||||
...
|
||||
LL | recursive_ident!();
|
||||
| ------------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
LL + ($variant:ident) => (if let EnumUnit::<i32, u32>::$variant {} = 5 { true } else { false });
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:33
|
||||
|
|
||||
LL | ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | recursive_ident!();
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:51
|
||||
|
|
||||
LL | ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| -------- ^^^ ^^^ type argument not allowed
|
||||
| |
|
||||
| not allowed on this type
|
||||
...
|
||||
LL | nested1_tt!();
|
||||
| -------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
LL + ($variant:tt) => (if let EnumUnit::<i32, u32>::$variant {} = 5 { true } else { false });
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:30
|
||||
|
|
||||
LL | ($variant:tt) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | nested1_tt!();
|
||||
| ------------- in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:54
|
||||
|
|
||||
LL | () => (nested2_ident!(VariantB));
|
||||
| -------- not allowed on this type
|
||||
...
|
||||
LL | ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^ ^^^ type argument not allowed
|
||||
...
|
||||
LL | nested1_ident!();
|
||||
| ----------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
LL + ($variant:ident) => (if let EnumUnit::<i32, u32>::$variant {} = 5 { true } else { false });
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:33
|
||||
|
|
||||
LL | ($variant:ident) => (if let EnumUnit::$variant::<i32, u32> {} = 5 { true } else { false });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | nested1_ident!();
|
||||
| ---------------- in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:64:58
|
||||
|
|
||||
LL | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
| -------- ^^^^^ ^^^^^ type argument not allowed
|
||||
| |
|
||||
| not allowed on this type
|
||||
...
|
||||
LL | nested1_tt_args_in_first_macro!();
|
||||
| ---------------------------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
LL + ($arg1:tt, $arg2:tt) => (if let EnumUnit::<$arg1, $arg2>::VariantB {}
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:64:37
|
||||
|
|
||||
LL | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | = 5 { true } else { false });
|
||||
| - this expression has type `{integer}`
|
||||
...
|
||||
LL | nested1_tt_args_in_first_macro!();
|
||||
| --------------------------------- in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `nested2_tt_args_in_first_macro` which comes from the expansion of the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:64
|
||||
|
|
||||
LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
| -------- ^^^^^ ^^^^^ type argument not allowed
|
||||
| |
|
||||
| not allowed on this type
|
||||
...
|
||||
LL | nested1_ident_args_in_first_macro!();
|
||||
| ------------------------------------
|
||||
| |
|
||||
| in this macro invocation
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
= note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
LL + ($arg1:ident, $arg2:ident) => (if let EnumUnit::<$arg1, $arg2>::VariantB {}
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:43
|
||||
|
|
||||
LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>`
|
||||
...
|
||||
LL | = 5 { true } else { false });
|
||||
| - this expression has type `{integer}`
|
||||
...
|
||||
LL | nested1_ident_args_in_first_macro!();
|
||||
| ------------------------------------ in this macro invocation
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
= note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0109]: type arguments are not allowed on this type
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:93:33
|
||||
|
|
||||
LL | if let EnumUnit::VariantB::<i32, u32> {} = 5 { true } else { false };
|
||||
| -------- ^^^ ^^^ type argument not allowed
|
||||
| |
|
||||
| not allowed on this type
|
||||
|
|
||||
= note: enum variants can't have type parameters
|
||||
help: you might have meant to specify type parameters on enum `Enum`
|
||||
|
|
||||
LL - if let EnumUnit::VariantB::<i32, u32> {} = 5 { true } else { false };
|
||||
LL + if let EnumUnit::<i32, u32>::VariantB {} = 5 { true } else { false };
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-116473-ice-wrong-span-variant-args.rs:93:12
|
||||
|
|
||||
LL | if let EnumUnit::VariantB::<i32, u32> {} = 5 { true } else { false };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `Enum<(), ()>`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found enum `Enum<(), ()>`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0109, E0308.
|
||||
For more information about an error, try `rustc --explain E0109`.
|
Loading…
Add table
Reference in a new issue