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