Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8a12be7

Browse files
committedSep 27, 2021
Auto merge of #89249 - Aaron1011:higher-ranked-cause, r=estebank
Improve cause information for NLL higher-ranked errors This PR has several interconnected pieces: 1. In some of the NLL region error code, we now pass around an `ObligationCause`, instead of just a plain `Span`. This gets forwarded into `fulfill_cx.register_predicate_obligation` during error reporting. 2. The general InferCtxt error reporting code is extended to handle `ObligationCauseCode::BindingObligation` 3. A new enum variant `ConstraintCategory::Predicate` is added. We try to avoid using this as the 'best blame constraint' - instead, we use it to enhance the `ObligationCause` of the `BlameConstraint` that we do end up choosing. As a result, several NLL error messages now contain the same "the lifetime requirement is introduced here" message as non-NLL errors. Having an `ObligationCause` available will likely prove useful for future improvements to NLL error messages.
2 parents 98c8619 + 41ad383 commit 8a12be7

File tree

16 files changed

+209
-86
lines changed

16 files changed

+209
-86
lines changed
 

‎compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
99
use rustc_span::Span;
1010
use rustc_trait_selection::traits::query::type_op;
1111
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
12-
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span};
12+
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
1313

1414
use std::fmt;
1515
use std::rc::Rc;
@@ -45,21 +45,20 @@ impl UniverseInfo<'tcx> {
4545
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
4646
placeholder: ty::PlaceholderRegion,
4747
error_element: RegionElement,
48-
span: Span,
48+
cause: ObligationCause<'tcx>,
4949
) {
5050
match self.0 {
5151
UniverseInfoInner::RelateTys { expected, found } => {
52-
let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id());
5352
let err = mbcx.infcx.report_mismatched_types(
54-
&ObligationCause::misc(span, body_id),
53+
&cause,
5554
expected,
5655
found,
5756
TypeError::RegionsPlaceholderMismatch,
5857
);
5958
err.buffer(&mut mbcx.errors_buffer);
6059
}
6160
UniverseInfoInner::TypeOp(ref type_op_info) => {
62-
type_op_info.report_error(mbcx, placeholder, error_element, span);
61+
type_op_info.report_error(mbcx, placeholder, error_element, cause);
6362
}
6463
UniverseInfoInner::Other => {
6564
// FIXME: This error message isn't great, but it doesn't show
@@ -68,7 +67,7 @@ impl UniverseInfo<'tcx> {
6867
mbcx.infcx
6968
.tcx
7069
.sess
71-
.struct_span_err(span, "higher-ranked subtype error")
70+
.struct_span_err(cause.span, "higher-ranked subtype error")
7271
.buffer(&mut mbcx.errors_buffer);
7372
}
7473
}
@@ -130,7 +129,7 @@ trait TypeOpInfo<'tcx> {
130129
fn nice_error(
131130
&self,
132131
tcx: TyCtxt<'tcx>,
133-
span: Span,
132+
cause: ObligationCause<'tcx>,
134133
placeholder_region: ty::Region<'tcx>,
135134
error_region: Option<ty::Region<'tcx>>,
136135
) -> Option<DiagnosticBuilder<'tcx>>;
@@ -140,7 +139,7 @@ trait TypeOpInfo<'tcx> {
140139
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
141140
placeholder: ty::PlaceholderRegion,
142141
error_element: RegionElement,
143-
span: Span,
142+
cause: ObligationCause<'tcx>,
144143
) {
145144
let tcx = mbcx.infcx.tcx;
146145
let base_universe = self.base_universe();
@@ -150,7 +149,7 @@ trait TypeOpInfo<'tcx> {
150149
{
151150
adjusted
152151
} else {
153-
self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
152+
self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer);
154153
return;
155154
};
156155

@@ -175,7 +174,8 @@ trait TypeOpInfo<'tcx> {
175174

176175
debug!(?placeholder_region);
177176

178-
let nice_error = self.nice_error(tcx, span, placeholder_region, error_region);
177+
let span = cause.span;
178+
let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
179179

