Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_resolve/src/diagnostics/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2314,6 +2314,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// | ^
return;
}
if span.in_derive_expansion() {
return;
}
let span = self.tcx.sess.source_map().guess_head_span(def_span);
let candidate_descr = suggestion.res.descr();
let candidate = suggestion.candidate;
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
self.suggest_range_struct_destructuring(&mut err, path, source);
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
self.detect_resolution_error_in_derive(&mut err, base_error.span);

if let Some((span, label)) = base_error.span_label {
err.span_label(span, label);
Expand Down Expand Up @@ -1904,6 +1905,26 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}

/// If the name resolution error occurs in an ident that has no span context, but the enclosing
/// item is within a derive macro, point at the derive, as the error can either be because of an
/// invalid derive macro *or* a non-existing item that will already have been reported through
/// the annotated item.
fn detect_resolution_error_in_derive(&self, err: &mut Diag<'_>, span: Span) {
if let Some(item) = self.diag_metadata.current_item
&& !item.span.eq_ctxt(span)
&& item.span.in_derive_expansion()
{
// `item` comes from a `#[derive()]`, but the error `span` doesn't, which means that the
// derive is referencing a name coming from the annotated item. If the item exists, then
// the derive macro itself is buggy. If the item exists, then an error will have already
// been emitted while evaluating the annotated item itself, but we can't silence this
// one because one *can* write a derive macro referencing a non-existing item that is
// part of the expansion, *not* from the user's code. Because of that, at least for now,
// we just add context to the current error.
err.span_label(item.span, "in this derive macro");
}
}
Comment on lines +1912 to +1926

