Auto merge of #68583 - estebank:hrlt, r=oli-obk
Account for HR lifetimes when suggesting introduction of named lifetime ``` error[E0106]: missing lifetime specifier --> src/test/ui/suggestions/fn-missing-lifetime-in-item.rs:2:32 | 2 | struct S2<F: Fn(&i32, &i32) -> &i32>(F); | ---- ---- ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the bound lifetime-generic with a new `'a` lifetime | 2 | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F); | ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^ help: consider introducing a named lifetime parameter | 2 | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F);= | ^^^ ^^^^^^^ ^^^^^^^ ^^^ ``` Follow up to #68267. Addresses the diagnostics part of #49287.
This commit is contained in:
commit
333c32a5a4
@ -2260,10 +2260,10 @@ impl TraitRef<'_> {
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
|
||||
pub struct PolyTraitRef<'hir> {
|
||||
/// The `'a` in `<'a> Foo<&'a T>`.
|
||||
/// The `'a` in `for<'a> Foo<&'a T>`.
|
||||
pub bound_generic_params: &'hir [GenericParam<'hir>],
|
||||
|
||||
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
|
||||
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
|
||||
pub trait_ref: TraitRef<'hir>,
|
||||
|
||||
pub span: Span,
|
||||
|
@ -20,6 +20,7 @@ use syntax::ast::{self, Ident, Path};
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
|
||||
use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
||||
use crate::lifetimes::{ElisionFailureInfo, LifetimeContext};
|
||||
use crate::path_names_to_string;
|
||||
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
|
||||
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
|
||||
@ -48,6 +49,40 @@ crate struct ImportSuggestion {
|
||||
pub path: Path,
|
||||
}
|
||||
|
||||
crate enum MissingLifetimeSpot<'tcx> {
|
||||
Generics(&'tcx hir::Generics<'tcx>),
|
||||
HigherRanked { span: Span, span_type: ForLifetimeSpanType },
|
||||
}
|
||||
|
||||
crate enum ForLifetimeSpanType {
|
||||
BoundEmpty,
|
||||
BoundTail,
|
||||
TypeEmpty,
|
||||
TypeTail,
|
||||
}
|
||||
|
||||
impl ForLifetimeSpanType {
|
||||
crate fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
Self::BoundEmpty | Self::BoundTail => "bound",
|
||||
Self::TypeEmpty | Self::TypeTail => "type",
|
||||
}
|
||||
}
|
||||
|
||||
crate fn suggestion(&self, sugg: &str) -> String {
|
||||
match self {
|
||||
Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
|
||||
Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
|
||||
fn into(self) -> MissingLifetimeSpot<'tcx> {
|
||||
MissingLifetimeSpot::Generics(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
||||
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
|
||||
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
|
||||
@ -1457,72 +1492,206 @@ crate fn show_candidates(
|
||||
}
|
||||
}
|
||||
|
||||
crate fn report_missing_lifetime_specifiers(
|
||||
sess: &Session,
|
||||
span: Span,
|
||||
count: usize,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
|
||||
}
|
||||
impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||
crate fn report_missing_lifetime_specifiers(
|
||||
&self,
|
||||
span: Span,
|
||||
count: usize,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0106,
|
||||
"missing lifetime specifier{}",
|
||||
pluralize!(count)
|
||||
)
|
||||
}
|
||||
|
||||
crate fn add_missing_lifetime_specifiers_label(
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
count: usize,
|
||||
lifetime_names: &FxHashSet<ast::Ident>,
|
||||
snippet: Option<&str>,
|
||||
missing_named_lifetime_spots: &[&hir::Generics<'_>],
|
||||
) {
|
||||
if count > 1 {
|
||||
err.span_label(span, format!("expected {} lifetime parameters", count));
|
||||
} else {
|
||||
let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider using the named lifetime",
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
lifetime_ref.span,
|
||||
E0261,
|
||||
"use of undeclared lifetime name `{}`",
|
||||
lifetime_ref
|
||||
);
|
||||
err.span_label(lifetime_ref.span, "undeclared lifetime");
|
||||
for missing in &self.missing_named_lifetime_spots {
|
||||
match missing {
|
||||
MissingLifetimeSpot::Generics(generics) => {
|
||||
let (span, sugg) = if let Some(param) = generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|p| match p.kind {
|
||||
hir::GenericParamKind::Type {
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
..
|
||||
} => false,
|
||||
_ => true,
|
||||
})
|
||||
.next()
|
||||
{
|
||||
(param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
|
||||
} else {
|
||||
(generics.span, format!("<{}>", lifetime_ref))
|
||||
};
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("consider introducing lifetime `{}` here", lifetime_ref),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
MissingLifetimeSpot::HigherRanked { span, span_type } => {
|
||||
err.span_suggestion(
|
||||
*span,
|
||||
&format!(
|
||||
"consider making the {} lifetime-generic with a new `{}` lifetime",
|
||||
span_type.descr(),
|
||||
lifetime_ref
|
||||
),
|
||||
span_type.suggestion(&lifetime_ref.to_string()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.note(
|
||||
"for more information on higher-ranked polymorphism, visit \
|
||||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
|
||||
if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res {
|
||||
if [
|
||||
self.tcx.lang_items().fn_once_trait(),
|
||||
self.tcx.lang_items().fn_trait(),
|
||||
self.tcx.lang_items().fn_mut_trait(),
|
||||
]
|
||||
.contains(&Some(did))
|
||||
{
|
||||
let (span, span_type) = match &trait_ref.bound_generic_params {
|
||||
[] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
|
||||
[.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
|
||||
};
|
||||
self.missing_named_lifetime_spots
|
||||
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
||||
return true;
|
||||
}
|
||||
};
|
||||
let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg| {
|
||||
err.span_label(span, "expected named lifetime parameter");
|
||||
false
|
||||
}
|
||||
|
||||
if let Some(generics) = missing_named_lifetime_spots.iter().last() {
|
||||
let mut introduce_suggestion = vec![];
|
||||
introduce_suggestion.push(match &generics.params {
|
||||
[] => (generics.span, "<'lifetime>".to_string()),
|
||||
[param, ..] => (param.span.shrink_to_lo(), "'lifetime, ".to_string()),
|
||||
});
|
||||
introduce_suggestion.push((span, sugg));
|
||||
err.multipart_suggestion(
|
||||
"consider introducing a named lifetime parameter",
|
||||
introduce_suggestion,
|
||||
crate fn add_missing_lifetime_specifiers_label(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
count: usize,
|
||||
lifetime_names: &FxHashSet<ast::Ident>,
|
||||
params: &[ElisionFailureInfo],
|
||||
) {
|
||||
if count > 1 {
|
||||
err.span_label(span, format!("expected {} lifetime parameters", count));
|
||||
} else {
|
||||
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
|
||||
let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider using the named lifetime",
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
let suggest_new =
|
||||
|err: &mut DiagnosticBuilder<'_>, sugg: &str| {
|
||||
err.span_label(span, "expected named lifetime parameter");
|
||||
|
||||
match (lifetime_names.len(), lifetime_names.iter().next(), snippet) {
|
||||
(1, Some(name), Some("&")) => {
|
||||
suggest_existing(err, format!("&{} ", name));
|
||||
}
|
||||
(1, Some(name), Some("'_")) => {
|
||||
suggest_existing(err, name.to_string());
|
||||
}
|
||||
(1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
|
||||
suggest_existing(err, format!("{}<{}>", snippet, name));
|
||||
}
|
||||
(0, _, Some("&")) => {
|
||||
suggest_new(err, "&'lifetime ".to_string());
|
||||
}
|
||||
(0, _, Some("'_")) => {
|
||||
suggest_new(err, "'lifetime".to_string());
|
||||
}
|
||||
(0, _, Some(snippet)) if !snippet.ends_with(">") => {
|
||||
suggest_new(err, format!("{}<'lifetime>", snippet));
|
||||
}
|
||||
_ => {
|
||||
err.span_label(span, "expected lifetime parameter");
|
||||
for missing in self.missing_named_lifetime_spots.iter().rev() {
|
||||
let mut introduce_suggestion = vec![];
|
||||
let msg;
|
||||
let should_break;
|
||||
introduce_suggestion.push(match missing {
|
||||
MissingLifetimeSpot::Generics(generics) => {
|
||||
msg = "consider introducing a named lifetime parameter".to_string();
|
||||
should_break = true;
|
||||
if let Some(param) = generics.params.iter().filter(|p| match p.kind {
|
||||
hir::GenericParamKind::Type {
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
..
|
||||
} => false,
|
||||
_ => true,
|
||||
}).next() {
|
||||
(param.span.shrink_to_lo(), "'a, ".to_string())
|
||||
} else {
|
||||
(generics.span, "<'a>".to_string())
|
||||
}
|
||||
}
|
||||
MissingLifetimeSpot::HigherRanked { span, span_type } => {
|
||||
msg = format!(
|
||||
"consider making the {} lifetime-generic with a new `'a` lifetime",
|
||||
span_type.descr(),
|
||||
);
|
||||
should_break = false;
|
||||
err.note(
|
||||
"for more information on higher-ranked polymorphism, visit \
|
||||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||
);
|
||||
(*span, span_type.suggestion("'a"))
|
||||
}
|
||||
});
|
||||
for param in params {
|
||||
if let Ok(snippet) =
|
||||
self.tcx.sess.source_map().span_to_snippet(param.span)
|
||||
{
|
||||
if snippet.starts_with("&") && !snippet.starts_with("&'") {
|
||||
introduce_suggestion
|
||||
.push((param.span, format!("&'a {}", &snippet[1..])));
|
||||
} else if snippet.starts_with("&'_ ") {
|
||||
introduce_suggestion
|
||||
.push((param.span, format!("&'a {}", &snippet[4..])));
|
||||
}
|
||||
}
|
||||
}
|
||||
introduce_suggestion.push((span, sugg.to_string()));
|
||||
err.multipart_suggestion(
|
||||
&msg,
|
||||
introduce_suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if should_break {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match (
|
||||
lifetime_names.len(),
|
||||
lifetime_names.iter().next(),
|
||||
snippet.as_ref().map(|s| s.as_str()),
|
||||
) {
|
||||
(1, Some(name), Some("&")) => {
|
||||
suggest_existing(err, format!("&{} ", name));
|
||||
}
|
||||
(1, Some(name), Some("'_")) => {
|
||||
suggest_existing(err, name.to_string());
|
||||
}
|
||||
(1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
|
||||
suggest_existing(err, format!("{}<{}>", snippet, name));
|
||||
}
|
||||
(0, _, Some("&")) => {
|
||||
suggest_new(err, "&'a ");
|
||||
}
|
||||
(0, _, Some("'_")) => {
|
||||
suggest_new(err, "'a");
|
||||
}
|
||||
(0, _, Some(snippet)) if !snippet.ends_with(">") => {
|
||||
suggest_new(err, &format!("{}<'a>", snippet));
|
||||
}
|
||||
_ => {
|
||||
err.span_label(span, "expected lifetime parameter");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,7 @@
|
||||
//! used between functions, and they operate in a purely top-down
|
||||
//! way. Therefore, we break lifetime name resolution into a separate pass.
|
||||
|
||||
use crate::diagnostics::{
|
||||
add_missing_lifetime_specifiers_label, report_missing_lifetime_specifiers,
|
||||
};
|
||||
use crate::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint;
|
||||
use rustc::middle::resolve_lifetime::*;
|
||||
@ -153,8 +151,8 @@ struct NamedRegionMap {
|
||||
object_lifetime_defaults: HirIdMap<Vec<ObjectLifetimeDefault>>,
|
||||
}
|
||||
|
||||
struct LifetimeContext<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
crate struct LifetimeContext<'a, 'tcx> {
|
||||
crate tcx: TyCtxt<'tcx>,
|
||||
map: &'a mut NamedRegionMap,
|
||||
scope: ScopeRef<'a>,
|
||||
|
||||
@ -186,7 +184,7 @@ struct LifetimeContext<'a, 'tcx> {
|
||||
|
||||
/// When encountering an undefined named lifetime, we will suggest introducing it in these
|
||||
/// places.
|
||||
missing_named_lifetime_spots: Vec<&'tcx hir::Generics<'tcx>>,
|
||||
crate missing_named_lifetime_spots: Vec<MissingLifetimeSpot<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -264,13 +262,14 @@ enum Elide {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ElisionFailureInfo {
|
||||
crate struct ElisionFailureInfo {
|
||||
/// Where we can find the argument pattern.
|
||||
parent: Option<hir::BodyId>,
|
||||
/// The index of the argument in the original definition.
|
||||
index: usize,
|
||||
lifetime_count: usize,
|
||||
have_bound_regions: bool,
|
||||
crate span: Span,
|
||||
}
|
||||
|
||||
type ScopeRef<'a> = &'a Scope<'a>;
|
||||
@ -389,7 +388,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn(ref sig, ref generics, _) => {
|
||||
self.missing_named_lifetime_spots.push(generics);
|
||||
self.missing_named_lifetime_spots.push(generics.into());
|
||||
self.visit_early_late(None, &sig.decl, generics, |this| {
|
||||
intravisit::walk_item(this, item);
|
||||
});
|
||||
@ -424,7 +423,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
| hir::ItemKind::Trait(_, _, ref generics, ..)
|
||||
| hir::ItemKind::TraitAlias(ref generics, ..)
|
||||
| hir::ItemKind::Impl { ref generics, .. } => {
|
||||
self.missing_named_lifetime_spots.push(generics);
|
||||
self.missing_named_lifetime_spots.push(generics.into());
|
||||
|
||||
// Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
|
||||
// This is not true for other kinds of items.x
|
||||
@ -492,6 +491,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
let next_early_index = self.next_early_index();
|
||||
let was_in_fn_syntax = self.is_in_fn_syntax;
|
||||
self.is_in_fn_syntax = true;
|
||||
let lifetime_span: Option<Span> = c
|
||||
.generic_params
|
||||
.iter()
|
||||
.filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => Some(param.span),
|
||||
_ => None,
|
||||
})
|
||||
.last();
|
||||
let (span, span_type) = if let Some(span) = lifetime_span {
|
||||
(span.shrink_to_hi(), ForLifetimeSpanType::TypeTail)
|
||||
} else {
|
||||
(ty.span.shrink_to_lo(), ForLifetimeSpanType::TypeEmpty)
|
||||
};
|
||||
self.missing_named_lifetime_spots
|
||||
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
||||
let scope = Scope::Binder {
|
||||
lifetimes: c
|
||||
.generic_params
|
||||
@ -514,6 +528,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
this.check_lifetime_params(old_scope, &c.generic_params);
|
||||
intravisit::walk_ty(this, ty);
|
||||
});
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
self.is_in_fn_syntax = was_in_fn_syntax;
|
||||
}
|
||||
hir::TyKind::TraitObject(bounds, ref lifetime) => {
|
||||
@ -696,7 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
||||
use self::hir::TraitItemKind::*;
|
||||
self.missing_named_lifetime_spots.push(&trait_item.generics);
|
||||
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
|
||||
match trait_item.kind {
|
||||
Method(ref sig, _) => {
|
||||
let tcx = self.tcx;
|
||||
@ -753,7 +768,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||
use self::hir::ImplItemKind::*;
|
||||
self.missing_named_lifetime_spots.push(&impl_item.generics);
|
||||
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
|
||||
match impl_item.kind {
|
||||
Method(ref sig, _) => {
|
||||
let tcx = self.tcx;
|
||||
@ -953,6 +968,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
) {
|
||||
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
|
||||
|
||||
let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref);
|
||||
if !self.trait_ref_hack
|
||||
|| trait_ref.bound_generic_params.iter().any(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => true,
|
||||
@ -988,10 +1004,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
self.with(scope, |old_scope, this| {
|
||||
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
|
||||
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
|
||||
this.visit_trait_ref(&trait_ref.trait_ref)
|
||||
this.visit_trait_ref(&trait_ref.trait_ref);
|
||||
})
|
||||
} else {
|
||||
self.visit_trait_ref(&trait_ref.trait_ref)
|
||||
self.visit_trait_ref(&trait_ref.trait_ref);
|
||||
}
|
||||
if should_pop_missing_lt {
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1824,29 +1843,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
|
||||
self.insert_lifetime(lifetime_ref, def);
|
||||
} else {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
lifetime_ref.span,
|
||||
E0261,
|
||||
"use of undeclared lifetime name `{}`",
|
||||
lifetime_ref
|
||||
);
|
||||
err.span_label(lifetime_ref.span, "undeclared lifetime");
|
||||
if !self.is_in_fn_syntax {
|
||||
for generics in &self.missing_named_lifetime_spots {
|
||||
let (span, sugg) = match &generics.params {
|
||||
[] => (generics.span, format!("<{}>", lifetime_ref)),
|
||||
[param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)),
|
||||
};
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("consider introducing lifetime `{}` here", lifetime_ref),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
self.emit_undeclared_lifetime_error(lifetime_ref);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2230,6 +2227,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
index: i,
|
||||
lifetime_count: gather.lifetimes.len(),
|
||||
have_bound_regions: gather.have_bound_regions,
|
||||
span: input.span,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -2385,7 +2383,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len());
|
||||
let mut err = self.report_missing_lifetime_specifiers(span, lifetime_refs.len());
|
||||
let mut add_label = true;
|
||||
|
||||
if let Some(params) = error {
|
||||
@ -2394,13 +2392,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if add_label {
|
||||
add_missing_lifetime_specifiers_label(
|
||||
self.add_missing_lifetime_specifiers_label(
|
||||
&mut err,
|
||||
span,
|
||||
lifetime_refs.len(),
|
||||
&lifetime_names,
|
||||
self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
|
||||
&self.missing_named_lifetime_spots,
|
||||
error.map(|p| &p[..]).unwrap_or(&[]),
|
||||
);
|
||||
}
|
||||
|
||||
@ -2442,8 +2439,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
let elided_len = elided_params.len();
|
||||
|
||||
for (i, info) in elided_params.into_iter().enumerate() {
|
||||
let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions } = info;
|
||||
let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } =
|
||||
info;
|
||||
|
||||
db.span_label(span, "");
|
||||
let help_name = if let Some(ident) =
|
||||
parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident())
|
||||
{
|
||||
@ -2477,7 +2476,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
if len == 0 {
|
||||
db.help(
|
||||
"this function's return type contains a borrowed value, \
|
||||
but there is no value for it to be borrowed from",
|
||||
but there is no value for it to be borrowed from",
|
||||
);
|
||||
self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
|
||||
} else if elided_len == 0 {
|
||||
@ -2491,14 +2490,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
} else if elided_len == 1 {
|
||||
db.help(&format!(
|
||||
"this function's return type contains a borrowed value, \
|
||||
but the signature does not say which {} it is borrowed from",
|
||||
but the signature does not say which {} it is borrowed from",
|
||||
m
|
||||
));
|
||||
true
|
||||
} else {
|
||||
db.help(&format!(
|
||||
"this function's return type contains a borrowed value, \
|
||||
but the signature does not say whether it is borrowed from {}",
|
||||
but the signature does not say whether it is borrowed from {}",
|
||||
m
|
||||
));
|
||||
true
|
||||
|
@ -1307,12 +1307,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
);
|
||||
}
|
||||
};
|
||||
// FIXME: point at the type params that don't have appropriate lifetimes:
|
||||
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
// ---- ---- ^^^^^^^
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
binding.span,
|
||||
E0582,
|
||||
"binding for associated type `{}` references lifetime `{}`, \
|
||||
which does not appear in the trait input types",
|
||||
which does not appear in the trait input types",
|
||||
binding.item_name,
|
||||
br_name
|
||||
)
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-63388-2.rs:12:10
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| -------- -----------
|
||||
LL | ) -> &dyn Foo
|
||||
| ^ help: consider using the named lifetime: `&'a`
|
||||
|
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-63388-2.rs:12:10
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| -------- -----------
|
||||
LL | ) -> &dyn Foo
|
||||
| ^ help: consider using the named lifetime: `&'a`
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | x: &bool,
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Foo<'lifetime> {
|
||||
LL | x: &'lifetime bool,
|
||||
LL | struct Foo<'a> {
|
||||
LL | x: &'a bool,
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
@ -18,9 +18,9 @@ LL | B(&bool),
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | enum Bar<'lifetime> {
|
||||
LL | enum Bar<'a> {
|
||||
LL | A(u8),
|
||||
LL | B(&'lifetime bool),
|
||||
LL | B(&'a bool),
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
@ -31,8 +31,8 @@ LL | type MyStr = &str;
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | type MyStr<'lifetime> = &'lifetime str;
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | type MyStr<'a> = &'a str;
|
||||
| ^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/E0106.rs:17:10
|
||||
@ -42,8 +42,8 @@ LL | baz: Baz,
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Quux<'lifetime> {
|
||||
LL | baz: Baz<'lifetime>,
|
||||
LL | struct Quux<'a> {
|
||||
LL | baz: Baz<'a>,
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifiers
|
||||
|
@ -9,12 +9,24 @@ error[E0261]: use of undeclared lifetime name `'a`
|
||||
|
|
||||
LL | pub fn life4<'b>(x: for<'c> fn(&'a i32));
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
|
||||
| ^^^^
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/generic-extern-lifetime.rs:11:38
|
||||
|
|
||||
LL | pub fn life7<'b>() -> for<'c> fn(&'a i32);
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | type Output = &i32;
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | type Output<'lifetime> = &'lifetime i32;
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | type Output<'a> = &'a i32;
|
||||
| ^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/assoc-type.rs:16:20
|
||||
@ -17,8 +17,8 @@ LL | type Output = &'_ i32;
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | type Output<'lifetime> = &'lifetime i32;
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^
|
||||
LL | type Output<'a> = &'a i32;
|
||||
| ^^^^ ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | struct Heartbreak(Betrayal);
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Heartbreak<'lifetime>(Betrayal<'lifetime>);
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
|
||||
LL | struct Heartbreak<'a>(Betrayal<'a>);
|
||||
| ^^^^ ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -11,6 +11,16 @@ error[E0261]: use of undeclared lifetime name `'test`
|
||||
|
|
||||
LL | let y: fn(&'test u32) = foo2;
|
||||
| ^^^^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider introducing lifetime `'test` here
|
||||
|
|
||||
LL | fn bar<'test>() {
|
||||
| ^^^^^^^
|
||||
help: consider making the type lifetime-generic with a new `'test` lifetime
|
||||
|
|
||||
LL | let y: for<'test> fn(&'test u32) = foo2;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -2,25 +2,35 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-19707.rs:3:28
|
||||
|
|
||||
LL | type Foo = fn(&u8, &u8) -> &u8;
|
||||
| ^ expected named lifetime parameter
|
||||
| --- --- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8;
|
||||
| ^^^^^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | type Foo<'lifetime> = fn(&u8, &u8) -> &'lifetime u8;
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8;
|
||||
| ^^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-19707.rs:5:27
|
||||
|
|
||||
LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
|
||||
| ^ expected named lifetime parameter
|
||||
| --- --- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | fn bar<F: for<'a> Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
|
||||
| ^^^^^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn bar<'lifetime, F: Fn(&u8, &u8) -> &'lifetime u8>(f: &F) {}
|
||||
| ^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
|
||||
| ^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-26638.rs:1:62
|
||||
|
|
||||
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
|
||||
| ^ expected named lifetime parameter
|
||||
| ------------------------------------ ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn parse_type<'lifetime>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'lifetime str { iter.next() }
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
|
||||
| ^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-26638.rs:4:40
|
||||
|
@ -2,37 +2,37 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-30255.rs:9:24
|
||||
|
|
||||
LL | fn f(a: &S, b: i32) -> &i32 {
|
||||
| ^ expected named lifetime parameter
|
||||
| -- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn f<'lifetime>(a: &S, b: i32) -> &'lifetime i32 {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 {
|
||||
| ^^^^ ^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-30255.rs:14:34
|
||||
|
|
||||
LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
|
||||
| ^ expected named lifetime parameter
|
||||
| -- ---- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn g<'lifetime>(a: &S, b: bool, c: &i32) -> &'lifetime i32 {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 {
|
||||
| ^^^^ ^^^^^ ^^^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-30255.rs:19:44
|
||||
|
|
||||
LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
|
||||
| ^ expected named lifetime parameter
|
||||
| ----- -- ---- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn h<'lifetime>(a: &bool, b: bool, c: &S, d: &i32) -> &'lifetime i32 {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 {
|
||||
| ^^^^ ^^^^^^^^ ^^^^^ ^^^^^^^ ^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -10,25 +10,25 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33
|
||||
|
|
||||
LL | fn g(_x: &isize, _y: &isize) -> &isize {
|
||||
| ^ expected named lifetime parameter
|
||||
| ------ ------ ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn g<'lifetime>(_x: &isize, _y: &isize) -> &'lifetime isize {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize {
|
||||
| ^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19
|
||||
|
|
||||
LL | fn h(_x: &Foo) -> &isize {
|
||||
| ^ expected named lifetime parameter
|
||||
| ---- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn h<'lifetime>(_x: &Foo) -> &'lifetime isize {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn h<'a>(_x: &'a Foo) -> &'a isize {
|
||||
| ^^^^ ^^^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20
|
||||
|
@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/ex1b-return-no-names-if-else.rs:1:29
|
||||
|
|
||||
LL | fn foo(x: &i32, y: &i32) -> &i32 {
|
||||
| ^ expected named lifetime parameter
|
||||
| ---- ---- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn foo<'lifetime>(x: &i32, y: &i32) -> &'lifetime i32 {
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^^
|
||||
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
|
||||
| ^^^^ ^^^^^^^ ^^^^^^^ ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | a: &u64
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct A<'lifetime> {
|
||||
LL | a: &'lifetime u64
|
||||
LL | struct A<'a> {
|
||||
LL | a: &'a u64
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -6,8 +6,8 @@ LL | Bar(&isize)
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | enum Foo<'lifetime> {
|
||||
LL | Bar(&'lifetime isize)
|
||||
LL | enum Foo<'a> {
|
||||
LL | Bar(&'a isize)
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -6,8 +6,8 @@ LL | x: &isize
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Foo<'lifetime> {
|
||||
LL | x: &'lifetime isize
|
||||
LL | struct Foo<'a> {
|
||||
LL | x: &'a isize
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -88,12 +88,32 @@ error[E0261]: use of undeclared lifetime name `'b`
|
||||
|
|
||||
LL | ... &'b isize,
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider introducing lifetime `'b` here
|
||||
|
|
||||
LL | fn fn_types<'b>(a: &'a isize,
|
||||
| ^^^^
|
||||
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
||||
|
|
||||
LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
|
||||
| ^^^^
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/regions-name-undeclared.rs:45:36
|
||||
|
|
||||
LL | ... &'b isize)>,
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider introducing lifetime `'b` here
|
||||
|
|
||||
LL | fn fn_types<'b>(a: &'a isize,
|
||||
| ^^^^
|
||||
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
||||
|
|
||||
LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
|
||||
| ^^^^
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/regions-name-undeclared.rs:46:17
|
||||
|
13
src/test/ui/rfc1623-2.rs
Normal file
13
src/test/ui/rfc1623-2.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
|
||||
a
|
||||
}
|
||||
|
||||
// the boundaries of elision
|
||||
static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
|
||||
//~^ ERROR missing lifetime specifier [E0106]
|
||||
&(non_elidable as fn(&u8, &u8) -> &u8);
|
||||
//~^ ERROR missing lifetime specifier [E0106]
|
||||
|
||||
fn main() {}
|
29
src/test/ui/rfc1623-2.stderr
Normal file
29
src/test/ui/rfc1623-2.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/rfc1623-2.rs:8:42
|
||||
|
|
||||
LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
|
||||
| --- --- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
|
||||
| ^^^^^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/rfc1623-2.rs:10:39
|
||||
|
|
||||
LL | &(non_elidable as fn(&u8, &u8) -> &u8);
|
||||
| --- --- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
|
||||
| ^^^^^^^ ^^^^^^ ^^^^^^ ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
@ -4,11 +4,10 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
|
||||
a
|
||||
}
|
||||
|
||||
// the boundaries of elision
|
||||
static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
|
||||
//~^ ERROR missing lifetime specifier [E0106]
|
||||
&(non_elidable as fn(&u8, &u8) -> &u8);
|
||||
//~^ ERROR missing lifetime specifier [E0106]
|
||||
// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs`
|
||||
static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
|
||||
&(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
|
||||
|
||||
|
||||
struct SomeStruct<'x, 'y, 'z: 'x> {
|
||||
foo: &'x Foo<'z>,
|
||||
@ -20,10 +19,12 @@ fn id<T>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
|
||||
static SOME_STRUCT: &SomeStruct = SomeStruct {
|
||||
static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types
|
||||
foo: &Foo { bools: &[false, true] },
|
||||
bar: &Bar { bools: &[true, true] },
|
||||
f: &id,
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| ERROR type mismatch resolving
|
||||
};
|
||||
|
||||
// very simple test for a 'static static with default lifetime
|
||||
|
@ -1,19 +1,46 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/rfc1623.rs:8:42
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/rfc1623.rs:22:35
|
||||
|
|
||||
LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
|
||||
| ^ expected named lifetime parameter
|
||||
LL | static SOME_STRUCT: &SomeStruct = SomeStruct {
|
||||
| ___________________________________^
|
||||
LL | | foo: &Foo { bools: &[false, true] },
|
||||
LL | | bar: &Bar { bools: &[true, true] },
|
||||
LL | | f: &id,
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct`
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
|
||||
LL | foo: &Foo { bools: &[false, true] },
|
||||
LL | bar: &Bar { bools: &[true, true] },
|
||||
LL | f: &id,
|
||||
LL |
|
||||
LL |
|
||||
...
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/rfc1623.rs:10:39
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/rfc1623.rs:25:8
|
||||
|
|
||||
LL | &(non_elidable as fn(&u8, &u8) -> &u8);
|
||||
| ^ expected named lifetime parameter
|
||||
LL | fn id<T>(t: T) -> T {
|
||||
| ------------------- found signature of `fn(_) -> _`
|
||||
...
|
||||
LL | f: &id,
|
||||
| ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _`
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0271]: type mismatch resolving `for<'a, 'b> <fn(_) -> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>`
|
||||
--> $DIR/rfc1623.rs:25:8
|
||||
|
|
||||
LL | f: &id,
|
||||
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
|
||||
|
|
||||
= note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0308, E0631.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
8
src/test/ui/suggestions/fn-missing-lifetime-in-item.rs
Normal file
8
src/test/ui/suggestions/fn-missing-lifetime-in-item.rs
Normal file
@ -0,0 +1,8 @@
|
||||
struct S1<F: Fn(&i32, &i32) -> &'a i32>(F); //~ ERROR use of undeclared lifetime name `'a`
|
||||
struct S2<F: Fn(&i32, &i32) -> &i32>(F); //~ ERROR missing lifetime specifier
|
||||
struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
|
||||
struct S4<F: for<'x> Fn(&'x i32, &'x i32) -> &'x i32>(F);
|
||||
const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
|
||||
//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
|
||||
fn main() {}
|
49
src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
Normal file
49
src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
Normal file
@ -0,0 +1,49 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/fn-missing-lifetime-in-item.rs:1:33
|
||||
|
|
||||
LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F);
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
|
||||
| ^^^
|
||||
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/fn-missing-lifetime-in-item.rs:2:32
|
||||
|
|
||||
LL | struct S2<F: Fn(&i32, &i32) -> &i32>(F);
|
||||
| ---- ---- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F);
|
||||
| ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F);
|
||||
| ^^^ ^^^^^^^ ^^^^^^^ ^^^
|
||||
|
||||
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
|
||||
--> $DIR/fn-missing-lifetime-in-item.rs:3:40
|
||||
|
|
||||
LL | struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
|
||||
--> $DIR/fn-missing-lifetime-in-item.rs:6:55
|
||||
|
|
||||
LL | const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0106, E0261, E0582.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
2
src/test/ui/suggestions/impl-trait-missing-lifetime.rs
Normal file
2
src/test/ui/suggestions/impl-trait-missing-lifetime.rs
Normal file
@ -0,0 +1,2 @@
|
||||
fn f(_: impl Iterator<Item = &'_ ()>) {} //~ ERROR missing lifetime specifier
|
||||
fn main() {}
|
14
src/test/ui/suggestions/impl-trait-missing-lifetime.stderr
Normal file
14
src/test/ui/suggestions/impl-trait-missing-lifetime.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/impl-trait-missing-lifetime.rs:1:31
|
||||
|
|
||||
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
|
||||
| ^^ expected named lifetime parameter
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
|
||||
| ^^^^ ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
@ -8,7 +8,7 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/return-without-lifetime.rs:5:34
|
||||
|
|
||||
LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
|
||||
| ^ help: consider using the named lifetime: `&'a`
|
||||
| --------- ^ help: consider using the named lifetime: `&'a`
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
|
||||
|
||||
@ -16,7 +16,7 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/return-without-lifetime.rs:7:35
|
||||
|
|
||||
LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
|
||||
| ^ help: consider using the named lifetime: `&'a`
|
||||
| ---------- ^ help: consider using the named lifetime: `&'a`
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
|
||||
|
||||
|
@ -2,12 +2,12 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39
|
||||
|
|
||||
LL | let _: dyn Foo(&isize, &usize) -> &usize;
|
||||
| ^ expected named lifetime parameter
|
||||
| ------ ------ ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn main<'lifetime>() {
|
||||
LL | fn main<'a>() {
|
||||
LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>,
|
||||
LL | dyn Foo(&isize) -> &isize >();
|
||||
LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
|
||||
|
@ -6,8 +6,8 @@ LL | x: Box<dyn Debug + '_>,
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Foo<'lifetime> {
|
||||
LL | x: Box<dyn Debug + 'lifetime>,
|
||||
LL | struct Foo<'a> {
|
||||
LL | x: Box<dyn Debug + 'a>,
|
||||
|
|
||||
|
||||
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
|
||||
|
@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/in-fn-return-illegal.rs:5:30
|
||||
|
|
||||
LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
|
||||
| ^^ expected named lifetime parameter
|
||||
| ---- ---- ^^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn foo<'lifetime>(x: &u32, y: &u32) -> &'lifetime u32 { loop { } }
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^
|
||||
LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } }
|
||||
| ^^^^ ^^^^^^^ ^^^^^^^ ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | x: &'_ u32,
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Foo<'lifetime> {
|
||||
LL | x: &'lifetime u32,
|
||||
LL | struct Foo<'a> {
|
||||
LL | x: &'a u32,
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
@ -18,8 +18,8 @@ LL | Variant(&'_ u32),
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | enum Bar<'lifetime> {
|
||||
LL | Variant(&'lifetime u32),
|
||||
LL | enum Bar<'a> {
|
||||
LL | Variant(&'a u32),
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -28,13 +28,13 @@ error[E0106]: missing lifetime specifier
|
||||
--> $DIR/underscore-lifetime-binders.rs:16:35
|
||||
|
|
||||
LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
|
||||
| ^^ expected named lifetime parameter
|
||||
| ------ ------ ^^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn foo2<'lifetime>(_: &'_ u8, y: &'_ u8) -> &'lifetime u8 { y }
|
||||
| ^^^^^^^^^^^ ^^^^^^^^^
|
||||
LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y }
|
||||
| ^^^^ ^^^^^^ ^^^^^^ ^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user