]> git.proxmox.com Git - rustc.git/blame - src/librustc/middle/infer/resolve.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc / middle / infer / resolve.rs
CommitLineData
1a4d82fc
JJ
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
c1a9b12d 11use super::{InferCtxt, FixupError, FixupResult};
9cc50fc6 12use middle::ty::{self, Ty, TypeFoldable};
1a4d82fc
JJ
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.
22pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
23 infcx: &'a InferCtxt<'a, 'tcx>,
24}
25
26impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
27 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
28 OpportunisticTypeResolver { infcx: infcx }
29 }
30}
31
e9174d1e 32impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
1a4d82fc
JJ
33 fn tcx(&self) -> &ty::ctxt<'tcx> {
34 self.infcx.tcx
35 }
36
37 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
c1a9b12d 38 if !t.has_infer_types() {
1a4d82fc
JJ
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);
9cc50fc6
SL
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.
50pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx:'a> {
51 infcx: &'a InferCtxt<'a, 'tcx>,
52}
53
54impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> {
55 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
56 OpportunisticTypeAndRegionResolver { infcx: infcx }
57 }
58}
59
60impl<'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,
1a4d82fc
JJ
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.
c1a9b12d 88pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> FixupResult<T>
1a4d82fc
JJ
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.
101struct FullTypeResolver<'a, 'tcx:'a> {
102 infcx: &'a InferCtxt<'a, 'tcx>,
c1a9b12d 103 err: Option<FixupError>,
1a4d82fc
JJ
104}
105
e9174d1e 106impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
1a4d82fc
JJ
107 fn tcx(&self) -> &ty::ctxt<'tcx> {
108 self.infcx.tcx
109 }
110
111 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
c1a9b12d 112 if !t.needs_infer() {
1a4d82fc
JJ
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 {
62682a34 117 ty::TyInfer(ty::TyVar(vid)) => {
c1a9b12d 118 self.err = Some(FixupError::UnresolvedTy(vid));
1a4d82fc
JJ
119 self.tcx().types.err
120 }
62682a34 121 ty::TyInfer(ty::IntVar(vid)) => {
c1a9b12d 122 self.err = Some(FixupError::UnresolvedIntTy(vid));
1a4d82fc
JJ
123 self.tcx().types.err
124 }
62682a34 125 ty::TyInfer(ty::FloatVar(vid)) => {
c1a9b12d 126 self.err = Some(FixupError::UnresolvedFloatTy(vid));
1a4d82fc
JJ
127 self.tcx().types.err
128 }
62682a34 129 ty::TyInfer(_) => {
1a4d82fc 130 self.infcx.tcx.sess.bug(
62682a34
SL
131 &format!("Unexpected type in full type resolver: {:?}",
132 t));
1a4d82fc
JJ
133 }
134 _ => {
9cc50fc6 135 t.super_fold_with(self)
1a4d82fc
JJ
136 }
137 }
138 }
139 }
140
141 fn fold_region(&mut self, r: ty::Region) -> ty::Region {
142 match r {
e9174d1e 143 ty::ReVar(rid) => self.infcx.region_vars.resolve_var(rid),
1a4d82fc
JJ
144 _ => r,
145 }
146 }
147}