Skip to content

Commit e70cbef

Browse files
committed
Auto merge of #103590 - compiler-errors:ocx-more, r=lcnr
(almost) Always use `ObligationCtxt` when dealing with canonical queries Hope this is a step in the right direction. cc rust-lang/types-team#50. r? `@lcnr`
2 parents c493bae + 2f9794b commit e70cbef

File tree

10 files changed

+121
-134
lines changed

10 files changed

+121
-134
lines changed

Diff for: compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+18-23
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use rustc_infer::infer::region_constraints::Constraint;
55
use rustc_infer::infer::region_constraints::RegionConstraintData;
66
use rustc_infer::infer::RegionVariableOrigin;
77
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
8-
use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
8+
use rustc_infer::traits::ObligationCause;
99
use rustc_middle::ty::error::TypeError;
1010
use rustc_middle::ty::RegionVid;
1111
use rustc_middle::ty::UniverseIndex;
1212
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
1313
use rustc_span::Span;
1414
use rustc_trait_selection::traits::query::type_op;
15-
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
15+
use rustc_trait_selection::traits::ObligationCtxt;
1616
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
1717

1818
use std::fmt;
@@ -240,9 +240,9 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
240240
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
241241
let (ref infcx, key, _) =
242242
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
243-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
244-
type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
245-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
243+
let ocx = ObligationCtxt::new(infcx);
244+
type_op_prove_predicate_with_cause(&ocx, key, cause);
245+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
246246
}
247247
}
248248

@@ -281,9 +281,7 @@ where
281281
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
282282
let (ref infcx, key, _) =
283283
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
284-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
285-
286-
let mut selcx = SelectionContext::new(infcx);
284+
let ocx = ObligationCtxt::new(infcx);
287285

288286
// FIXME(lqd): Unify and de-duplicate the following with the actual
289287
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
@@ -292,11 +290,9 @@ where
292290
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
293291
// after #85499 lands to see if its fixes have erased this difference.
294292
let (param_env, value) = key.into_parts();
295-
let Normalized { value: _, obligations } =
296-
rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value);
297-
fulfill_cx.register_predicate_obligations(infcx, obligations);
293+
let _ = ocx.normalize(cause, param_env, value.value);
298294

299-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
295+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
300296
}
301297
}
302298

@@ -329,9 +325,9 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
329325
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
330326
let (ref infcx, key, _) =
331327
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
332-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
333-
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?;
334-
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
328+
let ocx = ObligationCtxt::new(infcx);
329+
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
330+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
335331
}
336332
}
337333

@@ -372,25 +368,24 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
372368
}
373369
}
374370

375-
#[instrument(skip(fulfill_cx, infcx), level = "debug")]
371+
#[instrument(skip(ocx), level = "debug")]
376372
fn try_extract_error_from_fulfill_cx<'tcx>(
377-
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
378-
infcx: &InferCtxt<'tcx>,
373+
ocx: &ObligationCtxt<'_, 'tcx>,
379374
placeholder_region: ty::Region<'tcx>,
380375
error_region: Option<ty::Region<'tcx>>,
381376
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
382377
// We generally shouldn't have errors here because the query was
383378
// already run, but there's no point using `delay_span_bug`
384379
// when we're going to emit an error here anyway.
385-
let _errors = fulfill_cx.select_all_or_error(infcx);
386-
let region_constraints = infcx.with_region_constraints(|r| r.clone());
380+
let _errors = ocx.select_all_or_error();
381+
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
387382
try_extract_error_from_region_constraints(
388-
infcx,
383+
ocx.infcx,
389384
placeholder_region,
390385
error_region,
391386
&region_constraints,
392-
|vid| infcx.region_var_origin(vid),
393-
|vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))),
387+
|vid| ocx.infcx.region_var_origin(vid),
388+
|vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
394389
)
395390
}
396391

Diff for: compiler/rustc_hir_analysis/src/check/compare_method.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -290,23 +290,16 @@ fn compare_predicate_entailment<'tcx>(
290290
// type would be more appropriate. In other places we have a `Vec<Span>`
291291
// corresponding to their `Vec<Predicate>`, but we don't have that here.
292292
// Fixing this would improve the output of test `issue-83765.rs`.
293-
let mut result = infcx
294-
.at(&cause, param_env)
295-
.sup(trait_fty, impl_fty)
296-
.map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
293+
let mut result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
297294

