Skip to content

Commit d09cf61

Browse files
committed
Added checks for attribute in type case
1 parent f63685d commit d09cf61

14 files changed

+395
-23
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ parse_attr_without_generics = attribute without generic parameters
7171
parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
7272
.label = attributes are not allowed here
7373
74+
parse_attribute_on_type = attributes cannot be applied to types
75+
.label = attributes are not allowed here
76+
.suggestion = remove attribute from here
77+
78+
parse_attribute_on_generic_arg = attributes cannot be applied to generic arguments
79+
.label = attributes are not allowed here
80+
.suggestion = remove attribute from here
81+
82+
parse_attribute_on_empty_type = attributes cannot be applied here
83+
.label = attributes are not allowed here
84+
7485
parse_bad_assoc_type_bounds = bounds on associated types do not belong here
7586
.label = belongs in `where` clause
7687

compiler/rustc_parse/src/errors.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,34 @@ pub(crate) struct AttributeOnParamType {
14891489
pub span: Span,
14901490
}
14911491

1492+
#[derive(Diagnostic)]
1493+
#[diag(parse_attribute_on_type)]
1494+
pub(crate) struct AttributeOnType {
1495+
#[primary_span]
1496+
#[label]
1497+
pub span: Span,
1498+
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
1499+
pub fix_span: Span,
1500+
}
1501+
1502+
#[derive(Diagnostic)]
1503+
#[diag(parse_attribute_on_generic_arg)]
1504+
pub(crate) struct AttributeOnGenericArg {
1505+
#[primary_span]
1506+
#[label]
1507+
pub span: Span,
1508+
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
1509+
pub fix_span: Span,
1510+
}
1511+
1512+
#[derive(Diagnostic)]
1513+
#[diag(parse_attribute_on_empty_type)]
1514+
pub(crate) struct AttributeOnEmptyType {
1515+
#[primary_span]
1516+
#[label]
1517+
pub span: Span,
1518+
}
1519+
14921520
#[derive(Diagnostic)]
14931521
#[diag(parse_pattern_method_param_without_body, code = E0642)]
14941522
pub(crate) struct PatternMethodParamWithoutBody {

compiler/rustc_parse/src/parser/path.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
1717
use super::{Parser, Restrictions, TokenType};
1818
use crate::ast::{PatKind, TyKind};
1919
use crate::errors::{
20-
self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams,
21-
PathSingleColon, PathTripleColon,
20+
self, AttributeOnEmptyType, AttributeOnGenericArg, FnPathFoundNamedParams,
21+
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
2222
};
2323
use crate::exp;
24-
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
24+
use crate::parser::{CommaRecoveryMode, ExprKind, RecoverColon, RecoverComma};
2525

2626
/// Specifies how to parse a path.
2727
#[derive(Copy, Clone, PartialEq)]
@@ -880,6 +880,12 @@ impl<'a> Parser<'a> {
880880
&mut self,
881881
ty_generics: Option<&Generics>,
882882
) -> PResult<'a, Option<GenericArg>> {
883+
let mut attr_span: Option<Span> = None;
884+
if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
885+
let attrs_wrapper = self.parse_outer_attributes()?;
886+
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
887+
attr_span = Some(raw_attrs[0].span.to(raw_attrs.last().unwrap().span));
888+
}
883889
let start = self.token.span;
884890
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
885891
// Parse lifetime argument.
@@ -934,6 +940,9 @@ impl<'a> Parser<'a> {
934940
}
935941
} else if self.token.is_keyword(kw::Const) {
936942
return self.recover_const_param_declaration(ty_generics);
943+
} else if let Some(attr_span) = attr_span {
944+
let diag = self.dcx().create_err(AttributeOnEmptyType { span: attr_span });
945+
return Err(diag);
937946
} else {
938947
// Fall back by trying to parse a const-expr expression. If we successfully do so,
939948
// then we should report an error that it needs to be wrapped in braces.
@@ -953,6 +962,22 @@ impl<'a> Parser<'a> {
953962
}
954963
}
955964
};
965+
966+
if let Some(attr_span) = attr_span {
967+
let guar = self.dcx().emit_err(AttributeOnGenericArg {
968+
span: attr_span,
969+
fix_span: attr_span.until(arg.span()),
970+
});
971+
return Ok(Some(match arg {
972+
GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))),
973+
GenericArg::Const(_) => {
974+
let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar));
975+
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr })
976+
}
977+
GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt),
978+
}));
979+
}
980+
956981
Ok(Some(arg))
957982
}
958983

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ use thin_vec::{ThinVec, thin_vec};
1414

