| //@ 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) => { |
| // FIXME: replacement span is corrupted due to a collision in metavar span table. |
| // struct Foo<$a, $b $colon $a>(&$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 everything_outside_with_tt_both { |
| macro_rules! m { |
| ($b:tt $colon:tt $a:tt) => { |
| // FIXME: replacement span is corrupted due to a collision in metavar span table. |
| // struct Foo<$a, $b $colon $a>(&$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); |
| } |
| |
| fn main() {} |