Skip to content

Commit 0339831

Browse files
committed
Lint against E::V::<P>, suggest E::<P>::V
1 parent aafdbb6 commit 0339831

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+517
-57
lines changed

src/librustc_ast_lowering/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19771977
args: &[],
19781978
bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
19791979
parenthesized: false,
1980+
span,
19801981
});
19811982

19821983
// ::std::future::Future<future_params>
@@ -2655,11 +2656,12 @@ impl<'hir> GenericArgsCtor<'hir> {
26552656
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
26562657
}
26572658

2658-
fn into_generic_args(self, arena: &'hir Arena<'hir>) -> hir::GenericArgs<'hir> {
2659+
fn into_generic_args(self, arena: &'hir Arena<'hir>, span: Span) -> hir::GenericArgs<'hir> {
26592660
hir::GenericArgs {
26602661
args: arena.alloc_from_iter(self.args),
26612662
bindings: self.bindings,
26622663
parenthesized: self.parenthesized,
2664+
span,
26632665
}
26642666
}
26652667
}

src/librustc_ast_lowering/path.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
360360
segment.ident, segment.id, id,
361361
);
362362

363+
let param_span = path_span.with_lo(segment.ident.span.shrink_to_hi().lo());
363364
hir::PathSegment {
364365
ident: segment.ident,
365366
hir_id: Some(id),
@@ -368,7 +369,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
368369
args: if generic_args.is_empty() {
369370
None
370371
} else {
371-
Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
372+
Some(self.arena.alloc(generic_args.into_generic_args(self.arena, param_span)))
372373
},
373374
}
374375
}

src/librustc_hir/hir.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,13 @@ pub struct GenericArgs<'hir> {
311311
/// This is required mostly for pretty-printing and diagnostics,
312312
/// but also for changing lifetime elision rules to be "function-like".
313313
pub parenthesized: bool,
314+
/// The `Span` encompassing the entirety of the parameters `<A, B>` or `(A, B)`.
315+
pub span: Span,
314316
}
315317

316318
impl GenericArgs<'_> {
317319
pub const fn none() -> Self {
318-
Self { args: &[], bindings: &[], parenthesized: false }
320+
Self { args: &[], bindings: &[], parenthesized: false, span: DUMMY_SP }
319321
}
320322

321323
pub fn is_empty(&self) -> bool {

src/librustc_session/lint/builtin.rs

+8
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ declare_lint! {
256256
};
257257
}
258258

