Skip to content

Commit

Permalink
add with_bounds to OutlivesEnvironment and implied_bounds_tys t…
Browse files Browse the repository at this point in the history
…o `outlives_bounds::InferCtxtExt`
  • Loading branch information
SparrowLii committed Aug 22, 2022
1 parent 5d9e4d0 commit d037f18
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 82 deletions.
41 changes: 20 additions & 21 deletions compiler/rustc_infer/src/infer/outlives/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,10 @@ pub struct OutlivesEnvironment<'tcx> {
region_bound_pairs: RegionBoundPairs<'tcx>,
}

/// Builder of OutlivesEnvironment. Use this structure if you need to add more outlives
/// bounds than `explicit_outlives_bounds(param_env)`.
pub struct OutlivesEnvironmentBuilder<'tcx> {
pub param_env: ty::ParamEnv<'tcx>,
/// Builder of OutlivesEnvironment.
struct OutlivesEnvironmentBuilder<'tcx> {
param_env: ty::ParamEnv<'tcx>,
region_relation: TransitiveRelationBuilder<Region<'tcx>>,

region_bound_pairs: RegionBoundPairs<'tcx>,
}

Expand All @@ -69,7 +67,7 @@ pub type RegionBoundPairs<'tcx> =

impl<'tcx> OutlivesEnvironment<'tcx> {
/// Create a builder using `ParamEnv` and add explicit outlives bounds into it.
pub fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
let mut builder = OutlivesEnvironmentBuilder {
param_env,
region_relation: Default::default(),
Expand All @@ -87,6 +85,17 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
Self::builder(param_env).build()
}

/// Create a new `OutlivesEnvironment` with extra outlives bounds.
pub fn with_bounds<'a>(
param_env: ty::ParamEnv<'tcx>,
infcx: Option<&InferCtxt<'a, 'tcx>>,
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
) -> Self {
let mut builder = Self::builder(param_env);
builder.add_outlives_bounds(infcx, extra_bounds);
builder.build()
}

/// Borrows current value of the `free_region_map`.
pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
&self.free_region_map
Expand All @@ -108,26 +117,14 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
}
}

// Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
// (with the exception that `'static: 'x` is not notable)
fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
if sub.is_free_or_static() && sup.is_free() {
self.region_relation.add(sub, sup)
}
}

