Skip to content

Commit 7bba5c1

Browse files
authored
Rollup merge of #89734 - estebank:issue-72312, r=nikomatsakis
Point at capture points for non-`'static` reference crossing a `yield` point ``` error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-72312.rs:10:24 | LL | pub async fn start(&self) { | ^^^^^ this data with an anonymous lifetime `'_`... ... LL | require_static(async move { | -------------- ...is required to live as long as `'static` here... LL | &self; | ----- ...and is captured here | note: `'static` lifetime requirement introduced by this trait bound --> $DIR/issue-72312.rs:2:22 | LL | fn require_static<T: 'static>(val: T) -> T { | ^^^^^^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0759`. ``` Fix #72312.
2 parents 433a13b + d2d9eb3 commit 7bba5c1

File tree

37 files changed

+466
-133
lines changed

37 files changed

+466
-133
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
368368
error_region,
369369
cause.clone(),
370370
placeholder_region,
371+
vec![],
371372
),
372373
),
373374
(Some(error_region), _) => NiceRegionError::new(

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
384384
sub_r,
385385
sup_origin,
386386
sup_r,
387+
_,
387388
) => {
388389
if sub_r.is_placeholder() {
389390
self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
@@ -464,7 +465,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
464465
errors.sort_by_key(|u| match *u {
465466
RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
466467
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
467-
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
468+
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
468469
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
469470
});
470471
errors

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
6767
pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
6868
match (&self.error, self.regions) {
6969
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)),
70-
(Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => {
70+
(Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
7171
Some((origin.span(), sub, sup))
7272
}
7373
(None, Some((span, sub, sup))) => Some((span, sub, sup)),

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl NiceRegionError<'me, 'tcx> {
3434
sub_placeholder @ ty::RePlaceholder(_),
3535
_,
3636
sup_placeholder @ ty::RePlaceholder(_),
37+
_,
3738
)) => self.try_report_trait_placeholder_mismatch(
3839
Some(self.tcx().mk_region(ty::ReVar(*vid))),
3940
cause,
@@ -49,6 +50,7 @@ impl NiceRegionError<'me, 'tcx> {
4950
sub_placeholder @ ty::RePlaceholder(_),
5051
_,
5152
_,
53+
_,
5254
)) => self.try_report_trait_placeholder_mismatch(
5355
Some(self.tcx().mk_region(ty::ReVar(*vid))),
5456
cause,
@@ -64,6 +66,7 @@ impl NiceRegionError<'me, 'tcx> {
6466
_,
6567
_,
6668
sup_placeholder @ ty::RePlaceholder(_),
69+
_,
6770
)) => self.try_report_trait_placeholder_mismatch(
6871
Some(self.tcx().mk_region(ty::ReVar(*vid))),
6972
cause,
@@ -79,6 +82,7 @@ impl NiceRegionError<'me, 'tcx> {
7982
_,
8083
SubregionOrigin::Subtype(box TypeTrace { cause, values }),
8184
sup_placeholder @ ty::RePlaceholder(_),
85+
_,
8286
)) => self.try_report_trait_placeholder_mismatch(
8387
Some(self.tcx().mk_region(ty::ReVar(*vid))),
8488
cause,

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs

+93-46
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
1010
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
1111
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
1212
use rustc_middle::ty::{
13-
self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
13+
self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable,
14+
TypeVisitor,
1415
};
1516
use rustc_span::symbol::Ident;
1617
use rustc_span::{MultiSpan, Span};
@@ -23,16 +24,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
2324
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
2425
debug!("try_report_static_impl_trait(error={:?})", self.error);
2526
let tcx = self.tcx();
26-
let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
27+
let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
2728
RegionResolutionError::SubSupConflict(
2829
_,
2930
var_origin,
3031
sub_origin,
3132
sub_r,
3233
sup_origin,
3334
sup_r,
35+
spans,
3436
) if **sub_r == RegionKind::ReStatic => {
35-
(var_origin, sub_origin, sub_r, sup_origin, sup_r)
37+
(var_origin, sub_origin, sub_r, sup_origin, sup_r, spans)
3638
}
3739
RegionResolutionError::ConcreteFailure(
3840
SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
@@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
7476
err.span_label(
7577
cause.span,
7678
&format!(
77-
"...is captured and required to live as long as `'static` here \
79+
"...is used and required to live as long as `'static` here \
7880
because of an implicit lifetime bound on the {}",
7981
match ctxt.assoc_item.container {
8082
AssocItemContainer::TraitContainer(id) =>
@@ -123,56 +125,101 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
123125
param_name,
124126
lifetime,
125127
);
126-
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
127-
debug!("try_report_static_impl_trait: param_info={:?}", param);
128128

129-
// We try to make the output have fewer overlapping spans if possible.
130-
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
131-
&& sup_origin.span() != return_sp
132-
{
133-
// FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
134-
135-
// Customize the spans and labels depending on their relative order so
136-
// that split sentences flow correctly.
137-
if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
138-
// Avoid the following:
139-
//
140-
// error: cannot infer an appropriate lifetime
141-
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
142-
// |
143-
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
144-
// | ---- ---------^-
129+
let (mention_influencer, influencer_point) =
130+
if sup_origin.span().overlaps(param.param_ty_span) {
131+
// Account for `async fn` like in `async-await/issues/issue-62097.rs`.
132+
// The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same
133+
// place (but with different `ctxt`, hence `overlaps` instead of `==` above).
145134
//
146-
// and instead show:
135+
// This avoids the following:
147136
//
148-
// error: cannot infer an appropriate lifetime
149-
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
150-
// |
151-
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
152-
// | ---- ^
153-
err.span_label(
154-
sup_origin.span(),
155-
"...is captured here, requiring it to live as long as `'static`",
156-
);
137+
// LL | pub async fn run_dummy_fn(&self) {
138+
// | ^^^^^
139+
// | |
140+
// | this data with an anonymous lifetime `'_`...
141+
// | ...is captured here...
142+
(false, sup_origin.span())
157143
} else {
158-
err.span_label(sup_origin.span(), "...is captured here...");
159-
if return_sp < sup_origin.span() {
160-
err.span_note(
161-
return_sp,
162-
"...and is required to live as long as `'static` here",
144+
(!sup_origin.span().overlaps(return_sp), param.param_ty_span)
145+
};
146+
err.span_label(influencer_point, &format!("this data with {}...", lifetime));
147+
148+
debug!("try_report_static_impl_trait: param_info={:?}", param);
149+
150+
let mut spans = spans.clone();
151+
152+
if mention_influencer {
153+
spans.push(sup_origin.span());
154+
}
155+
// We dedup the spans *ignoring* expansion context.
156+
spans.sort();
157+
spans.dedup_by_key(|span| (span.lo(), span.hi()));
158+
159+
// We try to make the output have fewer overlapping spans if possible.
160+
let require_msg = if spans.is_empty() {
161+
"...is used and required to live as long as `'static` here"
162+
} else {
163+
"...and is required to live as long as `'static` here"
164+
};
165+
let require_span =
166+
if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
167+
168+
for span in &spans {
169+
err.span_label(*span, "...is used here...");
170+
}
171+
172+
if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) {
173+
// If any of the "captured here" labels appears on the same line or after
174+
// `require_span`, we put it on a note to ensure the text flows by appearing
175+
// always at the end.
176+
err.span_note(require_span, require_msg);
177+
} else {
178+
// We don't need a note, it's already at the end, it can be shown as a `span_label`.
179+
err.span_label(require_span, require_msg);
180+
}
181+
182+
if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
183+
err.span_note(*bound, "`'static` lifetime requirement introduced by this bound");
184+
}
185+
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
186+
if let ObligationCauseCode::ReturnValue(hir_id)
187+
| ObligationCauseCode::BlockTailExpression(hir_id) = &cause.code
188+
{
189+
let parent_id = tcx.hir().get_parent_item(*hir_id);
190+
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
191+
let mut span: MultiSpan = fn_decl.output.span().into();
192+
let mut add_label = true;
193+
if let hir::FnRetTy::Return(ty) = fn_decl.output {
194+
let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
195+
v.visit_ty(ty);
196+
if !v.0.is_empty() {
197+
span = v.0.clone().into();
198+
for sp in v.0 {
199+
span.push_span_label(
200+
sp,
201+
"`'static` requirement introduced here".to_string(),
202+
);
203+
}
204+
add_label = false;
205+
}
206+
}
207+
if add_label {
208+
span.push_span_label(
209+
fn_decl.output.span(),
210+
"requirement introduced by this return type".to_string(),
211+
);
212+
}
213+
span.push_span_label(
214+
cause.span,
215+
"because of this returned expression".to_string(),
163216
);
164-
} else {
165-
err.span_label(
166-
return_sp,
167-
"...and is required to live as long as `'static` here",
217+
err.span_note(
218+
span,
219+
"`'static` lifetime requirement introduced by the return type",
168220
);
169221
}
170222
}
171-
} else {
172-
err.span_label(
173-
return_sp,
174-
"...is captured and required to live as long as `'static` here",
175-
);
176223
}
177224

178225
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
2828
_sub,
2929
sup_origin,
3030
_sup,
31+
_,
3132
) = error.clone()
3233
{
3334
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
1919
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
2020
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
2121
use rustc_middle::ty::{Region, RegionVid};
22+
use rustc_span::Span;
2223
use std::fmt;
2324

2425
/// This function performs lexical region resolution given a complete
@@ -96,6 +97,7 @@ pub enum RegionResolutionError<'tcx> {
9697
Region<'tcx>,
9798
SubregionOrigin<'tcx>,
9899
Region<'tcx>,
100+
Vec<Span>, // All the influences on a given value that didn't meet its constraints.
99101
),
100102

101103
/// Indicates a `'b: 'a` constraint where `'a` is in a universe that
@@ -567,7 +569,30 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
567569
// if this rule starts to create problems we'll
568570
// have to revisit this portion of the code and
569571
// think hard about it. =) -- nikomatsakis
570-
self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
572+
573+
// Obtain the spans for all the places that can
574+
// influence the constraints on this value for
575+
// richer diagnostics in `static_impl_trait`.
576+
let influences: Vec<Span> = self
577+
.data
578+
.constraints
579+
.iter()
580+
.filter_map(|(constraint, origin)| match (constraint, origin) {
581+
(
582+
Constraint::VarSubVar(_, sup),
583+
SubregionOrigin::DataBorrowed(_, sp),
584+
) if sup == &node_vid => Some(*sp),
585+
_ => None,
586+
})
587+
.collect();
588+
589+
self.collect_error_for_expanding_node(
590+
graph,
591+
&mut dup_vec,
592+
node_vid,
593+
errors,
594+
influences,
595+
);
571596
}
572597
}
573598
}
@@ -621,6 +646,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
621646
dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
622647
node_idx: RegionVid,
623648
errors: &mut Vec<RegionResolutionError<'tcx>>,
649+
influences: Vec<Span>,
624650
) {
625651
// Errors in expanding nodes result from a lower-bound that is
626652
// not contained by an upper-bound.
@@ -667,13 +693,15 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
667693
sup: {:?}",
668694
origin, node_idx, lower_bound.region, upper_bound.region
669695
);
696+
670697
errors.push(RegionResolutionError::SubSupConflict(
671698
node_idx,
672699
origin,
673700
lower_bound.origin.clone(),
674701
lower_bound.region,
675702
upper_bound.origin.clone(),
676703
upper_bound.region,
704+
influences,
677705
));
678706
return;
679707
}

compiler/rustc_middle/src/ty/context.rs

+2-34
Original file line numberDiff line numberDiff line change
@@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> {
14811481
scope_def_id: LocalDefId,
14821482
) -> Vec<&'tcx hir::Ty<'tcx>> {
14831483
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
1484-
let hir_output = match self.hir().get(hir_id) {
1485-
Node::Item(hir::Item {
1486-
kind:
1487-
ItemKind::Fn(
1488-
hir::FnSig {
1489-
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
1490-
..
1491-
},
1492-
..,
1493-
),
1494-
..
1495-
})
1496-
| Node::ImplItem(hir::ImplItem {
1497-
kind:
1498-
hir::ImplItemKind::Fn(
1499-
hir::FnSig {
1500-
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
1501-
..
1502-
},
1503-
_,
1504-
),
1505-
..
1506-
})
1507-
| Node::TraitItem(hir::TraitItem {
1508-
kind:
1509-
hir::TraitItemKind::Fn(
1510-
hir::FnSig {
1511-
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
1512-
..
1513-
},
1514-
_,
1515-
),
1516-
..
1517-
}) => ty,
1484+
let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
1485+
Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
15181486
_ => return vec![],
15191487
};
15201488

0 commit comments

Comments
 (0)