Keep spans for generics in #[derive(_)]
desugaring
Keep the spans for generics coming from a `derive`d Item, so that errors and suggestions have better detail. Fix #84003.
This commit is contained in:
parent
e5038e2099
commit
e70105f971
10 changed files with 312 additions and 53 deletions
|
@ -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);
|
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
|
// Create the generic parameters
|
||||||
params.extend(generics.params.iter().map(|param| match ¶m.kind {
|
params.extend(generics.params.iter().map(|param| match ¶m.kind {
|
||||||
|
@ -589,7 +591,7 @@ impl<'a> TraitDef<'a> {
|
||||||
param.bounds.iter().cloned()
|
param.bounds.iter().cloned()
|
||||||
).collect();
|
).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, .. } => {
|
GenericParamKind::Const { ty, kw_span, .. } => {
|
||||||
let const_nodefault_kind = GenericParamKind::Const {
|
let const_nodefault_kind = GenericParamKind::Const {
|
||||||
|
@ -610,7 +612,7 @@ impl<'a> TraitDef<'a> {
|
||||||
match *clause {
|
match *clause {
|
||||||
ast::WherePredicate::BoundPredicate(ref wb) => {
|
ast::WherePredicate::BoundPredicate(ref wb) => {
|
||||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||||
span: self.span,
|
span: wb.span,
|
||||||
bound_generic_params: wb.bound_generic_params.clone(),
|
bound_generic_params: wb.bound_generic_params.clone(),
|
||||||
bounded_ty: wb.bounded_ty.clone(),
|
bounded_ty: wb.bounded_ty.clone(),
|
||||||
bounds: wb.bounds.to_vec(),
|
bounds: wb.bounds.to_vec(),
|
||||||
|
@ -618,7 +620,7 @@ impl<'a> TraitDef<'a> {
|
||||||
}
|
}
|
||||||
ast::WherePredicate::RegionPredicate(ref rb) => {
|
ast::WherePredicate::RegionPredicate(ref rb) => {
|
||||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||||
span: self.span,
|
span: rb.span,
|
||||||
lifetime: rb.lifetime,
|
lifetime: rb.lifetime,
|
||||||
bounds: rb.bounds.to_vec(),
|
bounds: rb.bounds.to_vec(),
|
||||||
})
|
})
|
||||||
|
@ -626,7 +628,7 @@ impl<'a> TraitDef<'a> {
|
||||||
ast::WherePredicate::EqPredicate(ref we) => {
|
ast::WherePredicate::EqPredicate(ref we) => {
|
||||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: self.span,
|
span: we.span,
|
||||||
lhs_ty: we.lhs_ty.clone(),
|
lhs_ty: we.lhs_ty.clone(),
|
||||||
rhs_ty: we.rhs_ty.clone(),
|
rhs_ty: we.rhs_ty.clone(),
|
||||||
})
|
})
|
||||||
|
@ -691,13 +693,13 @@ impl<'a> TraitDef<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| match param.kind {
|
.map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
GenericArg::Lifetime(cx.lifetime(self.span, param.ident))
|
GenericArg::Lifetime(cx.lifetime(param.ident.span, param.ident))
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } => {
|
||||||
GenericArg::Type(cx.ty_ident(self.span, param.ident))
|
GenericArg::Type(cx.ty_ident(param.ident.span, param.ident))
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { .. } => {
|
GenericParamKind::Const { .. } => {
|
||||||
GenericArg::Const(cx.const_ident(self.span, param.ident))
|
GenericArg::Const(cx.const_ident(param.ident.span, param.ident))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1556,11 +1558,9 @@ impl<'a> TraitDef<'a> {
|
||||||
|
|
||||||
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
||||||
match (just_spans.is_empty(), named_idents.is_empty()) {
|
match (just_spans.is_empty(), named_idents.is_empty()) {
|
||||||
(false, false) => cx.span_bug(
|
(false, false) => {
|
||||||
self.span,
|
cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`")
|
||||||
"a struct with named and unnamed \
|
}
|
||||||
fields in generic `derive`",
|
|
||||||
),
|
|
||||||
// named fields
|
// named fields
|
||||||
(_, false) => Named(named_idents),
|
(_, false) => Named(named_idents),
|
||||||
// unnamed fields
|
// unnamed fields
|
||||||
|
|
|
@ -211,14 +211,6 @@ fn mk_ty_param(
|
||||||
cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None)
|
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.
|
/// Bounds on type parameters.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Bounds {
|
pub struct Bounds {
|
||||||
|
@ -236,7 +228,7 @@ impl Bounds {
|
||||||
self_ty: Ident,
|
self_ty: Ident,
|
||||||
self_generics: &Generics,
|
self_generics: &Generics,
|
||||||
) -> Generics {
|
) -> Generics {
|
||||||
let generic_params = self
|
let params = self
|
||||||
.bounds
|
.bounds
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
|
@ -245,7 +237,11 @@ impl Bounds {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
mk_generics(generic_params, span)
|
Generics {
|
||||||
|
params,
|
||||||
|
where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
|
||||||
|
span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,7 @@ use rustc_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{def_id::LocalDefId, BytePos};
|
use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP};
|
||||||
use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
|
||||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
|
@ -529,7 +528,6 @@ impl GenericParam<'hir> {
|
||||||
pub fn bounds_span(&self) -> Option<Span> {
|
pub fn bounds_span(&self) -> Option<Span> {
|
||||||
self.bounds.iter().fold(None, |span, bound| {
|
self.bounds.iter().fold(None, |span, bound| {
|
||||||
let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
|
let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
|
||||||
|
|
||||||
Some(span)
|
Some(span)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1803,7 +1803,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||||
);
|
);
|
||||||
err.span_label(lifetime_ref.span, "undeclared lifetime");
|
err.span_label(lifetime_ref.span, "undeclared lifetime");
|
||||||
let mut suggests_in_band = false;
|
let mut suggests_in_band = false;
|
||||||
let mut suggest_note = true;
|
let mut suggested_spans = vec![];
|
||||||
for missing in &self.missing_named_lifetime_spots {
|
for missing in &self.missing_named_lifetime_spots {
|
||||||
match missing {
|
match missing {
|
||||||
MissingLifetimeSpot::Generics(generics) => {
|
MissingLifetimeSpot::Generics(generics) => {
|
||||||
|
@ -1821,6 +1821,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||||
suggests_in_band = true;
|
suggests_in_band = true;
|
||||||
(generics.span, format!("<{}>", lifetime_ref))
|
(generics.span, format!("<{}>", lifetime_ref))
|
||||||
};
|
};
|
||||||
|
if suggested_spans.contains(&span) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
suggested_spans.push(span);
|
||||||
if !span.from_expansion() {
|
if !span.from_expansion() {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
|
@ -1828,16 +1832,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||||
sugg,
|
sugg,
|
||||||
Applicability::MaybeIncorrect,
|
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 } => {
|
MissingLifetimeSpot::HigherRanked { span, span_type } => {
|
||||||
|
|
|
@ -10,6 +10,10 @@ note: required because of the requirements on the impl of `IntoNullable` for `<C
|
||||||
LL | impl<T: NotNull> IntoNullable for T {
|
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)
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
//~^ 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 `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
|
//~| ERROR `i32` is not an iterator
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-50480.rs:3:12
|
||||||
|
|
|
|
||||||
LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| ^^^^^^^^^^ not found in this scope
|
| -^ not found in this scope
|
||||||
|
| |
|
||||||
|
| help: you might be missing a type parameter: `<N>`
|
||||||
|
|
||||||
error[E0412]: cannot find type `NotDefined` in this scope
|
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
|
--> $DIR/issue-50480.rs:3:12
|
||||||
|
|
|
|
||||||
LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| ^^^^^^^^^^ not found in this scope
|
| -^ 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
|
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);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
|
| ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
|
||||||
|
|
|
|
||||||
= help: the trait `Iterator` is not implemented for `i32`
|
= 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`
|
= 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 | #[derive(Clone, Copy)]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| -------- ------ this field does not implement `Copy`
|
| -------- ------ this field does not implement `Copy`
|
||||||
| |
|
| |
|
||||||
| 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)
|
= 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[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 10 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0204, E0277, E0412.
|
Some errors have detailed explanations: E0204, E0277, E0412.
|
||||||
For more information about an error, try `rustc --explain E0204`.
|
For more information about an error, try `rustc --explain E0204`.
|
||||||
|
|
|
@ -11,9 +11,8 @@ LL | a: &'b str,
|
||||||
error[E0261]: use of undeclared lifetime name `'b`
|
error[E0261]: use of undeclared lifetime name `'b`
|
||||||
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
|
--> $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 {
|
LL | struct Test {
|
||||||
|
| - help: consider introducing lifetime `'b` here: `<'b>`
|
||||||
LL | a: &'b str,
|
LL | a: &'b str,
|
||||||
| ^^ undeclared lifetime
|
| ^^ undeclared lifetime
|
||||||
|
|
|
|
||||||
|
|
89
src/test/ui/suggestions/derive-macro-missing-bounds.rs
Normal file
89
src/test/ui/suggestions/derive-macro-missing-bounds.rs
Normal file
|
@ -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() {}
|
107
src/test/ui/suggestions/derive-macro-missing-bounds.stderr
Normal file
107
src/test/ui/suggestions/derive-macro-missing-bounds.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue