Skip to content

Commit 1aefec0

Browse files
authored
Rollup merge of #110220 - lcnr:regionzz, r=compiler-errors
cleanup our region error API - require `TypeErrCtxt` to always result in an error, closing #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 9d478e3 + c0d3d32 commit 1aefec0

File tree

15 files changed

+192
-237
lines changed

15 files changed

+192
-237
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+2-5
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

+11-29
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

+2-9
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

+2-4
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

+1-2
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

+28-2
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

+1-141
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),

0 commit comments

Comments
 (0)