1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use rustc::infer::InferCtxt;
use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints,
QueryResult};
use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc::traits::{FulfillmentContext, TraitEngine};
use rustc::traits::query::NoSolution;
use rustc::ty;
use std::fmt::Debug;
type CanonicalizedQueryResult<'gcx, 'tcx, T> =
<QueryResult<'tcx, T> as Canonicalize<'gcx, 'tcx>>::Canonicalized;
crate fn make_query_response<'gcx, 'tcx, T>(
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut FulfillmentContext<'tcx>,
) -> Result<CanonicalizedQueryResult<'gcx, 'tcx, T>, NoSolution>
where
T: Debug,
QueryResult<'tcx, T>: Canonicalize<'gcx, 'tcx>,
{
let tcx = infcx.tcx;
debug!(
"make_query_response(\
inference_vars={:?}, \
answer={:?})",
inference_vars, answer,
);
let true_errors = match fulfill_cx.select_where_possible(infcx) {
Ok(()) => vec![],
Err(errors) => errors,
};
debug!("true_errors = {:#?}", true_errors);
if !true_errors.is_empty() {
debug!("make_query_response: true_errors={:#?}", true_errors);
return Err(NoSolution);
}
let ambig_errors = match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => vec![],
Err(errors) => errors,
};
debug!("ambig_errors = {:#?}", ambig_errors);
let region_obligations = infcx.take_registered_region_obligations();
let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| {
let RegionConstraintData {
constraints,
verifys,
givens,
} = region_constraints;
assert!(verifys.is_empty());
assert!(givens.is_empty());
let region_outlives: Vec<_> = constraints
.into_iter()
.map(|(k, _)| match *k {
Constraint::VarSubVar(v1, v2) => {
(tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2)))
}
Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2),
Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))),
Constraint::RegSubReg(r1, r2) => (r1, r2),
})
.collect();
let ty_outlives: Vec<_> = region_obligations
.into_iter()
.map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
.collect();
(region_outlives, ty_outlives)
});
let certainty = if ambig_errors.is_empty() {
Certainty::Proven
} else {
Certainty::Ambiguous
};
let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
var_values: inference_vars,
region_constraints: QueryRegionConstraints {
region_outlives,
ty_outlives,
},
certainty,
value: answer,
});
debug!(
"make_query_response: canonical_result = {:#?}",
canonical_result
);
Ok(canonical_result)
}