Skip to content

Commit 1f4d100

Browse files
committed
move E0637 to lowering and improve output, add more tests
1 parent 68da108 commit 1f4d100

36 files changed

+539
-79
lines changed

src/librustc/hir/intravisit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,9 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
436436
visitor.visit_ident(ident);
437437
}
438438
LifetimeName::Param(ParamName::Fresh(_)) |
439+
LifetimeName::Param(ParamName::Error) |
439440
LifetimeName::Static |
441+
LifetimeName::Error |
440442
LifetimeName::Implicit |
441443
LifetimeName::Underscore => {}
442444
}
@@ -747,7 +749,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
747749
walk_list!(visitor, visit_attribute, &param.attrs);
748750
match param.name {
749751
ParamName::Plain(ident) => visitor.visit_ident(ident),
750-
ParamName::Fresh(_) => {}
752+
ParamName::Error | ParamName::Fresh(_) => {}
751753
}
752754
match param.kind {
753755
GenericParamKind::Lifetime { .. } => {}

src/librustc/hir/lowering.rs

+84-22
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ enum AnonymousLifetimeMode {
316316
/// For **Deprecated** cases, report an error.
317317
CreateParameter,
318318

319+
/// Give a hard error when either `&` or `'_` is written. Used to
320+
/// rule out things like `where T: Foo<'_>`. Does not imply an
321+
/// error on default object bounds (e.g., `Box<dyn Foo>`).
322+
ReportError,
323+
319324
/// Pass responsibility to `resolve_lifetime` code for all cases.
320325
PassThrough,
321326
}
@@ -736,6 +741,10 @@ impl<'a> LoweringContext<'a> {
736741
keywords::UnderscoreLifetime.name().as_interned_str(),
737742
hir::LifetimeParamKind::Elided,
738743
),
744+
ParamName::Error => (
745+
keywords::UnderscoreLifetime.name().as_interned_str(),
746+
hir::LifetimeParamKind::Error,
747+
),
739748
};
740749

741750
// Add a definition for the in-band lifetime def
@@ -792,7 +801,7 @@ impl<'a> LoweringContext<'a> {
792801
}
793802

794803
/// When we have either an elided or `'_` lifetime in an impl
795-
/// header, we convert it to
804+
/// header, we convert it to an in-band lifetime.
796805
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
797806
assert!(self.is_collecting_in_band_lifetimes);
798807
let index = self.lifetimes_to_define.len();
@@ -1475,7 +1484,7 @@ impl<'a> LoweringContext<'a> {
14751484
}
14761485
}
14771486
hir::LifetimeName::Param(_) => lifetime.name,
1478-
hir::LifetimeName::Static => return,
1487+
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
14791488
};
14801489

14811490
if !self.currently_bound_lifetimes.contains(&name)
@@ -2163,7 +2172,7 @@ impl<'a> LoweringContext<'a> {
21632172
}
21642173
}
21652174
hir::LifetimeName::Param(_) => lifetime.name,
2166-
hir::LifetimeName::Static => return,
2175+
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
21672176
};
21682177