180180
if let Some(nice_error) = nice_error {
181181
nice_error.buffer(&mut mbcx.errors_buffer);
@@ -205,15 +205,24 @@ impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
205205
fn nice_error(
206206
&self,
207207
tcx: TyCtxt<'tcx>,
208-
span: Span,
208+
cause: ObligationCause<'tcx>,
209209
placeholder_region: ty::Region<'tcx>,
210210
error_region: Option<ty::Region<'tcx>>,
211211
) -> Option<DiagnosticBuilder<'tcx>> {
212-
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
213-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
214-
type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span));
215-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
216-
})
212+
tcx.infer_ctxt().enter_with_canonical(
213+
cause.span,
214+
&self.canonical_query,
215+
|ref infcx, key, _| {
216+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
217+
type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
218+
try_extract_error_from_fulfill_cx(
219+
fulfill_cx,
220+
infcx,
221+
placeholder_region,
222+
error_region,
223+
)
224+
},
225+
)
217226
}
218227
}
219228

@@ -239,32 +248,41 @@ where
239248
fn nice_error(
240249
&self,
241250
tcx: TyCtxt<'tcx>,
242-
span: Span,
251+
cause: ObligationCause<'tcx>,
243252
placeholder_region: ty::Region<'tcx>,
244253
error_region: Option<ty::Region<'tcx>>,
245254
) -> Option<DiagnosticBuilder<'tcx>> {
246-
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
247-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
248-
249-
let mut selcx = SelectionContext::new(infcx);
250-
251-
// FIXME(lqd): Unify and de-duplicate the following with the actual
252-
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
253-
// `ObligationCause`. The normalization results are currently different between
254-
// `AtExt::normalize` used in the query and `normalize` called below: the former fails
255-
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
256-
// after #85499 lands to see if its fixes have erased this difference.
257-
let (param_env, value) = key.into_parts();
258-
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
259-
&mut selcx,
260-
param_env,
261-
ObligationCause::dummy_with_span(span),
262-
value.value,
263-
);
264-
fulfill_cx.register_predicate_obligations(infcx, obligations);
265-
266-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
267-
})
255+
tcx.infer_ctxt().enter_with_canonical(
256+
cause.span,
257+
&self.canonical_query,
258+
|ref infcx, key, _| {
259+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
260+
261+
let mut selcx = SelectionContext::new(infcx);
262+
263+
// FIXME(lqd): Unify and de-duplicate the following with the actual
264+
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
265+
// `ObligationCause`. The normalization results are currently different between
266+
// `AtExt::normalize` used in the query and `normalize` called below: the former fails
267+
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
268+
// after #85499 lands to see if its fixes have erased this difference.
269+
let (param_env, value) = key.into_parts();
270+
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
271+
&mut selcx,
272+
param_env,
273+
cause,
274+
value.value,
275+
);
276+
fulfill_cx.register_predicate_obligations(infcx, obligations);
277+
278+
try_extract_error_from_fulfill_cx(
279+
fulfill_cx,
280+
infcx,
281+
placeholder_region,
282+
error_region,
283+
)
284+
},
285+
)
268286
}
269287
}
270288

@@ -287,15 +305,25 @@ impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
287305
fn nice_error(
288306
&self,
289307
tcx: TyCtxt<'tcx>,
290-
span: Span,
308+
cause: ObligationCause<'tcx>,
291309
placeholder_region: ty::Region<'tcx>,
292310
error_region: Option<ty::Region<'tcx>>,
293311
) -> Option<DiagnosticBuilder<'tcx>> {
294-
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
295-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
296-
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(span)).ok()?;
297-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
298-
})
312+
tcx.infer_ctxt().enter_with_canonical(
313+
cause.span,
314+
&self.canonical_query,
315+
|ref infcx, key, _| {
316+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
317+
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
318+
.ok()?;
319+
try_extract_error_from_fulfill_cx(
320+
fulfill_cx,
321+
infcx,
322+
placeholder_region,
323+
error_region,
324+
)
325+
},
326+
)
299327
}
300328
}
301329

‎compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
300300
borrow_region: RegionVid,
301301
outlived_region: RegionVid,
302302
) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
303-
let BlameConstraint { category, from_closure, span, variance_info: _ } =
303+
let BlameConstraint { category, from_closure, cause, variance_info: _ } =
304304
self.regioncx.best_blame_constraint(
305305
&self.body,
306306
borrow_region,
@@ -310,7 +310,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
310310

311311
let outlived_fr_name = self.give_region_a_name(outlived_region);
312312

313-
(category, from_closure, span, outlived_fr_name)
313+
(category, from_closure, cause.span, outlived_fr_name)
314314
}
315315

316316
/// Returns structured explanation for *why* the borrow contains the

‎compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_span::{BytePos, Span};
1313

1414
use crate::borrowck_errors;
1515

