diff options
| author | bors <bors@rust-lang.org> | 2023-04-10 21:50:46 +0000 | 
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-04-10 21:50:46 +0000 | 
| commit | 194a0bb5d6fbdd36e0df58b4698311bb8fed6bca (patch) | |
| tree | 6c3419ffdd07c011177621862badf4991e6b8ffd /compiler/rustc_resolve | |
| parent | 88fb1b922b047981fc0cfc62aa1418b4361ae72e (diff) | |
| parent | 668a62984ac51a09987c5b1a7c1589814f7a95d4 (diff) | |
| download | rust-194a0bb5d6fbdd36e0df58b4698311bb8fed6bca.tar.gz rust-194a0bb5d6fbdd36e0df58b4698311bb8fed6bca.zip | |
Auto merge of #109638 - NotStirred:suggest/non-derive, r=davidtwco
Add suggestion to remove `derive()` if invoked macro is non-derive
Adds to the existing `expected derive macro, found {}` error message:
```
help: remove the surrounding "derive()":
  --> $DIR/macro-path-prelude-fail-4.rs:1:3
   |
LL | #[derive(inline)]
   |   ^^^^^^^      ^
```
This suggestion will either fix the issue, in the case that the macro was valid, or provide a better error message if not
Not ready for merge yet, as the highlighted span is only valid for trivial formatting. Is there a nice way to get the parent span of the macro path within `smart_resolve_macro_path`?
Closes #109589
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/messages.ftl | 10 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/errors.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 30 | 
3 files changed, 61 insertions, 6 deletions
| diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 2199ceee532..2628f247c54 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -213,3 +213,13 @@ resolve_tool_module_imported = resolve_module_only = visibility must resolve to a module + +resolve_macro_expected_found = + expected {$expected}, found {$found} `{$macro_path}` + +resolve_remove_surrounding_derive = + remove from the surrounding `derive()` + +resolve_add_as_non_derive = + add as non-Derive macro + `#[{$macro_path}]` diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 07aaaa1eb7f..afa796cb645 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -481,3 +481,30 @@ pub(crate) struct ToolModuleImported { #[derive(Diagnostic)] #[diag(resolve_module_only)] pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span); + +#[derive(Diagnostic, Default)] +#[diag(resolve_macro_expected_found)] +pub(crate) struct MacroExpectedFound<'a> { + #[primary_span] + pub(crate) span: Span, + pub(crate) found: &'a str, + pub(crate) expected: &'a str, + pub(crate) macro_path: &'a str, + #[subdiagnostic] + pub(crate) remove_surrounding_derive: Option<RemoveSurroundingDerive>, + #[subdiagnostic] + pub(crate) add_as_non_derive: Option<AddAsNonDerive<'a>>, +} + +#[derive(Subdiagnostic)] +#[help(resolve_remove_surrounding_derive)] +pub(crate) struct RemoveSurroundingDerive { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[help(resolve_add_as_non_derive)] +pub(crate) struct AddAsNonDerive<'a> { + pub(crate) macro_path: &'a str, +} diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 48707d37a10..22b014c0651 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1,6 +1,7 @@ //! A bunch of methods and structures more or less related to resolving macros and //! interface provided by `Resolver` to macro expander. +use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive}; use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; @@ -543,12 +544,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; if let Some((article, expected)) = unexpected_res { let path_str = pprust::path_to_string(path); - let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str); - self.tcx - .sess - .struct_span_err(path.span, &msg) - .span_label(path.span, format!("not {} {}", article, expected)) - .emit(); + + let mut err = MacroExpectedFound { + span: path.span, + expected, + found: res.descr(), + macro_path: &path_str, + ..Default::default() // Subdiagnostics default to None + }; + + // Suggest moving the macro out of the derive() if the macro isn't Derive + if !path.span.from_expansion() + && kind == MacroKind::Derive + && ext.macro_kind() != MacroKind::Derive + { + err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span }); + err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); + } + + let mut err = self.tcx.sess.create_err(err); + err.span_label(path.span, format!("not {} {}", article, expected)); + + err.emit(); + return Ok((self.dummy_ext(kind), Res::Err)); } | 