@estebank estebank Sep 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd originally made this delay the error as bug, so that the resolve error would not be present, under the assumption that other errors would already have been emitted (if it was a non-existing item, we'd have an error when evaluating the item itself, if a proc-macro error, we have the other errors)...

View changes since the review


fn explain_functions_in_pattern(
&self,
err: &mut Diag<'_>,
Expand Down Expand Up @@ -3681,6 +3702,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
(Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
}
(Some(Item { span, .. }), _, _) if span.in_derive_expansion() => {
return (None, None);
}
(
Some(Item {
kind:
Expand Down
50 changes: 50 additions & 0 deletions tests/ui/derives/auxiliary/derive-no-generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,53 @@ pub fn derive(item: TokenStream) -> TokenStream {
};
tokens
}

#[proc_macro_derive(B)]
pub fn derive_2(item: TokenStream) -> TokenStream {
let mut tokens = item.into_iter();
let _enum = tokens.next();
let name = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let TokenTree::Group(group) = tokens.next().unwrap() else { panic!() };
let mut group = group.stream().into_iter();
let variant = group.next().unwrap();
let TokenTree::Group(args) = group.next().unwrap() else { panic!() };
let arg = args.stream().into_iter().next().unwrap();
let tokens = quote! {
trait X {}
impl X for $name {}

impl $name {
fn foo(&self) {
if let Self :: $variant(val) = self {
let _: T = val;
}
}
}

};
tokens
}

#[proc_macro_derive(C)]
pub fn derive_3(item: TokenStream) -> TokenStream {
let mut tokens = item.into_iter();
let _enum = tokens.next();
let name = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let _ = tokens.next().unwrap();
let TokenTree::Group(group) = tokens.next().unwrap() else { panic!() };
let mut group = group.stream().into_iter();
let variant = group.next().unwrap();
let TokenTree::Group(args) = group.next().unwrap() else { panic!() };
let arg = args.stream().into_iter().next().unwrap();
let tokens = quote! {
fn foo(val: $name<$arg>) {
$name :: $variant($arg) = val;
}
};
tokens
}

@estebank estebank Sep 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...but this macro is written such that if the name resolution error isn't emitted...

View changes since the review

15 changes: 15 additions & 0 deletions tests/ui/derives/derive-macro-unsupported-type-params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,18 @@ enum A<T> {
Variant(T),
//~^ ERROR: cannot find type `T` in this scope
}

// Resolution error comes entirely from within the derive macro:
#[derive(B)] //~ ERROR: cannot find type `T` in this scope
enum B<T> {
//~^ ERROR: missing generics for enum `B`
//~| ERROR: missing generics for enum `B`
Variant(T),
}

#[derive(C)]
enum C<T> {
Variant(T),
//~^ ERROR: cannot find value `T` in this scope
//~| ERROR: cannot find type `T` in this scope
}
Comment on lines +23 to +28

@estebank estebank Sep 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and this is the only code in the crate being built, we end up with an ICE.

This is why I'm adding context instead of silencing. I'd love it if we could come up with a strategy where we silence in every other case, but not this one.

View changes since the review

60 changes: 59 additions & 1 deletion tests/ui/derives/derive-macro-unsupported-type-params.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
error[E0425]: cannot find type `T` in this scope
--> $DIR/derive-macro-unsupported-type-params.rs:11:13
|
LL | #[derive(A)]
| - in this derive macro
...
LL | Variant(T),
| ^ not found in this scope

error[E0425]: cannot find type `T` in this scope
--> $DIR/derive-macro-unsupported-type-params.rs:16:10
|
LL | #[derive(B)]
| ^ not found in this scope
|
= note: this error originates in the derive macro `B` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0425]: cannot find type `T` in this scope
--> $DIR/derive-macro-unsupported-type-params.rs:25:13
|
LL | #[derive(C)]
| - in this derive macro
LL | enum C<T> {
LL | Variant(T),
| ^ not found in this scope
|
note: similarly named enum `A` defined here
--> $DIR/derive-macro-unsupported-type-params.rs:8:1
|
LL | enum A<T> {
| ^^^^^^^^^
help: an enum with a similar name exists
|
LL - Variant(T),
LL + Variant(A),
|

error[E0425]: cannot find value `T` in this scope
--> $DIR/derive-macro-unsupported-type-params.rs:25:13
|
LL | #[derive(C)]
| - in this derive macro
LL | enum C<T> {
LL | Variant(T),
| ^ not found in this scope

Expand All @@ -22,7 +62,25 @@ LL | enum A<T> {
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 3 previous errors
error[E0107]: missing generics for enum `B`
--> $DIR/derive-macro-unsupported-type-params.rs:17:6
|
LL | #[derive(B)]
| - this derive macro might not support items with generic parameters
LL | enum B<T> {
| ^

error[E0107]: missing generics for enum `B`
--> $DIR/derive-macro-unsupported-type-params.rs:17:6
|
LL | #[derive(B)]
| - this derive macro might not support items with generic parameters
LL | enum B<T> {
| ^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 8 previous errors

Some errors have detailed explanations: E0107, E0425.
For more information about an error, try `rustc --explain E0107`.
5 changes: 3 additions & 2 deletions tests/ui/macros/tokenstream-ice-issue-149954.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,14 @@ LL | A: A<{ struct A<A: A<{ #[cfg] () }>> ; enum A }
error[E0404]: expected trait, found struct `A`
--> $DIR/tokenstream-ice-issue-149954.rs:10:16
|
LL | #[derive(Debug)]
| ----- in this derive macro
...
LL | A: A<{ struct A<A: A<{ #[cfg] () }>> ; enum A }
| ________________^
... |
LL | | >;
| |_________^ not a trait
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0404]: expected trait, found type parameter `A`
--> $DIR/tokenstream-ice-issue-149954.rs:10:32
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ LL | struct Foo(NonExistent);
error[E0425]: cannot find type `NonExistent` in this scope
--> $DIR/issue-119493-type-error-ice.rs:5:16
|
LL | #[derive(Copy, Clone)]
| ----- in this derive macro
LL | struct Foo(NonExistent);
| ^^^^^^^^^^^ not found in this scope
|
help: you might be missing a type parameter
|
LL | struct Foo<NonExistent>(NonExistent);
| +++++++++++++

error[E0658]: `impl Trait` in type aliases is unstable
--> $DIR/issue-119493-type-error-ice.rs:9:14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,10 @@ LL | struct Foo<const S: /* Type */>([u8; S]);
error[E0425]: cannot find value `S` in this scope
--> $DIR/issue-119778-type-error-ice.rs:5:21
|
LL | #[derive(Copy, Clone)]
| ----- in this derive macro
LL | struct Foo([u8; S]);
| ^ not found in this scope
|
help: you might be missing a const parameter
|
LL | struct Foo<const S: /* Type */>([u8; S]);
| +++++++++++++++++++++

error[E0658]: `impl Trait` in type aliases is unstable
--> $DIR/issue-119778-type-error-ice.rs:9:14
Expand Down
14 changes: 4 additions & 10 deletions tests/ui/traits/issue-50480.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,18 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
error[E0425]: cannot find type `N` in this scope
--> $DIR/issue-50480.rs:2:12
|
LL | #[derive(Clone, Copy)]
| ----- in this derive macro
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
| ^ not found in this scope
|
help: you might be missing a type parameter
|
LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
| +++

error[E0425]: cannot find type `NotDefined` in this scope
--> $DIR/issue-50480.rs:2:15
|
LL | #[derive(Clone, Copy)]
| ----- in this derive macro
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
| ^^^^^^^^^^ not found in this scope
|
help: you might be missing a type parameter
|
LL | struct Foo<NotDefined>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
| ++++++++++++

error[E0425]: cannot find type `N` in this scope
--> $DIR/issue-50480.rs:12:18
Expand Down
Loading