/// Processes outlives bounds that are known to hold, whether from implied or other sources.
///
/// The `infcx` parameter is optional; if the implied bounds may
/// contain inference variables, it must be supplied, in which
/// case we will register "givens" on the inference context. (See
/// `RegionConstraintData`.)
pub fn add_outlives_bounds<I>(
&mut self,
infcx: Option<&InferCtxt<'a, 'tcx>>,
outlives_bounds: I,
) where
fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
where
I: IntoIterator<Item = OutlivesBound<'tcx>>,
{
// Record relationships such as `T:'x` that don't go into the
Expand Down Expand Up @@ -159,7 +156,9 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
// system to be more general and to make use
// of *every* relationship that arises here,
// but presently we do not.)
self.relate_regions(r_a, r_b);
if r_a.is_free_or_static() && r_b.is_free() {
self.region_relation.add(r_a, r_b)
}
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_typeck/src/check/compare_method.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::potentially_plural_count;
use crate::check::regionck::OutlivesEnvironmentExt;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
use rustc_hir as hir;
Expand Down Expand Up @@ -401,9 +401,11 @@ fn compare_predicate_entailment<'tcx>(

// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let mut outlives_environment = OutlivesEnvironment::builder(param_env);
outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
let outlives_environment = outlives_environment.build();
let outlives_environment = OutlivesEnvironment::with_bounds(
param_env,
Some(infcx),
infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
);
infcx.check_region_obligations_and_report_errors(
impl_m.def_id.expect_local(),
&outlives_environment,
Expand Down Expand Up @@ -1517,6 +1519,7 @@ pub fn check_type_bounds<'tcx>(
let mut outlives_environment = OutlivesEnvironment::builder(param_env);
outlives_environment.add_implied_bounds(&infcx, assumed_wf_types, impl_ty_hir_id);
let outlives_environment = outlives_environment.build();

infcx.check_region_obligations_and_report_errors(
impl_ty.def_id.expect_local(),
&outlives_environment,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ mod op;
mod pat;
mod place_op;
mod region;
pub mod regionck;
pub mod rvalue_scopes;
mod upvar;
pub mod wfcheck;
Expand Down
47 changes: 0 additions & 47 deletions compiler/rustc_typeck/src/check/regionck.rs

This file was deleted.

11 changes: 7 additions & 4 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::check::regionck::OutlivesEnvironmentExt;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
Expand Down Expand Up @@ -107,6 +107,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
let mut outlives_environment = OutlivesEnvironment::builder(param_env);
outlives_environment.add_implied_bounds(infcx, assumed_wf_types, body_id);
let outlives_environment = outlives_environment.build();

infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
})
}
Expand Down Expand Up @@ -695,9 +696,11 @@ fn resolve_regions_with_wf_tys<'tcx>(
// region constraints get added and solved there and we need to test each
// call individually.
tcx.infer_ctxt().enter(|infcx| {
let mut outlives_environment = OutlivesEnvironment::builder(param_env);
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
let outlives_environment = outlives_environment.build();
let outlives_environment = OutlivesEnvironment::with_bounds(
param_env,
Some(&infcx),
infcx.implied_bounds_tys(param_env, id, wf_tys.iter().map(|ty| *ty)),
);
let region_bound_pairs = outlives_environment.region_bound_pairs();

add_constraints(&infcx, region_bound_pairs);
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@
//! cause use after frees with purely safe code in the same way as specializing
//! on traits with methods can.

use crate::check::regionck::OutlivesEnvironmentExt;
use crate::constrained_generic_params as cgp;
use crate::errors::SubstsOnOverriddenImpl;
use crate::outlives::outlives_bounds::InferCtxtExt;

use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, LocalDefId};
Expand Down Expand Up @@ -147,10 +147,17 @@ fn get_impl_substs<'tcx>(
let assumed_wf_types =
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);

let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
let impl2_substs =
translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);








let errors = ocx.select_all_or_error();
if !errors.is_empty() {
ocx.infcx.report_fulfillment_errors(&errors, None, false);
Expand Down
30 changes: 27 additions & 3 deletions compiler/rustc_typeck/src/outlives/outlives_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use rustc_hir as hir;
use rustc_middle::ty::{self, Ty};
use rustc_hir::HirId;
use rustc_middle::ty::{self, ParamEnv, Ty};
use rustc_trait_selection::infer::InferCtxt;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use rustc_trait_selection::traits::query::NoSolution;
use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};

pub use rustc_middle::traits::query::OutlivesBound;

pub trait InferCtxtExt<'tcx> {
pub trait InferCtxtExt<'a, 'tcx> {
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
ty: Ty<'tcx>,
) -> Vec<OutlivesBound<'tcx>>;

fn implied_bounds_tys(
&'a self,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
tys: impl IntoIterator<Item = Ty<'tcx>> + 'a,
) -> Box<dyn Iterator<Item = OutlivesBound<'tcx>> + 'a>;
}

impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
/// Implied bounds are region relationships that we deduce
/// automatically. The idea is that (e.g.) a caller must check that a
/// function's argument types are well-formed immediately before
Expand Down Expand Up @@ -87,4 +95,20 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {

output
}

fn implied_bounds_tys(
&'a self,
param_env: ParamEnv<'tcx>,
body_id: HirId,
tys: impl IntoIterator<Item = Ty<'tcx>> + 'a,
) -> Box<dyn Iterator<Item = OutlivesBound<'tcx>> + 'a> {
Box::new(
tys.into_iter()
.map(move |ty| {
let ty = self.resolve_vars_if_possible(ty);
self.implied_outlives_bounds(param_env, body_id, ty)
})
.flatten(),
)
}
}

0 comments on commit d037f18

Please sign in to comment.