//! imply that `'b: 'a`.
use crate::infer::outlives::components::{push_outlives_components, Component};
+use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::outlives::verify::VerifyBoundCx;
use crate::infer::{
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
};
use crate::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
-
-use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::undo_log::UndoLogs;
-use rustc_hir as hir;
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
use smallvec::smallvec;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// and later processed by regionck, when full type information is
/// available (see `region_obligations` field for more
/// information).
- pub fn register_region_obligation(
- &self,
- body_id: hir::HirId,
- obligation: RegionObligation<'tcx>,
- ) {
- debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation);
-
+ #[instrument(level = "debug", skip(self))]
+ pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) {
let mut inner = self.inner.borrow_mut();
inner.undo_log.push(UndoLog::PushRegionObligation);
- inner.region_obligations.push((body_id, obligation));
+ inner.region_obligations.push(obligation);
}
pub fn register_region_obligation_with_cause(
)
});
- self.register_region_obligation(
- cause.body_id,
- RegionObligation { sup_type, sub_region, origin },
- );
+ self.register_region_obligation(RegionObligation { sup_type, sub_region, origin });
}
/// Trait queries just want to pass back type obligations "as is"
- pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
+ pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>> {
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
}
+ /// NOTE: Prefer using [`InferCtxt::check_region_obligations_and_report_errors`]
+ /// instead of calling this directly.
+ ///
/// Process the region obligations that must be proven (during
/// `regionck`) for the given `body_id`, given information about
/// the region bounds in scope and so forth. This function must be
/// `('a, K)` in this list tells us that the bounds in scope
/// indicate that `K: 'a`, where `K` is either a generic
/// parameter like `T` or a projection like `T::Item`.
- /// - `implicit_region_bound`: if some, this is a region bound
- /// that is considered to hold for all type parameters (the
- /// function body).
/// - `param_env` is the parameter environment for the enclosing function.
/// - `body_id` is the body-id whose region obligations are being
/// processed.
- #[instrument(level = "debug", skip(self, region_bound_pairs_map))]
+ #[instrument(level = "debug", skip(self, region_bound_pairs))]
pub fn process_registered_region_obligations(
&self,
- region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
- implicit_region_bound: Option<ty::Region<'tcx>>,
+ region_bound_pairs: &RegionBoundPairs<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) {
assert!(
let my_region_obligations = self.take_registered_region_obligations();
- for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations {
+ for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
debug!(
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
sup_type, sub_region, origin
let sup_type = self.resolve_vars_if_possible(sup_type);
- if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
- let outlives = &mut TypeOutlives::new(
- self,
- self.tcx,
- ®ion_bound_pairs,
- implicit_region_bound,
- param_env,
- );
- outlives.type_must_outlive(origin, sup_type, sub_region);
- } else {
- self.tcx.sess.delay_span_bug(
- origin.span(),
- &format!("no region-bound-pairs for {:?}", body_id),
- );
- }
+ let outlives =
+ &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env);
+ outlives.type_must_outlive(origin, sup_type, sub_region);
}
}
+
+ /// Processes registered region obliations and resolves regions, reporting
+ /// any errors if any were raised. Prefer using this function over manually
+ /// calling `resolve_regions_and_report_errors`.
+ pub fn check_region_obligations_and_report_errors(
+ &self,
+ generic_param_scope: LocalDefId,
+ outlives_env: &OutlivesEnvironment<'tcx>,
+ ) {
+ self.process_registered_region_obligations(
+ outlives_env.region_bound_pairs(),
+ outlives_env.param_env,
+ );
+
+ self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
+ }
}
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`