diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 58269737784..d8f2e833d74 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -19,6 +19,7 @@ use hir::def::Def; use hir::def_id::DefId; use middle::resolve_lifetime as rl; use namespace::Namespace; +use rustc::infer::InferCtxt; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; @@ -1433,26 +1434,21 @@ impl<'tcx> ExplicitSelf<'tcx> { /// ``` /// pub fn determine<'a, 'gcx>( - tcx: TyCtxt<'a, 'gcx, 'tcx>, + infcx: &InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - self_ty: Ty<'a>, - self_arg_ty: Ty<'a> + self_ty: Ty<'tcx>, + self_arg_ty: Ty<'tcx> ) -> ExplicitSelf<'tcx> { use self::ExplicitSelf::*; - tcx.infer_ctxt().enter(|infcx| { - let can_eq = |expected, actual| { - let cause = traits::ObligationCause::dummy(); - infcx.at(&cause, param_env).eq(expected, actual).is_ok() - }; + let can_eq = |expected, actual| infcx.can_eq(param_env, expected, actual).is_ok(); - match self_arg_ty.sty { - _ if can_eq(self_arg_ty, self_ty) => ByValue, - ty::TyRef(region, ty::TypeAndMut { ty, mutbl}) if can_eq(ty, self_ty) => ByReference(region, mutbl), - ty::TyAdt(def, _) if def.is_box() && can_eq(self_arg_ty.boxed_ty(), self_ty) => ByBox, - _ => Other - } - }) + match self_arg_ty.sty { + _ if can_eq(self_arg_ty, self_ty) => ByValue, + ty::TyRef(region, ty::TypeAndMut { ty, mutbl}) if can_eq(ty, self_ty) => ByReference(region, mutbl), + ty::TyAdt(def, _) if def.is_box() && can_eq(self_arg_ty.boxed_ty(), self_ty) => ByBox, + _ => Other + } } } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index a008d73238d..e2e8868e8f3 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -505,12 +505,14 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); let param_env = ty::ParamEnv::empty(Reveal::All); - match ExplicitSelf::determine(tcx, param_env, untransformed_self_ty, self_arg_ty) { - ExplicitSelf::ByValue => "self".to_string(), - ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), - ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), - _ => format!("self: {}", self_arg_ty) - } + tcx.infer_ctxt().enter(|infcx| { + match ExplicitSelf::determine(&infcx, param_env, untransformed_self_ty, self_arg_ty) { + ExplicitSelf::ByValue => "self".to_string(), + ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), + ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), + _ => format!("self: {}", self_arg_ty) + } + }) }; match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 2e87f41c7dc..949188ac3f0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -471,25 +471,26 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let self_arg_ty = sig.inputs()[0]; let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); - let at = fcx.at(&cause, fcx.param_env); + let eq = |expected, actual| fcx.at(&cause, fcx.param_env).eq(expected, actual); let mut autoderef = fcx.autoderef(span, self_arg_ty); loop { if let Some((potential_self_ty, _)) = autoderef.next() { debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", potential_self_ty, self_ty); - if let Ok(InferOk { obligations, value: () }) = at.eq(self_ty, potential_self_ty) { + if let Ok(InferOk { obligations, value: () }) = eq(self_ty, potential_self_ty) { fcx.register_predicates(obligations); autoderef.finalize(); break; } } else { - span_err!(fcx.tcx.sess, span, E0307, "invalid self type: {:?}", self_arg_ty); + span_err!(fcx.tcx.sess, span, E0307, "invalid `self` type: {:?}", self_arg_ty); + return; } } - if let ExplicitSelf::Other = ExplicitSelf::determine(fcx.tcx, fcx.param_env, self_ty, self_arg_ty) { + if let ExplicitSelf::Other = ExplicitSelf::determine(fcx, fcx.param_env, self_ty, self_arg_ty) { if !fcx.tcx.sess.features.borrow().arbitrary_self_types { fcx.tcx.sess.span_err(span, "Arbitrary `self` types are experimental"); }