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 6f1500a

Browse files
authoredApr 13, 2023
Rollup merge of rust-lang#110220 - lcnr:regionzz, r=compiler-errors
cleanup our region error API - require `TypeErrCtxt` to always result in an error, closing rust-lang#108810 - move `resolve_regions_and_report_errors` to the `ObligationCtxt` - call `process_registered_region_obligations` in `resolve_regions` - move `resolve_regions` into the `outlives` submodule - add `#[must_use]` to functions returning lists of errors r? types
2 parents 35c4ea5 + c0d3d32 commit 6f1500a

File tree

15 files changed

+192
-237
lines changed

15 files changed

+192
-237
lines changed
 

‎compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,11 +452,8 @@ fn check_opaque_meets_bounds<'tcx>(
452452
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
453453
// Can have different predicates to their defining use
454454
hir::OpaqueTyOrigin::TyAlias => {
455-
let outlives_environment = OutlivesEnvironment::new(param_env);
456-
let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(
457-
defining_use_anchor,
458-
&outlives_environment,
459-
);
455+
let outlives_env = OutlivesEnvironment::new(param_env);
456+
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
460457
}
461458
}
462459
// Clean up after ourselves

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,6 @@ fn compare_method_predicate_entailment<'tcx>(
332332
param_env,
333333
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
334334
);
335-
infcx.process_registered_region_obligations(
336-
outlives_env.region_bound_pairs(),
337-
outlives_env.param_env,
338-
);
339335
let errors = infcx.resolve_regions(&outlives_env);
340336
if !errors.is_empty() {
341337
// FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
@@ -722,18 +718,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
722718
return Err(reported);
723719
}
724720

721+
let collected_types = collector.types;
722+
725723
// Finally, resolve all regions. This catches wily misuses of
726724
// lifetime parameters.
727-
let outlives_environment = OutlivesEnvironment::with_bounds(
725+
let outlives_env = OutlivesEnvironment::with_bounds(
728726
param_env,
729727
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
730728
);
731-
infcx
732-
.err_ctxt()
733-
.check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
729+
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
734730

735731
let mut collected_tys = FxHashMap::default();
736-
for (def_id, (ty, substs)) in collector.types {
732+
for (def_id, (ty, substs)) in collected_types {
737733
match infcx.fully_resolve(ty) {
738734
Ok(ty) => {
739735
// `ty` contains free regions that we created earlier while liberating the
@@ -1742,11 +1738,8 @@ pub(super) fn compare_impl_const_raw(
17421738
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
17431739
}
17441740

1745-
let outlives_environment = OutlivesEnvironment::new(param_env);
1746-
infcx
1747-
.err_ctxt()
1748-
.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
1749-
Ok(())
1741+
let outlives_env = OutlivesEnvironment::new(param_env);
1742+
ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
17501743
}
17511744

17521745
pub(super) fn compare_impl_ty<'tcx>(
@@ -1845,13 +1838,8 @@ fn compare_type_predicate_entailment<'tcx>(
18451838

18461839
// Finally, resolve all regions. This catches wily misuses of
18471840
// lifetime parameters.
1848-
let outlives_environment = OutlivesEnvironment::new(param_env);
1849-
infcx.err_ctxt().check_region_obligations_and_report_errors(
1850-
impl_ty.def_id.expect_local(),
1851-
&outlives_environment,
1852-
)?;
1853-
1854-
Ok(())
1841+
let outlives_env = OutlivesEnvironment::new(param_env);
1842+
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
18551843
}
18561844

18571845
/// Validate that `ProjectionCandidate`s created for this associated type will
@@ -2063,14 +2051,8 @@ pub(super) fn check_type_bounds<'tcx>(
20632051
// Finally, resolve all regions. This catches wily misuses of
20642052
// lifetime parameters.
20652053
let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
2066-
let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
2067-
2068-
infcx.err_ctxt().check_region_obligations_and_report_errors(
2069-
impl_ty.def_id.expect_local(),
2070-
&outlives_environment,
2071-
)?;
2072-
2073-
Ok(())
2054+
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
2055+
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
20742056
}
20752057

20762058
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,9 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
114114
return;
115115
}
116116

117-
let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
117+
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
118118

119-
let _ = infcx
120-
.err_ctxt()
121-
.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
119+
let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
122120
}
123121

