Skip to content

Commit 08ed1a1

Browse files
committed
Bind undeclared lifetimes as erroneous bound vars
Undeclared lifetimes that appear in user code always give rise to an error (E0261) early in name resolution. This patch adds such undeclared lifetimes to the relevant context's bound vars, so that they resolve to regions with `RegionKind::Error(ErrorGuaranteed)`, in order to suppress some ensuing diagnostics (that might be resolved if the lifetime becomes properly declared).
1 parent 79a1e77 commit 08ed1a1

11 files changed

Lines changed: 81 additions & 43 deletions

File tree

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
880880

881881
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind))
882882
}
883-
LifetimeRes::Static { .. } | LifetimeRes::Error => return None,
883+
LifetimeRes::Static { .. } | LifetimeRes::Error { .. } => return None,
884884
res => panic!(
885885
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
886886
res, ident, ident.span
@@ -1933,7 +1933,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19331933
source: LifetimeSource,
19341934
syntax: LifetimeSyntax,
19351935
) -> &'hir hir::Lifetime {
1936-
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
1936+
let res =
1937+
self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error { undeclared: None });
19371938
let res = match res {
19381939
LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),
19391940
LifetimeRes::Fresh { param, .. } => {
@@ -1949,7 +1950,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19491950
assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
19501951
hir::LifetimeKind::Static
19511952
}
1952-
LifetimeRes::Error => hir::LifetimeKind::Error,
1953+
LifetimeRes::Error { undeclared } => hir::LifetimeKind::Error { undeclared },
19531954
LifetimeRes::ElidedAnchor { .. } => {
19541955
panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span);
19551956
}
@@ -2016,12 +2017,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20162017
// AST resolution emitted an error on those parameters, so we lower them using
20172018
// `ParamName::Error`.
20182019
let ident = self.lower_ident(param.ident);
2019-
let param_name =
2020-
if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) {
2021-
ParamName::Error(ident)
2022-
} else {
2023-
ParamName::Plain(ident)
2024-
};
2020+
let param_name = if let Some(LifetimeRes::Error { .. }) =
2021+
self.resolver.get_lifetime_res(param.id)
2022+
{
2023+
ParamName::Error(ident)
2024+
} else {
2025+
ParamName::Plain(ident)
2026+
};
20252027
let kind =
20262028
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
20272029

compiler/rustc_hir/src/def.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ pub enum LifetimeRes {
990990
/// `'static` lifetime.
991991
Static,
992992
/// Resolution failure.
993-
Error,
993+
Error { undeclared: Option<rustc_span::ErrorGuaranteed> },
994994
/// HACK: This is used to recover the NodeId of an elided lifetime.
995995
ElidedAnchor { start: NodeId, end: NodeId },
996996
}

compiler/rustc_hir/src/hir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub enum LifetimeKind {
237237

238238
/// Indicates an error during lowering (usually `'_` in wrong place)
239239
/// that was already reported.
240-
Error,
240+
Error { undeclared: Option<ErrorGuaranteed> },
241241

242242
/// User wrote an anonymous lifetime, either `'_` or nothing (which gets
243243
/// converted to `'_`). The semantics of this lifetime should be inferred
@@ -257,7 +257,7 @@ impl LifetimeKind {
257257
// -- but this is because, as far as the code in the compiler is
258258
// concerned -- `Fresh` variants act equivalently to "some fresh name".
259259
// They correspond to early-bound regions on an impl, in other words.
260-
LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false,
260+
LifetimeKind::Error { .. } | LifetimeKind::Param(..) | LifetimeKind::Static => false,
261261
}
262262
}
263263
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
663663
LifetimeKind::Param(def_id) => {
664664
self.resolve_lifetime_ref(def_id, lt);
665665
}
666-
LifetimeKind::Error => {}
666+
LifetimeKind::Error { .. } => {}
667667
LifetimeKind::ImplicitObjectLifetimeDefault
668668
| LifetimeKind::Infer
669669
| LifetimeKind::Static => {
@@ -804,7 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
804804
// If the user wrote an explicit name, use that.
805805
self.visit_lifetime(&*lifetime);
806806
}
807-
LifetimeKind::Error => {}
807+
LifetimeKind::Error { .. } => {}
808808
}
809809
}
810810
hir::TyKind::Ref(lifetime_ref, ref mt) => {
@@ -892,7 +892,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
892892
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
893893
}
894894
// If we've already reported an error, just ignore `lifetime_ref`.
895-
hir::LifetimeKind::Error => {}
895+
hir::LifetimeKind::Error { undeclared: None } => {}
896+
hir::LifetimeKind::Error { undeclared: Some(guar) } => {
897+
self.insert_lifetime(lifetime_ref, ResolvedArg::Error(guar))
898+
}
896899
// Those will be resolved by typechecking.
897900
hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {}
898901
}

