Skip to content

Commit f5bae72

Browse files
committed
Point at explicit 'static obligations on a trait
Given `trait Any: 'static` and a `struct` with a `Box<dyn Any + 'a>` field, point at the `'static` bound in `Any` to explain why `'a: 'static`. ``` error[E0478]: lifetime bound not satisfied --> f202.rs:2:12 | 2 | value: Box<dyn std::any::Any + 'a>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> f202.rs:1:14 | 1 | struct Hello<'a> { | ^^ note: but lifetime parameter must outlive the static lifetime --> /home/gh-estebank/rust/library/core/src/any.rs:113:16 | 113 | pub trait Any: 'static { | ^^^^^^^ ``` Partially address rust-lang#33652.
1 parent 4d5b3b1 commit f5bae72

File tree

8 files changed

+80
-11
lines changed

8 files changed

+80
-11
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ fn region_known_to_outlive<'tcx>(
747747
region_b: ty::Region<'tcx>,
748748
) -> bool {
749749
test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
750-
infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a);
750+
infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a);
751751
})
752752
}
753753

compiler/rustc_infer/src/infer/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
167167
}
168168

169169
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
170-
self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), sub, sup)
170+
self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup)
171171
}
172172

173173
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {

compiler/rustc_infer/src/infer/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ pub enum SubregionOrigin<'tcx> {
390390

391391
/// The given region parameter was instantiated with a region
392392
/// that must outlive some other region.
393-
RelateRegionParamBound(Span),
393+
RelateRegionParamBound(Span, Option<Ty<'tcx>>),
394394

395395
/// Creating a pointer `b` to contents of another reference.
396396
Reborrow(Span),
@@ -859,7 +859,7 @@ impl<'tcx> InferCtxt<'tcx> {
859859
) {
860860
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
861861
let origin = SubregionOrigin::from_obligation_cause(cause, || {
862-
RelateRegionParamBound(cause.span)
862+
RelateRegionParamBound(cause.span, None)
863863
});
864864
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
865865
})
@@ -1685,7 +1685,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
16851685
Subtype(ref a) => a.span(),
16861686
RelateObjectBound(a) => a,
16871687
RelateParamBound(a, ..) => a,
1688-
RelateRegionParamBound(a) => a,
1688+
RelateRegionParamBound(a, _) => a,
16891689
Reborrow(a) => a,
16901690
ReferenceOutlivesReferent(_, a) => a,
16911691
CompareImplItemObligation { span, .. } => span,
@@ -1726,6 +1726,10 @@ impl<'tcx> SubregionOrigin<'tcx> {
17261726
SubregionOrigin::AscribeUserTypeProvePredicate(span)
17271727
}
17281728

1729+
traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => {
1730+
SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty))
1731+
}
1732+
17291733
_ => default(),
17301734
}
17311735
}

compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
1111
pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> {
1212
match &self.error {
1313
Some(RegionResolutionError::ConcreteFailure(
14-
SubregionOrigin::RelateRegionParamBound(span),
14+
SubregionOrigin::RelateRegionParamBound(span, _),
1515
Region(Interned(
1616
RePlaceholder(ty::Placeholder {
1717
bound: ty::BoundRegion { kind: sub_name, .. },

compiler/rustc_trait_selection/src/error_reporting/infer/note.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
5252
.add_to_diag(err);
5353
}
5454
}
55-
infer::RelateRegionParamBound(span) => {
55+
infer::RelateRegionParamBound(span, _) => {
5656
RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
5757
.add_to_diag(err);
5858
}
@@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
199199
note,
200200
})
201201
}
202-
infer::RelateRegionParamBound(span) => {
202+
infer::RelateRegionParamBound(span, _) => {
203203
let param_instantiated = note_and_explain::RegionExplanation::new(
204204
self.tcx,
205205
generic_param_scope,

compiler/rustc_trait_selection/src/error_reporting/infer/region.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
257257
.add_to_diag(err);
258258
}
259259
}
260-
infer::RelateRegionParamBound(span) => {
260+
infer::RelateRegionParamBound(span, _) => {
261261
RegionOriginNote::Plain {
262262
span,
263263
msg: fluent::trait_selection_relate_region_param_bound,
@@ -410,7 +410,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
410410
note,
411411
})
412412
}
413-
infer::RelateRegionParamBound(span) => {
413+
infer::RelateRegionParamBound(span, ty) => {
414414
let param_instantiated = note_and_explain::RegionExplanation::new(
415415
self.tcx,
416416
generic_param_scope,
@@ -419,11 +419,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
419419
note_and_explain::PrefixKind::LfParamInstantiatedWith,
420420
note_and_explain::SuffixKind::Empty,
421421
);
422+
let mut alt_span = None;
423+
if let Some(ty) = ty
424+
&& sub.is_static()
425+
&& let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind()
426+
&& let Some(def_id) = preds.principal_def_id()
427+
{
428+
for (clause, span) in
429+
self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
430+
{
431+
if let ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) =
432+
clause.kind().skip_binder()
433+
&& let ty::Param(param) = a.kind()
434+
&& param.name == kw::SelfUpper
435+
&& b.is_static()
436+
{
437+
// Point at explicit `'static` bound on the trait (`trait T: 'static`).
438+
alt_span = Some(span);
439+
}
440+
}
441+
}
422442
let param_must_outlive = note_and_explain::RegionExplanation::new(
423443
self.tcx,
424444
generic_param_scope,
425445
sub,
426-
None,
446+
alt_span,
427447
note_and_explain::PrefixKind::LfParamMustOutlive,
428448
note_and_explain::SuffixKind::Empty,
429449
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct Hello<'a> {
2+
value: Box<dyn std::any::Any + 'a>,
3+
//~^ ERROR lifetime bound not satisfied
4+
}
5+
6+
impl<'a> Hello<'a> {
7+
fn new<T: 'a>(value: T) -> Self {
8+
Self { value: Box::new(value) }
9+
//~^ ERROR the parameter type `T` may not live long enough
10+
}
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0478]: lifetime bound not satisfied
2+
--> $DIR/explicit-static-bound-on-trait.rs:2:12
3+
|
4+
LL | value: Box<dyn std::any::Any + 'a>,
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: lifetime parameter instantiated with the lifetime `'a` as defined here
8+
--> $DIR/explicit-static-bound-on-trait.rs:1:14
9+
|
10+
LL | struct Hello<'a> {
11+
| ^^
12+
note: but lifetime parameter must outlive the static lifetime
13+
--> $SRC_DIR/core/src/any.rs:LL:COL
14+
15+
error[E0310]: the parameter type `T` may not live long enough
16+
--> $DIR/explicit-static-bound-on-trait.rs:8:23
17+
|
18+
LL | Self { value: Box::new(value) }
19+
| ^^^^^^^^^^^^^^^
20+
| |
21+
| the parameter type `T` must be valid for the static lifetime...
22+
| ...so that the type `T` will meet its required lifetime bounds
23+
|
24+
help: consider adding an explicit lifetime bound
25+
|
26+
LL | fn new<T: 'a + 'static>(value: T) -> Self {
27+
| +++++++++
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors have detailed explanations: E0310, E0478.
32+
For more information about an error, try `rustc --explain E0310`.

0 commit comments

Comments
 (0)