21692178
if !self.currently_bound_lifetimes.contains(&name) {
@@ -2294,17 +2303,15 @@ impl<'a> LoweringContext<'a> {
22942303
itctx: ImplTraitContext<'_>,
22952304
) -> hir::GenericBound {
22962305
match *tpb {
2297-
GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
2298-
self.lower_poly_trait_ref(ty, itctx),
2299-
self.lower_trait_bound_modifier(modifier),
2300-
),
2301-
GenericBound::Outlives(ref lifetime) => {
2302-
// We don't want to accept `'a: '_`:
2303-
self.with_anonymous_lifetime_mode(
2304-
AnonymousLifetimeMode::PassThrough,
2305-
|this| hir::GenericBound::Outlives(this.lower_lifetime(lifetime)),
2306+
GenericBound::Trait(ref ty, modifier) => {
2307+
hir::GenericBound::Trait(
2308+
self.lower_poly_trait_ref(ty, itctx),
2309+
self.lower_trait_bound_modifier(modifier),
23062310
)
23072311
}
2312+
GenericBound::Outlives(ref lifetime) => {
2313+
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
2314+
}
23082315
}
23092316
}
23102317

@@ -2323,6 +2330,8 @@ impl<'a> LoweringContext<'a> {
23232330
AnonymousLifetimeMode::PassThrough => {
23242331
self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
23252332
}
2333+
2334+
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
23262335
},
23272336
ident => {
23282337
self.maybe_collect_in_band_lifetime(ident);
@@ -2361,16 +2370,26 @@ impl<'a> LoweringContext<'a> {
23612370
add_bounds: &NodeMap<Vec<GenericBound>>,
23622371
mut itctx: ImplTraitContext<'_>)
23632372
-> hir::GenericParam {
2364-
let mut bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
2373+
let mut bounds = self.with_anonymous_lifetime_mode(
2374+
AnonymousLifetimeMode::ReportError,
2375+
|this| this.lower_param_bounds(&param.bounds, itctx.reborrow()),
2376+
);
2377+
23652378
match param.kind {
23662379
GenericParamKind::Lifetime => {
23672380
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
23682381
self.is_collecting_in_band_lifetimes = false;
23692382

2370-
let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
2383+
let lt = self.with_anonymous_lifetime_mode(
2384+
AnonymousLifetimeMode::ReportError,
2385+
|this| this.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }),
2386+
);
23712387
let param_name = match lt.name {
23722388
hir::LifetimeName::Param(param_name) => param_name,
2373-
_ => hir::ParamName::Plain(lt.name.ident()),
2389+
hir::LifetimeName::Implicit
2390+
| hir::LifetimeName::Underscore
2391+
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
2392+
hir::LifetimeName::Error => ParamName::Error,
23742393
};
23752394
let param = hir::GenericParam {
23762395
id: lt.id,
@@ -2494,13 +2513,18 @@ impl<'a> LoweringContext<'a> {
24942513
}
24952514

24962515
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
2497-
hir::WhereClause {
2498-
id: self.lower_node_id(wc.id).node_id,
2499-
predicates: wc.predicates
2500-
.iter()
2501-
.map(|predicate| self.lower_where_predicate(predicate))
2502-
.collect(),
2503-
}
2516+
self.with_anonymous_lifetime_mode(
2517+
AnonymousLifetimeMode::ReportError,
2518+
|this| {
2519+
hir::WhereClause {
2520+
id: this.lower_node_id(wc.id).node_id,
2521+
predicates: wc.predicates
2522+
.iter()
2523+
.map(|predicate| this.lower_where_predicate(predicate))
2524+
.collect(),
2525+
}
2526+
},
2527+
)
25042528
}
25052529

25062530
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
@@ -4843,10 +4867,38 @@ impl<'a> LoweringContext<'a> {
48434867
}
48444868
}
48454869

4870+
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
4871+
48464872
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
48474873
}
48484874
}
48494875

4876+
/// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
4877+
/// return a "error lifetime".
4878+
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
4879+
let (id, msg, label) = match id {
4880+
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
4881+
4882+
None => (
4883+
self.next_id().node_id,
4884+
"`&` without an explicit lifetime name cannot be used here",
4885+
"explicit lifetime name needed here",
4886+
),
4887+
};
4888+
4889+
let mut err = struct_span_err!(
4890+
self.sess,
4891+
span,
4892+
E0637,
4893+
"{}",
4894+
msg,
4895+
);
4896+
err.span_label(span, label);
4897+
err.emit();
4898+
4899+
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
4900+
}
4901+
48504902
/// Invoked to create the lifetime argument(s) for a path like
48514903
/// `std::cell::Ref<T>`; note that implicit lifetimes in these
48524904
/// sorts of cases are deprecated. This may therefore report a warning or an
@@ -4861,6 +4913,12 @@ impl<'a> LoweringContext<'a> {
48614913
// impl Foo for std::cell::Ref<u32> // note lack of '_
48624914
AnonymousLifetimeMode::CreateParameter => {}
48634915

4916+
AnonymousLifetimeMode::ReportError => {
4917+
return (0..count)
4918+
.map(|_| self.new_error_lifetime(None, span))
4919+
.collect();
4920+
}
4921+
48644922
// This is the normal case.
48654923
AnonymousLifetimeMode::PassThrough => {}
48664924
}
@@ -4891,6 +4949,10 @@ impl<'a> LoweringContext<'a> {
48914949
// `resolve_lifetime` has the code to make that happen.
48924950
AnonymousLifetimeMode::CreateParameter => {}
48934951

4952+
AnonymousLifetimeMode::ReportError => {
4953+
// ReportError applies to explicit use of `'_`.
4954+
}
4955+
48944956
// This is the normal case.
48954957
AnonymousLifetimeMode::PassThrough => {}
48964958
}

src/librustc/hir/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,18 @@ pub enum ParamName {
208208
/// where `'f` is something like `Fresh(0)`. The indices are
209209
/// unique per impl, but not necessarily continuous.
210210
Fresh(usize),
211+
212+
/// Indicates an illegal name was given and an error has been
213+
/// repored (so we should squelch other derived errors). Occurs
214+
/// when e.g. `'_` is used in the wrong place.
215+
Error,
211216
}
212217

213218
impl ParamName {
214219
pub fn ident(&self) -> Ident {
215220
match *self {
216221
ParamName::Plain(ident) => ident,
217-
ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
222+
ParamName::Error | ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(),
218223
}
219224
}
220225

@@ -234,6 +239,10 @@ pub enum LifetimeName {
234239
/// User typed nothing. e.g. the lifetime in `&u32`.
235240
Implicit,
236241

242+
/// Indicates an error during lowering (usually `'_` in wrong place)
243+
/// that was already reported.
244+
Error,
245+
237246
/// User typed `'_`.
238247
Underscore,
239248

@@ -245,6 +254,7 @@ impl LifetimeName {
245254
pub fn ident(&self) -> Ident {
246255
match *self {
247256
LifetimeName::Implicit => keywords::Invalid.ident(),
257+
LifetimeName::Error => keywords::Invalid.ident(),
248258
LifetimeName::Underscore => keywords::UnderscoreLifetime.ident(),
249259
LifetimeName::Static => keywords::StaticLifetime.ident(),
250260
LifetimeName::Param(param_name) => param_name.ident(),
@@ -260,7 +270,7 @@ impl LifetimeName {
260270
// in the compiler is concerned -- `Fresh(_)` variants act
261271
// equivalently to "some fresh name". They correspond to
262272
// early-bound regions on an impl, in other words.
263-
LifetimeName::Param(_) | LifetimeName::Static => false,
273+
LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
264274
}
265275
}
266276

@@ -513,6 +523,9 @@ pub enum LifetimeParamKind {
513523
// Indication that the lifetime was elided like both cases here:
514524
// `fn foo(x: &u8) -> &'_ u8 { x }`
515525
Elided,
526+
527+
// Indication that the lifetime name was somehow in error.
528+
Error,
516529
}
517530

518531
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

src/librustc/ich/impls_hir.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
144144

145145
impl_stable_hash_for!(enum hir::ParamName {
146146
Plain(name),
147-
Fresh(index)
147+
Fresh(index),
148+
Error,
148149
});
149150

150151
impl_stable_hash_for!(enum hir::LifetimeName {
151152
Param(param_name),
152153
Implicit,
153154
Underscore,
154155
Static,
156+
Error,
155157
});
156158

157159
impl_stable_hash_for!(struct hir::Label {
@@ -210,7 +212,8 @@ impl_stable_hash_for!(struct hir::GenericParam {
210212
impl_stable_hash_for!(enum hir::LifetimeParamKind {
211213
Explicit,
212214
InBand,
213-
Elided
215+
Elided,
216+
Error,
214217
});
215218

216219
impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {

src/librustc/ich/impls_ty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -755,8 +755,9 @@ for ::middle::resolve_lifetime::Set1<T>
755755
}
756756

757757
impl_stable_hash_for!(enum ::middle::resolve_lifetime::LifetimeDefOrigin {
758-
Explicit,
759-
InBand
758+
ExplicitOrElided,
759+
InBand,
760+
Error,
760761
});
761762

762763
impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {

0 commit comments

Comments
 (0)