16+
use super::{OutlivesSuggestionBuilder, RegionName};
1617
use crate::region_infer::BlameConstraint;
1718
use crate::{
1819
nll::ConstraintDescription,
@@ -21,8 +22,6 @@ use crate::{
2122
MirBorrowckCtxt,
2223
};
2324

24-
use super::{OutlivesSuggestionBuilder, RegionName};
25-
2625
impl ConstraintDescription for ConstraintCategory {
2726
fn description(&self) -> &'static str {
2827
// Must end with a space. Allows for empty names to be provided.
@@ -41,7 +40,8 @@ impl ConstraintDescription for ConstraintCategory {
4140
ConstraintCategory::OpaqueType => "opaque type ",
4241
ConstraintCategory::ClosureUpvar(_) => "closure capture ",
4342
ConstraintCategory::Usage => "this usage ",
44-
ConstraintCategory::Boring
43+
ConstraintCategory::Predicate(_)
44+
| ConstraintCategory::Boring
4545
| ConstraintCategory::BoringNoLocation
4646
| ConstraintCategory::Internal => "",
4747
}
@@ -217,7 +217,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
217217
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
218218

219219
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
220-
let (_, span) = self.regioncx.find_outlives_blame_span(
220+
let (_, cause) = self.regioncx.find_outlives_blame_span(
221221
&self.body,
222222
longer_fr,
223223
NllRegionVariableOrigin::Placeholder(placeholder),
@@ -227,7 +227,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
227227
let universe = placeholder.universe;
228228
let universe_info = self.regioncx.universe_info(universe);
229229

230-
universe_info.report_error(self, placeholder, error_element, span);
230+
universe_info.report_error(self, placeholder, error_element, cause);
231231
}
232232

233233
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
@@ -275,15 +275,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
275275
) {
276276
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
277277

278-
let BlameConstraint { category, span, variance_info, from_closure: _ } =
278+
let BlameConstraint { category, cause, variance_info, from_closure: _ } =
279279
self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
280280
self.regioncx.provides_universal_region(r, fr, outlived_fr)
281281
});
282282

283-
debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info);
283+
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
284284
// Check if we can use one of the "nice region errors".
285285
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
286-
let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
286+
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
287287
if let Some(diag) = nice.try_report_from_nll() {
288288
diag.buffer(&mut self.errors_buffer);
289289
return;
@@ -306,7 +306,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
306306
fr_is_local,
307307
outlived_fr_is_local,
308308
category,
309-
span,
309+
span: cause.span,
310310
};
311311

312312
let mut diag = match (category, fr_is_local, outlived_fr_is_local) {

‎compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use rustc_data_structures::binary_search_util;
55
use rustc_data_structures::frozen::Frozen;
66
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_data_structures::graph::scc::Sccs;
8-
use rustc_hir::def_id::DefId;
8+
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
9+
use rustc_hir::CRATE_HIR_ID;
910
use rustc_index::vec::IndexVec;
1011
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
1112
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
@@ -14,6 +15,8 @@ use rustc_middle::mir::{
1415
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
1516
ConstraintCategory, Local, Location, ReturnConstraint,
1617
};
18+
use rustc_middle::traits::ObligationCause;
19+
use rustc_middle::traits::ObligationCauseCode;
1720
use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
1821
use rustc_span::Span;
1922

@@ -1596,7 +1599,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15961599
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
15971600
subject: ClosureOutlivesSubject::Region(fr_minus),
15981601
outlived_free_region: fr,
1599-
blame_span: blame_span_category.1,
1602+
blame_span: blame_span_category.1.span,
16001603
category: blame_span_category.0,
16011604
});
16021605
}
@@ -1738,7 +1741,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17381741
return BlameConstraint {
17391742
category: constraint.category,
17401743
from_closure: false,
1741-
span,
1744+
cause: ObligationCause::dummy_with_span(span),
17421745
variance_info: constraint.variance_info,
17431746
};
17441747
}
@@ -1751,30 +1754,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17511754
.map(|&(category, span)| BlameConstraint {
17521755
category,
17531756
from_closure: true,
1754-
span: span,
1757+
cause: ObligationCause::dummy_with_span(span),
17551758
variance_info: constraint.variance_info,
17561759
})
17571760
.unwrap_or(BlameConstraint {
17581761
category: constraint.category,
17591762
from_closure: false,
1760-
span: body.source_info(loc).span,
1763+
cause: ObligationCause::dummy_with_span(body.source_info(loc).span),
17611764
variance_info: constraint.variance_info,
17621765
})
17631766
}
17641767

