]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/infer/resolve.rs
Merge pull request #20510 from tshepang/patch-6
[rust.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, fixup_err, fres, unresolved_ty, unresolved_int_ty, unresolved_float_ty};
12 use middle::ty::{self, Ty};
13 use middle::ty_fold::{self, TypeFoldable};
14 use util::ppaux::Repr;
15
16 ///////////////////////////////////////////////////////////////////////////
17 // OPPORTUNISTIC TYPE RESOLVER
18
19 /// The opportunistic type resolver can be used at any time. It simply replaces
20 /// type variables that have been unified with the things they have
21 /// been unified with (similar to `shallow_resolve`, but deep). This is
22 /// useful for printing messages etc but also required at various
23 /// points for correctness.
24 pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
25     infcx: &'a InferCtxt<'a, 'tcx>,
26 }
27
28 impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
29     pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
30         OpportunisticTypeResolver { infcx: infcx }
31     }
32 }
33
34 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
35     fn tcx(&self) -> &ty::ctxt<'tcx> {
36         self.infcx.tcx
37     }
38
39     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
40         if !ty::type_has_ty_infer(t) {
41             t // micro-optimize -- if there is nothing in this type that this fold affects...
42         } else {
43             let t0 = self.infcx.shallow_resolve(t);
44             ty_fold::super_fold_ty(self, t0)
45         }
46     }
47 }
48
49 ///////////////////////////////////////////////////////////////////////////
50 // FULL TYPE RESOLUTION
51
52 /// Full type resolution replaces all type and region variables with
53 /// their concrete results. If any variable cannot be replaced (never unified, etc)
54 /// then an `Err` result is returned.
55 pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> fres<T>
56     where T : TypeFoldable<'tcx>
57 {
58     let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
59     let result = value.fold_with(&mut full_resolver);
60     match full_resolver.err {
61         None => Ok(result),
62         Some(e) => Err(e),
63     }
64 }
65
66 // N.B. This type is not public because the protocol around checking the
67 // `err` field is not enforcable otherwise.
68 struct FullTypeResolver<'a, 'tcx:'a> {
69     infcx: &'a InferCtxt<'a, 'tcx>,
70     err: Option<fixup_err>,
71 }
72
73 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
74     fn tcx(&self) -> &ty::ctxt<'tcx> {
75         self.infcx.tcx
76     }
77
78     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
79         if !ty::type_needs_infer(t) {
80             t // micro-optimize -- if there is nothing in this type that this fold affects...
81         } else {
82             let t = self.infcx.shallow_resolve(t);
83             match t.sty {
84                 ty::ty_infer(ty::TyVar(vid)) => {
85                     self.err = Some(unresolved_ty(vid));
86                     self.tcx().types.err
87                 }
88                 ty::ty_infer(ty::IntVar(vid)) => {
89                     self.err = Some(unresolved_int_ty(vid));
90                     self.tcx().types.err
91                 }
92                 ty::ty_infer(ty::FloatVar(vid)) => {
93                     self.err = Some(unresolved_float_ty(vid));
94                     self.tcx().types.err
95                 }
96                 ty::ty_infer(_) => {
97                     self.infcx.tcx.sess.bug(
98                         format!("Unexpected type in full type resolver: {}",
99                                 t.repr(self.infcx.tcx))[]);
100                 }
101                 _ => {
102                     ty_fold::super_fold_ty(self, t)
103                 }
104             }
105         }
106     }
107
108     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
109         match r {
110           ty::ReInfer(ty::ReVar(rid)) => self.infcx.region_vars.resolve_var(rid),
111           _ => r,
112         }
113     }
114 }
115