mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 22:13:27 +00:00
Suggest using 'static
in assoc consts and suggest when multiple lts are needed
This commit is contained in:
parent
becd479482
commit
6a3deb0ae0
@ -33,6 +33,7 @@ enum AssocSuggestion {
|
|||||||
crate enum MissingLifetimeSpot<'tcx> {
|
crate enum MissingLifetimeSpot<'tcx> {
|
||||||
Generics(&'tcx hir::Generics<'tcx>),
|
Generics(&'tcx hir::Generics<'tcx>),
|
||||||
HigherRanked { span: Span, span_type: ForLifetimeSpanType },
|
HigherRanked { span: Span, span_type: ForLifetimeSpanType },
|
||||||
|
Static,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate enum ForLifetimeSpanType {
|
crate enum ForLifetimeSpanType {
|
||||||
@ -1186,6 +1187,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||||||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nightly_options::is_nightly_build()
|
if nightly_options::is_nightly_build()
|
||||||
@ -1358,6 +1360,42 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||||||
);
|
);
|
||||||
(*span, span_type.suggestion("'a"))
|
(*span, span_type.suggestion("'a"))
|
||||||
}
|
}
|
||||||
|
MissingLifetimeSpot::Static => {
|
||||||
|
let (span, sugg) = match snippet.as_deref() {
|
||||||
|
Some("&") => (span.shrink_to_hi(), "'static ".to_owned()),
|
||||||
|
Some("'_") => (span, "'static".to_owned()),
|
||||||
|
Some(snippet) if !snippet.ends_with('>') => {
|
||||||
|
if snippet == "" {
|
||||||
|
(
|
||||||
|
span,
|
||||||
|
std::iter::repeat("'static")
|
||||||
|
.take(count)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", "),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
span.shrink_to_hi(),
|
||||||
|
format!(
|
||||||
|
"<{}>",
|
||||||
|
std::iter::repeat("'static")
|
||||||
|
.take(count)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
"consider using the `'static` lifetime",
|
||||||
|
sugg.to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
for param in params {
|
for param in params {
|
||||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
|
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
|
||||||
@ -1408,13 +1446,23 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||||||
([], Some("'_")) if count == 1 => {
|
([], Some("'_")) if count == 1 => {
|
||||||
suggest_new(err, "'a");
|
suggest_new(err, "'a");
|
||||||
}
|
}
|
||||||
([], Some(snippet)) if !snippet.ends_with('>') && count == 1 => {
|
([], Some(snippet)) if !snippet.ends_with('>') => {
|
||||||
if snippet == "" {
|
if snippet == "" {
|
||||||
// This happens when we have `type Bar<'a> = Foo<T>` where we point at the space
|
// This happens when we have `type Bar<'a> = Foo<T>` where we point at the space
|
||||||
// before `T`. We will suggest `type Bar<'a> = Foo<'a, T>`.
|
// before `T`. We will suggest `type Bar<'a> = Foo<'a, T>`.
|
||||||
suggest_new(err, "'a, ");
|
suggest_new(
|
||||||
|
err,
|
||||||
|
&std::iter::repeat("'a, ").take(count).collect::<Vec<_>>().join(""),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
suggest_new(err, &format!("{}<'a>", snippet));
|
suggest_new(
|
||||||
|
err,
|
||||||
|
&format!(
|
||||||
|
"{}<{}>",
|
||||||
|
snippet,
|
||||||
|
std::iter::repeat("'a").take(count).collect::<Vec<_>>().join(", ")
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(lts, ..) if lts.len() > 1 => {
|
(lts, ..) if lts.len() > 1 => {
|
||||||
|
@ -764,26 +764,30 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
Const(_, _) => {
|
Const(_, _) => {
|
||||||
// Only methods and types support generics.
|
// Only methods and types support generics.
|
||||||
assert!(trait_item.generics.params.is_empty());
|
assert!(trait_item.generics.params.is_empty());
|
||||||
|
self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
|
||||||
intravisit::walk_trait_item(self, trait_item);
|
intravisit::walk_trait_item(self, trait_item);
|
||||||
|
self.missing_named_lifetime_spots.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||||
use self::hir::ImplItemKind::*;
|
use self::hir::ImplItemKind::*;
|
||||||
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
|
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
Fn(ref sig, _) => {
|
Fn(ref sig, _) => {
|
||||||
|
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
self.visit_early_late(
|
self.visit_early_late(
|
||||||
Some(tcx.hir().get_parent_item(impl_item.hir_id)),
|
Some(tcx.hir().get_parent_item(impl_item.hir_id)),
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
&impl_item.generics,
|
&impl_item.generics,
|
||||||
|this| intravisit::walk_impl_item(this, impl_item),
|
|this| intravisit::walk_impl_item(this, impl_item),
|
||||||
)
|
);
|
||||||
|
self.missing_named_lifetime_spots.pop();
|
||||||
}
|
}
|
||||||
TyAlias(ref ty) => {
|
TyAlias(ref ty) => {
|
||||||
let generics = &impl_item.generics;
|
let generics = &impl_item.generics;
|
||||||
|
self.missing_named_lifetime_spots.push(generics.into());
|
||||||
let mut index = self.next_early_index();
|
let mut index = self.next_early_index();
|
||||||
let mut non_lifetime_count = 0;
|
let mut non_lifetime_count = 0;
|
||||||
debug!("visit_ty: index = {}", index);
|
debug!("visit_ty: index = {}", index);
|
||||||
@ -812,15 +816,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
});
|
});
|
||||||
|
self.missing_named_lifetime_spots.pop();
|
||||||
}
|
}
|
||||||
Const(_, _) => {
|
Const(_, _) => {
|
||||||
// Only methods and types support generics.
|
// Only methods and types support generics.
|
||||||
assert!(impl_item.generics.params.is_empty());
|
assert!(impl_item.generics.params.is_empty());
|
||||||
|
self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
|
||||||
intravisit::walk_impl_item(self, impl_item);
|
intravisit::walk_impl_item(self, impl_item);
|
||||||
}
|
|
||||||
}
|
|
||||||
self.missing_named_lifetime_spots.pop();
|
self.missing_named_lifetime_spots.pop();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
||||||
debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref);
|
debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref);
|
||||||
|
@ -51,6 +51,15 @@ error[E0106]: missing lifetime specifiers
|
|||||||
|
|
|
|
||||||
LL | buzz: Buzz,
|
LL | buzz: Buzz,
|
||||||
| ^^^^ expected 2 lifetime parameters
|
| ^^^^ expected 2 lifetime parameters
|
||||||
|
|
|
||||||
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
||||||
|
LL | struct Quux<'a> {
|
||||||
|
LL | baz: Baz,
|
||||||
|
LL |
|
||||||
|
LL |
|
||||||
|
LL | buzz: Buzz<'a, 'a>,
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
trait ZstAssert: Sized {
|
trait ZstAssert: Sized {
|
||||||
const TYPE_NAME: &str = ""; //~ ERROR missing lifetime specifier
|
const A: &str = ""; //~ ERROR missing lifetime specifier
|
||||||
|
const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
|
||||||
|
const C: &'_ str = ""; //~ ERROR missing lifetime specifier
|
||||||
|
const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S<'a> {
|
||||||
|
s: &'a (),
|
||||||
|
}
|
||||||
|
struct T<'a, 'b> {
|
||||||
|
a: &'a (),
|
||||||
|
b: &'b (),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,15 +1,73 @@
|
|||||||
error[E0106]: missing lifetime specifier
|
error[E0106]: missing lifetime specifier
|
||||||
--> $DIR/missing-lifetime-in-assoc-const-type.rs:2:22
|
--> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14
|
||||||
|
|
|
|
||||||
LL | const TYPE_NAME: &str = "";
|
LL | const A: &str = "";
|
||||||
| ^ expected named lifetime parameter
|
| ^ expected named lifetime parameter
|
||||||
|
|
|
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | const A: &'static str = "";
|
||||||
|
| ^^^^^^^
|
||||||
help: consider introducing a named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
|
||||||
LL | trait ZstAssert<'a>: Sized {
|
LL | trait ZstAssert<'a>: Sized {
|
||||||
LL | const TYPE_NAME: &'a str = "";
|
LL | const A: &'a str = "";
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14
|
||||||
|
|
|
||||||
|
LL | const B: S = S { s: &() };
|
||||||
|
| ^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | const B: S<'static> = S { s: &() };
|
||||||
|
| ^^^^^^^^^
|
||||||
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
||||||
|
LL | trait ZstAssert<'a>: Sized {
|
||||||
|
LL | const A: &str = "";
|
||||||
|
LL | const B: S<'a> = S { s: &() };
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15
|
||||||
|
|
|
||||||
|
LL | const C: &'_ str = "";
|
||||||
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | const C: &'static str = "";
|
||||||
|
| ^^^^^^^
|
||||||
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
||||||
|
LL | trait ZstAssert<'a>: Sized {
|
||||||
|
LL | const A: &str = "";
|
||||||
|
LL | const B: S = S { s: &() };
|
||||||
|
LL | const C: &'a str = "";
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0106]: missing lifetime specifiers
|
||||||
|
--> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14
|
||||||
|
|
|
||||||
|
LL | const D: T = T { a: &(), b: &() };
|
||||||
|
| ^ expected 2 lifetime parameters
|
||||||
|
|
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | const D: T<'static, 'static> = T { a: &(), b: &() };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
||||||
|
LL | trait ZstAssert<'a>: Sized {
|
||||||
|
LL | const A: &str = "";
|
||||||
|
LL | const B: S = S { s: &() };
|
||||||
|
LL | const C: &'_ str = "";
|
||||||
|
LL | const D: T<'a, 'a> = T { a: &(), b: &() };
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0106`.
|
For more information about this error, try `rustc --explain E0106`.
|
||||||
|
Loading…
Reference in New Issue
Block a user