Skip to content

Commit 138472b

Browse files
committed
Checking location and syntax of non_exhaustive attribute.
1 parent 934902a commit 138472b

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

src/librustc/diagnostics.rs

+27
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,33 @@ where 'x: 'y
20582058
```
20592059
"##,
20602060

2061+
E0910: r##"
2062+
This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed
2063+
on something other than a struct or enum.
2064+
2065+
Examples of erroneous code:
2066+
2067+
```compile_fail,E0910
2068+
# #![feature(non_exhaustive)]
2069+
2070+
#[non_exhaustive]
2071+
trait Foo { }
2072+
```
2073+
"##,
2074+
2075+
E0911: r##"
2076+
This error indicates that a `#[non_exhaustive]` attribute had a value. The
2077+
`#[non_exhaustive]` should be empty.
2078+
2079+
Examples of erroneous code:
2080+
2081+
```compile_fail,E0911
2082+
# #![feature(non_exhaustive)]
2083+
2084+
#[non_exhaustive(anything)]
2085+
struct Foo;
2086+
```
2087+
"##,
20612088

20622089
}
20632090

src/librustc/hir/check_attr.rs

+27
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
6666
for attr in &item.attrs {
6767
if attr.check_name("inline") {
6868
self.check_inline(attr, &item.span, target)
69+
} else if attr.check_name("non_exhaustive") {
70+
self.check_non_exhaustive(attr, item, target)
6971
} else if attr.check_name("wasm_import_module") {
7072
has_wasm_import_module = true;
7173
if attr.value_str().is_none() {
@@ -113,6 +115,31 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
113115
}
114116
}
115117

118+
/// Check if the `#[non_exhaustive]` attribute on an `item` is valid.
119+
fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
120+
match target {
121+
Target::Struct | Target::Enum => { /* Valid */ },
122+
_ => {
123+
struct_span_err!(self.tcx.sess,
124+
attr.span,
125+
E0910,
126+
"attribute can only be applied to a struct or enum")
127+
.span_label(item.span, "not a struct or enum")
128+
.emit();
129+
return;
130+
}
131+
}
132+
133+
if attr.meta_item_list().is_some() || attr.value_str().is_some() {
134+
struct_span_err!(self.tcx.sess,
135+
attr.span,
136+
E0911,
137+
"attribute should be empty")
138+
.span_label(item.span, "not empty")
139+
.emit();
140+
}
141+
}
142+
116143
/// Check if the `#[repr]` attributes on `item` are valid.
117144
fn check_repr(&self, item: &hir::Item, target: Target) {
118145
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(non_exhaustive)]
12+
13+
#[non_exhaustive(anything)]
14+
//~^ ERROR attribute should be empty [E0911]
15+
struct Foo;
16+
17+
#[non_exhaustive]
18+
//~^ ERROR attribute can only be applied to a struct or enum [E0910]
19+
trait Bar { }
20+
21+
#[non_exhaustive]
22+
//~^ ERROR attribute can only be applied to a struct or enum [E0910]
23+
union Baz {
24+
f1: u16,
25+
f2: u16
26+
}
27+
28+
fn main() { }

0 commit comments

Comments
 (0)