Skip to content

Commit 62b272d

Browse files
committed
Auto merge of #99501 - lcnr:check-regions-infcx, r=oli-obk
move `considering_regions` to the infcx it seems weird to prove some obligations which constrain inference vars while ignoring regions in a context which considers regions. This is especially weird because even for a fulfillment context with ignored regions, we still added region outlives bounds when directly relating regions. tbh our handling of regions is still very weird, but at least this is a step in the right direction imo. r? rust-lang/types
2 parents af7ab34 + 43ccacf commit 62b272d

File tree

16 files changed

+82
-122
lines changed

16 files changed

+82
-122
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ E0790: include_str!("./error_codes/E0790.md"),
559559
// E0273, // on_unimplemented #1
560560
// E0274, // on_unimplemented #2
561561
// E0278, // requirement is not satisfied
562-
E0279, // requirement is not satisfied
562+
// E0279,
563563
E0280, // requirement is not satisfied
564564
// E0285, // overflow evaluation builtin bounds
565565
// E0296, // replaced with a generic attribute input check

compiler/rustc_infer/src/infer/at.rs

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
6565
Self {
6666
tcx: self.tcx,
6767
defining_use_anchor: self.defining_use_anchor,
68+
considering_regions: self.considering_regions,
6869
in_progress_typeck_results: self.in_progress_typeck_results,
6970
inner: self.inner.clone(),
7071
skip_leak_check: self.skip_leak_check.clone(),

compiler/rustc_infer/src/infer/mod.rs

+25-12
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ pub struct InferCtxt<'a, 'tcx> {
265265
/// might come up during inference or typeck.
266266
pub defining_use_anchor: DefiningAnchor,
267267

268+
/// Whether this inference context should care about region obligations in
269+
/// the root universe. Most notably, this is used during hir typeck as region
270+
/// solving is left to borrowck instead.
271+
pub considering_regions: bool,
272+
268273
/// During type-checking/inference of a body, `in_progress_typeck_results`
269274
/// contains a reference to the typeck results being built up, which are
270275
/// used for reading closure kinds/signatures as they are inferred,
@@ -539,8 +544,9 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
539544
/// without using `Rc` or something similar.
540545
pub struct InferCtxtBuilder<'tcx> {
541546
tcx: TyCtxt<'tcx>,
542-
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
543547
defining_use_anchor: DefiningAnchor,
548+
considering_regions: bool,
549+
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
544550
}
545551

546552
pub trait TyCtxtInferExt<'tcx> {
@@ -552,6 +558,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
552558
InferCtxtBuilder {
553559
tcx: self,
554560
defining_use_anchor: DefiningAnchor::Error,
561+
considering_regions: true,
555562
fresh_typeck_results: None,
556563
}
557564
}
@@ -577,6 +584,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
577584
self
578585
}
579586

587+
pub fn ignoring_regions(mut self) -> Self {
588+
self.considering_regions = false;
589+
self
590+
}
591+
580592
/// Given a canonical value `C` as a starting point, create an
581593
/// inference context that contains each of the bound values
582594
/// within instantiated as a fresh variable. The `f` closure is
@@ -601,11 +613,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
601613
}
602614

603615
pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
604-
let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
616+
let InferCtxtBuilder {
617+
tcx,
618+
defining_use_anchor,
619+
considering_regions,
620+
ref fresh_typeck_results,
621+
} = *self;
605622
let in_progress_typeck_results = fresh_typeck_results.as_ref();
606623
f(InferCtxt {
607624
tcx,
608625
defining_use_anchor,
626+
considering_regions,
609627
in_progress_typeck_results,
610628
inner: RefCell::new(InferCtxtInner::new()),
611629
lexical_region_resolutions: RefCell::new(None),
@@ -1043,16 +1061,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10431061
&self,
10441062
cause: &traits::ObligationCause<'tcx>,
10451063
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
1046-
) -> UnitResult<'tcx> {
1047-
self.commit_if_ok(|_snapshot| {
1048-
let ty::OutlivesPredicate(r_a, r_b) =
1049-
self.replace_bound_vars_with_placeholders(predicate);
1050-
let origin = SubregionOrigin::from_obligation_cause(cause, || {
1051-
RelateRegionParamBound(cause.span)
1052-
});
1053-
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
1054-
Ok(())
1055-
})
1064+
) {
1065+
let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate);
1066+
let origin =
1067+
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
1068+
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
10561069
}
10571070

