|
| 1 | +// Copyright 2014 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 middle::ty; |
| 12 | +use syntax::ast; |
| 13 | + |
| 14 | +use self::SimplifiedType::*; |
| 15 | + |
| 16 | +/** See `simplify_type */ |
| 17 | +#[deriving(Clone, PartialEq, Eq, Hash)] |
| 18 | +pub enum SimplifiedType { |
| 19 | + BoolSimplifiedType, |
| 20 | + CharSimplifiedType, |
| 21 | + IntSimplifiedType(ast::IntTy), |
| 22 | + UintSimplifiedType(ast::UintTy), |
| 23 | + FloatSimplifiedType(ast::FloatTy), |
| 24 | + EnumSimplifiedType(ast::DefId), |
| 25 | + StrSimplifiedType, |
| 26 | + VecSimplifiedType, |
| 27 | + PtrSimplifiedType, |
| 28 | + TupleSimplifiedType(uint), |
| 29 | + TraitSimplifiedType(ast::DefId), |
| 30 | + StructSimplifiedType(ast::DefId), |
| 31 | + UnboxedClosureSimplifiedType(ast::DefId), |
| 32 | + FunctionSimplifiedType(uint), |
| 33 | + ParameterSimplifiedType, |
| 34 | +} |
| 35 | + |
| 36 | +pub fn simplify_type(tcx: &ty::ctxt, |
| 37 | + ty: ty::t, |
| 38 | + can_simplify_params: bool) |
| 39 | + -> Option<SimplifiedType> |
| 40 | +{ |
| 41 | + /*! |
| 42 | + * Tries to simplify a type by dropping type parameters, deref'ing |
| 43 | + * away any reference types, etc. The idea is to get something |
| 44 | + * simple that we can use to quickly decide if two types could |
| 45 | + * unify during method lookup. |
| 46 | + * |
| 47 | + * If `can_simplify_params` is false, then we will fail to |
| 48 | + * simplify type parameters entirely. This is useful when those |
| 49 | + * type parameters would be instantiated with fresh type |
| 50 | + * variables, since then we can't say much about whether two types |
| 51 | + * would unify. Put another way, `can_simplify_params` should be |
| 52 | + * true if type parameters appear free in `ty` and `false` if they |
| 53 | + * are to be considered bound. |
| 54 | + */ |
| 55 | + |
| 56 | + match ty::get(ty).sty { |
| 57 | + ty::ty_bool => Some(BoolSimplifiedType), |
| 58 | + ty::ty_char => Some(CharSimplifiedType), |
| 59 | + ty::ty_int(int_type) => Some(IntSimplifiedType(int_type)), |
| 60 | + ty::ty_uint(uint_type) => Some(UintSimplifiedType(uint_type)), |
| 61 | + ty::ty_float(float_type) => Some(FloatSimplifiedType(float_type)), |
| 62 | + ty::ty_enum(def_id, _) => Some(EnumSimplifiedType(def_id)), |
| 63 | + ty::ty_str => Some(StrSimplifiedType), |
| 64 | + ty::ty_vec(..) => Some(VecSimplifiedType), |
| 65 | + ty::ty_ptr(_) => Some(PtrSimplifiedType), |
| 66 | + ty::ty_trait(ref trait_info) => { |
| 67 | + Some(TraitSimplifiedType(trait_info.principal.def_id)) |
| 68 | + } |
| 69 | + ty::ty_struct(def_id, _) => { |
| 70 | + Some(StructSimplifiedType(def_id)) |
| 71 | + } |
| 72 | + ty::ty_rptr(_, mt) => { |
| 73 | + // since we introduce auto-refs during method lookup, we |
| 74 | + // just treat &T and T as equivalent from the point of |
| 75 | + // view of possibly unifying |
| 76 | + simplify_type(tcx, mt.ty, can_simplify_params) |
| 77 | + } |
| 78 | + ty::ty_uniq(_) => { |
| 79 | + // treat like we would treat `Box` |
| 80 | + let def_id = tcx.lang_items.owned_box().unwrap(); |
| 81 | + Some(StructSimplifiedType(def_id)) |
| 82 | + } |
| 83 | + ty::ty_unboxed_closure(def_id, _, _) => { |
| 84 | + Some(UnboxedClosureSimplifiedType(def_id)) |
| 85 | + } |
| 86 | + ty::ty_tup(ref tys) => { |
| 87 | + Some(TupleSimplifiedType(tys.len())) |
| 88 | + } |
| 89 | + ty::ty_closure(ref f) => { |
| 90 | + Some(FunctionSimplifiedType(f.sig.inputs.len())) |
| 91 | + } |
| 92 | + ty::ty_bare_fn(ref f) => { |
| 93 | + Some(FunctionSimplifiedType(f.sig.inputs.len())) |
| 94 | + } |
| 95 | + ty::ty_param(_) => { |
| 96 | + if can_simplify_params { |
| 97 | + Some(ParameterSimplifiedType) |
| 98 | + } else { |
| 99 | + None |
| 100 | + } |
| 101 | + } |
| 102 | + ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None, |
| 103 | + } |
| 104 | +} |
| 105 | + |
0 commit comments