use crate::infer::free_regions::FreeRegionMap;
use crate::infer::{GenericKind, InferCtxt};
use crate::traits::query::OutlivesBound;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
use super::explicit_outlives_bounds;
pub param_env: ty::ParamEnv<'tcx>,
free_region_map: FreeRegionMap<'tcx>,
- // Contains, for each body B that we are checking (that is, the fn
- // item, but also any nested closures), the set of implied region
- // bounds that are in scope in that particular body.
+ // Contains the implied region bounds in scope for our current body.
//
// Example:
//
// } // body B0
// ```
//
- // Here, for body B0, the list would be `[T: 'a]`, because we
+ // Here, when checking the body B0, the list would be `[T: 'a]`, because we
// infer that `T` must outlive `'a` from the implied bounds on the
// fn declaration.
//
- // For the body B1, the list would be `[T: 'a, T: 'b]`, because we
+ // For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
// also can see that -- within the closure body! -- `T` must
// outlive `'b`. This is not necessarily true outside the closure
// body, since the closure may never be called.
- //
- // We collect this map as we descend the tree. We then use the
- // results when proving outlives obligations like `T: 'x` later
- // (e.g., if `T: 'x` must be proven within the body B1, then we
- // know it is true if either `'a: 'x` or `'b: 'x`).
- region_bound_pairs_map: FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
-
- // Used to compute `region_bound_pairs_map`: contains the set of
- // in-scope region-bound pairs thus far.
- region_bound_pairs_accum: RegionBoundPairs<'tcx>,
+ region_bound_pairs: RegionBoundPairs<'tcx>,
}
/// "Region-bound pairs" tracks outlives relations that are known to
let mut env = OutlivesEnvironment {
param_env,
free_region_map: Default::default(),
- region_bound_pairs_map: Default::default(),
- region_bound_pairs_accum: vec![],
+ region_bound_pairs: Default::default(),
};
env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
&self.free_region_map
}
- /// Borrows current value of the `region_bound_pairs`.
- pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>> {
- &self.region_bound_pairs_map
- }
-
- /// This is a hack to support the old-school regionck, which
- /// processes region constraints from the main function and the
- /// closure together. In that context, when we enter a closure, we
- /// want to be able to "save" the state of the surrounding a
- /// function. We can then add implied bounds and the like from the
- /// closure arguments into the environment -- these should only
- /// apply in the closure body, so once we exit, we invoke
- /// `pop_snapshot_post_typeck_child` to remove them.
- ///
- /// Example:
- ///
- /// ```ignore (pseudo-rust)
- /// fn foo<T>() {
- /// callback(for<'a> |x: &'a T| {
- /// // ^^^^^^^ not legal syntax, but probably should be
- /// // within this closure body, `T: 'a` holds
- /// })
- /// }
- /// ```
- ///
- /// This "containment" of closure's effects only works so well. In
- /// particular, we (intentionally) leak relationships between free
- /// regions that are created by the closure's bounds. The case
- /// where this is useful is when you have (e.g.) a closure with a
- /// signature like `for<'a, 'b> fn(x: &'a &'b u32)` -- in this
- /// case, we want to keep the relationship `'b: 'a` in the
- /// free-region-map, so that later if we have to take `LUB('b,
- /// 'a)` we can get the result `'b`.
- ///
- /// I have opted to keep **all modifications** to the
- /// free-region-map, however, and not just those that concern free
- /// variables bound in the closure. The latter seems more correct,
- /// but it is not the existing behavior, and I could not find a
- /// case where the existing behavior went wrong. In any case, it
- /// seems like it'd be readily fixed if we wanted. There are
- /// similar leaks around givens that seem equally suspicious, to
- /// be honest. --nmatsakis
- pub fn push_snapshot_pre_typeck_child(&self) -> usize {
- self.region_bound_pairs_accum.len()
- }
-
- /// See `push_snapshot_pre_typeck_child`.
- pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) {
- self.region_bound_pairs_accum.truncate(len);
- }
-
- /// Save the current set of region-bound pairs under the given `body_id`.
- pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
- let old =
- self.region_bound_pairs_map.insert(body_id, self.region_bound_pairs_accum.clone());
- assert!(old.is_none());
+ /// Borrows current `region_bound_pairs`.
+ pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
+ &self.region_bound_pairs
}
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
match outlives_bound {
OutlivesBound::RegionSubParam(r_a, param_b) => {
- self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b)));
+ self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
}
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
- self.region_bound_pairs_accum
- .push((r_a, GenericKind::Projection(projection_b)));
+ self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b)));
}
OutlivesBound::RegionSubRegion(r_a, r_b) => {
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
//! 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 crate::infer::outlives::env::OutlivesEnvironment;
-use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_hir as hir;
+use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
use smallvec::smallvec;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// - `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>>,
+ 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 (_body_id, 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, None, 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);
}
}
outlives_env: &OutlivesEnvironment<'tcx>,
) {
self.process_registered_region_obligations(
- outlives_env.region_bound_pairs_map(),
+ outlives_env.region_bound_pairs(),
outlives_env.param_env,
);
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
}
- let body_id_map: FxHashMap<_, _> = infcx
- .inner
- .borrow()
- .region_obligations()
- .iter()
- .map(|&(id, _)| (id, vec![]))
- .collect();
-
- infcx.process_registered_region_obligations(&body_id_map, full_env);
+ infcx.process_registered_region_obligations(&Default::default(), full_env);
let region_data = infcx
.inner
//use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::CRATE_HIR_ID;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{util, TraitEngine};
use rustc_middle::traits::specialization_graph::OverlapMode;
return false;
}
- let mut outlives_env = OutlivesEnvironment::new(param_env);
- // FIXME -- add "assumed to be well formed" types into the `outlives_env`
-
- // "Save" the accumulated implied bounds into the outlives environment
- // (due to the FIXME above, there aren't any, but this step is still needed).
- // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used
- // by the "dummy" causes elsewhere (body-id is only relevant when checking
- // function bodies with closures).
- outlives_env.save_implied_bounds(CRATE_HIR_ID);
-
- infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env);
+ // FIXME -- also add "assumed to be well formed" types into the `outlives_env`
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
let errors = infcx.resolve_regions(&outlives_env);
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias => {
- let mut outlives_environment = OutlivesEnvironment::new(param_env);
- outlives_environment.save_implied_bounds(hir_id);
+ let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(&outlives_environment);
}
}
// lifetime parameters.
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
- outlives_environment.save_implied_bounds(impl_m_hir_id);
infcx.check_region_obligations_and_report_errors(&outlives_environment);
Ok(())
return;
}
- let mut outlives_environment = OutlivesEnvironment::new(param_env);
- outlives_environment.save_implied_bounds(impl_c_hir_id);
+ let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.resolve_regions_and_report_errors(&outlives_environment);
});
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let mut outlives_environment = OutlivesEnvironment::new(param_env);
- outlives_environment.save_implied_bounds(impl_ty_hir_id);
+ let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(&outlives_environment);
Ok(())
};
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(infcx, implied_bounds, impl_ty_hir_id);
- outlives_environment.save_implied_bounds(impl_ty_hir_id);
infcx.check_region_obligations_and_report_errors(&outlives_environment);
Ok(())
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(&fcx.infcx, wf_tys, id);
- outlives_environment.save_implied_bounds(id);
fcx.infcx.check_region_obligations_and_report_errors(&outlives_environment);
});
}
tcx.infer_ctxt().enter(|infcx| {
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
- outlives_environment.save_implied_bounds(id);
- let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
+ let region_bound_pairs = outlives_environment.region_bound_pairs();
add_constraints(&infcx, region_bound_pairs);