298295
// HACK(RPITIT): #101614. When we are trying to infer the hidden types for
299296
// RPITITs, we need to equate the output tys instead of just subtyping. If
300297
// we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
301298
// us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
302299
// fixed up to `ReEmpty`, and which is certainly not what we want.
303300
if trait_fty.has_infer_types() {
304-
result = result.and_then(|()| {
305-
infcx
306-
.at(&cause, param_env)
307-
.eq(trait_sig.output(), impl_sig.output())
308-
.map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok))
309-
});
301+
result =
302+
result.and_then(|()| ocx.eq(&cause, param_env, trait_sig.output(), impl_sig.output()));
310303
}
311304

312305
if let Err(terr) = result {
@@ -1389,10 +1382,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
13891382

13901383
debug!("compare_const_impl: trait_ty={:?}", trait_ty);
13911384

1392-
let err = infcx
1393-
.at(&cause, param_env)
1394-
.sup(trait_ty, impl_ty)
1395-
.map(|ok| ocx.register_infer_ok_obligations(ok));
1385+
let err = ocx.sup(&cause, param_env, trait_ty, impl_ty);
13961386

13971387
if let Err(terr) = err {
13981388
debug!(

Diff for: compiler/rustc_hir_analysis/src/check/wfcheck.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,7 @@ fn receiver_is_valid<'tcx>(
16741674

16751675
// `self: Self` is always valid.
16761676
if can_eq_self(receiver_ty) {
1677-
if let Err(err) = wfcx.equate_types(&cause, wfcx.param_env, self_ty, receiver_ty) {
1677+
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, receiver_ty) {
16781678
infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
16791679
}
16801680
return true;
@@ -1704,9 +1704,7 @@ fn receiver_is_valid<'tcx>(
17041704
if can_eq_self(potential_self_ty) {
17051705
wfcx.register_obligations(autoderef.into_obligations());
17061706

1707-
if let Err(err) =
1708-
wfcx.equate_types(&cause, wfcx.param_env, self_ty, potential_self_ty)
1709-
{
1707+
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty) {
17101708
infcx
17111709
.err_ctxt()
17121710
.report_mismatched_types(&cause, self_ty, potential_self_ty, err)

Diff for: compiler/rustc_infer/src/infer/canonical/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
4343
///
4444
/// This is only meant to be invoked as part of constructing an
4545
/// inference context at the start of a query (see
46-
/// `InferCtxtBuilder::enter_with_canonical`). It basically
46+
/// `InferCtxtBuilder::build_with_canonical`). It basically
4747
/// brings the canonical value "into scope" within your new infcx.
4848
///
4949
/// At the end of processing, the substitution S (once

Diff for: compiler/rustc_trait_selection/src/infer.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
2-
use crate::traits::{self, TraitEngine, TraitEngineExt};
2+
use crate::traits::{self, ObligationCtxt};
33

44
use rustc_hir::def_id::DefId;
55
use rustc_hir::lang_items::LangItem;
@@ -142,7 +142,7 @@ pub trait InferCtxtBuilderExt<'tcx> {
142142
fn enter_canonical_trait_query<K, R>(
143143
&mut self,
144144
canonical_key: &Canonical<'tcx, K>,
145-
operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
145+
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
146146
) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
147147
where
148148
K: TypeFoldable<'tcx>,
@@ -170,17 +170,17 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
170170
fn enter_canonical_trait_query<K, R>(
171171
&mut self,
172172
canonical_key: &Canonical<'tcx, K>,
173-
operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
173+
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
174174
) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
175175
where
176176
K: TypeFoldable<'tcx>,
177177
R: Debug + TypeFoldable<'tcx>,
178178
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
179179
{
180-
let (ref infcx, key, canonical_inference_vars) =
180+
let (infcx, key, canonical_inference_vars) =
181181
self.build_with_canonical(DUMMY_SP, canonical_key);
182-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
183-
let value = operation(infcx, &mut *fulfill_cx, key)?;
184-
infcx.make_canonicalized_query_response(canonical_inference_vars, value, &mut *fulfill_cx)
182+
let ocx = ObligationCtxt::new(&infcx);
183+
let value = operation(&ocx, key)?;
184+
ocx.make_canonicalized_query_response(canonical_inference_vars, value)
185185
}
186186
}

Diff for: compiler/rustc_trait_selection/src/traits/engine.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
use std::cell::RefCell;
2+
use std::fmt::Debug;
23

34
use super::TraitEngine;
45
use super::{ChalkFulfillmentContext, FulfillmentContext};
56
use crate::infer::InferCtxtExt;
67
use rustc_data_structures::fx::FxHashSet;
78
use rustc_hir::def_id::{DefId, LocalDefId};
9+
use rustc_infer::infer::at::ToTrace;
10+
use rustc_infer::infer::canonical::{
11+
Canonical, CanonicalVarValues, CanonicalizedQueryResponse, QueryResponse,
12+
};
813
use rustc_infer::infer::{InferCtxt, InferOk};
14+
use rustc_infer::traits::query::Fallible;
915
use rustc_infer::traits::{
1016
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
1117
};
18+
use rustc_middle::arena::ArenaAllocatable;
1219
use rustc_middle::ty::error::TypeError;
1320
use rustc_middle::ty::ToPredicate;
1421
use rustc_middle::ty::TypeFoldable;
@@ -105,12 +112,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
105112
self.register_infer_ok_obligations(infer_ok)
106113
}
107114

108-
pub fn equate_types(
115+
pub fn eq<T: ToTrace<'tcx>>(
109116
&self,
110117
cause: &ObligationCause<'tcx>,
111118
param_env: ty::ParamEnv<'tcx>,
112-
expected: Ty<'tcx>,
113-
actual: Ty<'tcx>,
119+
expected: T,
120+
actual: T,
114121
) -> Result<(), TypeError<'tcx>> {
115122
match self.infcx.at(cause, param_env).eq(expected, actual) {
116123
Ok(InferOk { obligations, value: () }) => {
@@ -121,6 +128,22 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
121128
}
122129
}
123130

131+
pub fn sup<T: ToTrace<'tcx>>(
132+
&self,
133+
cause: &ObligationCause<'tcx>,
134+
param_env: ty::ParamEnv<'tcx>,
135+
expected: T,
136+
actual: T,
137+
) -> Result<(), TypeError<'tcx>> {
138+
match self.infcx.at(cause, param_env).sup(expected, actual) {
139+
Ok(InferOk { obligations, value: () }) => {
140+
self.register_obligations(obligations);
141+
Ok(())
142+
}
143+
Err(e) => Err(e),
144+
}
145+
}
146+
124147
pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
125148
self.engine.borrow_mut().select_all_or_error(self.infcx)
126149
}
@@ -154,4 +177,20 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
154177
}
155178
implied_bounds
156179
}
180+
181+
pub fn make_canonicalized_query_response<T>(
182+
&self,
183+
inference_vars: CanonicalVarValues<'tcx>,
184+
answer: T,
185+
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
186+
where
187+
T: Debug + TypeFoldable<'tcx>,
188+
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
189+
{
190+
self.infcx.make_canonicalized_query_response(
191+
inference_vars,
192+
answer,
193+
&mut **self.engine.borrow_mut(),
194+
)
195+
}
157196
}

