提交 eb6ea5d4 编写于 作者: N Niko Matsakis

Cleanup type resolution to use type folding infrastructure and not

have such a silly over-engineered interface.
上级 3efc9d2c
......@@ -60,10 +60,9 @@
//! sort of a minor point so I've opted to leave it for later---after all
//! we may want to adjust precisely when coercions occur.
use super::{CoerceResult, resolve_type, Coercion};
use super::{CoerceResult, Coercion};
use super::combine::{CombineFields, Combine};
use super::sub::Sub;
use super::resolve::try_resolve_tvar_shallow;
use middle::subst;
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
......@@ -197,18 +196,7 @@ pub fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
pub fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
F: FnOnce(&ty::sty<'tcx>) -> T,
{
match resolve_type(self.get_ref().infcx, None,
a, try_resolve_tvar_shallow) {
Ok(t) => {
f(&t.sty)
}
Err(e) => {
self.get_ref().infcx.tcx.sess.span_bug(
self.get_ref().trace.origin.span(),
format!("failed to resolve even without \
any force options: {}", e).as_slice());
}
}
f(&self.get_ref().infcx.shallow_resolve(a).sty)
}
// ~T -> &T or &mut T -> &T (including where T = [U] or str)
......
......@@ -19,13 +19,6 @@
pub use self::ValuePairs::*;
pub use self::fixup_err::*;
pub use middle::ty::IntVarValue;
pub use self::resolve::resolve_and_force_all_but_regions;
pub use self::resolve::{force_all, not_regions};
pub use self::resolve::{force_ivar};
pub use self::resolve::{force_tvar, force_rvar};
pub use self::resolve::{resolve_ivar, resolve_all};
pub use self::resolve::{resolve_nested_tvar};
pub use self::resolve::{resolve_rvar};
pub use self::skolemize::TypeSkolemizer;
use middle::subst;
......@@ -47,7 +40,6 @@
use self::coercion::Coerce;
use self::combine::{Combine, CombineFields};
use self::region_inference::{RegionVarBindings, RegionSnapshot};
use self::resolve::{resolver};
use self::equate::Equate;
use self::sub::Sub;
use self::lub::Lub;
......@@ -453,22 +445,6 @@ pub fn mk_coercety<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
})
}
// See comment on the type `resolve_state` below
pub fn resolve_type<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
span: Option<Span>,
a: Ty<'tcx>,
modes: uint)
-> fres<Ty<'tcx>> {
let mut resolver = resolver(cx, modes, span);
cx.commit_unconditionally(|| resolver.resolve_type_chk(a))
}
pub fn resolve_region(cx: &InferCtxt, r: ty::Region, modes: uint)
-> fres<ty::Region> {
let mut resolver = resolver(cx, modes, None);
resolver.resolve_region_chk(r)
}
trait then<'tcx> {
fn then<T, F>(&self, f: F) -> Result<T, ty::type_err<'tcx>> where
T: Clone,
......@@ -835,20 +811,21 @@ pub fn trait_ref_to_string(&self, t: &Rc<ty::TraitRef<'tcx>>) -> String {
trait_ref_to_string(self.tcx, &t)
}
pub fn contains_unbound_type_variables(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
match resolve_type(self,
None,
typ, resolve_nested_tvar | resolve_ivar) {
Ok(new_type) => new_type,
Err(_) => typ
}
}
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
match typ.sty {
ty::ty_infer(ty::TyVar(v)) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifying to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
self.type_variables.borrow()
.probe(v)
.map(|t| self.shallow_resolve(t))
.unwrap_or(typ)
}
......@@ -869,10 +846,33 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
}
pub fn resolve_type_vars_if_possible<T:TypeFoldable<'tcx>>(&self, value: &T) -> T {
let mut r = resolve::DeepTypeResolver::new(self);
/*!
* Where possible, replaces type/int/float variables in
* `value` with their final value. Note that region variables
* are unaffected. If a type variable has not been unified, it
* is left as is. This is an idempotent operation that does
* not affect inference state in any way and so you can do it
* at will.
*/
let mut r = resolve::OpportunisticTypeResolver::new(self);
value.fold_with(&mut r)
}
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> fres<T> {
/*!
* Attempts to resolve all type/region variables in
* `value`. Region inference must have been run already (e.g.,
* by calling `resolve_regions_and_report_errors`). If some
* variable was never unified, an `Err` results.
*
* This method is idempotent, but it not typically not invoked
* except during the writeback phase.
*/
resolve::fully_resolve(self, value)
}
// [Note-Type-error-reporting]
// An invariant is that anytime the expected or actual type is ty_err (the special
// error type, meaning that an error occurred when typechecking this expression),
......
......@@ -8,288 +8,108 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Resolution is the process of removing type variables and replacing
// them with their inferred values. Unfortunately our inference has
// become fairly complex and so there are a number of options to
// control *just how much* you want to resolve and how you want to do
// it.
//
// # Controlling the scope of resolution
//
// The options resolve_* determine what kinds of variables get
// resolved. Generally resolution starts with a top-level type
// variable; we will always resolve this. However, once we have
// resolved that variable, we may end up with a type that still
// contains type variables. For example, if we resolve `<T0>` we may
// end up with something like `[<T1>]`. If the option
// `resolve_nested_tvar` is passed, we will then go and recursively
// resolve `<T1>`.
//
// The options `resolve_rvar` controls whether we resolve region
// variables. The options `resolve_fvar` and `resolve_ivar` control
// whether we resolve floating point and integral variables,
// respectively.
//
// # What do if things are unconstrained
//
// Sometimes we will encounter a variable that has no constraints, and
// therefore cannot sensibly be mapped to any particular result. By
// default, we will leave such variables as is (so you will get back a
// variable in your result). The options force_* will cause the
// resolution to fail in this case instead, except for the case of
// integral variables, which resolve to `int` if forced.
//
// # resolve_all and force_all
//
// The options are a bit set, so you can use the *_all to resolve or
// force all kinds of variables (including those we may add in the
// future). If you want to resolve everything but one type, you are
// probably better off writing `resolve_all - resolve_ivar`.
#![allow(non_upper_case_globals)]
use super::{fixup_err, fres, InferCtxt};
use super::{unresolved_int_ty,unresolved_float_ty,unresolved_ty};
use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid};
use middle::ty::{IntType, UintType};
use super::{InferCtxt, fixup_err, fres, unresolved_ty, unresolved_int_ty, unresolved_float_ty};
use middle::ty::{mod, Ty};
use middle::ty_fold;
use syntax::codemap::Span;
use util::ppaux::{Repr, ty_to_string};
use middle::ty_fold::{mod, TypeFoldable};
use util::ppaux::Repr;
pub const resolve_nested_tvar: uint = 0b0000000001;
pub const resolve_rvar: uint = 0b0000000010;
pub const resolve_ivar: uint = 0b0000000100;
pub const resolve_fvar: uint = 0b0000001000;
pub const resolve_all: uint = 0b0000001111;
pub const force_tvar: uint = 0b0000100000;
pub const force_rvar: uint = 0b0001000000;
pub const force_ivar: uint = 0b0010000000;
pub const force_fvar: uint = 0b0100000000;
pub const force_all: uint = 0b0111100000;
pub const not_regions: uint = !(force_rvar | resolve_rvar);
pub const try_resolve_tvar_shallow: uint = 0;
pub const resolve_and_force_all_but_regions: uint =
(resolve_all | force_all) & not_regions;
///////////////////////////////////////////////////////////////////////////
// OPPORTUNISTIC TYPE RESOLVER
pub struct ResolveState<'a, 'tcx: 'a> {
/// The opportunistic type resolver can be used at any time. It simply replaces
/// type variables that have been unified with the things they have
/// been unified with (similar to `shallow_resolve`, but deep). This is
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
infcx: &'a InferCtxt<'a, 'tcx>,
modes: uint,
err: Option<fixup_err>,
type_depth: uint,
}
pub fn resolver<'a, 'tcx>(infcx: &'a InferCtxt<'a, 'tcx>,
modes: uint,
_: Option<Span>)
-> ResolveState<'a, 'tcx> {
ResolveState {
infcx: infcx,
modes: modes,
err: None,
type_depth: 0,
impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
OpportunisticTypeResolver { infcx: infcx }
}
}
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for ResolveState<'a, 'tcx> {
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
self.resolve_type(t)
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
self.resolve_region(r)
}
}
impl<'a, 'tcx> ResolveState<'a, 'tcx> {
pub fn should(&mut self, mode: uint) -> bool {
(self.modes & mode) == mode
}
pub fn resolve_type_chk(&mut self, typ: Ty<'tcx>) -> fres<Ty<'tcx>> {
self.err = None;
debug!("Resolving {} (modes={:x})",
ty_to_string(self.infcx.tcx, typ),
self.modes);
// n.b. This is a hokey mess because the current fold doesn't
// allow us to pass back errors in any useful way.
let rty = self.resolve_type(typ);
match self.err {
None => {
debug!("Resolved {} to {} (modes={:x})",
ty_to_string(self.infcx.tcx, typ),
ty_to_string(self.infcx.tcx, rty),
self.modes);
return Ok(rty);
}
Some(e) => {
return Err(e);
}
}
}
pub fn resolve_region_chk(&mut self,
orig: ty::Region)
-> fres<ty::Region> {
self.err = None;
let resolved = self.resolve_region(orig);
match self.err {
None => Ok(resolved),
Some(e) => Err(e)
}
}
pub fn resolve_type(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
debug!("resolve_type({})", typ.repr(self.infcx.tcx));
if !ty::type_needs_infer(typ) {
return typ;
}
if self.type_depth > 0 && !self.should(resolve_nested_tvar) {
return typ;
}
match typ.sty {
ty::ty_infer(TyVar(vid)) => {
self.resolve_ty_var(vid)
}
ty::ty_infer(IntVar(vid)) => {
self.resolve_int_var(vid)
}
ty::ty_infer(FloatVar(vid)) => {
self.resolve_float_var(vid)
}
_ => {
if self.modes & resolve_all == 0 {
// if we are only resolving top-level type
// variables, and this is not a top-level type
// variable, then shortcircuit for efficiency
typ
} else {
self.type_depth += 1;
let result = ty_fold::super_fold_ty(self, typ);
self.type_depth -= 1;
result
}
}
}
}
pub fn resolve_region(&mut self, orig: ty::Region) -> ty::Region {
debug!("Resolve_region({})", orig.repr(self.infcx.tcx));
match orig {
ty::ReInfer(ty::ReVar(rid)) => self.resolve_region_var(rid),
_ => orig
}
}
pub fn resolve_region_var(&mut self, rid: RegionVid) -> ty::Region {
if !self.should(resolve_rvar) {
return ty::ReInfer(ty::ReVar(rid));
}
self.infcx.region_vars.resolve_var(rid)
}
pub fn resolve_ty_var(&mut self, vid: TyVid) -> Ty<'tcx> {
let tcx = self.infcx.tcx;
let tv = self.infcx.type_variables.borrow();
match tv.probe(vid) {
Some(t) => {
self.resolve_type(t)
}
None => {
if self.should(force_tvar) {
self.err = Some(unresolved_ty(vid));
}
ty::mk_var(tcx, vid)
}
}
}
pub fn resolve_int_var(&mut self, vid: IntVid) -> Ty<'tcx> {
if !self.should(resolve_ivar) {
return ty::mk_int_var(self.infcx.tcx, vid);
}
let tcx = self.infcx.tcx;
let table = &self.infcx.int_unification_table;
let node = table.borrow_mut().get(tcx, vid);
match node.value {
Some(IntType(t)) => ty::mk_mach_int(t),
Some(UintType(t)) => ty::mk_mach_uint(t),
None => {
if self.should(force_ivar) {
// As a last resort, emit an error.
self.err = Some(unresolved_int_ty(vid));
}
ty::mk_int_var(self.infcx.tcx, vid)
}
}
}
pub fn resolve_float_var(&mut self, vid: FloatVid) -> Ty<'tcx> {
if !self.should(resolve_fvar) {
return ty::mk_float_var(self.infcx.tcx, vid);
}
let tcx = self.infcx.tcx;
let table = &self.infcx.float_unification_table;
let node = table.borrow_mut().get(tcx, vid);
match node.value {
Some(t) => ty::mk_mach_float(t),
None => {
if self.should(force_fvar) {
// As a last resort, emit an error.
self.err = Some(unresolved_float_ty(vid));
}
ty::mk_float_var(self.infcx.tcx, vid)
}
if !ty::type_has_ty_infer(t) {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t0 = self.infcx.shallow_resolve(t);
ty_fold::super_fold_ty(self, t0)
}
}
}
///////////////////////////////////////////////////////////////////////////
/// DEEP TYPE RESOLVER
///
/// This kind of resolver can be used at any time. It simply replaces
/// type variables that have been unified with the things they have
/// been unified with (similar to `shallow_resolve`, but deep). This is
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct DeepTypeResolver<'a, 'tcx:'a> {
infcx: &'a InferCtxt<'a, 'tcx>,
// FULL TYPE RESOLUTION
/// Full type resolution replaces all type and region variables with
/// their concrete results. If any variable cannot be replaced (never unified, etc)
/// then an `Err` result is returned.
pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> fres<T>
where T : TypeFoldable<'tcx>
{
let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
let result = value.fold_with(&mut full_resolver);
match full_resolver.err {
None => Ok(result),
Some(e) => Err(e),
}
}
impl<'a, 'tcx> DeepTypeResolver<'a, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> DeepTypeResolver<'a, 'tcx> {
DeepTypeResolver { infcx: infcx }
}
// N.B. This type is not public because the protocol around checking the
// `err` field is not enforcable otherwise.
struct FullTypeResolver<'a, 'tcx:'a> {
infcx: &'a InferCtxt<'a, 'tcx>,
err: Option<fixup_err>,
}
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for DeepTypeResolver<'a, 'tcx> {
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !ty::type_has_ty_infer(t) {
if !ty::type_needs_infer(t) {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t0 = self.infcx.shallow_resolve(t);
ty_fold::super_fold_ty(self, t0)
let t = self.infcx.shallow_resolve(t);
match t.sty {
ty::ty_infer(ty::TyVar(vid)) => {
self.err = Some(unresolved_ty(vid));
ty::mk_err()
}
ty::ty_infer(ty::IntVar(vid)) => {
self.err = Some(unresolved_int_ty(vid));
ty::mk_err()
}
ty::ty_infer(ty::FloatVar(vid)) => {
self.err = Some(unresolved_float_ty(vid));
ty::mk_err()
}
ty::ty_infer(_) => {
self.infcx.tcx.sess.bug(
format!("Unexpected type in full type resolver: {}",
t.repr(self.infcx.tcx))[]);
}
_ => {
ty_fold::super_fold_ty(self, t)
}
}
}
}
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
ty::ReInfer(ty::ReVar(rid)) => self.infcx.region_vars.resolve_var(rid),
_ => r,
}
}
}
......@@ -9,7 +9,7 @@
// except according to those terms.
use middle::def;
use middle::infer::{mod, resolve};
use middle::infer;
use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
use middle::subst::{Subst, Substs};
use middle::ty::{mod, Ty};
......@@ -143,11 +143,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
ast::PatRegion(ref inner) => {
let inner_ty = fcx.infcx().next_ty_var();
let mutbl = infer::resolve_type(
fcx.infcx(), Some(pat.span),
expected, resolve::try_resolve_tvar_shallow)
.ok()
.and_then(|t| ty::deref(t, true))
let mutbl =
ty::deref(fcx.infcx().shallow_resolve(expected), true)
.map_or(ast::MutImmutable, |mt| mt.mutbl);
let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
......@@ -214,23 +211,21 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
inner: &ast::Pat) -> bool {
let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
match infer::resolve_type(
fcx.infcx(), Some(span),
expected, resolve::try_resolve_tvar_shallow) {
Ok(t) if pat_is_binding(&tcx.def_map, inner) => {
ty::deref(t, true).map_or(true, |mt| match mt.ty.sty {
ty::ty_trait(_) => {
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
span_err!(tcx.sess, span, E0033,
"type `{}` cannot be dereferenced",
fcx.infcx().ty_to_string(t));
false
}
_ => true
})
}
_ => true
if pat_is_binding(&tcx.def_map, inner) {
let expected = fcx.infcx().shallow_resolve(expected);
ty::deref(expected, true).map_or(true, |mt| match mt.ty.sty {
ty::ty_trait(_) => {
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
span_err!(tcx.sess, span, E0033,
"type `{}` cannot be dereferenced",
fcx.infcx().ty_to_string(expected));
false
}
_ => true
})
} else {
true
}
}
......
......@@ -12,8 +12,6 @@
use check::FnCtxt;
use middle::ty::{mod, Ty};
use middle::infer;
use middle::infer::resolve_type;
use middle::infer::resolve::try_resolve_tvar_shallow;
use std::result::Result::{Err, Ok};
use syntax::ast;
......@@ -63,12 +61,7 @@ pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
debug!("demand::coerce(expected = {}, expr_ty = {})",
expected.repr(fcx.ccx.tcx),
expr_ty.repr(fcx.ccx.tcx));
let expected = if ty::type_needs_infer(expected) {
resolve_type(fcx.infcx(),
None,
expected,
try_resolve_tvar_shallow).unwrap_or(expected)
} else { expected };
let expected = fcx.infcx().resolve_type_vars_if_possible(&expected);
match fcx.mk_assignty(expr, expr_ty, expected) {
Ok(()) => { /* ok */ }
Err(ref err) => {
......
......@@ -124,8 +124,6 @@
use middle::traits;
use middle::ty::{ReScope};
use middle::ty::{mod, Ty, MethodCall};
use middle::infer::resolve_and_force_all_but_regions;
use middle::infer::resolve_type;
use middle::infer;
use middle::pat_util;
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap};
......@@ -307,11 +305,7 @@ pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
/// of b will be `&<R0>.int` and then `*b` will require that `<R0>` be bigger than the let and
/// the `*b` expression, so we will effectively resolve `<R0>` to be the block B.
pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> {
match resolve_type(self.fcx.infcx(), None, unresolved_ty,
resolve_and_force_all_but_regions) {
Ok(t) => t,
Err(_) => ty::mk_err()
}
self.fcx.infcx().resolve_type_vars_if_possible(&unresolved_ty)
}
/// Try to resolve the type for the given node.
......
......@@ -19,8 +19,6 @@
use middle::pat_util;
use middle::ty::{mod, Ty, MethodCall, MethodCallee};
use middle::ty_fold::{TypeFolder,TypeFoldable};
use middle::infer::{force_all, resolve_all, resolve_region};
use middle::infer::resolve_type;
use middle::infer;
use write_substs_to_tcx;
use write_ty_to_tcx;
......@@ -337,8 +335,8 @@ fn visit_method_map_entry(&self,
}
}
fn resolve<T:ResolveIn<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
t.resolve_in(&mut Resolver::new(self.fcx, reason))
fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
t.fold_with(&mut Resolver::new(self.fcx, reason))
}
}
......@@ -375,19 +373,6 @@ fn span(&self, tcx: &ty::ctxt) -> Span {
}
}
///////////////////////////////////////////////////////////////////////////
// Convenience methods for resolving different kinds of things.
trait ResolveIn<'tcx> {
fn resolve_in<'a>(&self, resolver: &mut Resolver<'a, 'tcx>) -> Self;
}
impl<'tcx, T: TypeFoldable<'tcx>> ResolveIn<'tcx> for T {
fn resolve_in<'a>(&self, resolver: &mut Resolver<'a, 'tcx>) -> T {
self.fold_with(resolver)
}
}
///////////////////////////////////////////////////////////////////////////
// The Resolver. This is the type folding engine that detects
// unresolved types and so forth.
......@@ -465,13 +450,11 @@ fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !ty::type_needs_infer(t) {
return t;
}
match resolve_type(self.infcx, None, t, resolve_all | force_all) {
match self.infcx.fully_resolve(&t) {
Ok(t) => t,
Err(e) => {
debug!("Resolver::fold_ty: input type `{}` not fully resolvable",
t.repr(self.tcx));
self.report_error(e);
ty::mk_err()
}
......@@ -479,7 +462,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match resolve_region(self.infcx, r, resolve_all | force_all) {
match self.infcx.fully_resolve(&r) {
Ok(r) => r,
Err(e) => {
self.report_error(e);
......
......@@ -26,12 +26,13 @@
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn};
use middle::ty::{type_is_ty_var};
use middle::ty::{ty_closure};
use middle::subst::Subst;
use middle::ty;
use CrateCtxt;
use middle::infer::combine::Combine;
use middle::infer::InferCtxt;
use middle::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
use middle::infer::{new_infer_ctxt};
use std::collections::{HashSet};
use std::cell::RefCell;
use std::rc::Rc;
......@@ -52,80 +53,35 @@
mod overlap;
mod unsafety;
fn get_base_type<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
span: Span,
original_type: Ty<'tcx>)
-> Option<Ty<'tcx>> {
let resolved_type = match resolve_type(inference_context,
Some(span),
original_type,
resolve_ivar) {
Ok(resulting_type) if !type_is_ty_var(resulting_type) => resulting_type,
_ => {
inference_context.tcx.sess.span_fatal(span,
"the type of this value must be known in order \
to determine the base type");
}
};
match resolved_type.sty {
ty_enum(..) | ty_struct(..) | ty_unboxed_closure(..) => {
debug!("(getting base type) found base type");
Some(resolved_type)
// Returns the def ID of the base type, if there is one.
fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
span: Span,
ty: Ty<'tcx>)
-> Option<DefId> {
match ty.sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) => {
Some(def_id)
}
_ if ty::type_is_trait(resolved_type) => {
debug!("(getting base type) found base type (trait)");
Some(resolved_type)
ty_trait(ref t) => {
Some(t.principal.def_id)
}
ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
ty_infer(..) | ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
ty_ptr(_) | ty_rptr(_, _) => {
debug!("(getting base type) no base type; found {}",
original_type.sty);
None
}
ty_trait(..) => panic!("should have been caught")
}
}
// Returns the def ID of the base type, if there is one.
fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
span: Span,
original_type: Ty<'tcx>)
-> Option<DefId> {
match get_base_type(inference_context, span, original_type) {
None => None,
Some(base_type) => {
match base_type.sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) |
ty_unboxed_closure(def_id, _, _) => {
Some(def_id)
}
ty_ptr(ty::mt {ty, ..}) |
ty_rptr(_, ty::mt {ty, ..}) |
ty_uniq(ty) => {
match ty.sty {
ty_trait(box ty::TyTrait { ref principal, .. }) => {
Some(principal.def_id)
}
_ => {
panic!("get_base_type() returned a type that wasn't an \
enum, struct, or trait");
}
}
}
ty_trait(box ty::TyTrait { ref principal, .. }) => {
Some(principal.def_id)
}
_ => {
panic!("get_base_type() returned a type that wasn't an \
enum, struct, or trait");
}
}
ty_infer(..) | ty_unboxed_closure(..) => {
// `ty` comes from a user declaration so we should only expect types
// that the user can type
inference_context.tcx.sess.span_bug(
span,
format!("coherence encountered unexpected type searching for base type: {}",
ty.repr(inference_context.tcx))[]);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册