compiler/rustc_resolve/src/late.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,7 +1785,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
17851785
self.emit_non_static_lt_in_const_param_ty_error(lifetime);
17861786
self.record_lifetime_res(
17871787
lifetime.id,
1788-
LifetimeRes::Error,
1788+
LifetimeRes::Error { undeclared: None },
17891789
LifetimeElisionCandidate::Ignore,
17901790
);
17911791
return;
@@ -1794,7 +1794,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
17941794
self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
17951795
self.record_lifetime_res(
17961796
lifetime.id,
1797-
LifetimeRes::Error,
1797+
LifetimeRes::Error { undeclared: None },
17981798
LifetimeElisionCandidate::Ignore,
17991799
);
18001800
return;
@@ -1812,8 +1812,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
18121812
let outer_res = lifetime_rib_iter
18131813
.find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer));
18141814

1815-
self.emit_undeclared_lifetime_error(lifetime, outer_res);
1816-
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
1815+
let guar = self.emit_undeclared_lifetime_error(lifetime, outer_res);
1816+
self.record_lifetime_res(
1817+
lifetime.id,
1818+
LifetimeRes::Error { undeclared: Some(guar) },
1819+
LifetimeElisionCandidate::Named,
1820+
);
18171821
}
18181822

18191823
#[instrument(level = "debug", skip(self))]
@@ -1953,7 +1957,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
19531957
span: lifetime.ident.span,
19541958
});
19551959
};
1956-
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1960+
self.record_lifetime_res(
1961+
lifetime.id,
1962+
LifetimeRes::Error { undeclared: None },
1963+
elision_candidate,
1964+
);
19571965
return;
19581966
}
19591967
LifetimeRibKind::Elided(res) => {
@@ -1962,7 +1970,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
19621970
}
19631971
LifetimeRibKind::ElisionFailure => {
19641972
self.diag_metadata.current_elision_failures.push(missing_lifetime);
1965-
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1973+
self.record_lifetime_res(
1974+
lifetime.id,
1975+
LifetimeRes::Error { undeclared: None },
1976+
elision_candidate,
1977+
);
19661978
return;
19671979
}
19681980
LifetimeRibKind::Item => break,
@@ -1973,7 +1985,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
19731985
}
19741986
}
19751987
}
1976-
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1988+
self.record_lifetime_res(
1989+
lifetime.id,
1990+
LifetimeRes::Error { undeclared: None },
1991+
elision_candidate,
1992+
);
19771993
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
19781994
}
19791995

@@ -2231,7 +2247,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22312247
for id in node_ids {
22322248
self.record_lifetime_res(
22332249
id,
2234-
LifetimeRes::Error,
2250+
LifetimeRes::Error { undeclared: None },
22352251
LifetimeElisionCandidate::Named,
22362252
);
22372253
}
@@ -2267,7 +2283,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22672283
for id in node_ids {
22682284
self.record_lifetime_res(
22692285
id,
2270-
LifetimeRes::Error,
2286+
LifetimeRes::Error { undeclared: None },
22712287
LifetimeElisionCandidate::Ignore,
22722288
);
22732289
}
@@ -2281,7 +2297,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22812297
for id in node_ids {
22822298
self.record_lifetime_res(
22832299
id,
2284-
LifetimeRes::Error,
2300+
LifetimeRes::Error { undeclared: None },
22852301
LifetimeElisionCandidate::Ignore,
22862302
);
22872303
}
@@ -2329,7 +2345,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
23292345
candidates.push((res, candidate));
23302346
}
23312347
}
2332-
LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
2348+
LifetimeRes::Infer | LifetimeRes::Error { .. } | LifetimeRes::ElidedAnchor { .. } => {}
23332349
}
23342350
}
23352351

