Skip to content

Commit f26c91b

Browse files
committed
Give all trait engines direct access to DefiningAnchor instead of passing it in every time
1 parent ad0bb9c commit f26c91b

File tree

12 files changed

+162
-149
lines changed

12 files changed

+162
-149
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
145145
.infcx
146146
.at(&cause, self.param_env)
147147
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
148-
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
148+
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx, self.defining_use_anchor);
149149
let normalized_ty =
150150
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
151-
let errors = fulfillcx.select_where_possible(&self.infcx, self.defining_use_anchor);
151+
let errors = fulfillcx.select_where_possible(&self.infcx);
152152
if !errors.is_empty() {
153153
// This shouldn't happen, except for evaluate/fulfill mismatches,
154154
// but that's not a reason for an ICE (`predicate_may_hold` is conservative

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,13 +1535,13 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
15351535
.ignoring_regions()
15361536
.build();
15371537

1538-
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
1538+
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx, DefiningAnchor::Bind(def_id));
15391539
for (predicate, cause) in generator_interior_predicates {
15401540
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
15411541
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
15421542
}
15431543
// Bind opaque types to `def_id` as they should have been checked by borrowck.
1544-
let errors = fulfillment_cx.select_all_or_error(&infcx, DefiningAnchor::Bind(def_id));
1544+
let errors = fulfillment_cx.select_all_or_error(&infcx);
15451545
debug!(?errors);
15461546
if !errors.is_empty() {
15471547
infcx.err_ctxt().report_fulfillment_errors(&errors, None);

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
594594
&self,
595595
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
596596
) {
597-
let mut result =
598-
self.fulfillment_cx.borrow_mut().select_where_possible(self, self.defining_use_anchor);
597+
let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
599598
if !result.is_empty() {
600599
mutate_fulfillment_errors(&mut result);
601600
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);

compiler/rustc_hir_typeck/src/inherited.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl<'tcx> Inherited<'tcx> {
127127
defining_use_anchor,
128128
typeck_results,
129129
infcx,
130-
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
130+
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx, defining_use_anchor)),
131131
locals: RefCell::new(Default::default()),
132132
deferred_sized_obligations: RefCell::new(Vec::new()),
133133
deferred_call_resolutions: RefCell::new(Default::default()),

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,12 @@ impl<'tcx> InferCtxt<'tcx> {
5757
inference_vars: CanonicalVarValues<'tcx>,
5858
answer: T,
5959
fulfill_cx: &mut dyn TraitEngine<'tcx>,
60-
defining_use_anchor: DefiningAnchor,
6160
) -> Fallible<CanonicalQueryResponse<'tcx, T>>
6261
where
6362
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
6463
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
6564
{
66-
let query_response =
67-
self.make_query_response(inference_vars, answer, fulfill_cx, defining_use_anchor)?;
65+
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
6866
debug!("query_response = {:#?}", query_response);
6967
let canonical_result = self.canonicalize_response(query_response);
7068
debug!("canonical_result = {:#?}", canonical_result);
@@ -106,15 +104,14 @@ impl<'tcx> InferCtxt<'tcx> {
106104
inference_vars: CanonicalVarValues<'tcx>,
107105
answer: T,
108106
fulfill_cx: &mut dyn TraitEngine<'tcx>,
109-
defining_use_anchor: DefiningAnchor,
110107
) -> Result<QueryResponse<'tcx, T>, NoSolution>
111108
where
112109
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
113110
{
114111
let tcx = self.tcx;
115112

116113
// Select everything, returning errors.
117-
let true_errors = fulfill_cx.select_where_possible(self, defining_use_anchor);
114+
let true_errors = fulfill_cx.select_where_possible(self);
118115
debug!("true_errors = {:#?}", true_errors);
119116

120117
if !true_errors.is_empty() {
@@ -124,7 +121,7 @@ impl<'tcx> InferCtxt<'tcx> {
124121
}
125122

126123
// Anything left unselected *now* must be an ambiguity.
127-
let ambig_errors = fulfill_cx.select_all_or_error(self, defining_use_anchor);
124+
let ambig_errors = fulfill_cx.select_all_or_error(self);
128125
debug!("ambig_errors = {:#?}", ambig_errors);
129126

130127
let region_obligations = self.take_registered_region_obligations();

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
3636
obligation: PredicateObligation<'tcx>,
3737
);
3838

39-
fn select_where_possible(
40-
&mut self,
41-
infcx: &InferCtxt<'tcx>,
42-
defining_use_anchor: DefiningAnchor,
43-
) -> Vec<FulfillmentError<'tcx>>;
39+
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
4440

4541
fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
4642

@@ -53,6 +49,8 @@ pub trait TraitEngine<'tcx>: 'tcx {
5349
&mut self,
5450
infcx: &InferCtxt<'tcx>,
5551
) -> Vec<PredicateObligation<'tcx>>;
52+
53+
fn defining_use_anchor(&self) -> DefiningAnchor;
5654
}
5755

5856
pub trait TraitEngineExt<'tcx> {
@@ -62,11 +60,7 @@ pub trait TraitEngineExt<'tcx> {
6260
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
6361
);
6462

