From 7fef1628735622ad005245ea2294449720ba7c5c Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Wed, 18 May 2016 00:02:04 -0500 Subject: [PATCH 1/2] Only print parameters with elided lifetimes in elision error messages. When displaying the function parameters for a lifetime elision error message, this changes it to first filter out the parameters that don't have elided lifetimes. Fixes #30255. --- src/librustc_typeck/astconv.rs | 26 ++++++++++++++------- src/test/compile-fail/issue-30255.rs | 35 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/issue-30255.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4faefb610562..c3633625436a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -215,15 +215,24 @@ fn report_elision_failure( { let mut m = String::new(); let len = params.len(); - let mut any_lifetimes = false; - for (i, info) in params.into_iter().enumerate() { + let elided_params: Vec<_> = params.into_iter() + .filter(|info| info.lifetime_count > 0) + .collect(); + + let elided_len = elided_params.len(); + + let any_lifetimes = if elided_len > 0 { + true + } else { + false + }; + + for (i, info) in elided_params.into_iter().enumerate() { let ElisionFailureInfo { name, lifetime_count: n, have_bound_regions } = info; - any_lifetimes = any_lifetimes || (n > 0); - let help_name = if name.is_empty() { format!("argument {}", i + 1) } else { @@ -237,13 +246,14 @@ fn report_elision_failure( if have_bound_regions { "free " } else { "" } ) })[..]); - if len == 2 && i == 0 { + if elided_len == 2 && i == 0 { m.push_str(" or "); - } else if i + 2 == len { + } else if i + 2 == elided_len { m.push_str(", or "); - } else if i + 1 != len { + } else if i != elided_len - 1 { m.push_str(", "); } + } if len == 0 { @@ -260,7 +270,7 @@ fn report_elision_failure( help!(db, "consider giving it an explicit bounded or 'static \ lifetime"); - } else if len == 1 { + } else if elided_len == 1 { help!(db, "this function's return type contains a borrowed value, but \ the signature does not say which {} it is borrowed from", diff --git a/src/test/compile-fail/issue-30255.rs b/src/test/compile-fail/issue-30255.rs new file mode 100644 index 000000000000..1daa6a61f777 --- /dev/null +++ b/src/test/compile-fail/issue-30255.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Test that lifetime elision error messages correctly omit parameters +// with no elided lifetimes + +struct S<'a> { + field: &'a i32, +} + +fn f(a: &S, b: i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] +//~^^ HELP does not say which one of `a`'s 2 elided lifetimes it is borrowed from + panic!(); +} + +fn g(a: &S, b: bool, c: &i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] +//~^^ HELP does not say whether it is borrowed from one of `a`'s 2 elided lifetimes or `c` + panic!(); +} + +fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] +//~^^ HELP does not say whether it is borrowed from `a`, one of `c`'s 2 elided lifetimes, or `d` + panic!(); +} + From a50c82bc3bde5988a8f32ef2b593f0b051545e8a Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Wed, 18 May 2016 13:09:25 -0500 Subject: [PATCH 2/2] Simplify report_elision_failure a little bit. --- src/librustc_typeck/astconv.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c3633625436a..8fc6b552e146 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -222,12 +222,6 @@ fn report_elision_failure( let elided_len = elided_params.len(); - let any_lifetimes = if elided_len > 0 { - true - } else { - false - }; - for (i, info) in elided_params.into_iter().enumerate() { let ElisionFailureInfo { name, lifetime_count: n, have_bound_regions @@ -262,7 +256,7 @@ fn report_elision_failure( there is no value for it to be borrowed from"); help!(db, "consider giving it a 'static lifetime"); - } else if !any_lifetimes { + } else if elided_len == 0 { help!(db, "this function's return type contains a borrowed value with \ an elided lifetime, but the lifetime cannot be derived from \