diff options
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/ty.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 16 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-38821.stderr | 4 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-50480.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-50480.stderr | 89 | ||||
| -rw-r--r-- | src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr | 3 | ||||
| -rw-r--r-- | src/test/ui/suggestions/derive-macro-missing-bounds.rs | 89 | ||||
| -rw-r--r-- | src/test/ui/suggestions/derive-macro-missing-bounds.stderr | 107 |
10 files changed, 312 insertions, 53 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 994a74a5a9b..0cdb86ea475 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -567,8 +567,10 @@ impl<'a> TraitDef<'a> { }) }); - let Generics { mut params, mut where_clause, span } = + let Generics { mut params, mut where_clause, .. } = self.generics.to_generics(cx, self.span, type_ident, generics); + where_clause.span = generics.where_clause.span; + let span = generics.span; // Create the generic parameters params.extend(generics.params.iter().map(|param| match ¶m.kind { @@ -589,7 +591,7 @@ impl<'a> TraitDef<'a> { param.bounds.iter().cloned() ).collect(); - cx.typaram(self.span, param.ident, vec![], bounds, None) + cx.typaram(param.ident.span, param.ident, vec![], bounds, None) } GenericParamKind::Const { ty, kw_span, .. } => { let const_nodefault_kind = GenericParamKind::Const { @@ -610,7 +612,7 @@ impl<'a> TraitDef<'a> { match *clause { ast::WherePredicate::BoundPredicate(ref wb) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: self.span, + span: wb.span, bound_generic_params: wb.bound_generic_params.clone(), bounded_ty: wb.bounded_ty.clone(), bounds: wb.bounds.to_vec(), @@ -618,7 +620,7 @@ impl<'a> TraitDef<'a> { } ast::WherePredicate::RegionPredicate(ref rb) => { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - span: self.span, + span: rb.span, lifetime: rb.lifetime, bounds: rb.bounds.to_vec(), }) @@ -626,7 +628,7 @@ impl<'a> TraitDef<'a> { ast::WherePredicate::EqPredicate(ref we) => { ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { id: ast::DUMMY_NODE_ID, - span: self.span, + span: we.span, lhs_ty: we.lhs_ty.clone(), rhs_ty: we.rhs_ty.clone(), }) @@ -691,13 +693,13 @@ impl<'a> TraitDef<'a> { .iter() .map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) + GenericArg::Lifetime(cx.lifetime(param.ident.span, param.ident)) } GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(self.span, param.ident)) + GenericArg::Type(cx.ty_ident(param.ident.span, param.ident)) } GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(self.span, param.ident)) + GenericArg::Const(cx.const_ident(param.ident.span, param.ident)) } }) .collect(); @@ -1556,11 +1558,9 @@ impl<'a> TraitDef<'a> { let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..)); match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx.span_bug( - self.span, - "a struct with named and unnamed \ - fields in generic `derive`", - ), + (false, false) => { + cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`") + } // named fields (_, false) => Named(named_idents), // unnamed fields diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 00d75be4399..7a418003250 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -211,14 +211,6 @@ fn mk_ty_param( cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None) } -fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics { - Generics { - params, - where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, - span, - } -} - /// Bounds on type parameters. #[derive(Clone)] pub struct Bounds { @@ -236,7 +228,7 @@ impl Bounds { self_ty: Ident, self_generics: &Generics, ) -> Generics { - let generic_params = self + let params = self .bounds .iter() .map(|t| { @@ -245,7 +237,11 @@ impl Bounds { }) .collect(); - mk_generics(generic_params, span) + Generics { + params, + where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, + span, + } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 61a96564a4c..69f770265dd 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -17,8 +17,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{def_id::LocalDefId, BytePos}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; @@ -529,7 +528,6 @@ impl GenericParam<'hir> { pub fn bounds_span(&self) -> Option<Span> { self.bounds.iter().fold(None, |span, bound| { let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); - Some(span) }) } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 69697f275e1..4e071d69e36 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1803,7 +1803,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { ); err.span_label(lifetime_ref.span, "undeclared lifetime"); let mut suggests_in_band = false; - let mut suggest_note = true; + let mut suggested_spans = vec![]; for missing in &self.missing_named_lifetime_spots { match missing { MissingLifetimeSpot::Generics(generics) => { @@ -1821,6 +1821,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { suggests_in_band = true; (generics.span, format!("<{}>", lifetime_ref)) }; + if suggested_spans.contains(&span) { + continue; + } + suggested_spans.push(span); if !span.from_expansion() { err.span_suggestion( span, @@ -1828,16 +1832,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { sugg, Applicability::MaybeIncorrect, ); - } else if suggest_note { - suggest_note = false; // Avoid displaying the same help multiple times. - err.span_label( - span, - &format!( - "lifetime `{}` is missing in item created through this procedural \ - macro", - lifetime_ref, - ), - ); } } MissingLifetimeSpot::HigherRanked { span, span_type } => { diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr index e53a543f3a0..3a8b69224d3 100644 --- a/src/test/ui/issues/issue-38821.stderr +++ b/src/test/ui/issues/issue-38821.stderr @@ -10,6 +10,10 @@ note: required because of the requirements on the impl of `IntoNullable` for `<C LL | impl<T: NotNull> IntoNullable for T { | ^^^^^^^^^^^^ ^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting the associated type + | +LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs index deb63872f69..10597caf5b2 100644 --- a/src/test/ui/issues/issue-50480.rs +++ b/src/test/ui/issues/issue-50480.rs @@ -1,8 +1,17 @@ #[derive(Clone, Copy)] //~^ ERROR the trait `Copy` may not be implemented for this type -struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); +struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope +//~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator + +#[derive(Clone, Copy)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); +//~^ ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator fn main() {} diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr index 15f38c89267..0bb1f9ae035 100644 --- a/src/test/ui/issues/issue-50480.stderr +++ b/src/test/ui/issues/issue-50480.stderr @@ -1,20 +1,61 @@ -error[E0412]: cannot find type `NotDefined` in this scope +error[E0412]: cannot find type `N` in this scope --> $DIR/issue-50480.rs:3:12 | -LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); - | ^^^^^^^^^^ not found in this scope +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: `<N>` error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `N` in this scope --> $DIR/issue-50480.rs:3:12 | -LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); - | ^^^^^^^^^^ not found in this scope +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: `<N>` + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +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: `<NotDefined>` + +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:12:18 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ~ +help: you might be missing a type parameter + | +LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:12:21 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^ not found in this scope error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:24 + --> $DIR/issue-50480.rs:3:27 | -LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); - | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` @@ -25,14 +66,36 @@ error[E0204]: the trait `Copy` may not be implemented for this type LL | #[derive(Clone, Copy)] | ^^^^ LL | -LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); - | -------- ------ this field does not implement `Copy` - | | - | this field does not implement `Copy` +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:12:33 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-50480.rs:10:17 + | +LL | #[derive(Clone, Copy)] + | ^^^^ +LL | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0204, E0277, E0412. For more information about an error, try `rustc --explain E0204`. diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr index e18d725faef..a2086895234 100644 --- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr +++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -11,9 +11,8 @@ LL | a: &'b str, error[E0261]: use of undeclared lifetime name `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 | -LL | #[derive(Eq, PartialEq)] - | -- lifetime `'b` is missing in item created through this procedural macro LL | struct Test { + | - help: consider introducing lifetime `'b` here: `<'b>` LL | a: &'b str, | ^^ undeclared lifetime | diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.rs b/src/test/ui/suggestions/derive-macro-missing-bounds.rs new file mode 100644 index 00000000000..56c218f97eb --- /dev/null +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.rs @@ -0,0 +1,89 @@ +mod a { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + + impl Debug for Inner<()> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR `a::Inner<T>` doesn't implement `Debug` +} + +mod b { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + + impl<T: Debug> Debug for Inner<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); +} + +mod c { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T: Debug + Trait> Debug for Inner<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: c::Trait` is not satisfied +} + +mod d { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T> Debug for Inner<T> where T: Debug, T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: d::Trait` is not satisfied +} + +mod e { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T> Debug for Inner<T> where T: Debug + Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: e::Trait` is not satisfied +} + +mod f { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T: Debug> Debug for Inner<T> where T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: f::Trait` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr new file mode 100644 index 00000000000..39678105930 --- /dev/null +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr @@ -0,0 +1,107 @@ +error[E0277]: `a::Inner<T>` doesn't implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:12:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ `a::Inner<T>` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `a::Inner<T>` + = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement + | +LL | struct Outer<T>(Inner<T>) where a::Inner<T>: Debug; + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: c::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:41:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `c::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `c::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:34:28 + | +LL | impl<T: Debug + Trait> Debug for Inner<T> { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&c::Inner<T>` + = note: required for the cast to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | #[derive(Debug + c::Trait)] + | ++++++++++ + +error[E0277]: the trait bound `T: d::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:56:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `d::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `d::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:49:13 + | +LL | impl<T> Debug for Inner<T> where T: Debug, T: Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&d::Inner<T>` + = note: required for the cast to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | #[derive(Debug + d::Trait)] + | ++++++++++ + +error[E0277]: the trait bound `T: e::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:71:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `e::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `e::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:64:13 + | +LL | impl<T> Debug for Inner<T> where T: Debug + Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&e::Inner<T>` + = note: required for the cast to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | #[derive(Debug + e::Trait)] + | ++++++++++ + +error[E0277]: the trait bound `T: f::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:86:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `f::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `f::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:79:20 + | +LL | impl<T: Debug> Debug for Inner<T> where T: Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&f::Inner<T>` + = note: required for the cast to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | #[derive(Debug + f::Trait)] + | ++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. |