@@ -3030,7 +3046,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
30303046
{
30313047
diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
30323048
// Record lifetime res, so lowering knows there is something fishy.
3033-
self.record_lifetime_param(param.id, LifetimeRes::Error);
3049+
self.record_lifetime_param(param.id, LifetimeRes::Error { undeclared: None });
30343050
continue;
30353051
}
30363052

@@ -3042,7 +3058,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
30423058
let rib = match param.kind {
30433059
GenericParamKind::Lifetime => {
30443060
// Record lifetime res, so lowering knows there is something fishy.
3045-
self.record_lifetime_param(param.id, LifetimeRes::Error);
3061+
self.record_lifetime_param(
3062+
param.id,
3063+
LifetimeRes::Error { undeclared: None },
3064+
);
30463065
continue;
30473066
}
30483067
GenericParamKind::Type { .. } => &mut function_type_rib,
@@ -3076,7 +3095,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
30763095
.create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
30773096
.emit_unless_delay(is_raw_underscore_lifetime);
30783097
// Record lifetime res, so lowering knows there is something fishy.
3079-
self.record_lifetime_param(param.id, LifetimeRes::Error);
3098+
self.record_lifetime_param(param.id, LifetimeRes::Error { undeclared: None });
30803099
continue;
30813100
}
30823101

@@ -3086,7 +3105,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
30863105
lifetime: param.ident,
30873106
});
30883107
// Record lifetime res, so lowering knows there is something fishy.
3089-
self.record_lifetime_param(param.id, LifetimeRes::Error);
3108+
self.record_lifetime_param(param.id, LifetimeRes::Error { undeclared: None });
30903109
continue;
30913110
}
30923111

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3274,7 +3274,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
32743274
&self,
32753275
lifetime_ref: &ast::Lifetime,
32763276
outer_lifetime_ref: Option<Ident>,
3277-
) {
3277+
) -> ErrorGuaranteed {
32783278
debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
32793279
let mut err = if let Some(outer) = outer_lifetime_ref {
32803280
struct_span_code_err!(
@@ -3319,7 +3319,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
33193319
);
33203320
}
33213321

3322-
err.emit();
3322+
err.emit()
33233323
}
33243324

33253325
fn suggest_introducing_lifetime(

tests/ui/cast/ice-cast-type-with-error-124848.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ fn main() {
1414
let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
1515
//~^ ERROR use of undeclared lifetime name `'a`
1616
//~| ERROR use of undeclared lifetime name `'a`
17-
//~| ERROR casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
1817
}

tests/ui/cast/ice-cast-type-with-error-124848.stderr

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,7 @@ help: provide the argument
5858
LL | let mut unpinned = MyType(Cell::new(None), /* value */);
5959
| +++++++++++++
6060

61-
error[E0606]: casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
62-
--> $DIR/ice-cast-type-with-error-124848.rs:14:20
63-
|
64-
LL | let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
65-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66-
67-
error: aborting due to 6 previous errors
61+
error: aborting due to 5 previous errors
6862

69-
Some errors have detailed explanations: E0061, E0261, E0425, E0606.
63+
Some errors have detailed explanations: E0061, E0261, E0425.
7064
For more information about an error, try `rustc --explain E0061`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! E0228 (lifetime bound for trait object cannot be deduced from context) should not be emitted
2+
//! when an undeclared lifetime bound has been specified.
3+
//!
4+
//! Regression test for https://github.com/rust-lang/rust/issues/152014
5+
6+
fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} //~ ERROR use of undeclared lifetime name `'undefined`
7+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0261]: use of undeclared lifetime name `'undefined`
2+
--> $DIR/undeclared-object-lifetime.rs:6:24
3+
|
4+
LL | fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}
5+
| ^^^^^^^^^^ undeclared lifetime
6+
|
7+
help: consider introducing lifetime `'undefined` here
8+
|
9+
LL | fn f<'undefined>(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}
10+
| ++++++++++++
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0261`.

0 commit comments

Comments
 (0)