259+
declare_lint! {
260+
pub TYPE_PARAM_ON_VARIANT_CTOR,
261+
Warn,
262+
"detects generic arguments in path segments corresponding to an enum variant instead of the \
263+
enum itself",
264+
}
265+
259266
declare_lint! {
260267
pub ORDER_DEPENDENT_TRAIT_OBJECTS,
261268
Deny,
@@ -531,6 +538,7 @@ declare_lint_pass! {
531538
PATTERNS_IN_FNS_WITHOUT_BODY,
532539
MISSING_FRAGMENT_SPECIFIER,
533540
LATE_BOUND_LIFETIME_ARGUMENTS,
541+
TYPE_PARAM_ON_VARIANT_CTOR,
534542
ORDER_DEPENDENT_TRAIT_OBJECTS,
535543
COHERENCE_LEAK_CHECK,
536544
DEPRECATED,

src/librustc_typeck/astconv.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -2500,8 +2500,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25002500
let enum_def_id = tcx.parent(def_id).unwrap();
25012501
(enum_def_id, last - 1)
25022502
} else {
2503-
// FIXME: lint here recommending `Enum::<...>::Variant` form
2504-
// instead of `Enum::Variant::<...>` form.
2503+
self.lint_type_param_on_variant_ctor(segments);
25052504

25062505
// Everything but the final segment should have no
25072506
// parameters at all.
@@ -2535,6 +2534,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25352534
path_segs
25362535
}
25372536

2537+
fn lint_type_param_on_variant_ctor(&self, segments: &[hir::PathSegment<'_>]) {
2538+
// Doing this to get around rustfmt-caused line too long.
2539+
use hir::PathSegment as P;
2540+
if let [.., prev, P { hir_id: Some(hir_id), args: Some(args), .. }] = segments {
2541+
let span = args.span;
2542+
if span.hi() == span.lo() {
2543+
// The params were not written by the user, but rather derived. These are expected.
2544+
return;
2545+
}
2546+
self.tcx().struct_span_lint_hir(
2547+
lint::builtin::TYPE_PARAM_ON_VARIANT_CTOR,
2548+
*hir_id,
2549+
span,
2550+
|lint| {
2551+
let mut err = lint.build("type parameter on variant");
2552+
let sugg_span = prev.ident.span.shrink_to_hi();
2553+
let msg = "set the type parameter on the enum";
2554+
match self.tcx().sess.source_map().span_to_snippet(span) {
2555+
Ok(snippet) => err.multipart_suggestion(
2556+
msg,
2557+
vec![(sugg_span, snippet), (span, "".to_string())],
2558+
Applicability::MachineApplicable,
2559+
),
2560+
Err(_) => err.span_label(sugg_span, msg),
2561+
};
2562+
err.emit();
2563+
},
2564+
);
2565+
}
2566+
}
2567+
25382568
// Check a type `Path` and convert it to a `Ty`.
25392569
pub fn res_to_ty(
25402570
&self,

src/test/ui/binding/simple-generic-match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![allow(non_camel_case_types)]
2+
#![allow(non_camel_case_types, type_param_on_variant_ctor)]
33

44
// pretty-expanded FIXME #23616
55

src/test/ui/binding/use-uninit-match.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// run-pass
2-
#![allow(dead_code)]
3-
#![allow(non_camel_case_types)]
4-
2+
#![allow(dead_code, non_camel_case_types, type_param_on_variant_ctor)]
53

64
fn foo<T>(o: myoption<T>) -> isize {
75
let mut x: isize = 5;
86
match o {
97
myoption::none::<T> => { }
10-
myoption::some::<T>(_t) => { x += 1; }
8+
myoption::some::<T>(_) => { x += 1; }
9+
}
10+
match o {
11+
myoption::<T>::none => { }
12+
myoption::<T>::some(_t) => { x += 1; }
1113
}
1214
return x;
1315
}

src/test/ui/binding/use-uninit-match2.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// run-pass
2-
#![allow(dead_code)]
3-
#![allow(unused_mut)]
4-
#![allow(non_camel_case_types)]
2+
#![allow(dead_code, unused_mut, non_camel_case_types, type_param_on_variant_ctor)]
53

64

75
fn foo<T>(o: myoption<T>) -> isize {
86
let mut x: isize;
97
match o {
108
myoption::none::<T> => { panic!(); }
11-
myoption::some::<T>(_t) => { x = 5; }
9+
myoption::some::<T>(_) => { x = 5; }
10+
}
11+
let _ = x;
12+
match o {
13+
myoption::<T>::none => { panic!(); }
14+
myoption::<T>::some(_t) => { x = 5; }
1215
}
1316
return x;
1417
}

src/test/ui/constructor-lifetime-args.rs

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ fn main() {
2121
E::V(&0); // OK
2222
E::V::<'static>(&0);
2323
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
24+
//~| WARNING type parameter on variant
2425
E::V::<'static, 'static, 'static>(&0);
2526
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
27+
//~| WARNING type parameter on variant
28+
E::<'static>::V(&0);
29+
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
30+
E::<'static, 'static, 'static>::V(&0);
31+
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
2632
}

src/test/ui/constructor-lifetime-args.stderr

+37-2
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,53 @@ error[E0107]: wrong number of lifetime arguments: expected 2, found 3
1010
LL | S::<'static, 'static, 'static>(&0, &0);
1111
| ^^^^^^^ unexpected lifetime argument
1212

13+
warning: type parameter on variant
14+
--> $DIR/constructor-lifetime-args.rs:22:9
15+
|
16+
LL | E::V::<'static>(&0);
17+
| ^^^^^^^^^^^
18+
|
19+
= note: `#[warn(type_param_on_variant_ctor)]` on by default
20+
help: set the type parameter on the enum
21+
|
22+
LL | E::<'static>::V(&0);
23+
| ^^^^^^^^^^^ --
24+
1325
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
1426
--> $DIR/constructor-lifetime-args.rs:22:5
1527
|
1628
LL | E::V::<'static>(&0);
1729
| ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
1830

31+
warning: type parameter on variant
32+
--> $DIR/constructor-lifetime-args.rs:25:9
33+
|
34+
LL | E::V::<'static, 'static, 'static>(&0);
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
|
37+
help: set the type parameter on the enum
38+
|
39+
LL | E::<'static, 'static, 'static>::V(&0);
40+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --
41+
1942
error[E0107]: wrong number of lifetime arguments: expected 2, found 3
20-
--> $DIR/constructor-lifetime-args.rs:24:30
43+
--> $DIR/constructor-lifetime-args.rs:25:30
2144
|
2245
LL | E::V::<'static, 'static, 'static>(&0);
2346
| ^^^^^^^ unexpected lifetime argument
2447

25-
error: aborting due to 4 previous errors
48+
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
49+
--> $DIR/constructor-lifetime-args.rs:28:5
50+
|
51+
LL | E::<'static>::V(&0);
52+
| ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
53+
54+
error[E0107]: wrong number of lifetime arguments: expected 2, found 3
55+
--> $DIR/constructor-lifetime-args.rs:30:27
56+
|
57+
LL | E::<'static, 'static, 'static>::V(&0);
58+
| ^^^^^^^ unexpected lifetime argument
59+
60+
error: aborting due to 6 previous errors
2661

2762
For more information about this error, try `rustc --explain E0107`.

src/test/ui/deriving/deriving-associated-types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// run-pass
2+
#![allow(type_param_on_variant_ctor)]
23
pub trait DeclaredTrait {
34
type Type;
45
}

src/test/ui/deriving/deriving-clone-generic-enum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![allow(dead_code)]
2+
#![allow(dead_code, type_param_on_variant_ctor)]
33
// pretty-expanded FIXME #23616
44

55
#[derive(Clone)]

src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ fn main() {
3333
Some(Wrapper::Simple::<u32>);
3434
//~^ ERROR overflow while adding drop-check rules for std::option::Option
3535
//~| ERROR overflow while adding drop-check rules for Wrapper
36+
//~| WARNING type parameter on variant
37+
let v = //~ ERROR overflow while adding drop-check rules for std::option
38+
Some(Wrapper::<u32>::Simple);
39+
//~^ ERROR overflow while adding drop-check rules for std::option::Option
40+
//~| ERROR overflow while adding drop-check rules for Wrapper
3641
}

src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
warning: type parameter on variant
2+
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:29
3+
|
4+
LL | Some(Wrapper::Simple::<u32>);
5+
| ^^^^^^^
6+
|
7+
= note: `#[warn(type_param_on_variant_ctor)]` on by default
8+
help: set the type parameter on the enum
9+
|
10+
LL | Some(Wrapper::<u32>::Simple);
11+
| ^^^^^^^ --
12+
113
error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
214
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:32:9
315
|
@@ -22,5 +34,29 @@ LL | Some(Wrapper::Simple::<u32>);
2234
|
2335
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2436

25-
error: aborting due to 3 previous errors
37+
error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
38+
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:37:9
39+
|
40+
LL | let v =
41+
| ^
42+
|
43+
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
44+
45+
error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
46+
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:38:9
47+
|
48+
LL | Some(Wrapper::<u32>::Simple);
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50+
|
51+
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
52+
53+
error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
54+
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:38:14
55+
|
56+
LL | Some(Wrapper::<u32>::Simple);
57+
| ^^^^^^^^^^^^^^^^^^^^^^
58+
|
59+
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
60+
61+
error: aborting due to 6 previous errors
2662

src/test/ui/enum-discriminant/niche.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![feature(const_panic)]
44
#![feature(const_if_match)]
5+
#![allow(type_param_on_variant_ctor)]
56

67
//! Make sure that we read and write enum discriminants correctly for corner cases caused
78
//! by layout optimizations.

src/test/ui/enum/lifetime-in-def-not-in-path-issue-69356.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ pub fn main() {
1414
if let Foo::<String>::Unit = Foo::<String>::Unit {}
1515
if let Foo::<String>::Tuple() = Foo::<String>::Tuple() {}
1616
if let Foo::<String>::Struct {} = (Foo::<String>::Struct {}) {}
17-
// // FIXME: these should be linted against.
18-
let _ = Foo::Unit::<String>;
19-
let _ = Foo::Tuple::<String>();
20-
let _ = Foo::Struct::<String> {};
17+
18+
let _ = Foo::Unit::<String>; //~ WARNING type parameter on variant
19+
let _ = Foo::Tuple::<String>(); //~ WARNING type parameter on variant
20+
let _ = Foo::Struct::<String> {}; //~ WARNING type parameter on variant
2121
if let Foo::Unit::<String> = Foo::Unit::<String> {}
22+
//~^ WARNING type parameter on variant
23+
//~| WARNING type parameter on variant
2224
if let Foo::Tuple::<String>() = Foo::Tuple::<String>() {}
25+
//~^ WARNING type parameter on variant
26+
//~| WARNING type parameter on variant
2327
if let Foo::Struct::<String> {} = (Foo::Struct::<String> {}) {}
28+
//~^ WARNING type parameter on variant
29+
//~| WARNING type parameter on variant
2430
}

0 commit comments

Comments
 (0)