move E0637 to lowering and improve output, add more tests
This commit is contained in:
parent
68da108d56
commit
1f4d100472
@ -436,7 +436,9 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
|
||||
visitor.visit_ident(ident);
|
||||
}
|
||||
LifetimeName::Param(ParamName::Fresh(_)) |
|
||||
LifetimeName::Param(ParamName::Error) |
|
||||
LifetimeName::Static |
|
||||
LifetimeName::Error |
|
||||
LifetimeName::Implicit |
|
||||
LifetimeName::Underscore => {}
|
||||
}
|
||||
@ -747,7 +749,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
|
||||
walk_list!(visitor, visit_attribute, ¶m.attrs);
|
||||
match param.name {
|
||||
ParamName::Plain(ident) => visitor.visit_ident(ident),
|
||||
ParamName::Fresh(_) => {}
|
||||
ParamName::Error | ParamName::Fresh(_) => {}
|
||||
}
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
|
@ -316,6 +316,11 @@ enum AnonymousLifetimeMode {
|
||||
/// For **Deprecated** cases, report an error.
|
||||
CreateParameter,
|
||||
|
||||
/// Give a hard error when either `&` or `'_` is written. Used to
|
||||
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
||||
/// error on default object bounds (e.g., `Box<dyn Foo>`).
|
||||
ReportError,
|
||||
|
||||
/// Pass responsibility to `resolve_lifetime` code for all cases.
|
||||
PassThrough,
|
||||
}
|
||||
@ -736,6 +741,10 @@ impl<'a> LoweringContext<'a> {
|
||||
keywords::UnderscoreLifetime.name().as_interned_str(),
|
||||
hir::LifetimeParamKind::Elided,
|
||||
),
|
||||
ParamName::Error => (
|
||||
keywords::UnderscoreLifetime.name().as_interned_str(),
|
||||
hir::LifetimeParamKind::Error,
|
||||
),
|
||||
};
|
||||
|
||||
// Add a definition for the in-band lifetime def
|
||||
@ -792,7 +801,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
/// When we have either an elided or `'_` lifetime in an impl
|
||||
/// header, we convert it to
|
||||
/// header, we convert it to an in-band lifetime.
|
||||
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
|
||||
assert!(self.is_collecting_in_band_lifetimes);
|
||||
let index = self.lifetimes_to_define.len();
|
||||
@ -1475,7 +1484,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
hir::LifetimeName::Param(_) => lifetime.name,
|
||||
hir::LifetimeName::Static => return,
|
||||
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
|
||||
};
|
||||
|
||||
if !self.currently_bound_lifetimes.contains(&name)
|
||||
@ -2163,7 +2172,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
hir::LifetimeName::Param(_) => lifetime.name,
|
||||
hir::LifetimeName::Static => return,
|
||||
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
|
||||
};
|
||||
|
||||
if !self.currently_bound_lifetimes.contains(&name) {
|
||||
@ -2294,17 +2303,15 @@ impl<'a> LoweringContext<'a> {
|
||||
itctx: ImplTraitContext<'_>,
|
||||
) -> hir::GenericBound {
|
||||
match *tpb {
|
||||
GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
|
||||
self.lower_poly_trait_ref(ty, itctx),
|
||||
self.lower_trait_bound_modifier(modifier),
|
||||
),
|
||||
GenericBound::Outlives(ref lifetime) => {
|
||||
// We don't want to accept `'a: '_`:
|
||||
self.with_anonymous_lifetime_mode(
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this| hir::GenericBound::Outlives(this.lower_lifetime(lifetime)),
|
||||
GenericBound::Trait(ref ty, modifier) => {
|
||||
hir::GenericBound::Trait(
|
||||
self.lower_poly_trait_ref(ty, itctx),
|
||||
self.lower_trait_bound_modifier(modifier),
|
||||
)
|
||||
}
|
||||
GenericBound::Outlives(ref lifetime) => {
|
||||
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2323,6 +2330,8 @@ impl<'a> LoweringContext<'a> {
|
||||
AnonymousLifetimeMode::PassThrough => {
|
||||
self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
|
||||
}
|
||||
|
||||
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
|
||||
},
|
||||
ident => {
|
||||
self.maybe_collect_in_band_lifetime(ident);
|
||||
@ -2361,16 +2370,26 @@ impl<'a> LoweringContext<'a> {
|
||||
add_bounds: &NodeMap<Vec<GenericBound>>,
|
||||
mut itctx: ImplTraitContext<'_>)
|
||||
-> hir::GenericParam {
|
||||
let mut bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow());
|
||||
let mut bounds = self.with_anonymous_lifetime_mode(
|
||||
AnonymousLifetimeMode::ReportError,
|
||||
|this| this.lower_param_bounds(¶m.bounds, itctx.reborrow()),
|
||||
);
|
||||
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
|
||||
self.is_collecting_in_band_lifetimes = false;
|
||||
|
||||
let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
|
||||
let lt = self.with_anonymous_lifetime_mode(
|
||||
AnonymousLifetimeMode::ReportError,
|
||||
|this| this.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }),
|
||||
);
|
||||
let param_name = match lt.name {
|
||||
hir::LifetimeName::Param(param_name) => param_name,
|
||||
_ => hir::ParamName::Plain(lt.name.ident()),
|
||||
hir::LifetimeName::Implicit
|
||||
| hir::LifetimeName::Underscore
|
||||
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
|
||||
hir::LifetimeName::Error => ParamName::Error,
|
||||
};
|
||||
let param = hir::GenericParam {
|
||||
id: lt.id,
|
||||
@ -2494,13 +2513,18 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
|
||||
hir::WhereClause {
|
||||
id: self.lower_node_id(wc.id).node_id,
|
||||
predicates: wc.predicates
|
||||
.iter()
|
||||
.map(|predicate| self.lower_where_predicate(predicate))
|
||||
.collect(),
|
||||
}
|
||||
self.with_anonymous_lifetime_mode(
|
||||
AnonymousLifetimeMode::ReportError,
|
||||
|this| {
|
||||
hir::WhereClause {
|
||||
id: this.lower_node_id(wc.id).node_id,
|
||||
predicates: wc.predicates
|
||||
.iter()
|
||||
.map(|predicate| this.lower_where_predicate(predicate))
|
||||
.collect(),
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
|
||||
@ -4843,10 +4867,38 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
|
||||
|
||||
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
|
||||
}
|
||||
}
|
||||
|
||||
/// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
|
||||
/// return a "error lifetime".
|
||||
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
|
||||
let (id, msg, label) = match id {
|
||||
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
|
||||
|
||||
None => (
|
||||
self.next_id().node_id,
|
||||
"`&` without an explicit lifetime name cannot be used here",
|
||||
"explicit lifetime name needed here",
|
||||
),
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
self.sess,
|
||||
span,
|
||||
E0637,
|
||||
"{}",
|
||||
msg,
|
||||
);
|
||||
err.span_label(span, label);
|
||||
err.emit();
|
||||
|
||||
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
|
||||
}
|
||||
|
||||
/// Invoked to create the lifetime argument(s) for a path like
|
||||
/// `std::cell::Ref<T>`; note that implicit lifetimes in these
|
||||
/// sorts of cases are deprecated. This may therefore report a warning or an
|
||||
@ -4861,6 +4913,12 @@ impl<'a> LoweringContext<'a> {
|
||||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||
AnonymousLifetimeMode::CreateParameter => {}
|
||||
|
||||
AnonymousLifetimeMode::ReportError => {
|
||||
return (0..count)
|
||||
.map(|_| self.new_error_lifetime(None, span))
|
||||
.collect();
|
||||
}
|
||||
|
||||
// This is the normal case.
|
||||
AnonymousLifetimeMode::PassThrough => {}
|
||||
}
|
||||
@ -4891,6 +4949,10 @@ impl<'a> LoweringContext<'a> {
|
||||
// `resolve_lifetime` has the code to make that happen.
|
||||
AnonymousLifetimeMode::CreateParameter => {}
|
||||
|
||||
AnonymousLifetimeMode::ReportError => {
|
||||
// ReportError applies to explicit use of `'_`.
|
||||
}
|
||||
|
||||
// This is the normal case.
|
||||
AnonymousLifetimeMode::PassThrough => {}
|
||||
}
|
||||
|
@ -208,13 +208,18 @@ pub enum ParamName {
|
||||
/// where `'f` is something like `Fresh(0)`. The indices are
|
||||
/// unique per impl, but not necessarily continuous.
|
||||
Fresh(usize),
|
||||
|
||||
/// Indicates an illegal name was given and an error has been
|
||||
/// repored (so we should squelch other derived errors). Occurs
|
||||
/// when e.g. `'_` is used in the wrong place.
|
||||
Error,
|
||||
}
|
||||
|
||||
impl ParamName {
|
||||
pub fn ident(&self) -> Ident {
|
||||
match *self {
|
||||
ParamName::Plain(ident) => ident,
|
||||
ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
|
||||
ParamName::Error | ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,6 +239,10 @@ pub enum LifetimeName {
|
||||
/// User typed nothing. e.g. the lifetime in `&u32`.
|
||||
Implicit,
|
||||
|
||||
/// Indicates an error during lowering (usually `'_` in wrong place)
|
||||
/// that was already reported.
|
||||
Error,
|
||||
|
||||
/// User typed `'_`.
|
||||
Underscore,
|
||||
|
||||
@ -245,6 +254,7 @@ impl LifetimeName {
|
||||
pub fn ident(&self) -> Ident {
|
||||
match *self {
|
||||
LifetimeName::Implicit => keywords::Invalid.ident(),
|
||||
LifetimeName::Error => keywords::Invalid.ident(),
|
||||
LifetimeName::Underscore => keywords::UnderscoreLifetime.ident(),
|
||||
LifetimeName::Static => keywords::StaticLifetime.ident(),
|
||||
LifetimeName::Param(param_name) => param_name.ident(),
|
||||
@ -260,7 +270,7 @@ impl LifetimeName {
|
||||
// in the compiler is concerned -- `Fresh(_)` variants act
|
||||
// equivalently to "some fresh name". They correspond to
|
||||
// early-bound regions on an impl, in other words.
|
||||
LifetimeName::Param(_) | LifetimeName::Static => false,
|
||||
LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -513,6 +523,9 @@ pub enum LifetimeParamKind {
|
||||
// Indication that the lifetime was elided like both cases here:
|
||||
// `fn foo(x: &u8) -> &'_ u8 { x }`
|
||||
Elided,
|
||||
|
||||
// Indication that the lifetime name was somehow in error.
|
||||
Error,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
|
@ -144,7 +144,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
|
||||
|
||||
impl_stable_hash_for!(enum hir::ParamName {
|
||||
Plain(name),
|
||||
Fresh(index)
|
||||
Fresh(index),
|
||||
Error,
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::LifetimeName {
|
||||
@ -152,6 +153,7 @@ impl_stable_hash_for!(enum hir::LifetimeName {
|
||||
Implicit,
|
||||
Underscore,
|
||||
Static,
|
||||
Error,
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::Label {
|
||||
@ -210,7 +212,8 @@ impl_stable_hash_for!(struct hir::GenericParam {
|
||||
impl_stable_hash_for!(enum hir::LifetimeParamKind {
|
||||
Explicit,
|
||||
InBand,
|
||||
Elided
|
||||
Elided,
|
||||
Error,
|
||||
});
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
|
||||
|
@ -755,8 +755,9 @@ for ::middle::resolve_lifetime::Set1<T>
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(enum ::middle::resolve_lifetime::LifetimeDefOrigin {
|
||||
Explicit,
|
||||
InBand
|
||||
ExplicitOrElided,
|
||||
InBand,
|
||||
Error,
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
|
||||
|
@ -43,20 +43,23 @@ use hir::{self, GenericParamKind, LifetimeParamKind};
|
||||
/// This is used to prevent the usage of in-band lifetimes in `Fn`/`fn` syntax.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum LifetimeDefOrigin {
|
||||
// Explicit binders like `fn foo<'a>(x: &'a u8)`
|
||||
Explicit,
|
||||
// Explicit binders like `fn foo<'a>(x: &'a u8)` or elided like `impl Foo<&u32>`
|
||||
ExplicitOrElided,
|
||||
// In-band declarations like `fn foo(x: &'a u8)`
|
||||
InBand,
|
||||
// Some kind of erroneous origin
|
||||
Error,
|
||||
}
|
||||
|
||||
impl LifetimeDefOrigin {
|
||||
fn from_param(param: &GenericParam) -> Self {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { kind } => {
|
||||
if kind == LifetimeParamKind::InBand {
|
||||
LifetimeDefOrigin::InBand
|
||||
} else {
|
||||
LifetimeDefOrigin::Explicit
|
||||
match kind {
|
||||
LifetimeParamKind::InBand => LifetimeDefOrigin::InBand,
|
||||
LifetimeParamKind::Explicit => LifetimeDefOrigin::ExplicitOrElided,
|
||||
LifetimeParamKind::Elided => LifetimeDefOrigin::ExplicitOrElided,
|
||||
LifetimeParamKind::Error => LifetimeDefOrigin::Error,
|
||||
}
|
||||
}
|
||||
_ => bug!("expected a lifetime param"),
|
||||
@ -612,6 +615,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
// If the user wrote an explicit name, use that.
|
||||
self.visit_lifetime(lifetime);
|
||||
}
|
||||
LifetimeName::Error => { }
|
||||
}
|
||||
}
|
||||
hir::TyKind::Rptr(ref lifetime_ref, ref mt) => {
|
||||
@ -1631,6 +1635,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
|
||||
fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
||||
debug!("resolve_lifetime_ref(lifetime_ref={:?})", lifetime_ref);
|
||||
|
||||
// If we've already reported an error, just ignore `lifetime_ref`.
|
||||
if let LifetimeName::Error = lifetime_ref.name {
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk up the scope chain, tracking the number of fn scopes
|
||||
// that we pass through, until we find a lifetime with the
|
||||
// given name or we run out of scopes.
|
||||
@ -1650,16 +1660,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
Scope::Binder { ref lifetimes, s, .. } => {
|
||||
let name = match lifetime_ref.name {
|
||||
LifetimeName::Param(param_name) => param_name,
|
||||
match lifetime_ref.name {
|
||||
LifetimeName::Param(param_name) => {
|
||||
if let Some(&def) = lifetimes.get(¶m_name.modern()) {
|
||||
break Some(def.shifted(late_depth));
|
||||
}
|
||||
}
|
||||
_ => bug!("expected LifetimeName::Param"),
|
||||
};
|
||||
if let Some(&def) = lifetimes.get(&name.modern()) {
|
||||
break Some(def.shifted(late_depth));
|
||||
} else {
|
||||
late_depth += 1;
|
||||
scope = s;
|
||||
}
|
||||
|
||||
late_depth += 1;
|
||||
scope = s;
|
||||
}
|
||||
|
||||
Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
|
||||
@ -1709,8 +1720,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
Region::Static
|
||||
| Region::EarlyBound(_, _, LifetimeDefOrigin::Explicit)
|
||||
| Region::LateBound(_, _, LifetimeDefOrigin::Explicit)
|
||||
| Region::EarlyBound(_, _, LifetimeDefOrigin::ExplicitOrElided)
|
||||
| Region::LateBound(_, _, LifetimeDefOrigin::ExplicitOrElided)
|
||||
| Region::EarlyBound(_, _, LifetimeDefOrigin::Error)
|
||||
| Region::LateBound(_, _, LifetimeDefOrigin::Error)
|
||||
| Region::LateBoundAnon(..)
|
||||
| Region::Free(..) => {}
|
||||
}
|
||||
@ -2339,14 +2352,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
match bound {
|
||||
hir::GenericBound::Outlives(lt) => match lt.name {
|
||||
hir::LifetimeName::Underscore => {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
lt.span,
|
||||
E0637,
|
||||
"invalid lifetime bound name: `'_`"
|
||||
);
|
||||
err.span_label(lt.span, "`'_` is a reserved lifetime name");
|
||||
err.emit();
|
||||
self.tcx.sess.delay_span_bug(lt.span, "use of `'_` in illegal place, but not caught by lowering")
|
||||
}
|
||||
hir::LifetimeName::Static => {
|
||||
self.insert_lifetime(lt, Region::Static);
|
||||
@ -2364,6 +2370,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
|
||||
self.resolve_lifetime_ref(lt);
|
||||
}
|
||||
hir::LifetimeName::Error => {
|
||||
// No need to do anything, error already reported.
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
|
@ -2074,6 +2074,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
|
||||
hir::GenericParamKind::Type { .. } => {
|
||||
match param.name {
|
||||
hir::ParamName::Fresh(_) => { continue; },
|
||||
hir::ParamName::Error => { continue; },
|
||||
hir::ParamName::Plain(name) => name.to_string()
|
||||
}
|
||||
}
|
||||
|
@ -563,6 +563,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
|
||||
match lifetime.name {
|
||||
hir::LifetimeName::Param(_)
|
||||
| hir::LifetimeName::Error
|
||||
| hir::LifetimeName::Static
|
||||
| hir::LifetimeName::Underscore => {
|
||||
let region_name = self.synthesize_region_name(counter);
|
||||
|
@ -816,7 +816,10 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
let param = &hir_generics.params[index];
|
||||
report_bivariance(tcx, param.span, param.name.ident().name);
|
||||
match param.name {
|
||||
hir::ParamName::Error => { }
|
||||
_ => report_bivariance(tcx, param.span, param.name.ident().name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
|
||||
fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
|
||||
struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here
|
||||
fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here
|
||||
|
||||
struct Bar<'a>(&'a u8);
|
||||
impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
|
||||
impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here
|
||||
fn bar() {}
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
error[E0637]: invalid lifetime bound name: `'_`
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/E0637.rs:11:16
|
||||
|
|
||||
LL | struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
|
||||
LL | struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: invalid lifetime bound name: `'_`
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/E0637.rs:12:12
|
||||
|
|
||||
LL | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
|
||||
LL | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: invalid lifetime bound name: `'_`
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/E0637.rs:15:10
|
||||
|
|
||||
LL | impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
|
||||
LL | impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
46
src/test/ui/underscore-lifetime/in-binder.Rust2015.stderr
Normal file
46
src/test/ui/underscore-lifetime/in-binder.Rust2015.stderr
Normal file
@ -0,0 +1,46 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:12:6
|
||||
|
|
||||
LL | impl<'_> IceCube<'_> {}
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:17:15
|
||||
|
|
||||
LL | struct Struct<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:23:11
|
||||
|
|
||||
LL | enum Enum<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:29:13
|
||||
|
|
||||
LL | union Union<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:35:13
|
||||
|
|
||||
LL | trait Trait<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:40:8
|
||||
|
|
||||
LL | fn foo<'_>() {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/in-binder.rs:12:18
|
||||
|
|
||||
LL | impl<'_> IceCube<'_> {}
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors occurred: E0106, E0637.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
39
src/test/ui/underscore-lifetime/in-binder.Rust2018.stderr
Normal file
39
src/test/ui/underscore-lifetime/in-binder.Rust2018.stderr
Normal file
@ -0,0 +1,39 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:12:6
|
||||
|
|
||||
LL | impl<'_> IceCube<'_> {}
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:17:15
|
||||
|
|
||||
LL | struct Struct<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:23:11
|
||||
|
|
||||
LL | enum Enum<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:29:13
|
||||
|
|
||||
LL | union Union<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:35:13
|
||||
|
|
||||
LL | trait Trait<'_> {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/in-binder.rs:40:8
|
||||
|
|
||||
LL | fn foo<'_>() {
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
45
src/test/ui/underscore-lifetime/in-binder.rs
Normal file
45
src/test/ui/underscore-lifetime/in-binder.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// Check that we error when `'_` appears as the name of a lifetime parameter.
|
||||
//
|
||||
// Regression test for #52098.
|
||||
|
||||
// revisions: Rust2015 Rust2018
|
||||
//[Rust2018] edition:2018
|
||||
|
||||
struct IceCube<'a> {
|
||||
v: Vec<&'a char>
|
||||
}
|
||||
|
||||
impl<'_> IceCube<'_> {}
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2015]~| ERROR
|
||||
//[Rust2018]~^^^ ERROR
|
||||
|
||||
struct Struct<'_> {
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2018]~^^ ERROR
|
||||
v: Vec<&'static char>
|
||||
}
|
||||
|
||||
enum Enum<'_> {
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2018]~^^ ERROR
|
||||
Variant
|
||||
}
|
||||
|
||||
union Union<'_> {
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2018]~^^ ERROR
|
||||
a: u32
|
||||
}
|
||||
|
||||
trait Trait<'_> {
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2018]~^^ ERROR
|
||||
}
|
||||
|
||||
fn foo<'_>() {
|
||||
//[Rust2015]~^ ERROR
|
||||
//[Rust2018]~^^ ERROR
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/ui/underscore-lifetime/in-fn-return-illegal.rs
Normal file
17
src/test/ui/underscore-lifetime/in-fn-return-illegal.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that the `'_` used in structs/enums gives an error.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR
|
||||
|
||||
fn main() { }
|
11
src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
Normal file
11
src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/in-fn-return-illegal.rs:15:30
|
||||
|
|
||||
LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR
|
||||
| ^^ expected 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`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
23
src/test/ui/underscore-lifetime/in-struct.rs
Normal file
23
src/test/ui/underscore-lifetime/in-struct.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that the `'_` used in structs/enums gives an error.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
struct Foo {
|
||||
x: &'_ u32, //~ ERROR
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
Variant(&'_ u32), //~ ERROR
|
||||
}
|
||||
|
||||
fn main() { }
|
15
src/test/ui/underscore-lifetime/in-struct.stderr
Normal file
15
src/test/ui/underscore-lifetime/in-struct.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: expected `:`, found `(`
|
||||
--> $DIR/in-struct.rs:20:12
|
||||
|
|
||||
LL | Variant(&'_ u32), //~ ERROR
|
||||
| ^ expected `:`
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/in-struct.rs:16:9
|
||||
|
|
||||
LL | x: &'_ u32, //~ ERROR
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
@ -15,13 +15,13 @@ impl Foo<'_> { //~ ERROR missing lifetime specifier
|
||||
fn x() {}
|
||||
}
|
||||
|
||||
fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
|
||||
fn foo<'_> //~ ERROR cannot be used here
|
||||
(_: Foo<'_>) {}
|
||||
|
||||
trait Meh<'a> {}
|
||||
impl<'a> Meh<'a> for u8 {}
|
||||
|
||||
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
|
||||
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
|
||||
//~^ ERROR missing lifetime specifier
|
||||
{
|
||||
Box::new(5u8)
|
||||
|
@ -1,3 +1,15 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/underscore-lifetime-binders.rs:18:8
|
||||
|
|
||||
LL | fn foo<'_> //~ ERROR cannot be used here
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/underscore-lifetime-binders.rs:24:21
|
||||
|
|
||||
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/underscore-lifetime-binders.rs:12:17
|
||||
|
|
||||
@ -10,22 +22,10 @@ error[E0106]: missing lifetime specifier
|
||||
LL | impl Foo<'_> { //~ ERROR missing lifetime specifier
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error[E0262]: invalid lifetime parameter name: `'_`
|
||||
--> $DIR/underscore-lifetime-binders.rs:18:8
|
||||
|
|
||||
LL | fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
|
||||
| ^^ '_ is a reserved lifetime name
|
||||
|
||||
error[E0262]: invalid lifetime parameter name: `'_`
|
||||
--> $DIR/underscore-lifetime-binders.rs:24:21
|
||||
|
|
||||
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
|
||||
| ^^ '_ is a reserved lifetime name
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/underscore-lifetime-binders.rs:24:29
|
||||
|
|
||||
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
|
||||
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
|
||||
| ^^ expected lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
||||
@ -41,5 +41,5 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime sp
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors occurred: E0106, E0262.
|
||||
Some errors occurred: E0106, E0637.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
||||
|
@ -0,0 +1,8 @@
|
||||
// Regression test to check that `'b: '_` gets an error, because it's
|
||||
// basically useless.
|
||||
//
|
||||
// #54902
|
||||
|
||||
trait Foo<'a> {}
|
||||
impl<'b: '_> Foo<'b> for i32 {}
|
||||
fn main() { }
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/underscore-outlives-bounds.rs:7:10
|
||||
|
|
||||
LL | impl<'b: '_> Foo<'b> for i32 {}
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,18 @@
|
||||
// revisions: rust2015 rust2018
|
||||
//[rust2018] edition:2018
|
||||
|
||||
trait WithType<T> {}
|
||||
trait WithRegion<'a> { }
|
||||
|
||||
struct Foo<T> {
|
||||
t: T
|
||||
}
|
||||
|
||||
impl<T> Foo<T>
|
||||
where
|
||||
T: WithType<&u32>
|
||||
//[rust2015]~^ ERROR
|
||||
//[rust2018]~^^ ERROR
|
||||
{ }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `&` without an explicit lifetime name cannot be used here
|
||||
--> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
|
||||
|
|
||||
LL | T: WithType<&u32>
|
||||
| ^ explicit lifetime name needed here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `&` without an explicit lifetime name cannot be used here
|
||||
--> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
|
||||
|
|
||||
LL | T: WithType<&u32>
|
||||
| ^ explicit lifetime name needed here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,18 @@
|
||||
// revisions: rust2015 rust2018
|
||||
//[rust2018] edition:2018
|
||||
|
||||
trait WithType<T> {}
|
||||
trait WithRegion<'a> { }
|
||||
|
||||
struct Foo<T> {
|
||||
t: T
|
||||
}
|
||||
|
||||
impl<T> Foo<T>
|
||||
where
|
||||
T: WithRegion<'_>
|
||||
//[rust2015]~^ ERROR
|
||||
//[rust2018]~^^ ERROR
|
||||
{ }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/where-clause-inherent-impl-underscore.rs:13:19
|
||||
|
|
||||
LL | T: WithRegion<'_>
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/where-clause-inherent-impl-underscore.rs:13:19
|
||||
|
|
||||
LL | T: WithRegion<'_>
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,16 @@
|
||||
// revisions: rust2015 rust2018
|
||||
//[rust2018] edition:2018
|
||||
|
||||
trait WithType<T> {}
|
||||
trait WithRegion<'a> { }
|
||||
|
||||
trait Foo { }
|
||||
|
||||
impl<T> Foo for Vec<T>
|
||||
where
|
||||
T: WithType<&u32>
|
||||
//[rust2015]~^ ERROR
|
||||
//[rust2018]~^^ ERROR
|
||||
{ }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `&` without an explicit lifetime name cannot be used here
|
||||
--> $DIR/where-clause-trait-impl-region.rs:11:17
|
||||
|
|
||||
LL | T: WithType<&u32>
|
||||
| ^ explicit lifetime name needed here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `&` without an explicit lifetime name cannot be used here
|
||||
--> $DIR/where-clause-trait-impl-region.rs:11:17
|
||||
|
|
||||
LL | T: WithType<&u32>
|
||||
| ^ explicit lifetime name needed here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,16 @@
|
||||
// revisions: rust2015 rust2018
|
||||
//[rust2018] edition:2018
|
||||
|
||||
trait WithType<T> {}
|
||||
trait WithRegion<'a> { }
|
||||
|
||||
trait Foo { }
|
||||
|
||||
impl<T> Foo for Vec<T>
|
||||
where
|
||||
T: WithRegion<'_>
|
||||
//[rust2015]~^ ERROR
|
||||
//[rust2018]~^^ ERROR
|
||||
{ }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/where-clause-trait-impl-underscore.rs:11:19
|
||||
|
|
||||
LL | T: WithRegion<'_>
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/where-clause-trait-impl-underscore.rs:11:19
|
||||
|
|
||||
LL | T: WithRegion<'_>
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
3
src/test/ui/underscore-lifetime/where-clauses.rs
Normal file
3
src/test/ui/underscore-lifetime/where-clauses.rs
Normal file
@ -0,0 +1,3 @@
|
||||
trait Foo<'a> {}
|
||||
impl<'b: '_> Foo<'b> for i32 {}
|
||||
fn main() { }
|
9
src/test/ui/underscore-lifetime/where-clauses.stderr
Normal file
9
src/test/ui/underscore-lifetime/where-clauses.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/where-clauses.rs:2:10
|
||||
|
|
||||
LL | impl<'b: '_> Foo<'b> for i32 {}
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0637`.
|
Loading…
x
Reference in New Issue
Block a user