124122
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
@@ -680,12 +678,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
680678

681679
add_constraints(&infcx, region_bound_pairs);
682680

683-
infcx.process_registered_region_obligations(
684-
outlives_environment.region_bound_pairs(),
685-
param_env,
686-
);
687681
let errors = infcx.resolve_regions(&outlives_environment);
688-
689682
debug!(?errors, "errors");
690683

691684
// If we were able to prove that the type outlives the region without

‎compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
354354

355355
// Finally, resolve all regions.
356356
let outlives_env = OutlivesEnvironment::new(param_env);
357-
let _ = infcx
358-
.err_ctxt()
359-
.check_region_obligations_and_report_errors(impl_did, &outlives_env);
357+
let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
360358
}
361359
}
362360
_ => {
@@ -592,7 +590,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
592590

593591
// Finally, resolve all regions.
594592
let outlives_env = OutlivesEnvironment::new(param_env);
595-
let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env);
593+
let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
596594

597595
CoerceUnsizedInfo { custom_kind: kind }
598596
}

‎compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,7 @@ fn get_impl_substs(
180180

181181
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
182182
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
183-
let _ =
184-
infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
183+
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
185184
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
186185
let span = tcx.def_span(impl1_def_id);
187186
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ use rustc_middle::ty::{
7474
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
7575
TypeVisitable, TypeVisitableExt,
7676
};
77+
use rustc_span::DUMMY_SP;
7778
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
7879
use rustc_target::spec::abi;
7980
use std::ops::{ControlFlow, Deref};
@@ -113,7 +114,11 @@ fn escape_literal(s: &str) -> String {
113114

114115
/// A helper for building type related errors. The `typeck_results`
115116
/// field is only populated during an in-progress typeck.
116-
/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`.
117+
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
118+
///
119+
/// You must only create this if you intend to actually emit an error.
120+
/// This provides a lot of utility methods which should not be used
121+
/// during the happy path.
117122
pub struct TypeErrCtxt<'a, 'tcx> {
118123
pub infcx: &'a InferCtxt<'tcx>,
119124
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
@@ -125,6 +130,19 @@ pub struct TypeErrCtxt<'a, 'tcx> {
125130
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
126131
}
127132

133+
impl Drop for TypeErrCtxt<'_, '_> {
134+
fn drop(&mut self) {
135+
if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() {
136+
// ok, emitted an error.
137+
} else {
138+
self.infcx
139+
.tcx
140+
.sess
141+
.delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
142+
}
143+
}
144+
}
145+
128146
impl TypeErrCtxt<'_, '_> {
129147
/// This is just to avoid a potential footgun of accidentally
130148
/// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
@@ -409,7 +427,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
409427
&self,
410428
generic_param_scope: LocalDefId,
411429
errors: &[RegionResolutionError<'tcx>],
412-
) {
430+
) -> ErrorGuaranteed {
431+
if let Some(guaranteed) = self.infcx.tainted_by_errors() {
432+
return guaranteed;
433+
}
434+
413435
debug!("report_region_errors(): {} errors to start", errors.len());
414436

415437
// try to pre-process the errors, which will group some of them
@@ -489,6 +511,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
489511
}
490512
}
491513
}
514+
515+
self.tcx
516+
.sess
517+
.delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
492518
}
493519

494520
// This method goes through all the errors and try to group certain types

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

Lines changed: 1 addition & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ use self::combine::CombineFields;
4545
use self::error_reporting::TypeErrCtxt;
4646
use self::free_regions::RegionRelations;
4747
use self::lexical_region_resolve::LexicalRegionResolutions;
48-
use self::outlives::env::OutlivesEnvironment;
49-
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
48+
use self::region_constraints::{GenericKind, VarInfos, VerifyBound};
5049
use self::region_constraints::{
5150
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
5251
};
@@ -1213,95 +1212,6 @@ impl<'tcx> InferCtxt<'tcx> {
12131212
self.tainted_by_errors.set(Some(e));
12141213
}
12151214

1216-
pub fn skip_region_resolution(&self) {
1217-
let (var_infos, _) = {
1218-
let mut inner = self.inner.borrow_mut();
1219-
let inner = &mut *inner;
1220-
// Note: `inner.region_obligations` may not be empty, because we
1221-
// didn't necessarily call `process_registered_region_obligations`.
1222-
// This is okay, because that doesn't introduce new vars.
1223-
inner
1224-
.region_constraint_storage
1225-
.take()
1226-
.expect("regions already resolved")
1227-
.with_log(&mut inner.undo_log)
1228-
.into_infos_and_data()
1229-
};
1230-
1231-
let lexical_region_resolutions = LexicalRegionResolutions {
1232-
values: rustc_index::vec::IndexVec::from_elem_n(
1233-
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
1234-
var_infos.len(),
1235-
),
1236-
};
1237-
1238-
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
1239-
assert!(old_value.is_none());
1240-
}
1241-
1242-
/// Process the region constraints and return any errors that
1243-
/// result. After this, no more unification operations should be
1244-
/// done -- or the compiler will panic -- but it is legal to use
1245-
/// `resolve_vars_if_possible` as well as `fully_resolve`.
1246-
pub fn resolve_regions(
1247-
&self,
1248-
outlives_env: &OutlivesEnvironment<'tcx>,
1249-
) -> Vec<RegionResolutionError<'tcx>> {
1250-
let (var_infos, data) = {
1251-
let mut inner = self.inner.borrow_mut();
1252-
let inner = &mut *inner;
1253-
assert!(
1254-
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
1255-
"region_obligations not empty: {:#?}",
1256-
inner.region_obligations
1257-
);
1258-
inner
1259-
.region_constraint_storage
1260-
.take()
1261-
.expect("regions already resolved")
1262-
.with_log(&mut inner.undo_log)
1263-
.into_infos_and_data()
1264-
};
1265-
1266-
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
1267-
1268-
let (lexical_region_resolutions, errors) =
1269-
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
1270-
1271-
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
1272-
assert!(old_value.is_none());
1273-
1274-
errors
1275-
}
1276-
/// Obtains (and clears) the current set of region
1277-
/// constraints. The inference context is still usable: further
1278-
/// unifications will simply add new constraints.
1279-
///
1280-
/// This method is not meant to be used with normal lexical region
1281-
/// resolution. Rather, it is used in the NLL mode as a kind of
1282-
/// interim hack: basically we run normal type-check and generate
1283-
/// region constraints as normal, but then we take them and
1284-
/// translate them into the form that the NLL solver
1285-
/// understands. See the NLL module for mode details.
1286-
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
1287-
assert!(
1288-
self.inner.borrow().region_obligations.is_empty(),
1289-
"region_obligations not empty: {:#?}",
1290-
self.inner.borrow().region_obligations
1291-
);
1292-
1293-
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
1294-
}
1295-
1296-
/// Gives temporary access to the region constraint data.
1297-
pub fn with_region_constraints<R>(
1298-
&self,
1299-
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
1300-
) -> R {
1301-
let mut inner = self.inner.borrow_mut();
1302-
op(inner.unwrap_region_constraints().data())
1303-
}
1304-
13051215
pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
13061216
let mut inner = self.inner.borrow_mut();
13071217
let inner = &mut *inner;
@@ -1754,56 +1664,6 @@ impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> {
17541664
}
17551665

17561666
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
1757-
/// Processes registered region obliations and resolves regions, reporting
1758-
/// any errors if any were raised. Prefer using this function over manually
1759-
/// calling `resolve_regions_and_report_errors`.
1760-
pub fn check_region_obligations_and_report_errors(
1761-
&self,
1762-
generic_param_scope: LocalDefId,
1763-
outlives_env: &OutlivesEnvironment<'tcx>,
1764-
) -> Result<(), ErrorGuaranteed> {
1765-
self.process_registered_region_obligations(
1766-
outlives_env.region_bound_pairs(),
1767-
outlives_env.param_env,
1768-
);
1769-
1770-
self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
1771-
}
1772-
1773-
/// Process the region constraints and report any errors that
1774-
/// result. After this, no more unification operations should be
1775-
/// done -- or the compiler will panic -- but it is legal to use
1776-
/// `resolve_vars_if_possible` as well as `fully_resolve`.
1777-
///
1778-
/// Make sure to call [`InferCtxt::process_registered_region_obligations`]
1779-
/// first, or preferably use [`TypeErrCtxt::check_region_obligations_and_report_errors`]
1780-
/// to do both of these operations together.
1781-
pub fn resolve_regions_and_report_errors(
1782-
&self,
1783-
generic_param_scope: LocalDefId,
1784-
outlives_env: &OutlivesEnvironment<'tcx>,
1785-
) -> Result<(), ErrorGuaranteed> {
1786-
let errors = self.resolve_regions(outlives_env);
1787-
1788-
if let None = self.tainted_by_errors() {
1789-
// As a heuristic, just skip reporting region errors
1790-
// altogether if other errors have been reported while
1791-
// this infcx was in use. This is totally hokey but
1792-
// otherwise we have a hard time separating legit region
1793-
// errors from silly ones.
1794-
self.report_region_errors(generic_param_scope, &errors);
1795-
}
1796-
1797-
if errors.is_empty() {
1798-
Ok(())
1799-
} else {
1800-
Err(self
1801-
.tcx
1802-
.sess
1803-
.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"))
1804-
}
1805-
}
1806-
18071667
// [Note-Type-error-reporting]
18081668
// An invariant is that anytime the expected or actual type is Error (the special
18091669
// error type, meaning that an error occurred when typechecking this expression),

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

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
//! Various code related to computing outlives relations.
2+
use self::env::OutlivesEnvironment;
3+
use super::region_constraints::RegionConstraintData;
4+
use super::{InferCtxt, RegionResolutionError};
5+
use crate::infer::free_regions::RegionRelations;
6+
use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
7+
use rustc_middle::traits::query::OutlivesBound;
8+
use rustc_middle::ty;
29

310
pub mod components;
411
pub mod env;
512
pub mod obligations;
613
pub mod test_type_match;
714
pub mod verify;
815

9-
use rustc_middle::traits::query::OutlivesBound;
10-
use rustc_middle::ty;
11-
1216
#[instrument(level = "debug", skip(param_env), ret)]
1317
pub fn explicit_outlives_bounds<'tcx>(
1418
param_env: ty::ParamEnv<'tcx>,
@@ -39,3 +43,98 @@ pub fn explicit_outlives_bounds<'tcx>(
3943
))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
4044
})
4145
}
46+
47+
impl<'tcx> InferCtxt<'tcx> {
48+
pub fn skip_region_resolution(&self) {
49+
let (var_infos, _) = {
50+
let mut inner = self.inner.borrow_mut();
51+
let inner = &mut *inner;
52+
// Note: `inner.region_obligations` may not be empty, because we
53+
// didn't necessarily call `process_registered_region_obligations`.
54+
// This is okay, because that doesn't introduce new vars.
55+
inner
56+
.region_constraint_storage
57+
.take()
58+
.expect("regions already resolved")
59+
.with_log(&mut inner.undo_log)
60+
.into_infos_and_data()
61+
};
62+
63+
let lexical_region_resolutions = LexicalRegionResolutions {
64+
values: rustc_index::vec::IndexVec::from_elem_n(
65+
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
66+
var_infos.len(),
67+
),
68+
};
69+
70+
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
71+
assert!(old_value.is_none());
72+
}
73+
74+
/// Process the region constraints and return any errors that
75+
/// result. After this, no more unification operations should be
76+
/// done -- or the compiler will panic -- but it is legal to use
77+
/// `resolve_vars_if_possible` as well as `fully_resolve`.
78+
#[must_use]
79+
pub fn resolve_regions(
80+
&self,
81+
outlives_env: &OutlivesEnvironment<'tcx>,
82+
) -> Vec<RegionResolutionError<'tcx>> {
83+
self.process_registered_region_obligations(outlives_env);
84+
85+
let (var_infos, data) = {
86+
let mut inner = self.inner.borrow_mut();
87+
let inner = &mut *inner;
88+
assert!(
89+
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
90+
"region_obligations not empty: {:#?}",
91+
inner.region_obligations
92+
);
93+
inner
94+
.region_constraint_storage
95+
.take()
96+
.expect("regions already resolved")
97+
.with_log(&mut inner.undo_log)
98+
.into_infos_and_data()
99+
};
100+
101+
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
102+
103+
let (lexical_region_resolutions, errors) =
104+
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
105+
106+
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
107+
assert!(old_value.is_none());
108+
109+
errors
110+
}
111+
112+
/// Obtains (and clears) the current set of region
113+
/// constraints. The inference context is still usable: further
114+
/// unifications will simply add new constraints.
115+
///
116+
/// This method is not meant to be used with normal lexical region
117+
/// resolution. Rather, it is used in the NLL mode as a kind of
118+
/// interim hack: basically we run normal type-check and generate
119+
/// region constraints as normal, but then we take them and
120+
/// translate them into the form that the NLL solver
121+
/// understands. See the NLL module for mode details.
122+
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
123+
assert!(
124+
self.inner.borrow().region_obligations.is_empty(),
125+
"region_obligations not empty: {:#?}",
126+
self.inner.borrow().region_obligations
127+
);
128+
129+
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
130+
}
131+
132+
/// Gives temporary access to the region constraint data.
133+
pub fn with_region_constraints<R>(
134+
&self,
135+
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
136+
) -> R {
137+
let mut inner = self.inner.borrow_mut();
138+
op(inner.unwrap_region_constraints().data())
139+
}
140+
}

‎compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ use rustc_middle::ty::subst::GenericArgKind;
7272
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
7373
use smallvec::smallvec;
7474

75+
use super::env::OutlivesEnvironment;
76+
7577
impl<'tcx> InferCtxt<'tcx> {
7678
/// Registers that the given region obligation must be resolved
7779
/// from within the scope of `body_id`. These regions are enqueued
@@ -112,39 +114,17 @@ impl<'tcx> InferCtxt<'tcx> {
112114
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
113115
}
114116

115-
/// NOTE: Prefer using `TypeErrCtxt::check_region_obligations_and_report_errors`
116-
/// instead of calling this directly.
117-
///
118117
/// Process the region obligations that must be proven (during
119118
/// `regionck`) for the given `body_id`, given information about
120-
/// the region bounds in scope and so forth. This function must be
121-
/// invoked for all relevant body-ids before region inference is
122-
/// done (or else an assert will fire).
119+
/// the region bounds in scope and so forth.
123120
///
124121
/// See the `region_obligations` field of `InferCtxt` for some
125122
/// comments about how this function fits into the overall expected
126123
/// flow of the inferencer. The key point is that it is
127124
/// invoked after all type-inference variables have been bound --
128-
/// towards the end of regionck. This also ensures that the
129-
/// region-bound-pairs are available (see comments above regarding
130-
/// closures).
131-
///
132-
/// # Parameters
133-
///
134-
/// - `region_bound_pairs_map`: the set of region bounds implied by
135-
/// the parameters and where-clauses. In particular, each pair
136-
/// `('a, K)` in this list tells us that the bounds in scope
137-
/// indicate that `K: 'a`, where `K` is either a generic
138-
/// parameter like `T` or a projection like `T::Item`.
139-
/// - `param_env` is the parameter environment for the enclosing function.
140-
/// - `body_id` is the body-id whose region obligations are being
141-
/// processed.
142-
#[instrument(level = "debug", skip(self, region_bound_pairs))]
143-
pub fn process_registered_region_obligations(
144-
&self,
145-
region_bound_pairs: &RegionBoundPairs<'tcx>,
146-
param_env: ty::ParamEnv<'tcx>,
147-
) {
125+
/// right before lexical region resolution.
126+
#[instrument(level = "debug", skip(self, outlives_env))]
127+
pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
148128
assert!(
149129
!self.in_snapshot.get(),
150130
"cannot process registered region obligations in a snapshot"
@@ -153,15 +133,16 @@ impl<'tcx> InferCtxt<'tcx> {
153133
let my_region_obligations = self.take_registered_region_obligations();
154134

155135
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
156-
debug!(
157-
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
158-
sup_type, sub_region, origin
159-
);
160-
136+
debug!(?sup_type, ?sub_region, ?origin);
161137
let sup_type = self.resolve_vars_if_possible(sup_type);
162138

163-
let outlives =
164-
&mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
139+
let outlives = &mut TypeOutlives::new(
140+
self,
141+
self.tcx,
142+
&outlives_env.region_bound_pairs(),
143+
None,
144+
outlives_env.param_env,
145+
);
165146
let category = origin.to_constraint_category();
166147
outlives.type_must_outlive(origin, sup_type, sub_region, category);
167148
}

‎compiler/rustc_infer/src/traits/engine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
3636
obligation: PredicateObligation<'tcx>,
3737
);
3838

39+
#[must_use]
3940
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
4041

4142
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
@@ -58,6 +59,7 @@ pub trait TraitEngineExt<'tcx> {
5859
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
5960
);
6061

62+
#[must_use]
6163
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
6264
}
6365

‎compiler/rustc_trait_selection/src/traits/auto_trait.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
186186
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
187187
}
188188

189-
infcx.process_registered_region_obligations(&Default::default(), full_env);
189+
let outlives_env = OutlivesEnvironment::new(full_env);
190+
infcx.process_registered_region_obligations(&outlives_env);
190191

191192
let region_data =
192193
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();

‎compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,6 @@ fn resolve_negative_obligation<'tcx>(
405405
param_env,
406406
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
407407
);
408-
409-
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
410-
411408
infcx.resolve_regions(&outlives_env).is_empty()
412409
}
413410

