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.
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.
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;
16 ///////////////////////////////////////////////////////////////////////////
17 // OPPORTUNISTIC TYPE RESOLVER
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>,
28 impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
29 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
30 OpportunisticTypeResolver { infcx: infcx }
34 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
35 fn tcx(&self) -> &ty::ctxt<'tcx> {
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...
43 let t0 = self.infcx.shallow_resolve(t);
44 ty_fold::super_fold_ty(self, t0)
49 ///////////////////////////////////////////////////////////////////////////
50 // FULL TYPE RESOLUTION
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>
58 let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
59 let result = value.fold_with(&mut full_resolver);
60 match full_resolver.err {
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>,
73 impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
74 fn tcx(&self) -> &ty::ctxt<'tcx> {
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...
82 let t = self.infcx.shallow_resolve(t);
84 ty::ty_infer(ty::TyVar(vid)) => {
85 self.err = Some(unresolved_ty(vid));
88 ty::ty_infer(ty::IntVar(vid)) => {
89 self.err = Some(unresolved_int_ty(vid));
92 ty::ty_infer(ty::FloatVar(vid)) => {
93 self.err = Some(unresolved_float_ty(vid));
97 self.infcx.tcx.sess.bug(
98 format!("Unexpected type in full type resolver: {}",
99 t.repr(self.infcx.tcx))[]);
102 ty_fold::super_fold_ty(self, t)
108 fn fold_region(&mut self, r: ty::Region) -> ty::Region {
110 ty::ReInfer(ty::ReVar(rid)) => self.infcx.region_vars.resolve_var(rid),