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 #33652.
This commit is contained in:
parent
4d5b3b1962
commit
f5bae722be
@ -747,7 +747,7 @@ fn region_known_to_outlive<'tcx>(
|
||||
region_b: ty::Region<'tcx>,
|
||||
) -> bool {
|
||||
test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
|
||||
infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a);
|
||||
infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
|
||||
}
|
||||
|
||||
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
|
||||
self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), sub, sup)
|
||||
self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup)
|
||||
}
|
||||
|
||||
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
|
||||
|
@ -390,7 +390,7 @@ pub enum SubregionOrigin<'tcx> {
|
||||
|
||||
/// The given region parameter was instantiated with a region
|
||||
/// that must outlive some other region.
|
||||
RelateRegionParamBound(Span),
|
||||
RelateRegionParamBound(Span, Option<Ty<'tcx>>),
|
||||
|
||||
/// Creating a pointer `b` to contents of another reference.
|
||||
Reborrow(Span),
|
||||
@ -859,7 +859,7 @@ pub fn region_outlives_predicate(
|
||||
) {
|
||||
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
|
||||
let origin = SubregionOrigin::from_obligation_cause(cause, || {
|
||||
RelateRegionParamBound(cause.span)
|
||||
RelateRegionParamBound(cause.span, None)
|
||||
});
|
||||
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
|
||||
})
|
||||
@ -1685,7 +1685,7 @@ pub fn span(&self) -> Span {
|
||||
Subtype(ref a) => a.span(),
|
||||
RelateObjectBound(a) => a,
|
||||
RelateParamBound(a, ..) => a,
|
||||
RelateRegionParamBound(a) => a,
|
||||
RelateRegionParamBound(a, _) => a,
|
||||
Reborrow(a) => a,
|
||||
ReferenceOutlivesReferent(_, a) => a,
|
||||
CompareImplItemObligation { span, .. } => span,
|
||||
@ -1726,6 +1726,10 @@ pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default:
|
||||
SubregionOrigin::AscribeUserTypeProvePredicate(span)
|
||||
}
|
||||
|
||||
traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => {
|
||||
SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty))
|
||||
}
|
||||
|
||||
_ => default(),
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||
pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> {
|
||||
match &self.error {
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::RelateRegionParamBound(span),
|
||||
SubregionOrigin::RelateRegionParamBound(span, _),
|
||||
Region(Interned(
|
||||
RePlaceholder(ty::Placeholder {
|
||||
bound: ty::BoundRegion { kind: sub_name, .. },
|
||||
|
@ -52,7 +52,7 @@ pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOr
|
||||
.add_to_diag(err);
|
||||
}
|
||||
}
|
||||
infer::RelateRegionParamBound(span) => {
|
||||
infer::RelateRegionParamBound(span, _) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
|
||||
.add_to_diag(err);
|
||||
}
|
||||
@ -199,7 +199,7 @@ pub(super) fn report_concrete_failure(
|
||||
note,
|
||||
})
|
||||
}
|
||||
infer::RelateRegionParamBound(span) => {
|
||||
infer::RelateRegionParamBound(span, _) => {
|
||||
let param_instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
|
@ -257,7 +257,7 @@ pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOr
|
||||
.add_to_diag(err);
|
||||
}
|
||||
}
|
||||
infer::RelateRegionParamBound(span) => {
|
||||
infer::RelateRegionParamBound(span, _) => {
|
||||
RegionOriginNote::Plain {
|
||||
span,
|
||||
msg: fluent::trait_selection_relate_region_param_bound,
|
||||
@ -410,7 +410,7 @@ pub(super) fn report_concrete_failure(
|
||||
note,
|
||||
})
|
||||
}
|
||||
infer::RelateRegionParamBound(span) => {
|
||||
infer::RelateRegionParamBound(span, ty) => {
|
||||
let param_instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
@ -419,11 +419,31 @@ pub(super) fn report_concrete_failure(
|
||||
note_and_explain::PrefixKind::LfParamInstantiatedWith,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
let mut alt_span = None;
|
||||
if let Some(ty) = ty
|
||||
&& sub.is_static()
|
||||
&& let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind()
|
||||
&& let Some(def_id) = preds.principal_def_id()
|
||||
{
|
||||
for (clause, span) in
|
||||
self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
|
||||
{
|
||||
if let ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) =
|
||||
clause.kind().skip_binder()
|
||||
&& let ty::Param(param) = a.kind()
|
||||
&& param.name == kw::SelfUpper
|
||||
&& b.is_static()
|
||||
{
|
||||
// Point at explicit `'static` bound on the trait (`trait T: 'static`).
|
||||
alt_span = Some(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
let param_must_outlive = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
alt_span,
|
||||
note_and_explain::PrefixKind::LfParamMustOutlive,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
|
13
tests/ui/regions/explicit-static-bound-on-trait.rs
Normal file
13
tests/ui/regions/explicit-static-bound-on-trait.rs
Normal file
@ -0,0 +1,13 @@
|
||||
struct Hello<'a> {
|
||||
value: Box<dyn std::any::Any + 'a>,
|
||||
//~^ ERROR lifetime bound not satisfied
|
||||
}
|
||||
|
||||
impl<'a> Hello<'a> {
|
||||
fn new<T: 'a>(value: T) -> Self {
|
||||
Self { value: Box::new(value) }
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
32
tests/ui/regions/explicit-static-bound-on-trait.stderr
Normal file
32
tests/ui/regions/explicit-static-bound-on-trait.stderr
Normal file
@ -0,0 +1,32 @@
|
||||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/explicit-static-bound-on-trait.rs:2:12
|
||||
|
|
||||
LL | value: Box<dyn std::any::Any + 'a>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||
--> $DIR/explicit-static-bound-on-trait.rs:1:14
|
||||
|
|
||||
LL | struct Hello<'a> {
|
||||
| ^^
|
||||
note: but lifetime parameter must outlive the static lifetime
|
||||
--> $SRC_DIR/core/src/any.rs:LL:COL
|
||||
|
||||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/explicit-static-bound-on-trait.rs:8:23
|
||||
|
|
||||
LL | Self { value: Box::new(value) }
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the parameter type `T` must be valid for the static lifetime...
|
||||
| ...so that the type `T` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | fn new<T: 'a + 'static>(value: T) -> Self {
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0310, E0478.
|
||||
For more information about an error, try `rustc --explain E0310`.
|
Loading…
Reference in New Issue
Block a user