]> git.proxmox.com Git - rustc.git/blob - src/librustc_traits/util.rs
New upstream version 1.27.1+dfsg1
[rustc.git] / src / librustc_traits / util.rs
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;
12 use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult};
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
64 let region_constraints = infcx.with_region_constraints(|region_constraints| {
65 let RegionConstraintData {
66 constraints,
67 verifys,
68 givens,
69 } = region_constraints;
70
71 assert!(verifys.is_empty());
72 assert!(givens.is_empty());
73
74 let mut outlives: Vec<_> = constraints
75 .into_iter()
76 .map(|(k, _)| match *k {
77 Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
78 tcx.mk_region(ty::ReVar(v1)).into(),
79 tcx.mk_region(ty::ReVar(v2)),
80 ),
81 Constraint::VarSubReg(v1, r2) => {
82 ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2)
83 }
84 Constraint::RegSubVar(r1, v2) => {
85 ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2)))
86 }
87 Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2),
88 })
89 .map(ty::Binder::dummy) // no bound regions in the code above
90 .collect();
91
92 outlives.extend(
93 region_obligations
94 .into_iter()
95 .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
96 .map(ty::Binder::dummy) // no bound regions in the code above
97 );
98
99 outlives
100 });
101
102 let certainty = if ambig_errors.is_empty() {
103 Certainty::Proven
104 } else {
105 Certainty::Ambiguous
106 };
107
108 let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
109 var_values: inference_vars,
110 region_constraints,
111 certainty,
112 value: answer,
113 });
114
115 debug!(
116 "make_query_response: canonical_result = {:#?}",
117 canonical_result
118 );
119
120 Ok(canonical_result)
121 }