]>
Commit | Line | Data |
---|---|---|
0531ce1d XL |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use rustc::infer::InferCtxt; | |
83c7162d | 12 | use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult}; |
0531ce1d XL |
13 | use rustc::infer::region_constraints::{Constraint, RegionConstraintData}; |
14 | use rustc::traits::{FulfillmentContext, TraitEngine}; | |
15 | use rustc::traits::query::NoSolution; | |
16 | use rustc::ty; | |
17 | use std::fmt::Debug; | |
18 | ||
19 | /// The canonicalization form of `QueryResult<'tcx, T>`. | |
20 | type CanonicalizedQueryResult<'gcx, 'tcx, T> = | |
21 | <QueryResult<'tcx, T> as Canonicalize<'gcx, 'tcx>>::Canonicalized; | |
22 | ||
23 | crate fn make_query_response<'gcx, 'tcx, T>( | |
24 | infcx: &InferCtxt<'_, 'gcx, 'tcx>, | |
25 | inference_vars: CanonicalVarValues<'tcx>, | |
26 | answer: T, | |
27 | fulfill_cx: &mut FulfillmentContext<'tcx>, | |
28 | ) -> Result<CanonicalizedQueryResult<'gcx, 'tcx, T>, NoSolution> | |
29 | where | |
30 | T: Debug, | |
31 | QueryResult<'tcx, T>: Canonicalize<'gcx, 'tcx>, | |
32 | { | |
33 | let tcx = infcx.tcx; | |
34 | ||
35 | debug!( | |
36 | "make_query_response(\ | |
37 | inference_vars={:?}, \ | |
38 | answer={:?})", | |
39 | inference_vars, answer, | |
40 | ); | |
41 | ||
42 | // Select everything, returning errors. | |
43 | let true_errors = match fulfill_cx.select_where_possible(infcx) { | |
44 | Ok(()) => vec![], | |
45 | Err(errors) => errors, | |
46 | }; | |
47 | debug!("true_errors = {:#?}", true_errors); | |
48 | ||
49 | if !true_errors.is_empty() { | |
50 | // FIXME -- we don't indicate *why* we failed to solve | |
51 | debug!("make_query_response: true_errors={:#?}", true_errors); | |
52 | return Err(NoSolution); | |
53 | } | |
54 | ||
55 | // Anything left unselected *now* must be an ambiguity. | |
56 | let ambig_errors = match fulfill_cx.select_all_or_error(infcx) { | |
57 | Ok(()) => vec![], | |
58 | Err(errors) => errors, | |
59 | }; | |
60 | debug!("ambig_errors = {:#?}", ambig_errors); | |
61 | ||
62 | let region_obligations = infcx.take_registered_region_obligations(); | |
63 | ||
83c7162d | 64 | let region_constraints = infcx.with_region_constraints(|region_constraints| { |
0531ce1d XL |
65 | let RegionConstraintData { |
66 | constraints, | |
67 | verifys, | |
68 | givens, | |
69 | } = region_constraints; | |
70 | ||
71 | assert!(verifys.is_empty()); | |
72 | assert!(givens.is_empty()); | |
73 | ||
83c7162d | 74 | let mut outlives: Vec<_> = constraints |
0531ce1d XL |
75 | .into_iter() |
76 | .map(|(k, _)| match *k { | |
94b46f34 XL |
77 | // Swap regions because we are going from sub (<=) to outlives |
78 | // (>=). | |
83c7162d | 79 | Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( |
94b46f34 XL |
80 | tcx.mk_region(ty::ReVar(v2)).into(), |
81 | tcx.mk_region(ty::ReVar(v1)), | |
83c7162d XL |
82 | ), |
83 | Constraint::VarSubReg(v1, r2) => { | |
94b46f34 | 84 | ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) |
0531ce1d | 85 | } |
83c7162d | 86 | Constraint::RegSubVar(r1, v2) => { |
94b46f34 | 87 | ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) |
83c7162d | 88 | } |
94b46f34 | 89 | Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), |
0531ce1d | 90 | }) |
83c7162d | 91 | .map(ty::Binder::dummy) // no bound regions in the code above |
0531ce1d XL |
92 | .collect(); |
93 | ||
83c7162d XL |
94 | outlives.extend( |
95 | region_obligations | |
96 | .into_iter() | |
97 | .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region)) | |
98 | .map(ty::Binder::dummy) // no bound regions in the code above | |
99 | ); | |
0531ce1d | 100 | |
83c7162d | 101 | outlives |
0531ce1d XL |
102 | }); |
103 | ||
104 | let certainty = if ambig_errors.is_empty() { | |
105 | Certainty::Proven | |
106 | } else { | |
107 | Certainty::Ambiguous | |
108 | }; | |
109 | ||
110 | let (canonical_result, _) = infcx.canonicalize_response(&QueryResult { | |
111 | var_values: inference_vars, | |
83c7162d | 112 | region_constraints, |
0531ce1d XL |
113 | certainty, |
114 | value: answer, | |
115 | }); | |
116 | ||
117 | debug!( | |
118 | "make_query_response: canonical_result = {:#?}", | |
119 | canonical_result | |
120 | ); | |
121 | ||
122 | Ok(canonical_result) | |
123 | } |