]> git.proxmox.com Git - rustc.git/blob - src/librustc/middle/infer/resolve.rs
Imported Upstream version 1.3.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, HasTypeFlags};
13 use middle::ty_fold::{self, TypeFoldable};
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, 'tcx:'a> {
24 infcx: &'a InferCtxt<'a, 'tcx>,
25 }
26
27 impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
28 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
29 OpportunisticTypeResolver { infcx: infcx }
30 }
31 }
32
33 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
34 fn tcx(&self) -> &ty::ctxt<'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 ty_fold::super_fold_ty(self, t0)
44 }
45 }
46 }
47
48 ///////////////////////////////////////////////////////////////////////////
49 // FULL TYPE RESOLUTION
50
51 /// Full type resolution replaces all type and region variables with
52 /// their concrete results. If any variable cannot be replaced (never unified, etc)
53 /// then an `Err` result is returned.
54 pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> FixupResult<T>
55 where T : TypeFoldable<'tcx>
56 {
57 let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
58 let result = value.fold_with(&mut full_resolver);
59 match full_resolver.err {
60 None => Ok(result),
61 Some(e) => Err(e),
62 }
63 }
64
65 // N.B. This type is not public because the protocol around checking the
66 // `err` field is not enforcable otherwise.
67 struct FullTypeResolver<'a, 'tcx:'a> {
68 infcx: &'a InferCtxt<'a, 'tcx>,
69 err: Option<FixupError>,
70 }
71
72 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
73 fn tcx(&self) -> &ty::ctxt<'tcx> {
74 self.infcx.tcx
75 }
76
77 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
78 if !t.needs_infer() {
79 t // micro-optimize -- if there is nothing in this type that this fold affects...
80 } else {
81 let t = self.infcx.shallow_resolve(t);
82 match t.sty {
83 ty::TyInfer(ty::TyVar(vid)) => {
84 self.err = Some(FixupError::UnresolvedTy(vid));
85 self.tcx().types.err
86 }
87 ty::TyInfer(ty::IntVar(vid)) => {
88 self.err = Some(FixupError::UnresolvedIntTy(vid));
89 self.tcx().types.err
90 }
91 ty::TyInfer(ty::FloatVar(vid)) => {
92 self.err = Some(FixupError::UnresolvedFloatTy(vid));
93 self.tcx().types.err
94 }
95 ty::TyInfer(_) => {
96 self.infcx.tcx.sess.bug(
97 &format!("Unexpected type in full type resolver: {:?}",
98 t));
99 }
100 _ => {
101 ty_fold::super_fold_ty(self, t)
102 }
103 }
104 }
105 }
106
107 fn fold_region(&mut self, r: ty::Region) -> ty::Region {
108 match r {
109 ty::ReInfer(ty::ReVar(rid)) => self.infcx.region_vars.resolve_var(rid),
110 _ => r,
111 }
112 }
113 }