Skip to content

Commit cdc8db4

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

15 files changed

+541
-33
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 a type
75+
.label = attributes are not allowed here
76+
.suggestion = remove attribute from here
77+
78+
parse_attribute_on_generic_type = attributes cannot be applied to generic type arguments
79+
.label = attributes are not allowed here
80+
.suggestion = remove attribute from here
81+
82+
parse_attribute_on_empty_generic = 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 = "verbose")]
1499+
pub fix_span: Span,
1500+
}
1501+
1502+
#[derive(Diagnostic)]
1503+
#[diag(parse_attribute_on_generic_type)]
1504+
pub(crate) struct AttributeOnGenericType {
1505+
#[primary_span]
1506+
#[label]
1507+
pub span: Span,
1508+
#[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
1509+
pub fix_span: Span,
1510+
}
1511+
1512+
#[derive(Diagnostic)]
1513+
#[diag(parse_attribute_on_empty_generic)]
1514+
pub(crate) struct AttributeOnEmptyGeneric {
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/attr_wrapper.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ impl AttrWrapper {
6969
self.attrs
7070
}
7171

72+
pub(super) fn attrs(&self) -> &AttrVec {
73+
&self.attrs
74+
}
75+
7276
/// Prepend `self.attrs` to `attrs`.
7377
// FIXME: require passing an NT to prevent misuse of this method
7478
pub(super) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) {

compiler/rustc_parse/src/parser/path.rs

Lines changed: 34 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, AttributeOnEmptyGeneric, AttributeOnGenericType, 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,15 @@ 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+
// Parse attribute.
886+
let attrs_wrapper = self.parse_outer_attributes()?;
887+
if !attrs_wrapper.is_empty() {
888+
let raw_attrs = attrs_wrapper.attrs();
889+
attr_span = Some(raw_attrs[0].span.to(raw_attrs.last().unwrap().span));
890+
}
891+
}
883892
let start = self.token.span;
884893
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
885894
// Parse lifetime argument.
@@ -934,6 +943,10 @@ impl<'a> Parser<'a> {
934943
}
935944
} else if self.token.is_keyword(kw::Const) {
936945
return self.recover_const_param_declaration(ty_generics);
946+
} else if let Some(attr_span) = attr_span {
947+
// Handle case where attribute is present but no valid generic argument follows.
948+
let guar = self.dcx().emit_err(AttributeOnEmptyGeneric { span: attr_span });
949+
return Ok(Some(GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar)))));
937950
} else {
938951
// Fall back by trying to parse a const-expr expression. If we successfully do so,
939952
// then we should report an error that it needs to be wrapped in braces.
@@ -953,6 +966,24 @@ impl<'a> Parser<'a> {
953966
}
954967
}
955968
};
969+
970+
if let Some(attr_span) = attr_span {
971+
let guar = self.dcx().emit_err(AttributeOnGenericType {
972+
span: attr_span,
973+
fix_span: attr_span.until(arg.span()),
974+
});
975+
976+
return Ok(Some(match arg {
977+
GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))),
978+
GenericArg::Const(_) => {
979+
// Create error const expression
980+
let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar));
981+
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr })
982+
}
983+
GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt), // Less common case
984+
}));
985+
}
986+
956987
Ok(Some(arg))
957988
}
958989

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 26 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, AttributeOnEmptyGeneric, 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,29 @@ 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+
if !attrs_wrapper.is_empty() {
259+
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
260+
let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
261+
let (full_span, guar) = match self.parse_ty() {
262+
Ok(ty) => {
263+
let full_span = attr_span.until(ty.span);
264+
let guar = self
265+
.dcx()
266+
.emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
267+
(attr_span, guar)
268+
}
269+
Err(err) => {
270+
err.cancel();
271+
let guar = self.dcx().emit_err(AttributeOnEmptyGeneric { span: attr_span });
272+
(attr_span, guar)
273+
}
274+
};
256275

276+
return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
277+
}
278+
}
257279
if let Some(ty) = self.eat_metavar_seq_with_matcher(
258280
|mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
259281
|this| this.parse_ty_no_question_mark_recover(),

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

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

0 commit comments

Comments
 (0)