10581071
/// Number of type variables created so far.

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -793,9 +793,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
793793
}
794794
ty::PredicateKind::RegionOutlives(binder) => {
795795
let binder = bound_predicate.rebind(binder);
796-
if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
797-
return false;
798-
}
796+
select.infcx().region_outlives_predicate(&dummy_cause, binder)
799797
}
800798
ty::PredicateKind::TypeOutlives(binder) => {
801799
let binder = bound_predicate.rebind(binder);

compiler/rustc_trait_selection/src/traits/codegen.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>(
3030

3131
// Do the initial selection for the obligation. This yields the
3232
// shallow result we are looking for -- that is, what specific impl.
33-
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(|infcx| {
33+
let mut infcx_builder =
34+
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
35+
infcx_builder.enter(|infcx| {
3436
//~^ HACK `Bubble` is required for
3537
// this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
3638
let mut selcx = SelectionContext::new(&infcx);

compiler/rustc_trait_selection/src/traits/engine.rs

-10
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
1515

1616
pub trait TraitEngineExt<'tcx> {
1717
fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
18-
19-
fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self>;
2018
}
2119

2220
impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
@@ -27,14 +25,6 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
2725
Box::new(FulfillmentContext::new())
2826
}
2927
}
30-
31-
fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self> {
32-
if tcx.sess.opts.unstable_opts.chalk {
33-
Box::new(ChalkFulfillmentContext::new())
34-
} else {
35-
Box::new(FulfillmentContext::new_ignoring_regions())
36-
}
37-
}
3828
}
3929

4030
/// Used if you want to have pleasant experience when dealing

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+3-18
Original file line numberDiff line numberDiff line change
@@ -789,24 +789,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
789789
span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
790790
}
791791

792-
ty::PredicateKind::RegionOutlives(predicate) => {
793-
let predicate = bound_predicate.rebind(predicate);
794-
let predicate = self.resolve_vars_if_possible(predicate);
795-
let err = self
796-
.region_outlives_predicate(&obligation.cause, predicate)
797-
.err()
798-
.unwrap();
799-
struct_span_err!(
800-
self.tcx.sess,
801-
span,
802-
E0279,
803-
"the requirement `{}` is not satisfied (`{}`)",
804-
predicate,
805-
err,
806-
)
807-
}
808-
809-
ty::PredicateKind::Projection(..) | ty::PredicateKind::TypeOutlives(..) => {
792+
ty::PredicateKind::RegionOutlives(..)
793+
| ty::PredicateKind::Projection(..)
794+
| ty::PredicateKind::TypeOutlives(..) => {
810795
let predicate = self.resolve_vars_if_possible(obligation.predicate);
811796
struct_span_err!(
812797
self.tcx.sess,

compiler/rustc_trait_selection/src/traits/fulfill.rs

+8-38
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,6 @@ pub struct FulfillmentContext<'tcx> {
5858

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

61-
// Should this fulfillment context register type-lives-for-region
62-
// obligations on its parent infcx? In some cases, region
63-
// obligations are either already known to hold (normalization) or
64-
// hopefully verified elsewhere (type-impls-bound), and therefore
65-
// should not be checked.
66-
//
67-
// Note that if we are normalizing a type that we already
68-
// know is well-formed, there should be no harm setting this
69-
// to true - all the region variables should be determinable
70-
// using the RFC 447 rules, which don't depend on
71-
// type-lives-for-region constraints, and because the type
72-
// is well-formed, the constraints should hold.
73-
register_region_obligations: bool,
7461
// Is it OK to register obligations into this infcx inside
7562
// an infcx snapshot?
7663
//
@@ -103,7 +90,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
10390
FulfillmentContext {
10491
predicates: ObligationForest::new(),
10592
relationships: FxHashMap::default(),
106-
register_region_obligations: true,
10793
usable_in_snapshot: false,
10894
}
10995
}
@@ -112,30 +98,18 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
11298
FulfillmentContext {
11399
predicates: ObligationForest::new(),
114100
relationships: FxHashMap::default(),
115-
register_region_obligations: true,
116101
usable_in_snapshot: true,
117102
}
118103
}
119104

120-
pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
121-
FulfillmentContext {
122-
predicates: ObligationForest::new(),
123-
relationships: FxHashMap::default(),
124-
register_region_obligations: false,
125-
usable_in_snapshot: false,
126-
}
127-
}
128-
129105
/// Attempts to select obligations using `selcx`.
130106
fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
131107
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
132108
let _enter = span.enter();
133109

134110
// Process pending obligations.
135-
let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut FulfillProcessor {
136-
selcx,
137-
register_region_obligations: self.register_region_obligations,
138-
});
111+
let outcome: Outcome<_, _> =
112+
self.predicates.process_obligations(&mut FulfillProcessor { selcx });
139113

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

