Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

continue nll transition by removing stuff #98584

Merged
merged 6 commits into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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