65-
fn select_all_or_error(
66-
&mut self,
67-
infcx: &InferCtxt<'tcx>,
68-
defining_use_anchor: DefiningAnchor,
69-
) -> Vec<FulfillmentError<'tcx>>;
63+
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
7064
}
7165

7266
impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
@@ -80,12 +74,8 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
8074
}
8175
}
8276

83-
fn select_all_or_error(
84-
&mut self,
85-
infcx: &InferCtxt<'tcx>,
86-
defining_use_anchor: DefiningAnchor,
87-
) -> Vec<FulfillmentError<'tcx>> {
88-
let errors = self.select_where_possible(infcx, defining_use_anchor);
77+
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
78+
let errors = self.select_where_possible(infcx);
8979
if !errors.is_empty() {
9080
return errors;
9181
}

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ use super::{Certainty, InferCtxtEvalExt};
2323
/// here as this will have to deal with far more root goals than `evaluate_all`.
2424
pub struct FulfillmentCtxt<'tcx> {
2525
obligations: Vec<PredicateObligation<'tcx>>,
26+
defining_use_anchor: DefiningAnchor,
2627
}
2728

2829
impl<'tcx> FulfillmentCtxt<'tcx> {
29-
pub fn new() -> FulfillmentCtxt<'tcx> {
30-
FulfillmentCtxt { obligations: Vec::new() }
30+
pub fn new(defining_use_anchor: impl Into<DefiningAnchor>) -> FulfillmentCtxt<'tcx> {
31+
FulfillmentCtxt { obligations: Vec::new(), defining_use_anchor: defining_use_anchor.into() }
3132
}
3233
}
3334

@@ -51,11 +52,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
5152
.collect()
5253
}
5354

