diff options
| author | bors <bors@rust-lang.org> | 2022-07-05 14:58:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-07-05 14:58:31 +0000 |
| commit | efb171e2350de2bec6dd1f035b99bc00535c1c15 (patch) | |
| tree | 978ba25322f303839483357bcf27aa55e9303482 /compiler/rustc_infer/src | |
| parent | 54f79babae06d3772c067f696e5b12db822ae25f (diff) | |
| parent | 9f95c605f83bcf4c158ea4b3fd5a7abb825a4178 (diff) | |
| download | rust-efb171e2350de2bec6dd1f035b99bc00535c1c15.tar.gz rust-efb171e2350de2bec6dd1f035b99bc00535c1c15.zip | |
Auto merge of #98584 - lcnr:region-stuff-more-beans, r=oli-obk
continue nll transition by removing stuff r? `@jackh726` for now building on #98641
Diffstat (limited to 'compiler/rustc_infer/src')
6 files changed, 48 insertions, 136 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8938ed78a94..7120d5ad934 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -128,7 +128,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( tcx, - region_obligations.iter().map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)), + region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)), region_constraints, ) }); diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 082eb1bf111..fad949a3bc6 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,6 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Lift, Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. @@ -14,16 +13,13 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt}; pub(crate) struct RegionRelations<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, - /// The context used for debug messages - pub context: DefId, - /// Free-region relationships. pub free_regions: &'a FreeRegionMap<'tcx>, } impl<'a, 'tcx> RegionRelations<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, context: DefId, free_regions: &'a FreeRegionMap<'tcx>) -> Self { - Self { tcx, context, free_regions } + pub fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { + Self { tcx, free_regions } } pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 68c709a2e24..87fa22b3835 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -120,13 +120,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ) -> LexicalRegionResolutions<'tcx> { let mut var_data = self.construct_var_data(self.tcx()); - // Dorky hack to cause `dump_constraints` to only get called - // if debug mode is enabled: - debug!( - "----() End constraint listing (context={:?}) {:?}---", - self.region_rels.context, - self.dump_constraints(self.region_rels) - ); + if cfg!(debug_assertions) { + self.dump_constraints(); + } let graph = self.construct_graph(); self.expand_givens(&graph); @@ -156,8 +152,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { - debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); + #[instrument(level = "debug", skip(self))] + fn dump_constraints(&self) { for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { debug!("Constraint {} => {:?}", idx, constraint); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6f88b83a473..c73302c7e41 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -15,7 +15,6 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; @@ -147,7 +146,7 @@ pub struct InferCtxtInner<'tcx> { /// for each body-id in this map, which will process the /// obligations within. This is expected to be done 'late enough' /// that all type inference variables have been bound and so forth. - region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, + region_obligations: Vec<RegionObligation<'tcx>>, undo_log: InferCtxtUndoLogs<'tcx>, @@ -171,7 +170,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - pub fn region_obligations(&self) -> &[(hir::HirId, RegionObligation<'tcx>)] { + pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] { &self.region_obligations } @@ -1267,7 +1266,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// `resolve_vars_if_possible` as well as `fully_resolve`. pub fn resolve_regions( &self, - region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec<RegionResolutionError<'tcx>> { let (var_infos, data) = { @@ -1286,8 +1284,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .into_infos_and_data() }; - let region_rels = - &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map()); + let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); @@ -1302,12 +1299,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions_and_report_errors( - &self, - region_context: DefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) { - let errors = self.resolve_regions(region_context, outlives_env); + pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + let errors = self.resolve_regions(outlives_env); if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 9ddda7b92eb..b897de7315a 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,8 +1,6 @@ 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; @@ -31,9 +29,7 @@ pub struct OutlivesEnvironment<'tcx> { 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: // @@ -43,24 +39,15 @@ pub struct OutlivesEnvironment<'tcx> { // } // 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 @@ -73,8 +60,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { 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)); @@ -87,62 +73,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { &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. @@ -164,11 +97,10 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { 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()) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1c1906f3375..b839566bec9 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -60,18 +60,16 @@ //! 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_data_structures::undo_log::UndoLogs; 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 smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -80,16 +78,11 @@ 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( @@ -109,14 +102,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) }); - 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) } @@ -144,10 +134,10 @@ 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!( @@ -157,7 +147,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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 @@ -165,18 +155,23 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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); } } + + pub fn check_region_obligations_and_report_errors( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.process_registered_region_obligations( + outlives_env.region_bound_pairs(), + outlives_env.param_env, + ); + + self.resolve_regions_and_report_errors(outlives_env) + } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` |
