Skip to content

Commit a9a4c9b

Browse files
authored
Rollup merge of #111741 - compiler-errors:custom-type-op, r=lcnr
Use `ObligationCtxt` in custom type ops We already make one when evaluating the `CustomTypeOp`, so it's simpler to just pass it to the user. Removes a redundant `ObligationCtxt::new_in_snapshot` usage and simplifies some other code. This makes several refactorings related to opaque types in the new solver simpler, but those are not included in this PR.
2 parents c373194 + 521a0bc commit a9a4c9b

File tree

5 files changed

+66
-60
lines changed

5 files changed

+66
-60
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
128128
}
129129
}
130130

131-
impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
131+
impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
132132
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
133133
// We can't rerun custom type ops.
134134
UniverseInfo::other()

compiler/rustc_borrowck/src/type_check/canonical.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::fmt;
22

3-
use rustc_infer::infer::{canonical::Canonical, InferOk};
3+
use rustc_infer::infer::canonical::Canonical;
44
use rustc_middle::mir::ConstraintCategory;
55
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
66
use rustc_span::def_id::DefId;
77
use rustc_span::Span;
88
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
99
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
10-
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
10+
use rustc_trait_selection::traits::ObligationCause;
1111

1212
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
1313

@@ -219,20 +219,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
219219