54-
fn select_where_possible(
55-
&mut self,
56-
infcx: &InferCtxt<'tcx>,
57-
defining_use_anchor: DefiningAnchor,
58-
) -> Vec<FulfillmentError<'tcx>> {
55+
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
5956
let mut errors = Vec::new();
6057
for i in 0.. {
6158
if !infcx.tcx.recursion_limit().value_within_limit(i) {
@@ -65,71 +62,71 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
6562
let mut has_changed = false;
6663
for obligation in mem::take(&mut self.obligations) {
6764
let goal = obligation.clone().into();
68-
let (changed, certainty) = match infcx.evaluate_root_goal(goal, defining_use_anchor)
69-
{
70-
Ok(result) => result,
71-
Err(NoSolution) => {
72-
errors.push(FulfillmentError {
73-
obligation: obligation.clone(),
74-
code: match goal.predicate.kind().skip_binder() {
75-
ty::PredicateKind::Clause(ty::Clause::Projection(_)) => {
76-
FulfillmentErrorCode::CodeProjectionError(
77-
// FIXME: This could be a `Sorts` if the term is a type
78-
MismatchedProjectionTypes { err: TypeError::Mismatch },
79-
)
80-
}
81-
ty::PredicateKind::AliasEq(_, _) => {
82-
FulfillmentErrorCode::CodeProjectionError(
83-
MismatchedProjectionTypes { err: TypeError::Mismatch },
84-
)
85-
}
86-
ty::PredicateKind::Subtype(pred) => {
87-
let (a, b) = infcx.instantiate_binder_with_placeholders(
88-
goal.predicate.kind().rebind((pred.a, pred.b)),
89-
);
90-
let expected_found = ExpectedFound::new(true, a, b);
91-
FulfillmentErrorCode::CodeSubtypeError(
92-
expected_found,
93-
TypeError::Sorts(expected_found),
94-
)
95-
}
96-
ty::PredicateKind::Coerce(pred) => {
97-
let (a, b) = infcx.instantiate_binder_with_placeholders(
98-
goal.predicate.kind().rebind((pred.a, pred.b)),
99-
);
100-
let expected_found = ExpectedFound::new(false, a, b);
101-
FulfillmentErrorCode::CodeSubtypeError(
102-
expected_found,
103-
TypeError::Sorts(expected_found),
104-
)
105-
}
106-
ty::PredicateKind::ConstEquate(a, b) => {
107-
let (a, b) = infcx.instantiate_binder_with_placeholders(
108-
goal.predicate.kind().rebind((a, b)),
109-
);
110-
let expected_found = ExpectedFound::new(true, a, b);
111-
FulfillmentErrorCode::CodeConstEquateError(
112-
expected_found,
113-
TypeError::ConstMismatch(expected_found),
114-
)
115-
}
116-
ty::PredicateKind::Clause(_)
117-
| ty::PredicateKind::WellFormed(_)
118-
| ty::PredicateKind::ObjectSafe(_)
119-
| ty::PredicateKind::ClosureKind(_, _, _)
120-
| ty::PredicateKind::ConstEvaluatable(_)
121-
| ty::PredicateKind::TypeWellFormedFromEnv(_)
122-
| ty::PredicateKind::Ambiguous => {
123-
FulfillmentErrorCode::CodeSelectionError(
124-
SelectionError::Unimplemented,
125-
)
126-
}
127-
},
128-
root_obligation: obligation,
129-
});
130-
continue;
131-
}
132-
};
65+
let (changed, certainty) =
66+
match infcx.evaluate_root_goal(goal, self.defining_use_anchor) {
67+
Ok(result) => result,
68+
Err(NoSolution) => {
69+
errors.push(FulfillmentError {
70+
obligation: obligation.clone(),
71+
code: match goal.predicate.kind().skip_binder() {
72+
ty::PredicateKind::Clause(ty::Clause::Projection(_)) => {
73+
FulfillmentErrorCode::CodeProjectionError(
74+
// FIXME: This could be a `Sorts` if the term is a type
75+
MismatchedProjectionTypes { err: TypeError::Mismatch },
76+
)
77+
}
78+
ty::PredicateKind::AliasEq(_, _) => {
79+
FulfillmentErrorCode::CodeProjectionError(
80+
MismatchedProjectionTypes { err: TypeError::Mismatch },
81+
)
82+
}
83+
ty::PredicateKind::Subtype(pred) => {
84+
let (a, b) = infcx.instantiate_binder_with_placeholders(
85+
goal.predicate.kind().rebind((pred.a, pred.b)),
86+
);
87+
let expected_found = ExpectedFound::new(true, a, b);
88+
FulfillmentErrorCode::CodeSubtypeError(
89+
expected_found,
90+
TypeError::Sorts(expected_found),
91+
)
92+
}
93+
ty::PredicateKind::Coerce(pred) => {
94+
let (a, b) = infcx.instantiate_binder_with_placeholders(
95+
goal.predicate.kind().rebind((pred.a, pred.b)),
96+
);
97+
let expected_found = ExpectedFound::new(false, a, b);
98+
FulfillmentErrorCode::CodeSubtypeError(
99+
expected_found,
100+
TypeError::Sorts(expected_found),
101+
)
102+
}
103+
ty::PredicateKind::ConstEquate(a, b) => {
104+
let (a, b) = infcx.instantiate_binder_with_placeholders(
105+
goal.predicate.kind().rebind((a, b)),
106+
);
107+
let expected_found = ExpectedFound::new(true, a, b);
108+
FulfillmentErrorCode::CodeConstEquateError(
109+
expected_found,
110+
TypeError::ConstMismatch(expected_found),
111+
)
112+
}
113+
ty::PredicateKind::Clause(_)
114+
| ty::PredicateKind::WellFormed(_)
115+
| ty::PredicateKind::ObjectSafe(_)
116+
| ty::PredicateKind::ClosureKind(_, _, _)
117+
| ty::PredicateKind::ConstEvaluatable(_)
118+
| ty::PredicateKind::TypeWellFormedFromEnv(_)
119+
| ty::PredicateKind::Ambiguous => {
120+
FulfillmentErrorCode::CodeSelectionError(
121+
SelectionError::Unimplemented,
122+
)
123+
}
124+
},
125+
root_obligation: obligation,
126+
});
127+
continue;
128+
}
129+
};
133130

134131
has_changed |= changed;
135132
match certainty {
@@ -156,4 +153,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
156153
) -> Vec<PredicateObligation<'tcx>> {
157154
unimplemented!()
158155
}
156+
157+
fn defining_use_anchor(&self) -> DefiningAnchor {
158+
self.defining_use_anchor
159+
}
159160
}

compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@ pub struct FulfillmentContext<'tcx> {
1515
obligations: FxIndexSet<PredicateObligation<'tcx>>,
1616

1717
usable_in_snapshot: bool,
18+
19+
defining_use_anchor: DefiningAnchor,
1820
}
1921

