Rollup merge of #77419 - GuillaumeGomez:create-e0777, r=jyn514

Create E0777 error code for invalid argument in derive

The second commit is to fix a nit reported by @jyn514 [here](https://github.com/rust-lang/rust/pull/76406/files#r485186592).
This commit is contained in:
Yuki Okushi 2020-10-04 11:45:03 +09:00 committed by GitHub
commit 830d1a0e32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 6 deletions

View File

@ -459,6 +459,7 @@ E0773: include_str!("./error_codes/E0773.md"),
E0774: include_str!("./error_codes/E0774.md"),
E0775: include_str!("./error_codes/E0775.md"),
E0776: include_str!("./error_codes/E0776.md"),
E0777: include_str!("./error_codes/E0777.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard

View File

@ -0,0 +1,19 @@
A literal value was used inside `#[derive]`.
Erroneous code example:
```compile_fail,E0777
#[derive("Clone")] // error!
struct Foo;
```
Only paths to traits are allowed as argument inside `#[derive]`. You can find
more information about the `#[derive]` attribute in the [Rust Book].
```
#[derive(Clone)] // ok!
struct Foo;
```
[Rust Book]: https://doc.rust-lang.org/book/appendix-03-derivable-traits.html

View File

@ -18,7 +18,7 @@ use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, PResult};
use rustc_errors::{struct_span_err, Applicability, PResult};
use rustc_feature::Features;
use rustc_parse::parser::Parser;
use rustc_parse::validate_attr;
@ -542,7 +542,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) {
let attr = self.cx.sess.find_by_name(item.attrs(), sym::derive);
let span = attr.map_or(item.span(), |attr| attr.span);
let mut err = rustc_errors::struct_span_err!(
let mut err = struct_span_err!(
self.cx.sess,
span,
E0774,

View File

@ -5,7 +5,8 @@ use rustc_ast::token;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::{self as ast, *};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, ErrorReported};
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
use rustc_lexer::is_ident;
use rustc_parse::nt_to_tokenstream;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
@ -182,9 +183,22 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>)
.filter_map(|nmi| match nmi {
NestedMetaItem::Literal(lit) => {
error_reported_filter_map = true;
cx.struct_span_err(lit.span, "expected path to a trait, found literal")
.help("for example, write `#[derive(Debug)]` for `Debug`")
.emit();
let mut err = struct_span_err!(
cx.sess,
lit.span,
E0777,
"expected path to a trait, found literal",
);
let token = lit.token.to_string();
if token.starts_with('"')
&& token.len() > 2
&& is_ident(&token[1..token.len() - 1])
{
err.help(&format!("try using `#[derive({})]`", &token[1..token.len() - 1]));
} else {
err.help("for example, write `#[derive(Debug)]` for `Debug`");
}
err.emit();
None
}
NestedMetaItem::MetaItem(mi) => Some(mi),

View File

@ -0,0 +1,7 @@
#[derive("Clone")] //~ ERROR E0777
#[derive("Clone
")]
//~^^ ERROR E0777
struct Foo;
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0777]: expected path to a trait, found literal
--> $DIR/E0777.rs:1:10
|
LL | #[derive("Clone")]
| ^^^^^^^
|
= help: try using `#[derive(Clone)]`
error[E0777]: expected path to a trait, found literal
--> $DIR/E0777.rs:2:10
|
LL | #[derive("Clone
| __________^
LL | | ")]
| |_^
|
= help: for example, write `#[derive(Debug)]` for `Debug`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0777`.