220220
let cause = ObligationCause::dummy_with_span(span);
221221
let param_env = self.param_env;
222-
let op = |infcx: &'_ _| {
223-
let ocx = ObligationCtxt::new_in_snapshot(infcx);
224-
let user_ty = ocx.normalize(&cause, param_env, user_ty);
225-
ocx.eq(&cause, param_env, user_ty, mir_ty)?;
226-
if !ocx.select_all_or_error().is_empty() {
227-
return Err(NoSolution);
228-
}
229-
Ok(InferOk { value: (), obligations: vec![] })
230-
};
231-
232222
self.fully_perform_op(
233223
Locations::All(span),
234224
ConstraintCategory::Boring,
235-
type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()),
225+
type_op::custom::CustomTypeOp::new(
226+
|ocx| {
227+
let user_ty = ocx.normalize(&cause, param_env, user_ty);
228+
ocx.eq(&cause, param_env, user_ty, mir_ty)?;
229+
Ok(())
230+
},
231+
"ascribe_user_type_skip_wf",
232+
),
236233
)
237234
.unwrap_or_else(|err| {
238235
span_mirbug!(

compiler/rustc_borrowck/src/type_check/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
2020
use rustc_infer::infer::region_constraints::RegionConstraintData;
2121
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2222
use rustc_infer::infer::{
23-
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
23+
InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
2424
};
2525
use rustc_middle::mir::tcx::PlaceTy;
2626
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
@@ -218,16 +218,16 @@ pub(crate) fn type_check<'mir, 'tcx>(
218218
Locations::All(body.span),
219219
ConstraintCategory::OpaqueType,
220220
CustomTypeOp::new(
221-
|infcx| {
222-
infcx.register_member_constraints(
221+
|ocx| {
222+
ocx.infcx.register_member_constraints(
223223
param_env,
224224
opaque_type_key,
225225
decl.hidden_type.ty,
226226
decl.hidden_type.span,
227227
);
228-
Ok(InferOk { value: (), obligations: vec![] })
228+
Ok(())
229229
},
230-
|| "opaque_type_map".to_string(),
230+
"opaque_type_map",
231231
),
232232
)
233233
.unwrap();
@@ -2713,8 +2713,9 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
27132713
type ErrorInfo = InstantiateOpaqueType<'tcx>;
27142714

27152715
fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
2716-
let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
2717-
Ok(InferOk { value: (), obligations: self.obligations.clone() })
2716+
let (mut output, region_constraints) = scrape_region_constraints(infcx, |ocx| {
2717+
ocx.register_obligations(self.obligations.clone());
2718+
Ok(())
27182719
})?;
27192720
self.region_constraints = Some(region_constraints);
27202721
output.error_info = Some(self);

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,25 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
185185
}
186186

187187
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
188-
self.type_checker
189-
.fully_perform_op(
190-
self.locations,
191-
self.category,
192-
InstantiateOpaqueType {
193-
obligations,
194-
// These fields are filled in during execution of the operation
195-
base_universe: None,
196-
region_constraints: None,
197-
},
198-
)
199-
.unwrap();
188+
match self.type_checker.fully_perform_op(
189+
self.locations,
190+
self.category,
191+
InstantiateOpaqueType {
192+
obligations,
193+
// These fields are filled in during execution of the operation
194+
base_universe: None,
195+
region_constraints: None,
196+
},
197+
) {
198+
Ok(()) => {}
199+
Err(_) => {
200+
// It's a bit redundant to delay a bug here, but I'd rather
201+
// delay more bugs than accidentally not delay a bug at all.
202+
self.type_checker.tcx().sess.delay_span_bug(
203+
self.locations.span(self.type_checker.body),
204+
"errors selecting obligation during MIR typeck",
205+
);
206+
}
207+
};
200208
}
201209
}

compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,31 @@
11
use crate::infer::canonical::query_response;
2-
use crate::infer::{InferCtxt, InferOk};
2+
use crate::infer::InferCtxt;
33
use crate::traits::query::type_op::TypeOpOutput;
44
use crate::traits::query::Fallible;
55
use crate::traits::ObligationCtxt;
66
use rustc_infer::infer::region_constraints::RegionConstraintData;
7+
use rustc_middle::traits::query::NoSolution;
78
use rustc_span::source_map::DUMMY_SP;
89

910
use std::fmt;
1011

11-
pub struct CustomTypeOp<F, G> {
12+
pub struct CustomTypeOp<F> {
1213
closure: F,
13-
description: G,
14+
description: &'static str,
1415
}
1516

16-
impl<F, G> CustomTypeOp<F, G> {
17-
pub fn new<'tcx, R>(closure: F, description: G) -> Self
17+
impl<F> CustomTypeOp<F> {
18+
pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
1819
where
19-
F: FnOnce(&InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
20-
G: Fn() -> String,
20+
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
2121
{
2222
CustomTypeOp { closure, description }
2323
}
2424
}
2525

26-
impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
26+
impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
2727
where
28-
F: for<'a, 'cx> FnOnce(&'a InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
29-
G: Fn() -> String,
28+
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
3029
{
3130
type Output = R;
3231
/// We can't do any custom error reporting for `CustomTypeOp`, so
@@ -41,24 +40,21 @@ where
4140
info!("fully_perform({:?})", self);
4241
}
4342

44-
Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0)
43+
Ok(scrape_region_constraints(infcx, self.closure)?.0)
4544
}
4645
}
4746

48-
impl<F, G> fmt::Debug for CustomTypeOp<F, G>
49-
where
50-
G: Fn() -> String,
51-
{
47+
impl<F> fmt::Debug for CustomTypeOp<F> {
5248
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53-
write!(f, "{}", (self.description)())
49+
self.description.fmt(f)
5450
}
5551
}
5652

5753
/// Executes `op` and then scrapes out all the "old style" region
5854
/// constraints that result, creating query-region-constraints.
5955
pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
6056
infcx: &InferCtxt<'tcx>,
61-
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
57+
op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
6258
) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
6359
// During NLL, we expect that nobody will register region
6460
// obligations **except** as part of a custom type op (and, at the
@@ -72,16 +68,20 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
7268
pre_obligations,
7369
);
7470

75-
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
76-
let ocx = ObligationCtxt::new(infcx);
77-
ocx.register_obligations(obligations);
78-
let errors = ocx.select_all_or_error();
79-
if !errors.is_empty() {
80-
infcx.tcx.sess.diagnostic().delay_span_bug(
81-
DUMMY_SP,
82-
format!("errors selecting obligation during MIR typeck: {:?}", errors),
83-
);
84-
}
71+
let value = infcx.commit_if_ok(|_| {
72+
let ocx = ObligationCtxt::new_in_snapshot(infcx);
73+
let value = op(&ocx)?;
74+
let errors = ocx.select_all_or_error();
75+
if errors.is_empty() {
76+
Ok(value)
77+
} else {
78+
infcx.tcx.sess.delay_span_bug(
79+
DUMMY_SP,
80+
format!("errors selecting obligation during MIR typeck: {:?}", errors),
81+
);
82+
Err(NoSolution)
83+
}
84+
})?;
8585

8686
let region_obligations = infcx.take_registered_region_obligations();
8787
let region_constraint_data = infcx.take_and_reset_region_constraints();

0 commit comments

Comments
 (0)