]> git.proxmox.com Git - rustc.git/blame - src/librustc/middle/infer/resolve.rs
Imported Upstream version 1.3.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
SL
11use super::{InferCtxt, FixupError, FixupResult};
12use middle::ty::{self, Ty, HasTypeFlags};
1a4d82fc 13use middle::ty_fold::{self, TypeFoldable};
1a4d82fc
JJ
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.
23pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
24 infcx: &'a InferCtxt<'a, 'tcx>,
25}
26
27impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
28 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
29 OpportunisticTypeResolver { infcx: infcx }
30 }
31}
32
33impl<'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> {
c1a9b12d 39 if !t.has_infer_types() {
1a4d82fc
JJ
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.
c1a9b12d 54pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> FixupResult<T>
1a4d82fc
JJ
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.
67struct FullTypeResolver<'a, 'tcx:'a> {
68 infcx: &'a InferCtxt<'a, 'tcx>,
c1a9b12d 69 err: Option<FixupError>,
1a4d82fc
JJ
70}
71
72impl<'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> {
c1a9b12d 78 if !t.needs_infer() {
1a4d82fc
JJ
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 {
62682a34 83 ty::TyInfer(ty::TyVar(vid)) => {
c1a9b12d 84 self.err = Some(FixupError::UnresolvedTy(vid));
1a4d82fc
JJ
85 self.tcx().types.err
86 }
62682a34 87 ty::TyInfer(ty::IntVar(vid)) => {
c1a9b12d 88 self.err = Some(FixupError::UnresolvedIntTy(vid));
1a4d82fc
JJ
89 self.tcx().types.err
90 }
62682a34 91 ty::TyInfer(ty::FloatVar(vid)) => {
c1a9b12d 92 self.err = Some(FixupError::UnresolvedFloatTy(vid));
1a4d82fc
JJ
93 self.tcx().types.err
94 }
62682a34 95 ty::TyInfer(_) => {
1a4d82fc 96 self.infcx.tcx.sess.bug(
62682a34
SL
97 &format!("Unexpected type in full type resolver: {:?}",
98 t));
1a4d82fc
JJ
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}