‎compiler/rustc_trait_selection/src/traits/engine.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ use super::{ChalkFulfillmentContext, FulfillmentContext};
66
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
77
use crate::traits::NormalizeExt;
88
use rustc_data_structures::fx::FxIndexSet;
9+
use rustc_errors::ErrorGuaranteed;
910
use rustc_hir::def_id::{DefId, LocalDefId};
1011
use rustc_infer::infer::at::ToTrace;
1112
use rustc_infer::infer::canonical::{
1213
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
1314
};
15+
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1416
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
1517
use rustc_infer::traits::query::Fallible;
1618
use rustc_infer::traits::{
@@ -173,14 +175,33 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
173175
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
174176
}
175177

178+
#[must_use]
176179
pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
177180
self.engine.borrow_mut().select_where_possible(self.infcx)
178181
}
179182

183+
#[must_use]
180184
pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
181185
self.engine.borrow_mut().select_all_or_error(self.infcx)
182186
}
183187

188+
/// Resolves regions and reports errors.
189+
///
190+
/// Takes ownership of the context as doing trait solving afterwards
191+
/// will result in region constraints getting ignored.
192+
pub fn resolve_regions_and_report_errors(
193+
self,
194+
generic_param_scope: LocalDefId,
195+
outlives_env: &OutlivesEnvironment<'tcx>,
196+
) -> Result<(), ErrorGuaranteed> {
197+
let errors = self.infcx.resolve_regions(&outlives_env);
198+
if errors.is_empty() {
199+
Ok(())
200+
} else {
201+
Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors))
202+
}
203+
}
204+
184205
pub fn assumed_wf_types(
185206
&self,
186207
param_env: ty::ParamEnv<'tcx>,

‎compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1776,7 +1776,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
17761776

17771777
// constrain inference variables a bit more to nested obligations from normalize so
17781778
// we can have more helpful errors.
1779-
ocx.select_where_possible();
1779+
//
1780+
// we intentionally drop errors from normalization here,
1781+
// since the normalization is just done to improve the error message.
1782+
let _ = ocx.select_where_possible();
17801783

17811784
if let Err(new_err) = ocx.eq_exp(
17821785
&obligation.cause,

‎compiler/rustc_trait_selection/src/traits/misc.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,6 @@ pub fn type_allowed_to_implement_copy<'tcx>(
117117
FxIndexSet::from_iter([self_type]),
118118
),
119119
);
120-
infcx.process_registered_region_obligations(
121-
outlives_env.region_bound_pairs(),
122-
param_env,
123-
);
124120
let errors = infcx.resolve_regions(&outlives_env);
125121
if !errors.is_empty() {
126122
infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));

0 commit comments

Comments
 (0)
Please sign in to comment.