1765-
/// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
1768+
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
17661769
crate fn find_outlives_blame_span(
17671770
&self,
17681771
body: &Body<'tcx>,
17691772
fr1: RegionVid,
17701773
fr1_origin: NllRegionVariableOrigin,
17711774
fr2: RegionVid,
1772-
) -> (ConstraintCategory, Span) {
1773-
let BlameConstraint { category, span, .. } =
1775+
) -> (ConstraintCategory, ObligationCause<'tcx>) {
1776+
let BlameConstraint { category, cause, .. } =
17741777
self.best_blame_constraint(body, fr1, fr1_origin, |r| {
17751778
self.provides_universal_region(r, fr1, fr2)
17761779
});
1777-
(category, span)
1780+
(category, cause)
17781781
}
17791782

17801783
/// Walks the graph of constraints (where `'a: 'b` is considered
@@ -1990,6 +1993,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
19901993
.collect::<Vec<_>>()
19911994
);
19921995

1996+
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
1997+
// Instead, we use it to produce an improved `ObligationCauseCode`.
1998+
// FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate`
1999+
// constraints. Currently, we just pick the first one.
2000+
let cause_code = path
2001+
.iter()
2002+
.find_map(|constraint| {
2003+
if let ConstraintCategory::Predicate(predicate_span) = constraint.category {
2004+
// We currentl'y doesn't store the `DefId` in the `ConstraintCategory`
2005+
// for perforamnce reasons. The error reporting code used by NLL only
2006+
// uses the span, so this doesn't cause any problems at the moment.
2007+
Some(ObligationCauseCode::BindingObligation(
2008+
CRATE_DEF_ID.to_def_id(),
2009+
predicate_span,
2010+
))
2011+
} else {
2012+
None
2013+
}
2014+
})
2015+
.unwrap_or_else(|| ObligationCauseCode::MiscObligation);
2016+
19932017
// Classify each of the constraints along the path.
19942018
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
19952019
.iter()
@@ -2000,7 +2024,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20002024
BlameConstraint {
20012025
category: constraint.category,
20022026
from_closure: false,
2003-
span: constraint.locations.span(body),
2027+
cause: ObligationCause::new(
2028+
constraint.locations.span(body),
2029+
CRATE_HIR_ID,
2030+
cause_code.clone(),
2031+
),
20042032
variance_info: constraint.variance_info,
20052033
}
20062034
}
@@ -2083,7 +2111,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20832111
ConstraintCategory::OpaqueType
20842112
| ConstraintCategory::Boring
20852113
| ConstraintCategory::BoringNoLocation
2086-
| ConstraintCategory::Internal => false,
2114+
| ConstraintCategory::Internal
2115+
| ConstraintCategory::Predicate(_) => false,
20872116
ConstraintCategory::TypeAnnotation
20882117
| ConstraintCategory::Return(_)
20892118
| ConstraintCategory::Yield => true,
@@ -2094,7 +2123,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20942123
ConstraintCategory::OpaqueType
20952124
| ConstraintCategory::Boring
20962125
| ConstraintCategory::BoringNoLocation
2097-
| ConstraintCategory::Internal => false,
2126+
| ConstraintCategory::Internal
2127+
| ConstraintCategory::Predicate(_) => false,
20982128
_ => true,
20992129
}
21002130
}
@@ -2249,6 +2279,6 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
22492279
pub struct BlameConstraint<'tcx> {
22502280
pub category: ConstraintCategory,
22512281
pub from_closure: bool,
2252-
pub span: Span,
2282+
pub cause: ObligationCause<'tcx>,
22532283
pub variance_info: ty::VarianceDiagInfo<'tcx>,
22542284
}

‎compiler/rustc_borrowck/src/type_check/canonical.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_infer::infer::canonical::Canonical;
44
use rustc_infer::traits::query::NoSolution;
55
use rustc_middle::mir::ConstraintCategory;
66
use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
7+
use rustc_span::def_id::DefId;
78
use rustc_span::Span;
89
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
910
use rustc_trait_selection::traits::query::Fallible;
@@ -100,12 +101,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
100101

