Skip to content

Commit

Permalink
Auto merge of rust-lang#98584 - lcnr:region-stuff-more-beans, r=oli-obk
Browse files Browse the repository at this point in the history
continue nll transition by removing stuff

r? `@jackh726` for now

building on rust-lang#98641
  • Loading branch information
bors committed Jul 5, 2022
2 parents 54f79ba + 9f95c60 commit efb171e
Show file tree
Hide file tree
Showing 21 changed files with 111 additions and 1,159 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
});
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_infer/src/infer/free_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand All @@ -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> {
Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
17 changes: 5 additions & 12 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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>,

Expand All @@ -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
}

Expand Down Expand Up @@ -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) = {
Expand All @@ -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);
Expand All @@ -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
Expand Down
88 changes: 10 additions & 78 deletions compiler/rustc_infer/src/infer/outlives/env.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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:
//
Expand All @@ -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
Expand All @@ -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));
Expand All @@ -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.
Expand All @@ -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()) {
Expand Down
55 changes: 25 additions & 30 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -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(
Expand All @@ -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)
}

Expand Down Expand Up @@ -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!(
Expand All @@ -157,26 +147,31 @@ 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
);

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, &region_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, &region_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`
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
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
Expand Down
Loading

0 comments on commit efb171e

Please sign in to comment.