3 use rustc_infer
::infer
::InferCtxt
;
4 use rustc_infer
::traits
::{
5 query
::NoSolution
, FulfillmentError
, FulfillmentErrorCode
, MismatchedProjectionTypes
,
6 PredicateObligation
, SelectionError
, TraitEngine
,
9 use rustc_middle
::ty
::error
::{ExpectedFound, TypeError}
;
11 use super::{Certainty, InferCtxtEvalExt}
;
13 /// A trait engine using the new trait solver.
15 /// This is mostly identical to how `evaluate_all` works inside of the
16 /// solver, except that the requirements are slightly different.
18 /// Unlike `evaluate_all` it is possible to add new obligations later on
19 /// and we also have to track diagnostics information by using `Obligation`
20 /// instead of `Goal`.
22 /// It is also likely that we want to use slightly different datastructures
23 /// here as this will have to deal with far more root goals than `evaluate_all`.
24 pub struct FulfillmentCtxt
<'tcx
> {
25 obligations
: Vec
<PredicateObligation
<'tcx
>>,
28 impl<'tcx
> FulfillmentCtxt
<'tcx
> {
29 pub fn new() -> FulfillmentCtxt
<'tcx
> {
30 FulfillmentCtxt { obligations: Vec::new() }
34 impl<'tcx
> TraitEngine
<'tcx
> for FulfillmentCtxt
<'tcx
> {
35 fn register_predicate_obligation(
37 _infcx
: &InferCtxt
<'tcx
>,
38 obligation
: PredicateObligation
<'tcx
>,
40 self.obligations
.push(obligation
);
43 fn collect_remaining_errors(&mut self) -> Vec
<FulfillmentError
<'tcx
>> {
46 .map(|obligation
| FulfillmentError
{
47 obligation
: obligation
.clone(),
48 code
: FulfillmentErrorCode
::CodeAmbiguity
,
49 root_obligation
: obligation
,
54 fn select_where_possible(&mut self, infcx
: &InferCtxt
<'tcx
>) -> Vec
<FulfillmentError
<'tcx
>> {
55 let mut errors
= Vec
::new();
57 if !infcx
.tcx
.recursion_limit().value_within_limit(i
) {
58 unimplemented
!("overflowed on pending obligations: {:?}", self.obligations
);
61 let mut has_changed
= false;
62 for obligation
in mem
::take(&mut self.obligations
) {
63 let goal
= obligation
.clone().into();
64 let (changed
, certainty
) = match infcx
.evaluate_root_goal(goal
) {
67 errors
.push(FulfillmentError
{
68 obligation
: obligation
.clone(),
69 code
: match goal
.predicate
.kind().skip_binder() {
70 ty
::PredicateKind
::Clause(ty
::Clause
::Projection(_
)) => {
71 FulfillmentErrorCode
::CodeProjectionError(
72 // FIXME: This could be a `Sorts` if the term is a type
73 MismatchedProjectionTypes { err: TypeError::Mismatch }
,
76 ty
::PredicateKind
::AliasEq(_
, _
) => {
77 FulfillmentErrorCode
::CodeProjectionError(
78 MismatchedProjectionTypes { err: TypeError::Mismatch }
,
81 ty
::PredicateKind
::Subtype(pred
) => {
82 let (a
, b
) = infcx
.instantiate_binder_with_placeholders(
83 goal
.predicate
.kind().rebind((pred
.a
, pred
.b
)),
85 let expected_found
= ExpectedFound
::new(true, a
, b
);
86 FulfillmentErrorCode
::CodeSubtypeError(
88 TypeError
::Sorts(expected_found
),
91 ty
::PredicateKind
::Coerce(pred
) => {
92 let (a
, b
) = infcx
.instantiate_binder_with_placeholders(
93 goal
.predicate
.kind().rebind((pred
.a
, pred
.b
)),
95 let expected_found
= ExpectedFound
::new(false, a
, b
);
96 FulfillmentErrorCode
::CodeSubtypeError(
98 TypeError
::Sorts(expected_found
),
101 ty
::PredicateKind
::ConstEquate(a
, b
) => {
102 let (a
, b
) = infcx
.instantiate_binder_with_placeholders(
103 goal
.predicate
.kind().rebind((a
, b
)),
105 let expected_found
= ExpectedFound
::new(true, a
, b
);
106 FulfillmentErrorCode
::CodeConstEquateError(
108 TypeError
::ConstMismatch(expected_found
),
111 ty
::PredicateKind
::Clause(_
)
112 | ty
::PredicateKind
::WellFormed(_
)
113 | ty
::PredicateKind
::ObjectSafe(_
)
114 | ty
::PredicateKind
::ClosureKind(_
, _
, _
)
115 | ty
::PredicateKind
::ConstEvaluatable(_
)
116 | ty
::PredicateKind
::TypeWellFormedFromEnv(_
)
117 | ty
::PredicateKind
::Ambiguous
=> {
118 FulfillmentErrorCode
::CodeSelectionError(
119 SelectionError
::Unimplemented
,
123 root_obligation
: obligation
,
129 has_changed
|= changed
;
132 Certainty
::Maybe(_
) => self.obligations
.push(obligation
),
144 fn pending_obligations(&self) -> Vec
<PredicateObligation
<'tcx
>> {
145 self.obligations
.clone()
148 fn drain_unstalled_obligations(
151 ) -> Vec
<PredicateObligation
<'tcx
>> {