101102
pub(super) fn normalize_and_prove_instantiated_predicates(
102103
&mut self,
104+
// Keep this parameter for now, in case we start using
105+
// it in `ConstraintCategory` at some point.
106+
_def_id: DefId,
103107
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
104108
locations: Locations,
105109
) {
106-
for predicate in instantiated_predicates.predicates {
110+
for (predicate, span) in instantiated_predicates
111+
.predicates
112+
.into_iter()
113+
.zip(instantiated_predicates.spans.into_iter())
114+
{
107115
let predicate = self.normalize(predicate, locations);
108-
self.prove_predicate(predicate, locations, ConstraintCategory::Boring);
116+
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
109117
}
110118
}
111119

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use rustc_middle::ty::{
3232
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
3333
ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
3434
};
35+
use rustc_span::def_id::CRATE_DEF_ID;
3536
use rustc_span::{Span, DUMMY_SP};
3637
use rustc_target::abi::VariantIdx;
3738
use rustc_trait_selection::infer::InferCtxtExt as _;
@@ -449,6 +450,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
449450
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
450451
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
451452
self.cx.normalize_and_prove_instantiated_predicates(
453+
def_id,
452454
instantiated_predicates,
453455
location.to_locations(),
454456
);
@@ -2572,9 +2574,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25722574
aggregate_kind, location
25732575
);
25742576

2575-
let instantiated_predicates = match aggregate_kind {
2577+
let (def_id, instantiated_predicates) = match aggregate_kind {
25762578
AggregateKind::Adt(def, _, substs, _, _) => {
2577-
tcx.predicates_of(def.did).instantiate(tcx, substs)
2579+
(def.did, tcx.predicates_of(def.did).instantiate(tcx, substs))
25782580
}
25792581

25802582
// For closures, we have some **extra requirements** we
@@ -2599,13 +2601,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25992601
// clauses on the struct.
26002602
AggregateKind::Closure(def_id, substs)
26012603
| AggregateKind::Generator(def_id, substs, _) => {
2602-
self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)
2604+
(*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
26032605
}
26042606

2605-
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
2607+
AggregateKind::Array(_) | AggregateKind::Tuple => {
2608+
(CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2609+
}
26062610
};
26072611

26082612
self.normalize_and_prove_instantiated_predicates(
2613+
def_id,
26092614
instantiated_predicates,
26102615
location.to_locations(),
26112616
);

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
609609
err: &mut DiagnosticBuilder<'tcx>,
610610
cause: &ObligationCause<'tcx>,
611611
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
612+
terr: &TypeError<'tcx>,
612613
) {
613614
match cause.code {
614615
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
@@ -785,7 +786,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
785786
err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
786787
err.help("...or use `match` instead of `let...else`");
787788
}
788-
_ => (),
789+
_ => {
790+
if let ObligationCauseCode::BindingObligation(_, binding_span) =
791+
cause.code.peel_derives()
792+
{
793+
if matches!(terr, TypeError::RegionsPlaceholderMismatch) {
794+
err.span_note(*binding_span, "the lifetime requirement is introduced here");
795+
}
796+
}
797+
}
789798
}
790799
}
791800

@@ -1724,7 +1733,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17241733

17251734
// It reads better to have the error origin as the final
17261735
// thing.
1727-
self.note_error_origin(diag, cause, exp_found);
1736+
self.note_error_origin(diag, cause, exp_found, terr);
17281737
}
17291738

17301739
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {

‎compiler/rustc_middle/src/mir/query.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ pub struct ClosureOutlivesRequirement<'tcx> {
309309
pub category: ConstraintCategory,
310310
}
311311

312+
// Make sure this enum doesn't unintentionally grow
313+
rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
314+
312315
/// Outlives-constraints can be categorized to determine whether and why they
313316
/// are interesting (for error reporting). Order of variants indicates sort
314317
/// order of the category, thereby influencing diagnostic output.
@@ -338,6 +341,11 @@ pub enum ConstraintCategory {
338341
OpaqueType,
339342
ClosureUpvar(hir::HirId),
340343

344+
/// A constraint from a user-written predicate
345+
/// with the provided span, written on the item
346+
/// with the given `DefId`
347+
Predicate(Span),
348+
341349
/// A "boring" constraint (caused by the given location) is one that
342350
/// the user probably doesn't want to see described in diagnostics,
343351
/// because it is kind of an artifact of the type system setup.

‎compiler/rustc_traits/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mod normalize_erasing_regions;
1919
mod normalize_projection_ty;
2020
mod type_op;
2121

22-
pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span};
22+
pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
2323

2424
use rustc_middle::ty::query::Providers;
2525

‎compiler/rustc_traits/src/type_op.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,25 +257,20 @@ fn type_op_prove_predicate<'tcx>(
257257
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
258258
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
259259
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
260-
type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None);
260+
type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy());
261261
Ok(())
262262
})
263263
}
264264

