diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4faefb610562d..8fc6b552e1462 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -215,15 +215,18 @@ 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(); + + 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 +240,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 { @@ -252,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 \ @@ -260,7 +264,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 0000000000000..1daa6a61f777c --- /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!(); +} +