]> git.proxmox.com Git - rustc.git/blob - src/librustc/infer/resolve.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / librustc / infer / resolve.rs
1 // Copyright 2012 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 super::{InferCtxt, FixupError, FixupResult};
12 use ty::{self, Ty, TyCtxt, TypeFoldable};
13 use ty::fold::TypeFolder;
14
15 ///////////////////////////////////////////////////////////////////////////
16 // OPPORTUNISTIC TYPE RESOLVER
17
18 /// The opportunistic type resolver can be used at any time. It simply replaces
19 /// type variables that have been unified with the things they have
20 /// been unified with (similar to `shallow_resolve`, but deep). This is
21 /// useful for printing messages etc but also required at various
22 /// points for correctness.
23 pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
24 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
25 }
26
27 impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
28 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
29 OpportunisticTypeResolver { infcx: infcx }
30 }
31 }
32
33 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
34 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
35 self.infcx.tcx
36 }
37
38 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
39 if !t.has_infer_types() {
40 t // micro-optimize -- if there is nothing in this type that this fold affects...
41 } else {
42 let t0 = self.infcx.shallow_resolve(t);
43 t0.super_fold_with(self)
44 }
45 }
46 }
47
48 /// The opportunistic type and region resolver is similar to the
49 /// opportunistic type resolver, but also opportunistly resolves
50 /// regions. It is useful for canonicalization.
51 pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
52 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
53 }
54
55 impl<'a, 'gcx, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
56 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
57 OpportunisticTypeAndRegionResolver { infcx: infcx }
58 }
59 }
60
61 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
62 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
63 self.infcx.tcx
64 }
65
66 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
67 if !t.needs_infer() {
68 t // micro-optimize -- if there is nothing in this type that this fold affects...
69 } else {
70 let t0 = self.infcx.shallow_resolve(t);
71 t0.super_fold_with(self)
72 }
73 }
74
75 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
76 match *r {
77 ty::ReVar(rid) => self.infcx.region_vars.opportunistic_resolve_var(rid),
78 _ => r,
79 }
80 }
81 }
82
83 ///////////////////////////////////////////////////////////////////////////
84 // FULL TYPE RESOLUTION
85
86 /// Full type resolution replaces all type and region variables with
87 /// their concrete results. If any variable cannot be replaced (never unified, etc)
88 /// then an `Err` result is returned.
89 pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
90 value: &T) -> FixupResult<T>
91 where T : TypeFoldable<'tcx>
92 {
93 let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
94 let result = value.fold_with(&mut full_resolver);
95 match full_resolver.err {
96 None => Ok(result),
97 Some(e) => Err(e),
98 }
99 }
100
101 // N.B. This type is not public because the protocol around checking the
102 // `err` field is not enforcable otherwise.
103 struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
104 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
105 err: Option<FixupError>,
106 }
107
108 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
109 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
110 self.infcx.tcx
111 }
112
113 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
114 if !t.needs_infer() {
115 t // micro-optimize -- if there is nothing in this type that this fold affects...
116 } else {
117 let t = self.infcx.shallow_resolve(t);
118 match t.sty {
119 ty::TyInfer(ty::TyVar(vid)) => {
120 self.err = Some(FixupError::UnresolvedTy(vid));
121 self.tcx().types.err
122 }
123 ty::TyInfer(ty::IntVar(vid)) => {
124 self.err = Some(FixupError::UnresolvedIntTy(vid));
125 self.tcx().types.err
126 }
127 ty::TyInfer(ty::FloatVar(vid)) => {
128 self.err = Some(FixupError::UnresolvedFloatTy(vid));
129 self.tcx().types.err
130 }
131 ty::TyInfer(_) => {
132 bug!("Unexpected type in full type resolver: {:?}", t);
133 }
134 _ => {
135 t.super_fold_with(self)
136 }
137 }
138 }
139 }
140
141 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
142 match *r {
143 ty::ReVar(rid) => self.infcx.region_vars.resolve_var(rid),
144 _ => r,
145 }
146 }
147 }