265265
/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
266266
/// this query can be re-run to better track the span of the obligation cause, and improve the error
267267
/// message. Do not call directly unless you're in that very specific context.
268-
pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>(
268+
pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>(
269269
infcx: &'a InferCtxt<'a, 'tcx>,
270270
fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
271271
key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
272-
span: Option<Span>,
272+
cause: ObligationCause<'tcx>,
273273
) {
274-
let cause = if let Some(span) = span {
275-
ObligationCause::dummy_with_span(span)
276-
} else {
277-
ObligationCause::dummy()
278-
};
279274
let (param_env, ProvePredicate { predicate }) = key.into_parts();
280275
fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate));
281276
}

‎src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | foo(());
66
|
77
= note: expected reference `&'a ()`
88
found reference `&()`
9+
note: the lifetime requirement is introduced here
10+
--> $DIR/higher-ranked-projection.rs:15:33
11+
|
12+
LL | where for<'a> &'a T: Mirror<Image=U>
13+
| ^^^^^^^
914

1015
error: aborting due to previous error
1116

‎src/test/ui/generator/resume-arg-late-bound.nll.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | test(gen);
66
|
77
= note: expected type `for<'a> Generator<&'a mut bool>`
88
found type `Generator<&mut bool>`
9+
note: the lifetime requirement is introduced here
10+
--> $DIR/resume-arg-late-bound.rs:8:17
11+
|
12+
LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
914

1015
error: aborting due to previous error
1116

‎src/test/ui/lifetimes/issue-79187-2.nll.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ note: this closure does not fulfill the lifetime requirements
3838
|
3939
LL | take_foo(|a| a);
4040
| ^^^^^
41+
note: the lifetime requirement is introduced here
42+
--> $DIR/issue-79187-2.rs:5:21
43+
|
44+
LL | fn take_foo(_: impl Foo) {}
45+
| ^^^
4146

4247
error[E0308]: mismatched types
4348
--> $DIR/issue-79187-2.rs:9:5
@@ -47,6 +52,11 @@ LL | take_foo(|a: &i32| a);
4752
|
4853
= note: expected reference `&i32`
4954
found reference `&i32`
55+
note: the lifetime requirement is introduced here
56+
--> $DIR/issue-79187-2.rs:5:21
57+
|
58+
LL | fn take_foo(_: impl Foo) {}
59+
| ^^^
5060

5161
error[E0308]: mismatched types
5262
--> $DIR/issue-79187-2.rs:10:5
@@ -56,6 +66,11 @@ LL | take_foo(|a: &i32| -> &i32 { a });
5666
|
5767
= note: expected reference `&i32`
5868
found reference `&i32`
69+
note: the lifetime requirement is introduced here
70+
--> $DIR/issue-79187-2.rs:5:21
71+
|
72+
LL | fn take_foo(_: impl Foo) {}
73+
| ^^^
5974

6075
error: aborting due to 6 previous errors
6176

‎src/test/ui/lifetimes/issue-79187.nll.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ note: this closure does not fulfill the lifetime requirements
1111
|
1212
LL | let f = |_| ();
1313
| ^^^^^^
14+
note: the lifetime requirement is introduced here
15+
--> $DIR/issue-79187.rs:1:18
16+
|
17+
LL | fn thing(x: impl FnOnce(&u32)) {}
18+
| ^^^^^^^^^^^^
1419

1520
error: implementation of `FnOnce` is not general enough
1621
--> $DIR/issue-79187.rs:5:5

‎src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ LL | f(data, identity)
1414
|
1515
= note: expected type `for<'r> Fn<(&'r T,)>`
1616
found type `Fn<(&T,)>`
17+
note: the lifetime requirement is introduced here
18+
--> $DIR/issue_74400.rs:8:34
19+
|
20+
LL | fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
21+
| ^^^^^^^^^^^
1722

1823
error: implementation of `FnOnce` is not general enough
1924
--> $DIR/issue_74400.rs:12:5

‎src/test/ui/mismatched_types/closure-mismatch.nll.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ note: this closure does not fulfill the lifetime requirements
2020
|
2121
LL | baz(|_| ());
2222
| ^^^^^^
23+
note: the lifetime requirement is introduced here
24+
--> $DIR/closure-mismatch.rs:5:11
25+
|
26+
LL | fn baz<T: Foo>(_: T) {}
27+
| ^^^
2328

2429
error: aborting due to 2 previous errors
2530

0 commit comments

Comments
 (0)
Please sign in to comment.