Skip to content

Commit 9d58e12

Browse files
committed
Specific error for +1 path segments with params
1 parent 0339831 commit 9d58e12

14 files changed

+180
-75
lines changed

src/librustc_ast_lowering/path.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ 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());
363+
let param_sp =
364+
segment.args.as_ref().map_or(segment.ident.span.shrink_to_hi(), |args| args.span());
364365
hir::PathSegment {
365366
ident: segment.ident,
366367
hir_id: Some(id),
@@ -369,7 +370,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
369370
args: if generic_args.is_empty() {
370371
None
371372
} else {
372-
Some(self.arena.alloc(generic_args.into_generic_args(self.arena, param_span)))
373+
Some(self.arena.alloc(generic_args.into_generic_args(self.arena, param_sp)))
373374
},
374375
}
375376
}

src/librustc_typeck/astconv.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -2327,7 +2327,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23272327
) -> bool {
23282328
let segments_with_params = segments
23292329
.into_iter()
2330-
.filter_map(|segment| segment.args.map(|_| segment.ident.span))
2330+
.filter_map(|segment| segment.args.map(|arg| arg.span))
23312331
.collect::<Vec<_>>();
23322332
if segments_with_params.len() <= 1 {
23332333
return false;
@@ -2537,16 +2537,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25372537
fn lint_type_param_on_variant_ctor(&self, segments: &[hir::PathSegment<'_>]) {
25382538
// Doing this to get around rustfmt-caused line too long.
25392539
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() {
2540+
if let [.., prev, P { ident, hir_id: Some(hir_id), args: Some(args), .. }] = segments {
2541+
let sp = args.span;
2542+
if sp.hi() == sp.lo() || sp == DUMMY_SP || sp.parent().is_some() {
25432543
// The params were not written by the user, but rather derived. These are expected.
2544+
// `Enum::Variant` where `Variant` has inferred lifetimes.
25442545
return;
25452546
}
2547+
let span = sp.with_lo(ident.span.hi()); // Account for `::`
25462548
self.tcx().struct_span_lint_hir(
25472549
lint::builtin::TYPE_PARAM_ON_VARIANT_CTOR,
25482550
*hir_id,
2549-
span,
2551+
sp,
25502552
|lint| {
25512553
let mut err = lint.build("type parameter on variant");
25522554
let sugg_span = prev.ident.span.shrink_to_hi();

src/librustc_typeck/check/mod.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -5378,8 +5378,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
53785378

53795379
let mut user_self_ty = None;
53805380
let mut is_alias_variant_ctor = false;
5381+
let mut is_variant = false;
53815382
match res {
53825383
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
5384+
is_variant = true;
53835385
if let Some(self_ty) = self_ty {
53845386
let adt_def = self_ty.ty_adt_def().unwrap();
53855387
user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did, self_ty });
@@ -5415,16 +5417,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54155417
// errors if type parameters are provided in an inappropriate place.
54165418

54175419
let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect();
5418-
let generics_has_err = AstConv::prohibit_generics(
5419-
self,
5420-
segments.iter().enumerate().filter_map(|(index, seg)| {
5421-
if !generic_segs.contains(&index) || is_alias_variant_ctor {
5422-
Some(seg)
5423-
} else {
5424-
None
5425-
}
5426-
}),
5427-
);
5420+
let generics_has_err = (is_variant && AstConv::prohibit_multiple_params(self, segments))
5421+
|| AstConv::prohibit_generics(
5422+
self,
5423+
segments.iter().enumerate().filter_map(|(index, seg)| {
5424+
if !generic_segs.contains(&index) || is_alias_variant_ctor {
5425+
Some(seg)
5426+
} else {
5427+
None
5428+
}
5429+
}),
5430+
);
54285431

54295432
if let Res::Local(hid) = res {
54305433
let ty = self.local_ty(span, hid).decl_ty;

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ LL | S::<'static, 'static, 'static>(&0, &0);
1111
| ^^^^^^^ unexpected lifetime argument
1212

1313
warning: type parameter on variant
14-
--> $DIR/constructor-lifetime-args.rs:22:9
14+
--> $DIR/constructor-lifetime-args.rs:22:11
1515
|
1616
LL | E::V::<'static>(&0);
17-
| ^^^^^^^^^^^
17+
| ^^^^^^^^^
1818
|
1919
= note: `#[warn(type_param_on_variant_ctor)]` on by default
2020
help: set the type parameter on the enum
@@ -29,10 +29,10 @@ LL | E::V::<'static>(&0);
2929
| ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
3030

3131
warning: type parameter on variant
32-
--> $DIR/constructor-lifetime-args.rs:25:9
32+
--> $DIR/constructor-lifetime-args.rs:25:11
3333
|
3434
LL | E::V::<'static, 'static, 'static>(&0);
35-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
3636
|
3737
help: set the type parameter on the enum
3838
|

src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
warning: type parameter on variant
2-
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:29
2+
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:31
33
|
44
LL | Some(Wrapper::Simple::<u32>);
5-
| ^^^^^^^
5+
| ^^^^^
66
|
77
= note: `#[warn(type_param_on_variant_ctor)]` on by default
88
help: set the type parameter on the enum
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pub enum Foo<'a, T: 'a> {
2+
Struct {},
3+
Tuple(),
4+
Unit,
5+
Usage(&'a T),
6+
}
7+
8+
pub fn main() {
9+
let _ = Foo::<String>::Unit::<String>; //~ ERROR multiple segments with type parameters
10+
let _ = Foo::<String>::Tuple::<String>(); //~ ERROR multiple segments with type parameters
11+
let _ = Foo::<String>::Struct::<String> {}; //~ ERROR multiple segments with type parameters
12+
if let Foo::<String>::Unit::<String> = Foo::<String>::Unit::<String> {}
13+
//~^ ERROR multiple segments with type parameters are not allowed
14+
//~| ERROR multiple segments with type parameters are not allowed
15+
if let Foo::<String>::Tuple::<String>() = Foo::<String>::Tuple::<String>() {}
16+
//~^ ERROR multiple segments with type parameters are not allowed
17+
//~| ERROR multiple segments with type parameters are not allowed
18+
if let Foo::<String>::Struct::<String> {} = (Foo::<String>::Struct::<String> {}) {}
19+
//~^ ERROR multiple segments with type parameters are not allowed
20+
//~| ERROR multiple segments with type parameters are not allowed
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
error: multiple segments with type parameters are not allowed
2+
--> $DIR/forbid-many-type-params.rs:9:18
3+
|
4+
LL | let _ = Foo::<String>::Unit::<String>;
5+
| ^^^^^^^^ ^^^^^^^^
6+
|
7+
= note: only a single path segment can specify type parameters
8+
9+
error: multiple segments with type parameters are not allowed
10+
--> $DIR/forbid-many-type-params.rs:10:18
11+
|
12+
LL | let _ = Foo::<String>::Tuple::<String>();
13+
| ^^^^^^^^ ^^^^^^^^
14+
|
15+
= note: only a single path segment can specify type parameters
16+
17+
error: multiple segments with type parameters are not allowed
18+
--> $DIR/forbid-many-type-params.rs:11:18
19+
|
20+
LL | let _ = Foo::<String>::Struct::<String> {};
21+
| ^^^^^^^^ ^^^^^^^^
22+
|
23+
= note: only a single path segment can specify type parameters
24+
25+
error: multiple segments with type parameters are not allowed
26+
--> $DIR/forbid-many-type-params.rs:12:49
27+
|
28+
LL | if let Foo::<String>::Unit::<String> = Foo::<String>::Unit::<String> {}
29+
| ^^^^^^^^ ^^^^^^^^
30+
|
31+
= note: only a single path segment can specify type parameters
32+
33+
error: multiple segments with type parameters are not allowed
34+
--> $DIR/forbid-many-type-params.rs:12:17
35+
|
36+
LL | if let Foo::<String>::Unit::<String> = Foo::<String>::Unit::<String> {}
37+
| ^^^^^^^^ ^^^^^^^^
38+
|
39+
= note: only a single path segment can specify type parameters
40+
41+
error: multiple segments with type parameters are not allowed
42+
--> $DIR/forbid-many-type-params.rs:15:52
43+
|
44+
LL | if let Foo::<String>::Tuple::<String>() = Foo::<String>::Tuple::<String>() {}
45+
| ^^^^^^^^ ^^^^^^^^
46+
|
47+
= note: only a single path segment can specify type parameters
48+
49+
error: multiple segments with type parameters are not allowed
50+
--> $DIR/forbid-many-type-params.rs:15:17
51+
|
52+
LL | if let Foo::<String>::Tuple::<String>() = Foo::<String>::Tuple::<String>() {}
53+
| ^^^^^^^^ ^^^^^^^^
54+
|
55+
= note: only a single path segment can specify type parameters
56+
57+
error: multiple segments with type parameters are not allowed
58+
--> $DIR/forbid-many-type-params.rs:18:55
59+
|
60+
LL | if let Foo::<String>::Struct::<String> {} = (Foo::<String>::Struct::<String> {}) {}
61+
| ^^^^^^^^ ^^^^^^^^
62+
|
63+
= note: only a single path segment can specify type parameters
64+
65+
error: multiple segments with type parameters are not allowed
66+
--> $DIR/forbid-many-type-params.rs:18:17
67+
|
68+
LL | if let Foo::<String>::Struct::<String> {} = (Foo::<String>::Struct::<String> {}) {}
69+
| ^^^^^^^^ ^^^^^^^^
70+
|
71+
= note: only a single path segment can specify type parameters
72+
73+
error: aborting due to 9 previous errors
74+

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

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
warning: type parameter on variant
2-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:18:22
2+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:18:24
33
|
44
LL | let _ = Foo::Unit::<String>;
5-
| ^^^^^^^^^^
5+
| ^^^^^^^^
66
|
77
= note: `#[warn(type_param_on_variant_ctor)]` on by default
88
help: set the type parameter on the enum
@@ -11,87 +11,87 @@ LL | let _ = Foo::<String>::Unit;
1111
| ^^^^^^^^^^ --
1212

1313
warning: type parameter on variant
14-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:19:23
14+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:19:25
1515
|
1616
LL | let _ = Foo::Tuple::<String>();
17-
| ^^^^^^^^^^
17+
| ^^^^^^^^
1818
|
1919
help: set the type parameter on the enum
2020
|
2121
LL | let _ = Foo::<String>::Tuple();
2222
| ^^^^^^^^^^ --
2323

2424
warning: type parameter on variant
25-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:20:24
25+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:20:26
2626
|
2727
LL | let _ = Foo::Struct::<String> {};
28-
| ^^^^^^^^^^
28+
| ^^^^^^^^
2929
|
3030
help: set the type parameter on the enum
3131
|
3232
LL | let _ = Foo::<String>::Struct {};
3333
| ^^^^^^^^^^ --
3434

3535
warning: type parameter on variant
36-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:21:43
36+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:21:45
3737
|
3838
LL | if let Foo::Unit::<String> = Foo::Unit::<String> {}
39-
| ^^^^^^^^^^
39+
| ^^^^^^^^
4040
|
4141
help: set the type parameter on the enum
4242
|
4343
LL | if let Foo::Unit::<String> = Foo::<String>::Unit {}
4444
| ^^^^^^^^^^ --
4545

4646
warning: type parameter on variant
47-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:21:21
47+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:21:23
4848
|
4949
LL | if let Foo::Unit::<String> = Foo::Unit::<String> {}
50-
| ^^^^^^^^^^
50+
| ^^^^^^^^
5151
|
5252
help: set the type parameter on the enum
5353
|
5454
LL | if let Foo::<String>::Unit = Foo::Unit::<String> {}
5555
| ^^^^^^^^^^ --
5656

5757
warning: type parameter on variant
58-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:24:47
58+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:24:49
5959
|
6060
LL | if let Foo::Tuple::<String>() = Foo::Tuple::<String>() {}
61-
| ^^^^^^^^^^
61+
| ^^^^^^^^
6262
|
6363
help: set the type parameter on the enum
6464
|
6565
LL | if let Foo::Tuple::<String>() = Foo::<String>::Tuple() {}
6666
| ^^^^^^^^^^ --
6767

6868
warning: type parameter on variant
69-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:24:22
69+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:24:24
7070
|
7171
LL | if let Foo::Tuple::<String>() = Foo::Tuple::<String>() {}
72-
| ^^^^^^^^^^
72+
| ^^^^^^^^
7373
|
7474
help: set the type parameter on the enum
7575
|
7676
LL | if let Foo::<String>::Tuple() = Foo::Tuple::<String>() {}
7777
| ^^^^^^^^^^ --
7878

7979
warning: type parameter on variant
80-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:27:51
80+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:27:53
8181
|
8282
LL | if let Foo::Struct::<String> {} = (Foo::Struct::<String> {}) {}
83-
| ^^^^^^^^^^
83+
| ^^^^^^^^
8484
|
8585
help: set the type parameter on the enum
8686
|
8787
LL | if let Foo::Struct::<String> {} = (Foo::<String>::Struct {}) {}
8888
| ^^^^^^^^^^ --
8989

9090
warning: type parameter on variant
91-
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:27:23
91+
--> $DIR/lifetime-in-def-not-in-path-issue-69356.rs:27:25
9292
|
9393
LL | if let Foo::Struct::<String> {} = (Foo::Struct::<String> {}) {}
94-
| ^^^^^^^^^^
94+
| ^^^^^^^^
9595
|
9696
help: set the type parameter on the enum
9797
|

0 commit comments

Comments
 (0)