Cleanup type resolution to use type folding infrastructure and not
have such a silly over-engineered interface.
This commit is contained in:
parent
3efc9d2c55
commit
eb6ea5d49b
@ -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 @@ impl<'f, 'tcx> Coerce<'f, '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::TypeOrigin::*;
|
||||
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 util::ppaux::{trait_ref_to_string, Repr};
|
||||
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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> InferCtxt<'a, '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,276 +8,30 @@
|
||||
// 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};
|
||||
|
||||
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;
|
||||
|
||||
pub struct ResolveState<'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> ty_fold::TypeFolder<'tcx> for ResolveState<'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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
use middle::ty_fold::{mod, TypeFoldable};
|
||||
use util::ppaux::Repr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// DEEP TYPE RESOLVER
|
||||
///
|
||||
/// This kind of resolver can be used at any time. It simply replaces
|
||||
// OPPORTUNISTIC TYPE RESOLVER
|
||||
|
||||
/// 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 DeepTypeResolver<'a, 'tcx:'a> {
|
||||
pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> DeepTypeResolver<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> DeepTypeResolver<'a, 'tcx> {
|
||||
DeepTypeResolver { infcx: infcx }
|
||||
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 DeepTypeResolver<'a, 'tcx> {
|
||||
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
|
||||
fn tcx(&self) -> &ty::ctxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
@ -292,4 +46,70 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for DeepTypeResolver<'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),
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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_needs_infer(t) {
|
||||
t // micro-optimize -- if there is nothing in this type that this fold affects...
|
||||
} else {
|
||||
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::region::CodeExtent;
|
||||
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 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
/// 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::def;
|
||||
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 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl ResolveReason {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, '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 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, '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_param, Polytype, ty_ptr};
|
||||
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 orphan;
|
||||
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))[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user