1515
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
1616
use crate::errors::{
17-
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
18-
FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidDynKeyword,
19-
LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
20-
ReturnTypesUseThinArrow,
17+
self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
18+
ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
19+
HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
20+
NestedCVariadicType, ReturnTypesUseThinArrow,
2121
};
2222
use crate::parser::item::FrontMatterParsingMode;
2323
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
@@ -253,7 +253,27 @@ impl<'a> Parser<'a> {
253253
) -> PResult<'a, P<Ty>> {
254254
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
255255
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
256+
if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
257+
let attrs_wrapper = self.parse_outer_attributes()?;
258+
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
259+
let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
260+
let (full_span, guar) = match self.parse_ty() {
261+
Ok(ty) => {
262+
let full_span = attr_span.until(ty.span);
263+
let guar = self
264+
.dcx()
265+
.emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
266+
(attr_span, guar)
267+
}
268+
Err(err) => {
269+
err.cancel();
270+
let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
271+
(attr_span, guar)
272+
}
273+
};
256274

275+
return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
276+
}
257277
if let Some(ty) = self.eat_metavar_seq_with_matcher(
258278
|mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
259279
|this| this.parse_ty_no_question_mark_recover(),

tests/ui/parser/attribute-on-empty.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
2+
//! <https://github.com/rust-lang/rust/issues/135017>
3+
4+
struct Baz<const N: usize>(i32);
5+
6+
fn main() {
7+
let _: Baz<#[cfg(any())]> = todo!();
8+
//~^ ERROR attributes cannot be applied here
9+
}
10+
11+
fn f(_param: #[attr]) {}
12+
//~^ ERROR attributes cannot be applied to a function parameter's type
13+
//~| ERROR expected type, found `)`
14+
15+
fn g() -> #[attr] { 0 }
16+
//~^ ERROR attributes cannot be applied here
17+
18+
struct S {
19+
field: #[attr],
20+
//~^ ERROR attributes cannot be applied here
21+
field1: (#[attr], i32),
22+
//~^ ERROR attributes cannot be applied here
23+
}
24+
25+
type Tuple = (#[attr], String);
26+
//~^ ERROR attributes cannot be applied here
27+
28+
impl #[attr] {}
29+
//~^ ERROR attributes cannot be applied here
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error: attributes cannot be applied here
2+
--> $DIR/attribute-on-empty.rs:7:16
3+
|
4+
LL | let _: Baz<#[cfg(any())]> = todo!();
5+
| - ^^^^^^^^^^^^^ attributes are not allowed here
6+
| |
7+
| while parsing the type for `_`
8+
9+
error: attributes cannot be applied to a function parameter's type
10+
--> $DIR/attribute-on-empty.rs:11:14
11+
|
12+
LL | fn f(_param: #[attr]) {}
13+
| ^^^^^^^ attributes are not allowed here
14+
15+
error: expected type, found `)`
16+
--> $DIR/attribute-on-empty.rs:11:21
17+
|
18+
LL | fn f(_param: #[attr]) {}
19+
| ^ expected type
20+
21+
error: attributes cannot be applied here
22+
--> $DIR/attribute-on-empty.rs:15:11
23+
|
24+
LL | fn g() -> #[attr] { 0 }
25+
| ^^^^^^^ attributes are not allowed here
26+
27+
error: attributes cannot be applied here
28+
--> $DIR/attribute-on-empty.rs:19:12
29+
|
30+
LL | field: #[attr],
31+
| ^^^^^^^ attributes are not allowed here
32+
33+
error: attributes cannot be applied here
34+
--> $DIR/attribute-on-empty.rs:21:14
35+
|
36+
LL | field1: (#[attr], i32),
37+
| ^^^^^^^ attributes are not allowed here
38+
39+
error: attributes cannot be applied here
40+
--> $DIR/attribute-on-empty.rs:25:15
41+
|
42+
LL | type Tuple = (#[attr], String);
43+
| ^^^^^^^ attributes are not allowed here
44+
45+
error: attributes cannot be applied here
46+
--> $DIR/attribute-on-empty.rs:28:6
47+
|
48+
LL | impl #[attr] {}
49+
| ^^^^^^^ attributes are not allowed here
50+
51+
error: aborting due to 8 previous errors
52+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
2+
//! <https://github.com/rust-lang/rust/issues/135017>
3+
4+
//@ run-rustfix
5+
6+
#![allow(dead_code, unused_variables)]
7+
8+
struct Foo<T>(T);
9+
struct Bar<'a>(&'a i32);
10+
struct Baz<const N: usize>(i32);
11+
12+
fn main() {
13+
let foo: Foo<i32> = Foo(2i32);
14+
//~^ ERROR attributes cannot be applied to generic arguments
15+
16+
let _: &'static str = "123";
17+
//~^ ERROR attributes cannot be applied to types
18+
19+
let _: Bar<'static> = Bar(&123);
20+
//~^ ERROR attributes cannot be applied to generic arguments
21+
22+
let _: Baz<42> = Baz(42);
23+
//~^ ERROR attributes cannot be applied to generic arguments
24+
25+
let _: Foo<String> = Foo(String::new());
26+
//~^ ERROR attributes cannot be applied to generic arguments
27+
28+
let _: Bar<'static> = Bar(&456);
29+
//~^ ERROR attributes cannot be applied to generic arguments
30+
31+
let _generic: Box<i32> = Box::new(1);
32+
//~^ ERROR attributes cannot be applied to generic arguments
33+
34+
let _assignment: i32 = *Box::new(1);
35+
//~^ ERROR attributes cannot be applied to types
36+
37+
let _complex: Vec<String> = vec![];
38+
//~^ ERROR attributes cannot be applied to generic arguments
39+
40+
let _nested: Box<Vec<u64>> = Box::new(vec![]);
41+
//~^ ERROR attributes cannot be applied to generic arguments
42+
}
43+
44+
fn g() -> i32 { 0 }
45+
//~^ ERROR attributes cannot be applied to types
46+
47+
struct S {
48+
field: i32,
49+
//~^ ERROR attributes cannot be applied to types
50+
field1: (i32, i32),
51+
//~^ ERROR attributes cannot be applied to types
52+
}
53+
54+
type Tuple = (i32, String);
55+
//~^ ERROR attributes cannot be applied to types
56+
57+
impl S {}
58+
//~^ ERROR attributes cannot be applied to types

tests/ui/parser/attribute-on-type.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! Regression test for: <https://github.com/rust-lang/rust/issues/144132>
2+
//! <https://github.com/rust-lang/rust/issues/135017>
3+
4+
//@ run-rustfix
5+
6+
#![allow(dead_code, unused_variables)]
7+
8+
struct Foo<T>(T);
9+
struct Bar<'a>(&'a i32);
10+
struct Baz<const N: usize>(i32);
11+
12+
fn main() {
13+
let foo: Foo<#[cfg(not(wrong))] i32> = Foo(2i32);
14+
//~^ ERROR attributes cannot be applied to generic arguments
15+
16+
let _: #[attr] &'static str = "123";
17+
//~^ ERROR attributes cannot be applied to types
18+
19+
let _: Bar<#[cfg(any())] 'static> = Bar(&123);
20+
//~^ ERROR attributes cannot be applied to generic arguments
21+
22+
let _: Baz<#[cfg(any())] 42> = Baz(42);
23+
//~^ ERROR attributes cannot be applied to generic arguments
24+
25+
let _: Foo<#[cfg(not(wrong))]String> = Foo(String::new());
26+
//~^ ERROR attributes cannot be applied to generic arguments
27+
28+
let _: Bar<#[cfg(any())] 'static> = Bar(&456);
29+
//~^ ERROR attributes cannot be applied to generic arguments
30+
31+
let _generic: Box<#[attr] i32> = Box::new(1);
32+
//~^ ERROR attributes cannot be applied to generic arguments
33+
34+
let _assignment: #[attr] i32 = *Box::new(1);
35+
//~^ ERROR attributes cannot be applied to types
36+
37+
let _complex: Vec<#[derive(Debug)] String> = vec![];
38+
//~^ ERROR attributes cannot be applied to generic arguments
39+
40+
let _nested: Box<Vec<#[cfg(feature = "test")] u64>> = Box::new(vec![]);
41+
//~^ ERROR attributes cannot be applied to generic arguments
42+
}
43+
44+
fn g() -> #[attr] i32 { 0 }
45+
//~^ ERROR attributes cannot be applied to types
46+
47+
struct S {
48+
field: #[attr] i32,
49+
//~^ ERROR attributes cannot be applied to types
50+
field1: (#[attr] i32, i32),
51+
//~^ ERROR attributes cannot be applied to types
52+
}
53+
54+
type Tuple = (#[attr] i32, String);
55+
//~^ ERROR attributes cannot be applied to types
56+
57+
impl #[attr] S {}
58+
//~^ ERROR attributes cannot be applied to types

0 commit comments

Comments
 (0)