240214
struct FulfillProcessor<'a, 'b, 'tcx> {
241215
selcx: &'a mut SelectionContext<'b, 'tcx>,
242-
register_region_obligations: bool,
243216
}
244217

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

387360
ty::PredicateKind::RegionOutlives(data) => {
388-
match infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)) {
389-
Ok(()) => ProcessResult::Changed(vec![]),
390-
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
361+
if infcx.considering_regions || data.has_placeholders() {
362+
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
391363
}
364+
365+
ProcessResult::Changed(vec![])
392366
}
393367

394368
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
395-
if self.register_region_obligations {
396-
self.selcx.infcx().register_region_obligation_with_cause(
397-
t_a,
398-
r_b,
399-
&obligation.cause,
400-
);
369+
if infcx.considering_regions {
370+
infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause);
401371
}
402372
ProcessResult::Changed(vec![])
403373
}

compiler/rustc_trait_selection/src/traits/mod.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
163163
// The handling of regions in this area of the code is terrible,
164164
// see issue #29149. We should be able to improve on this with
165165
// NLL.
166-
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
166+
let mut fulfill_cx = FulfillmentContext::new();
167167

168168
// We can use a dummy node-id here because we won't pay any mind
169169
// to region obligations that arise (there shouldn't really be any
@@ -207,21 +207,21 @@ fn do_normalize_predicates<'tcx>(
207207
predicates: Vec<ty::Predicate<'tcx>>,
208208
) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
209209
let span = cause.span;
210-
tcx.infer_ctxt().enter(|infcx| {
211-
// FIXME. We should really... do something with these region
212-
// obligations. But this call just continues the older
213-
// behavior (i.e., doesn't cause any new bugs), and it would
214-
// take some further refactoring to actually solve them. In
215-
// particular, we would have to handle implied bounds
216-
// properly, and that code is currently largely confined to
217-
// regionck (though I made some efforts to extract it
218-
// out). -nmatsakis
219-
//
220-
// @arielby: In any case, these obligations are checked
221-
// by wfcheck anyway, so I'm not sure we have to check
222-
// them here too, and we will remove this function when
223-
// we move over to lazy normalization *anyway*.
224-
let fulfill_cx = FulfillmentContext::new_ignoring_regions();
210+
// FIXME. We should really... do something with these region
211+
// obligations. But this call just continues the older
212+
// behavior (i.e., doesn't cause any new bugs), and it would
213+
// take some further refactoring to actually solve them. In
214+
// particular, we would have to handle implied bounds
215+
// properly, and that code is currently largely confined to
216+
// regionck (though I made some efforts to extract it
217+
// out). -nmatsakis
218+
//
219+
// @arielby: In any case, these obligations are checked
220+
// by wfcheck anyway, so I'm not sure we have to check
221+
// them here too, and we will remove this function when
222+
// we move over to lazy normalization *anyway*.
223+
tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
224+
let fulfill_cx = FulfillmentContext::new();
225225
let predicates =
226226
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
227227
Ok(predicates) => predicates,

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -207,18 +207,7 @@ fn fulfill_implication<'a, 'tcx>(
207207
// (which are packed up in penv)
208208

209209
infcx.save_and_restore_in_snapshot_flag(|infcx| {
210-
// If we came from `translate_substs`, we already know that the
211-
// predicates for our impl hold (after all, we know that a more
212-
// specialized impl holds, so our impl must hold too), and
213-
// we only want to process the projections to determine the
214-
// the types in our substs using RFC 447, so we can safely
215-
// ignore region obligations, which allows us to avoid threading
216-
// a node-id to assign them with.
217-
//
218-
// If we came from specialization graph construction, then
219-
// we already make a mockery out of the region system, so
220-
// why not ignore them a bit earlier?
221-
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
210+
let mut fulfill_cx = FulfillmentContext::new();
222211
for oblig in obligations.chain(more_obligations) {
223212
fulfill_cx.register_predicate_obligation(&infcx, oblig);
224213
}

compiler/rustc_typeck/src/check/inherited.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ impl<'tcx> Inherited<'_, 'tcx> {
8686
let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner;
8787

8888
InheritedBuilder {
89-
infcx: tcx.infer_ctxt().with_fresh_in_progress_typeck_results(hir_owner),
89+
infcx: tcx
90+
.infer_ctxt()
91+
.ignoring_regions()
92+
.with_fresh_in_progress_typeck_results(hir_owner),
9093
def_id,
9194
}
9295
}
@@ -113,7 +116,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
113116
maybe_typeck_results: infcx.in_progress_typeck_results,
114117
},
115118
infcx,
116-
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new_ignoring_regions(tcx)),
119+
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
117120
locals: RefCell::new(Default::default()),
118121
deferred_sized_obligations: RefCell::new(Vec::new()),
119122
deferred_call_resolutions: RefCell::new(Default::default()),

compiler/rustc_typeck/src/check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ mod op;
8787
mod pat;
8888
mod place_op;
8989
mod region;
90-
mod regionck;
90+
pub mod regionck;
9191
pub mod rvalue_scopes;
9292
mod upvar;
93-
mod wfcheck;
93+
pub mod wfcheck;
9494
pub mod writeback;
9595

9696
use check::{check_abi, check_fn, check_mod_item_types};

compiler/rustc_typeck/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1913,7 +1913,7 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
19131913
}
19141914
}
19151915

1916-
pub(super) fn impl_implied_bounds<'tcx>(
1916+
pub fn impl_implied_bounds<'tcx>(
19171917
tcx: TyCtxt<'tcx>,
19181918
param_env: ty::ParamEnv<'tcx>,
19191919
impl_def_id: LocalDefId,

compiler/rustc_typeck/src/coherence/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
116116
// why this field does not implement Copy. This is useful because sometimes
117117
// it is not immediately clear why Copy is not implemented for a field, since
118118
// all we point at is the field itself.
119-
tcx.infer_ctxt().enter(|infcx| {
120-
let mut fulfill_cx = traits::FulfillmentContext::new_ignoring_regions();
119+
tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
120+
let mut fulfill_cx = traits::FulfillmentContext::new();
121121
fulfill_cx.register_bound(
122122
&infcx,
123123
param_env,

0 commit comments

Comments
 (0)