Skip to content

move considering_regions to the infcx #99501

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

Merged
merged 2 commits into from
Jul 21, 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_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ E0790: include_str!("./error_codes/E0790.md"),
// E0273, // on_unimplemented #1
// E0274, // on_unimplemented #2
// E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
// E0279,
E0280, // requirement is not satisfied
// E0285, // overflow evaluation builtin bounds
// E0296, // replaced with a generic attribute input check
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Self {
tcx: self.tcx,
defining_use_anchor: self.defining_use_anchor,
considering_regions: self.considering_regions,
in_progress_typeck_results: self.in_progress_typeck_results,
inner: self.inner.clone(),
skip_leak_check: self.skip_leak_check.clone(),
Expand Down
37 changes: 25 additions & 12 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ pub struct InferCtxt<'a, 'tcx> {
/// might come up during inference or typeck.
pub defining_use_anchor: DefiningAnchor,

/// Whether this inference context should care about region obligations in
/// the root universe. Most notably, this is used during hir typeck as region
/// solving is left to borrowck instead.
pub considering_regions: bool,

/// During type-checking/inference of a body, `in_progress_typeck_results`
/// contains a reference to the typeck results being built up, which are
/// used for reading closure kinds/signatures as they are inferred,
Expand Down Expand Up @@ -539,8 +544,9 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
/// without using `Rc` or something similar.
pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
defining_use_anchor: DefiningAnchor,
considering_regions: bool,
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
}

pub trait TyCtxtInferExt<'tcx> {
Expand All @@ -552,6 +558,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
InferCtxtBuilder {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
considering_regions: true,
fresh_typeck_results: None,
}
}
Expand All @@ -577,6 +584,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self
}

pub fn ignoring_regions(mut self) -> Self {
self.considering_regions = false;
self
}

/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
Expand All @@ -601,11 +613,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}

pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
let InferCtxtBuilder {
tcx,
defining_use_anchor,
considering_regions,
ref fresh_typeck_results,
} = *self;
let in_progress_typeck_results = fresh_typeck_results.as_ref();
f(InferCtxt {
tcx,
defining_use_anchor,
considering_regions,
in_progress_typeck_results,
inner: RefCell::new(InferCtxtInner::new()),
lexical_region_resolutions: RefCell::new(None),
Expand Down Expand Up @@ -1043,16 +1061,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self,
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) -> UnitResult<'tcx> {
self.commit_if_ok(|_snapshot| {
let ty::OutlivesPredicate(r_a, r_b) =
self.replace_bound_vars_with_placeholders(predicate);
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
});
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
Ok(())
})
) {
let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate);
let origin =
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
}

/// Number of type variables created so far.
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
}
ty::PredicateKind::RegionOutlives(binder) => {
let binder = bound_predicate.rebind(binder);
if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
return false;
}
select.infcx().region_outlives_predicate(&dummy_cause, binder)
}
ty::PredicateKind::TypeOutlives(binder) => {
let binder = bound_predicate.rebind(binder);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/traits/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>(

// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(|infcx| {
let mut infcx_builder =
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
infcx_builder.enter(|infcx| {
//~^ HACK `Bubble` is required for
// this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
let mut selcx = SelectionContext::new(&infcx);
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};

pub trait TraitEngineExt<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;

fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self>;
}

impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
Expand All @@ -27,14 +25,6 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
Box::new(FulfillmentContext::new())
}
}

fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self> {
if tcx.sess.opts.unstable_opts.chalk {
Box::new(ChalkFulfillmentContext::new())
} else {
Box::new(FulfillmentContext::new_ignoring_regions())
}
}
}

/// Used if you want to have pleasant experience when dealing
Expand Down
21 changes: 3 additions & 18 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,24 +789,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
}

ty::PredicateKind::RegionOutlives(predicate) => {
let predicate = bound_predicate.rebind(predicate);
let predicate = self.resolve_vars_if_possible(predicate);
let err = self
.region_outlives_predicate(&obligation.cause, predicate)
.err()
.unwrap();
struct_span_err!(
self.tcx.sess,
span,
E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err,
)
}

ty::PredicateKind::Projection(..) | ty::PredicateKind::TypeOutlives(..) => {
ty::PredicateKind::RegionOutlives(..)
| ty::PredicateKind::Projection(..)
| ty::PredicateKind::TypeOutlives(..) => {
let predicate = self.resolve_vars_if_possible(obligation.predicate);
struct_span_err!(
self.tcx.sess,
Expand Down
46 changes: 8 additions & 38 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,6 @@ pub struct FulfillmentContext<'tcx> {

relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,

// Should this fulfillment context register type-lives-for-region
// obligations on its parent infcx? In some cases, region
// obligations are either already known to hold (normalization) or
// hopefully verified elsewhere (type-impls-bound), and therefore
// should not be checked.
//
// Note that if we are normalizing a type that we already
// know is well-formed, there should be no harm setting this
// to true - all the region variables should be determinable
// using the RFC 447 rules, which don't depend on
// type-lives-for-region constraints, and because the type
// is well-formed, the constraints should hold.
register_region_obligations: bool,
// Is it OK to register obligations into this infcx inside
// an infcx snapshot?
//
Expand Down Expand Up @@ -103,7 +90,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
relationships: FxHashMap::default(),
register_region_obligations: true,
usable_in_snapshot: false,
}
}
Expand All @@ -112,30 +98,18 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
relationships: FxHashMap::default(),
register_region_obligations: true,
usable_in_snapshot: true,
}
}

pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
relationships: FxHashMap::default(),
register_region_obligations: false,
usable_in_snapshot: false,
}
}

/// Attempts to select obligations using `selcx`.
fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
let _enter = span.enter();

// Process pending obligations.
let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut FulfillProcessor {
selcx,
register_region_obligations: self.register_region_obligations,
});
let outcome: Outcome<_, _> =
self.predicates.process_obligations(&mut FulfillProcessor { selcx });

// FIXME: if we kept the original cache key, we could mark projection
// obligations as complete for the projection cache here.
Expand Down Expand Up @@ -239,7 +213,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {

struct FulfillProcessor<'a, 'b, 'tcx> {
selcx: &'a mut SelectionContext<'b, 'tcx>,
register_region_obligations: bool,
}

fn mk_pending(os: Vec<PredicateObligation<'_>>) -> Vec<PendingPredicateObligation<'_>> {
Expand Down Expand Up @@ -385,19 +358,16 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}

ty::PredicateKind::RegionOutlives(data) => {
match infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
if infcx.considering_regions || data.has_placeholders() {
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
}

ProcessResult::Changed(vec![])
}

ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
if self.register_region_obligations {
self.selcx.infcx().register_region_obligation_with_cause(
t_a,
r_b,
&obligation.cause,
);
if infcx.considering_regions {
infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause);
}
ProcessResult::Changed(vec![])
}
Expand Down
32 changes: 16 additions & 16 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
// The handling of regions in this area of the code is terrible,
// see issue #29149. We should be able to improve on this with
// NLL.
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
let mut fulfill_cx = FulfillmentContext::new();

// We can use a dummy node-id here because we won't pay any mind
// to region obligations that arise (there shouldn't really be any
Expand Down Expand Up @@ -207,21 +207,21 @@ fn do_normalize_predicates<'tcx>(
predicates: Vec<ty::Predicate<'tcx>>,
) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
let span = cause.span;
tcx.infer_ctxt().enter(|infcx| {
// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
// behavior (i.e., doesn't cause any new bugs), and it would
// take some further refactoring to actually solve them. In
// particular, we would have to handle implied bounds
// properly, and that code is currently largely confined to
// regionck (though I made some efforts to extract it
// out). -nmatsakis
//
// @arielby: In any case, these obligations are checked
// by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when
// we move over to lazy normalization *anyway*.
let fulfill_cx = FulfillmentContext::new_ignoring_regions();
// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
// behavior (i.e., doesn't cause any new bugs), and it would
// take some further refactoring to actually solve them. In
// particular, we would have to handle implied bounds
// properly, and that code is currently largely confined to
// regionck (though I made some efforts to extract it
// out). -nmatsakis
//
// @arielby: In any case, these obligations are checked
// by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when
// we move over to lazy normalization *anyway*.
tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
let fulfill_cx = FulfillmentContext::new();
let predicates =
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
Ok(predicates) => predicates,
Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,7 @@ fn fulfill_implication<'a, 'tcx>(
// (which are packed up in penv)

infcx.save_and_restore_in_snapshot_flag(|infcx| {
// If we came from `translate_substs`, we already know that the
// predicates for our impl hold (after all, we know that a more
// specialized impl holds, so our impl must hold too), and
// we only want to process the projections to determine the
// the types in our substs using RFC 447, so we can safely
// ignore region obligations, which allows us to avoid threading
// a node-id to assign them with.
//
// If we came from specialization graph construction, then
// we already make a mockery out of the region system, so
// why not ignore them a bit earlier?
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
let mut fulfill_cx = FulfillmentContext::new();
for oblig in obligations.chain(more_obligations) {
fulfill_cx.register_predicate_obligation(&infcx, oblig);
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_typeck/src/check/inherited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ impl<'tcx> Inherited<'_, 'tcx> {
let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner;

InheritedBuilder {
infcx: tcx.infer_ctxt().with_fresh_in_progress_typeck_results(hir_owner),
infcx: tcx
.infer_ctxt()
.ignoring_regions()
.with_fresh_in_progress_typeck_results(hir_owner),
def_id,
}
}
Expand All @@ -113,7 +116,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
maybe_typeck_results: infcx.in_progress_typeck_results,
},
infcx,
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new_ignoring_regions(tcx)),
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
locals: RefCell::new(Default::default()),
deferred_sized_obligations: RefCell::new(Vec::new()),
deferred_call_resolutions: RefCell::new(Default::default()),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ mod op;
mod pat;
mod place_op;
mod region;
mod regionck;
pub mod regionck;
pub mod rvalue_scopes;
mod upvar;
mod wfcheck;
pub mod wfcheck;
pub mod writeback;

use check::{check_abi, check_fn, check_mod_item_types};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,7 +1913,7 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
}
}

pub(super) fn impl_implied_bounds<'tcx>(
pub fn impl_implied_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: LocalDefId,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
// why this field does not implement Copy. This is useful because sometimes
// it is not immediately clear why Copy is not implemented for a field, since
// all we point at is the field itself.
tcx.infer_ctxt().enter(|infcx| {
let mut fulfill_cx = traits::FulfillmentContext::new_ignoring_regions();
tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
let mut fulfill_cx = traits::FulfillmentContext::new();
fulfill_cx.register_bound(
&infcx,
param_env,
Expand Down
Loading