diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 4abb1d90f44..b6b242bfc27 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> { param.id, ¶m.kind, ¶m.bounds, + param.colon_span, + generics.span, itctx, PredicateOrigin::GenericParam, ) @@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], + colon_span: Option, + parent_span: Span, itctx: &ImplTraitContext, origin: PredicateOrigin, ) -> Option> { @@ -1377,21 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.lower_ident(ident); let param_span = ident.span; - let span = bounds - .iter() - .fold(Some(param_span.shrink_to_hi()), |span: Option, bound| { - let bound_span = bound.span(); - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. - if !bound_span.can_be_used_for_suggestions() { - None - } else if let Some(span) = span { - Some(span.to(bound_span)) - } else { - Some(bound_span) - } - }) - .unwrap_or(param_span.shrink_to_hi()); + + // Reconstruct the span of the entire predicate from the individual generic bounds. + let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi()); + let span = bounds.iter().fold(span_start, |span_accum, bound| { + match bound.span().find_ancestor_inside(parent_span) { + Some(bound_span) => span_accum.to(bound_span), + None => span_accum, + } + }); + let span = self.lower_span(span); + match kind { GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a089510493e..1fbc45a58e5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2245,6 +2245,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (hir::GenericParam<'hir>, Option>, hir::TyKind<'hir>) { // Add a definition for the in-band `Param`. let def_id = self.local_def_id(node_id); + let span = self.lower_span(span); // Set the name to `impl Bound1 + Bound2`. let param = hir::GenericParam { @@ -2252,7 +2253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, name: ParamName::Plain(self.lower_ident(ident)), pure_wrt_drop: false, - span: self.lower_span(span), + span, kind: hir::GenericParamKind::Type { default: None, synthetic: true }, colon_span: None, }; @@ -2262,6 +2263,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, + /* colon_span */ None, + span, &ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); @@ -2271,7 +2274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { - span: self.lower_span(span), + span, res, segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d6de6e70ead..cdb901b7f86 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2184,6 +2184,7 @@ impl ExplicitOutlivesRequirements { tcx: TyCtxt<'tcx>, bounds: &hir::GenericBounds<'_>, inferred_outlives: &[ty::Region<'tcx>], + predicate_span: Span, ) -> Vec<(usize, Span)> { use rustc_middle::middle::resolve_lifetime::Region; @@ -2191,23 +2192,28 @@ impl ExplicitOutlivesRequirements { .iter() .enumerate() .filter_map(|(i, bound)| { - if let hir::GenericBound::Outlives(lifetime) = bound { - let is_inferred = match tcx.named_region(lifetime.hir_id) { - Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| { - if let ty::ReEarlyBound(ebr) = **r { - ebr.def_id == def_id - } else { - false - } - }), - _ => false, - }; - is_inferred.then_some((i, bound.span())) - } else { - None + let hir::GenericBound::Outlives(lifetime) = bound else { + return None; + }; + + let is_inferred = match tcx.named_region(lifetime.hir_id) { + Some(Region::EarlyBound(def_id)) => inferred_outlives + .iter() + .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), + _ => false, + }; + + if !is_inferred { + return None; } + + let span = bound.span().find_ancestor_inside(predicate_span)?; + if in_external_macro(tcx.sess, span) { + return None; + } + + Some((i, span)) }) - .filter(|(_, span)| !in_external_macro(tcx.sess, *span)) .collect() } @@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_lifetime::Region; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, ref hir_generics) - | hir::ItemKind::Enum(_, ref hir_generics) - | hir::ItemKind::Union(_, ref hir_generics) = item.kind + if let hir::ItemKind::Struct(_, hir_generics) + | hir::ItemKind::Enum(_, hir_generics) + | hir::ItemKind::Union(_, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let mut dropped_predicate_count = 0; let num_predicates = hir_generics.predicates.len(); for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { - let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate { - hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(region_def_id)) = - cx.tcx.named_region(predicate.lifetime.hir_id) - { - ( - Self::lifetimes_outliving_lifetime( - inferred_outlives, - region_def_id, - ), - &predicate.bounds, - predicate.span, - predicate.in_where_clause, - ) - } else { - continue; - } - } - hir::WherePredicate::BoundPredicate(predicate) => { - // FIXME we can also infer bounds on associated types, - // and should check for them here. - match predicate.bounded_ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { - let Res::Def(DefKind::TyParam, def_id) = path.res else { - continue - }; - let index = ty_generics.param_def_id_to_index[&def_id]; + let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = + match where_predicate { + hir::WherePredicate::RegionPredicate(predicate) => { + if let Some(Region::EarlyBound(region_def_id)) = + cx.tcx.named_region(predicate.lifetime.hir_id) + { ( - Self::lifetimes_outliving_type(inferred_outlives, index), + Self::lifetimes_outliving_lifetime( + inferred_outlives, + region_def_id, + ), &predicate.bounds, predicate.span, - predicate.origin == PredicateOrigin::WhereClause, + predicate.in_where_clause, ) - } - _ => { + } else { continue; } } - } - _ => continue, - }; + hir::WherePredicate::BoundPredicate(predicate) => { + // FIXME we can also infer bounds on associated types, + // and should check for them here. + match predicate.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue; + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + predicate.origin == PredicateOrigin::WhereClause, + ) + } + _ => { + continue; + } + } + } + _ => continue, + }; if relevant_lifetimes.is_empty() { continue; } - let bound_spans = - self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes); + let bound_spans = self.collect_outlives_bound_spans( + cx.tcx, + bounds, + &relevant_lifetimes, + predicate_span, + ); bound_count += bound_spans.len(); let drop_predicate = bound_spans.len() == bounds.len(); @@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } if drop_predicate && !in_where_clause { - lint_spans.push(span); + lint_spans.push(predicate_span); } else if drop_predicate && i + 1 < num_predicates { // If all the bounds on a predicate were inferable and there are // further predicates, we want to eat the trailing comma. let next_predicate_span = hir_generics.predicates[i + 1].span(); - where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo())); + where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo())); } else { where_lint_spans.extend(self.consolidate_outlives_bound_spans( - span.shrink_to_lo(), + predicate_span.shrink_to_lo(), bounds, bound_spans, )); @@ -2374,12 +2385,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } else { hir_generics.span.shrink_to_hi().to(where_span) }; - lint_spans.push(full_where_span); + + // Due to macro expansions, the `full_where_span` might not actually contain all predicates. + if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) { + lint_spans.push(full_where_span); + } else { + lint_spans.extend(where_lint_spans); + } } else { lint_spans.extend(where_lint_spans); } if !lint_spans.is_empty() { + // Do not automatically delete outlives requirements from macros. + let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions()) + { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + cx.struct_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), @@ -2387,11 +2412,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { |lint| { lint.set_arg("count", bound_count).multipart_suggestion( fluent::suggestion, - lint_spans - .into_iter() - .map(|span| (span, String::new())) - .collect::>(), - Applicability::MachineApplicable, + lint_spans.into_iter().map(|span| (span, String::new())).collect(), + applicability, ) }, ); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 2181c090027..bee4b0a2332 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -796,6 +796,9 @@ impl Span { /// Returns a `Span` that would enclose both `self` and `end`. /// + /// Note that this can also be used to extend the span "backwards": + /// `start.to(end)` and `end.to(start)` return the same `Span`. + /// /// ```text /// ____ ___ /// self lorem ipsum end diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed new file mode 100644 index 00000000000..8cdb08e81b9 --- /dev/null +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed @@ -0,0 +1,137 @@ +// edition:2018 +// aux-build:edition-lint-infer-outlives-macro.rs +// run-rustfix + +#![deny(explicit_outlives_requirements)] +#![allow(dead_code)] + +#[macro_use] +extern crate edition_lint_infer_outlives_macro; + +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. +macro_rules! make_foo { + ($a:tt) => { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { + foo: &$a &'b (), + } + } +} + +gimme_a! {make_foo!} + +struct Bar<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +struct BarWhere<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs index d7a832831c1..647906c2dc2 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs @@ -1,18 +1,22 @@ // edition:2018 // aux-build:edition-lint-infer-outlives-macro.rs - -// Test that the lint does not fire if the where predicate -// is from the local crate, but all the bounds are from an -// external macro. +// run-rustfix #![deny(explicit_outlives_requirements)] +#![allow(dead_code)] #[macro_use] extern crate edition_lint_infer_outlives_macro; +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. macro_rules! make_foo { ($a:tt) => { - struct Foo<$a, 'b> where 'b: $a { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { foo: &$a &'b (), } } @@ -25,4 +29,109 @@ struct Bar<'a, 'b: 'a> { bar: &'a &'b (), } +struct BarWhere<'a, 'b> where 'b: 'a { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b: 'a>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b: 'a>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr index 553b1cd976a..734ae687978 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr @@ -1,14 +1,110 @@ error: outlives requirements can be inferred - --> $DIR/edition-lint-infer-outlives-macro.rs:23:18 + --> $DIR/edition-lint-infer-outlives-macro.rs:27:18 | LL | struct Bar<'a, 'b: 'a> { | ^^^^ help: remove this bound | note: the lint level is defined here - --> $DIR/edition-lint-infer-outlives-macro.rs:8:9 + --> $DIR/edition-lint-infer-outlives-macro.rs:5:9 | LL | #![deny(explicit_outlives_requirements)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:32:24 + | +LL | struct BarWhere<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:41:30 + | +LL | struct Foo<'a, 'b: 'a>(&'a &'b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:43:44 + | +LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:45:61 + | +LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:55:30 + | +LL | struct Foo<'a, $b: 'a>(&'a &$b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:57:44 + | +LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:59:61 + | +LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:114:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:126:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:128:50 + | +LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:130:61 + | +LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: aborting due to 12 previous errors