From e792ee00c264d9b25dcf2e84f42498b5161b0978 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 22 Oct 2021 23:05:15 +0200 Subject: [PATCH 1/5] Add beginner friendly lifetime elision hint to E0623 Suggest adding a new lifetime parameter when two elided lifetimes should match up but don't Issue #90170 --- .../nice_region_error/different_lifetimes.rs | 58 ++++++++++++++++- .../lifetimes/issue-90170-elision-mismatch.rs | 19 ++++++ .../issue-90170-elision-mismatch.stderr | 63 +++++++++++++++++++ .../ex3-both-anon-regions-2.stderr | 6 ++ .../ex3-both-anon-regions-3.stderr | 12 ++++ ...x3-both-anon-regions-using-fn-items.stderr | 6 ++ ...th-anon-regions-using-trait-objects.stderr | 6 ++ .../ex3-both-anon-regions.stderr | 6 ++ ...underscore-lifetime-elison-mismatch.stderr | 6 ++ 9 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.rs create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1b35c4032f44c..5833ee4b4aa04 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -7,7 +7,10 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::SubregionOrigin; -use rustc_errors::{struct_span_err, ErrorReported}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; +use rustc_hir as hir; +use rustc_hir::Ty; +use rustc_middle::ty::Region; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when both the concerned regions are anonymous. @@ -166,6 +169,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { e.span_label(span_2, String::new()); e.span_label(span, span_label); + self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut e); + if let Some(t) = future_return_type { let snip = self .tcx() @@ -178,7 +183,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { (_, "") => None, _ => Some(s), }) - .unwrap_or("{unnamed_type}".to_string()); + .unwrap_or_else(|| "{unnamed_type}".to_string()); e.span_label( t.span, @@ -188,4 +193,53 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { e.emit(); Some(ErrorReported) } + + fn suggest_adding_lifetime_params( + &self, + sub: Region<'tcx>, + ty_sup: &Ty<'_>, + ty_sub: &Ty<'_>, + e: &mut DiagnosticBuilder<'_>, + ) { + if let ( + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, + ) = (ty_sub, ty_sup) + { + if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() { + if let Some(anon_reg) = self.tcx().is_suitable_region(sub) { + let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id); + if let hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Fn(_, ref generics, ..), + .. + }) = self.tcx().hir().get(hir_id) + { + let add_lifetime_param = match &generics.params { + [] => (generics.span, "<'a>".to_string()), + [first, ..] => (first.span.shrink_to_lo(), "'a, ".to_string()), + }; + + e.multipart_suggestion( + "Explicitly declare a lifetime and assign it to both", + vec![ + add_lifetime_param, + if let hir::LifetimeName::Underscore = lifetime_sub.name { + (lifetime_sub.span, "'a".to_string()) + } else { + (lifetime_sub.span.shrink_to_hi(), "'a ".to_string()) + }, + if let hir::LifetimeName::Underscore = lifetime_sup.name { + (lifetime_sup.span, "'a".to_string()) + } else { + (lifetime_sup.span.shrink_to_hi(), "'a ".to_string()) + }, + ], + Applicability::MaybeIncorrect, + ); + e.note("Each elided lifetime in input position becomes a distinct lifetime."); + } + } + } + } + } } diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs new file mode 100644 index 0000000000000..44ec0928c4cc8 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs @@ -0,0 +1,19 @@ +fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { + core::mem::swap(&mut slice_a, &mut slice_b); //~ ERROR lifetime mismatch + //~^ ERROR lifetime mismatch +} + +fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { + core::mem::swap(&mut slice_a, &mut slice_b); //~ ERROR lifetime mismatch + //~^ ERROR lifetime mismatch +} + +fn ok<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { + core::mem::swap(&mut slice_a, &mut slice_b); +} + +fn main() { + let a = [1u8, 2, 3]; + let b = [4u8, 5, 6]; + foo(&mut a, &mut b); +} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr new file mode 100644 index 0000000000000..4fa58f6226871 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -0,0 +1,63 @@ +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:2:35 + | +LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { + | --------- --------- these two types are declared with different lifetimes... +LL | core::mem::swap(&mut slice_a, &mut slice_b); + | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { + | ++++ ++ ++ + +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:2:35 + | +LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { + | --------- --------- + | | + | these two types are declared with different lifetimes... +LL | core::mem::swap(&mut slice_a, &mut slice_b); + | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { + | ++++ ++ ++ + +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:7:35 + | +LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { + | --------- --------- these two types are declared with different lifetimes... +LL | core::mem::swap(&mut slice_a, &mut slice_b); + | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { + | +++ ++ ++ + +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:7:35 + | +LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { + | --------- --------- + | | + | these two types are declared with different lifetimes... +LL | core::mem::swap(&mut slice_a, &mut slice_b); + | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { + | +++ ++ ++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 0aff80c6fbdd3..89832568b61e8 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -5,6 +5,12 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { | --- --- these two types are declared with different lifetimes... LL | *v = x; | ^ ...but data from `x` flows here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr index 2e5ff6782d3b6..df4fcfe4c1d9d 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -5,6 +5,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { | --- --- these two types are declared with different lifetimes... LL | z.push((x,y)); | ^ ...but data flows into `z` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { + | ++++ ++ ++ error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions-3.rs:2:15 @@ -13,6 +19,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { | --- --- these two types are declared with different lifetimes... LL | z.push((x,y)); | ^ ...but data flows into `z` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { + | ++++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index d2cc3dba6a433..942f495bdef33 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -5,6 +5,12 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { | --- --- these two types are declared with different lifetimes... LL | y.push(z); | ^ ...but data from `z` flows into `y` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index 2acc4eaf60f55..b52b249398635 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -5,6 +5,12 @@ LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { | --- --- these two types are declared with different lifetimes... LL | y.push(z); | ^ ...but data from `z` flows into `y` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(x:Box , y: Vec<&u8>, z: &u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index b2784827672b8..843f79cb5cbfd 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) { | --- --- these two types are declared with different lifetimes... LL | x.push(y); | ^ ...but data from `y` flows into `x` here + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index 76c14ccc14b45..30a17e98dfcce 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | ------ ------ ^ ...but data from `y` flows into `x` here | | | these two types are declared with different lifetimes... + | + = note: Each elided lifetime in input position becomes a distinct lifetime. +help: Explicitly declare a lifetime and assign it to both + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ~~ error: aborting due to previous error From a8ebdbedc5d69ab43f9ba962f26da35a2521e56b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 22 Oct 2021 23:33:32 +0200 Subject: [PATCH 2/5] Fix formatting for lifetime elision mismatch hint --- .../error_reporting/nice_region_error/different_lifetimes.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 5833ee4b4aa04..06ddcd812a308 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -236,7 +236,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ], Applicability::MaybeIncorrect, ); - e.note("Each elided lifetime in input position becomes a distinct lifetime."); + e.note( + "Each elided lifetime in input position becomes a distinct lifetime.", + ); } } } From e7b8e73684998201485295f5a3fd4f1ccab01266 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 23 Oct 2021 11:19:57 +0200 Subject: [PATCH 3/5] Use lowercase letters for the lifetime elision mismatch suggestion --- .../nice_region_error/different_lifetimes.rs | 4 ++-- .../issue-90170-elision-mismatch.stderr | 16 ++++++++-------- .../ex3-both-anon-regions-2.stderr | 4 ++-- .../ex3-both-anon-regions-3.stderr | 8 ++++---- .../ex3-both-anon-regions-using-fn-items.stderr | 4 ++-- ...-both-anon-regions-using-trait-objects.stderr | 4 ++-- .../lifetime-errors/ex3-both-anon-regions.stderr | 4 ++-- .../underscore-lifetime-elison-mismatch.stderr | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 06ddcd812a308..0e9f62e5f6179 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; e.multipart_suggestion( - "Explicitly declare a lifetime and assign it to both", + "explicitly declare a lifetime and assign it to both", vec![ add_lifetime_param, if let hir::LifetimeName::Underscore = lifetime_sub.name { @@ -237,7 +237,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Applicability::MaybeIncorrect, ); e.note( - "Each elided lifetime in input position becomes a distinct lifetime.", + "each elided lifetime in input position becomes a distinct lifetime", ); } } diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr index 4fa58f6226871..881e74d2b5f7c 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -6,8 +6,8 @@ LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { LL | core::mem::swap(&mut slice_a, &mut slice_b); | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { | ++++ ++ ++ @@ -22,8 +22,8 @@ LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { LL | core::mem::swap(&mut slice_a, &mut slice_b); | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { | ++++ ++ ++ @@ -36,8 +36,8 @@ LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) LL | core::mem::swap(&mut slice_a, &mut slice_b); | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { | +++ ++ ++ @@ -52,8 +52,8 @@ LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) LL | core::mem::swap(&mut slice_a, &mut slice_b); | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { | +++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 89832568b61e8..020f72f8d7d1a 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -6,8 +6,8 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { LL | *v = x; | ^ ...but data from `x` flows here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr index df4fcfe4c1d9d..36dd15900db81 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -6,8 +6,8 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { LL | z.push((x,y)); | ^ ...but data flows into `z` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { | ++++ ++ ++ @@ -20,8 +20,8 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { LL | z.push((x,y)); | ^ ...but data flows into `z` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index 942f495bdef33..50091b4868eea 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -6,8 +6,8 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^ ...but data from `z` flows into `y` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index b52b249398635..870830fb277f9 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -6,8 +6,8 @@ LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^ ...but data from `z` flows into `y` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(x:Box , y: Vec<&u8>, z: &u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index 843f79cb5cbfd..961d6a502ec58 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -6,8 +6,8 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) { LL | x.push(y); | ^ ...but data from `y` flows into `x` here | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index 30a17e98dfcce..bf3ecc32703a4 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -6,8 +6,8 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | | | these two types are declared with different lifetimes... | - = note: Each elided lifetime in input position becomes a distinct lifetime. -help: Explicitly declare a lifetime and assign it to both + = note: each elided lifetime in input position becomes a distinct lifetime +help: explicitly declare a lifetime and assign it to both | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } | ++++ ~~ ~~ From 2f4d780d726927bfe8c4c0da69baac25f2e1a83e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 25 Oct 2021 21:21:18 +0200 Subject: [PATCH 4/5] Improve lifetime elision hint error This also changes the tests introduced by the previous commits because of another rustc issue (#90258) --- .../nice_region_error/different_lifetimes.rs | 82 ++++++++++++------- .../issue-90170-elision-mismatch.fixed | 17 ++++ .../lifetimes/issue-90170-elision-mismatch.rs | 14 ++-- .../issue-90170-elision-mismatch.stderr | 81 +++++++++--------- .../ex3-both-anon-regions-2.stderr | 2 +- .../ex3-both-anon-regions-3.stderr | 4 +- ...x3-both-anon-regions-using-fn-items.stderr | 2 +- ...th-anon-regions-using-trait-objects.stderr | 2 +- .../ex3-both-anon-regions.stderr | 2 +- ...underscore-lifetime-elison-mismatch.stderr | 2 +- 10 files changed, 123 insertions(+), 85 deletions(-) create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 0e9f62e5f6179..ac57796763fb3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -9,7 +9,7 @@ use crate::infer::SubregionOrigin; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; -use rustc_hir::Ty; +use rustc_hir::{GenericParamKind, Ty}; use rustc_middle::ty::Region; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -163,13 +163,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } }; - let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); + let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - e.span_label(span_1, main_label); - e.span_label(span_2, String::new()); - e.span_label(span, span_label); + err.span_label(span_1, main_label); + err.span_label(span_2, String::new()); + err.span_label(span, span_label); - self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut e); + self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err); if let Some(t) = future_return_type { let snip = self @@ -185,12 +185,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) .unwrap_or_else(|| "{unnamed_type}".to_string()); - e.span_label( + err.span_label( t.span, &format!("this `async fn` implicitly returns an `impl Future`", snip), ); } - e.emit(); + err.emit(); Some(ErrorReported) } @@ -199,7 +199,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sub: Region<'tcx>, ty_sup: &Ty<'_>, ty_sub: &Ty<'_>, - e: &mut DiagnosticBuilder<'_>, + err: &mut DiagnosticBuilder<'_>, ) { if let ( hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, @@ -214,29 +214,51 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .. }) = self.tcx().hir().get(hir_id) { - let add_lifetime_param = match &generics.params { - [] => (generics.span, "<'a>".to_string()), - [first, ..] => (first.span.shrink_to_lo(), "'a, ".to_string()), - }; - - e.multipart_suggestion( - "explicitly declare a lifetime and assign it to both", - vec![ - add_lifetime_param, - if let hir::LifetimeName::Underscore = lifetime_sub.name { - (lifetime_sub.span, "'a".to_string()) - } else { - (lifetime_sub.span.shrink_to_hi(), "'a ".to_string()) - }, - if let hir::LifetimeName::Underscore = lifetime_sup.name { - (lifetime_sup.span, "'a".to_string()) - } else { - (lifetime_sup.span.shrink_to_hi(), "'a ".to_string()) - }, - ], + let (suggestion_param_name, introduce_new) = generics + .params + .iter() + .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) + .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok()) + .map(|name| (name, false)) + .unwrap_or_else(|| ("'a".to_string(), true)); + + let mut suggestions = vec![ + if let hir::LifetimeName::Underscore = lifetime_sub.name { + (lifetime_sub.span, suggestion_param_name.clone()) + } else { + ( + lifetime_sub.span.shrink_to_hi(), + suggestion_param_name.clone() + " ", + ) + }, + if let hir::LifetimeName::Underscore = lifetime_sup.name { + (lifetime_sup.span, suggestion_param_name.clone()) + } else { + ( + lifetime_sup.span.shrink_to_hi(), + suggestion_param_name.clone() + " ", + ) + }, + ]; + + if introduce_new { + let new_param_suggestion = match &generics.params { + [] => (generics.span, format!("<{}>", suggestion_param_name)), + [first, ..] => ( + first.span.shrink_to_lo(), + format!("{}, ", suggestion_param_name), + ), + }; + + suggestions.push(new_param_suggestion); + } + + err.multipart_suggestion( + "consider introducing a named lifetime parameter", + suggestions, Applicability::MaybeIncorrect, ); - e.note( + err.note( "each elided lifetime in input position becomes a distinct lifetime", ); } diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed new file mode 100644 index 0000000000000..5e302068a78f2 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn ok<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { + core::mem::swap(&mut slice_a, &mut slice_b); +} + +fn main() { + let a = [1u8, 2, 3]; + let b = [4u8, 5, 6]; + foo(&mut a, &mut b); +} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs index 44ec0928c4cc8..16ed79894d0e0 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs @@ -1,12 +1,10 @@ -fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { - core::mem::swap(&mut slice_a, &mut slice_b); //~ ERROR lifetime mismatch - //~^ ERROR lifetime mismatch -} +// run-rustfix -fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { - core::mem::swap(&mut slice_a, &mut slice_b); //~ ERROR lifetime mismatch - //~^ ERROR lifetime mismatch -} +fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch fn ok<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { core::mem::swap(&mut slice_a, &mut slice_b); diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr index 881e74d2b5f7c..fe34969bf0587 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -1,63 +1,64 @@ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:2:35 + --> $DIR/issue-90170-elision-mismatch.rs:3:43 | -LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { - | --------- --------- these two types are declared with different lifetimes... -LL | core::mem::swap(&mut slice_a, &mut slice_b); - | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here +LL | fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | -LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { - | ++++ ++ ++ +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ++ ++ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:2:35 + --> $DIR/issue-90170-elision-mismatch.rs:5:47 | -LL | fn foo(slice_a: &mut [u8], slice_b: &mut [u8]) { - | --------- --------- - | | - | these two types are declared with different lifetimes... -LL | core::mem::swap(&mut slice_a, &mut slice_b); - | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here +LL | fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } + | ------ --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | -LL | fn foo<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { - | ++++ ++ ++ +LL | fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ++ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:7:35 + --> $DIR/issue-90170-elision-mismatch.rs:7:66 | -LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { - | --------- --------- these two types are declared with different lifetimes... -LL | core::mem::swap(&mut slice_a, &mut slice_b); - | ^^^^^^^^^^^^ ...but data from `slice_b` flows into `slice_a` here +LL | fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | -LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { - | +++ ++ ++ +LL | fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++ ++ -error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:7:35 +error[E0308]: mismatched types + --> $DIR/issue-90170-elision-mismatch.rs:16:9 | -LL | fn foo2(slice_a: &mut [u8], slice_b: &mut [u8], _: U, _: W, _: O) { - | --------- --------- - | | - | these two types are declared with different lifetimes... -LL | core::mem::swap(&mut slice_a, &mut slice_b); - | ^^^^^^^^^^^^ ...but data from `slice_a` flows into `slice_b` here +LL | foo(&mut a, &mut b); + | ^^^^^^ expected struct `Vec`, found array `[u8; 3]` | - = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both + = note: expected mutable reference `&mut Vec<&u8>` + found mutable reference `&mut [u8; 3]` + +error[E0308]: mismatched types + --> $DIR/issue-90170-elision-mismatch.rs:16:17 + | +LL | foo(&mut a, &mut b); + | ^^^^^^ expected `u8`, found array `[u8; 3]` | -LL | fn foo2<'a, U, W, O>(slice_a: &'a mut [u8], slice_b: &'a mut [u8], _: U, _: W, _: O) { - | +++ ++ ++ + = note: expected reference `&u8` + found mutable reference `&mut [u8; 3]` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0623`. +Some errors have detailed explanations: E0308, E0623. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 020f72f8d7d1a..5c793636778ea 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -7,7 +7,7 @@ LL | *v = x; | ^ ...but data from `x` flows here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr index 36dd15900db81..1a7b4fca1ba78 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -7,7 +7,7 @@ LL | z.push((x,y)); | ^ ...but data flows into `z` here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { | ++++ ++ ++ @@ -21,7 +21,7 @@ LL | z.push((x,y)); | ^ ...but data flows into `z` here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index 50091b4868eea..6ed3528bb9faa 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -7,7 +7,7 @@ LL | y.push(z); | ^ ...but data from `z` flows into `y` here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index 870830fb277f9..ede1631db271c 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -7,7 +7,7 @@ LL | y.push(z); | ^ ...but data from `z` flows into `y` here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x:Box , y: Vec<&u8>, z: &u8) { | ++++ ++ ++ diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index 961d6a502ec58..cf405c0de3f0b 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -7,7 +7,7 @@ LL | x.push(y); | ^ ...but data from `y` flows into `x` here | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { | ++++ ++ ++ diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index bf3ecc32703a4..8976da01e739b 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -7,7 +7,7 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime -help: explicitly declare a lifetime and assign it to both +help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } | ++++ ~~ ~~ From 76ec1aa50e9ccf868fc12c0283c3fc6048993ef2 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:26:17 +0200 Subject: [PATCH 5/5] Fix test for lifetime elision hint --- .../issue-90170-elision-mismatch.fixed | 16 ++--- .../lifetimes/issue-90170-elision-mismatch.rs | 16 ++--- .../issue-90170-elision-mismatch.stderr | 65 +++++++------------ 3 files changed, 31 insertions(+), 66 deletions(-) diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed index 5e302068a78f2..0bc889ee721dc 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed @@ -1,17 +1,9 @@ // run-rustfix -fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch -fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch -fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch -fn ok<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { - core::mem::swap(&mut slice_a, &mut slice_b); -} - -fn main() { - let a = [1u8, 2, 3]; - let b = [4u8, 5, 6]; - foo(&mut a, &mut b); -} +fn main() {} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs index 16ed79894d0e0..1d6573c00ad4f 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs @@ -1,17 +1,9 @@ // run-rustfix -fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch -fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch -fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch -fn ok<'a>(slice_a: &'a mut [u8], slice_b: &'a mut [u8]) { - core::mem::swap(&mut slice_a, &mut slice_b); -} - -fn main() { - let a = [1u8, 2, 3]; - let b = [4u8, 5, 6]; - foo(&mut a, &mut b); -} +fn main() {} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr index fe34969bf0587..7fa092ca220c2 100644 --- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -1,64 +1,45 @@ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:3:43 + --> $DIR/issue-90170-elision-mismatch.rs:3:47 | -LL | fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } - | --- --- ^ ...but data from `y` flows into `x` here - | | - | these two types are declared with different lifetimes... +LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime help: consider introducing a named lifetime parameter | -LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } - | ++++ ++ ++ +LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ++ ++ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:5:47 + --> $DIR/issue-90170-elision-mismatch.rs:5:51 | -LL | fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } - | ------ --- ^ ...but data from `y` flows into `x` here - | | - | these two types are declared with different lifetimes... +LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } + | ------ --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime help: consider introducing a named lifetime parameter | -LL | fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } - | ++++ ~~ ++ +LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ++ error[E0623]: lifetime mismatch - --> $DIR/issue-90170-elision-mismatch.rs:7:66 + --> $DIR/issue-90170-elision-mismatch.rs:7:70 | -LL | fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } - | --- --- ^ ...but data from `y` flows into `x` here - | | - | these two types are declared with different lifetimes... +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... | = note: each elided lifetime in input position becomes a distinct lifetime help: consider introducing a named lifetime parameter | -LL | fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } - | ++ ++ - -error[E0308]: mismatched types - --> $DIR/issue-90170-elision-mismatch.rs:16:9 - | -LL | foo(&mut a, &mut b); - | ^^^^^^ expected struct `Vec`, found array `[u8; 3]` - | - = note: expected mutable reference `&mut Vec<&u8>` - found mutable reference `&mut [u8; 3]` - -error[E0308]: mismatched types - --> $DIR/issue-90170-elision-mismatch.rs:16:17 - | -LL | foo(&mut a, &mut b); - | ^^^^^^ expected `u8`, found array `[u8; 3]` - | - = note: expected reference `&u8` - found mutable reference `&mut [u8; 3]` +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++ ++ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0623. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0623`.