2022
impl FulfillmentContext<'_> {
21-
pub(super) fn new() -> Self {
22-
FulfillmentContext { obligations: FxIndexSet::default(), usable_in_snapshot: false }
23+
pub(super) fn new(defining_use_anchor: impl Into<DefiningAnchor>) -> Self {
24+
FulfillmentContext {
25+
obligations: FxIndexSet::default(),
26+
usable_in_snapshot: false,
27+
defining_use_anchor: defining_use_anchor.into(),
28+
}
2329
}
2430

25-
pub(crate) fn new_in_snapshot() -> Self {
26-
FulfillmentContext { usable_in_snapshot: true, ..Self::new() }
31+
pub(crate) fn new_in_snapshot(defining_use_anchor: impl Into<DefiningAnchor>) -> Self {
32+
FulfillmentContext { usable_in_snapshot: true, ..Self::new(defining_use_anchor) }
2733
}
2834
}
2935

@@ -55,11 +61,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
5561
.collect()
5662
}
5763

58-
fn select_where_possible(
59-
&mut self,
60-
infcx: &InferCtxt<'tcx>,
61-
defining_use_anchor: DefiningAnchor,
62-
) -> Vec<FulfillmentError<'tcx>> {
64+
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
6365
if !self.usable_in_snapshot {
6466
assert!(!infcx.is_in_snapshot());
6567
}
@@ -95,7 +97,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
9597
obligation.param_env,
9698
&orig_values,
9799
&response,
98-
defining_use_anchor,
100+
self.defining_use_anchor,
99101
) {
100102
Ok(infer_ok) => next_round.extend(
101103
infer_ok.obligations.into_iter().map(|obligation| {
@@ -151,4 +153,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
151153
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
152154
self.obligations.iter().cloned().collect()
153155
}
156+
157+
fn defining_use_anchor(&self) -> DefiningAnchor {
158+
self.defining_use_anchor
159+
}
154160
}

0 commit comments

Comments
 (0)