Diff for: compiler/rustc_traits/src/implied_outlives_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ fn implied_outlives_bounds<'tcx>(
2828
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
2929
NoSolution,
3030
> {
31-
tcx.infer_ctxt().enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
31+
tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
3232
let (param_env, ty) = key.into_parts();
33-
compute_implied_outlives_bounds(&infcx, param_env, ty)
33+
compute_implied_outlives_bounds(&ocx.infcx, param_env, ty)
3434
})
3535
}
3636

Diff for: compiler/rustc_traits/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
#![deny(rustc::untranslatable_diagnostic)]
55
#![deny(rustc::diagnostic_outside_of_impl)]
6+
#![feature(let_chains)]
67
#![recursion_limit = "256"]
78

89
#[macro_use]

Diff for: compiler/rustc_traits/src/normalize_projection_ty.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
22
use rustc_infer::infer::TyCtxtInferExt;
3-
use rustc_infer::traits::TraitEngineExt as _;
43
use rustc_middle::ty::query::Providers;
54
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
65
use rustc_trait_selection::infer::InferCtxtBuilderExt;
@@ -23,8 +22,8 @@ fn normalize_projection_ty<'tcx>(
2322
tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
2423
tcx.infer_ctxt().enter_canonical_trait_query(
2524
&goal,
26-
|infcx, fulfill_cx, ParamEnvAnd { param_env, value: goal }| {
27-
let selcx = &mut SelectionContext::new(infcx);
25+
|ocx, ParamEnvAnd { param_env, value: goal }| {
26+
let selcx = &mut SelectionContext::new(ocx.infcx);
2827
let cause = ObligationCause::dummy();
2928
let mut obligations = vec![];
3029
let answer = traits::normalize_projection_type(
@@ -35,7 +34,7 @@ fn normalize_projection_ty<'tcx>(
3534
0,
3635
&mut obligations,
3736
);
38-
fulfill_cx.register_predicate_obligations(infcx, obligations);
37+
ocx.register_obligations(obligations);
3938
// FIXME(associated_const_equality): All users of normalize_projection_ty expected
4039
// a type, but there is the possibility it could've been a const now. Maybe change
4140
// it to a Term later?

0 commit comments

Comments
 (0)