From 0b27dcc665c846d32db0b6da59dcf7ee1da5b02c Mon Sep 17 00:00:00 2001 From: Michael Hewson Date: Wed, 8 Nov 2017 04:31:48 -0500 Subject: [PATCH] modify ExplicitSelf::determine to take an `is_self_type` predicate closure, instead of infcx --- src/librustc_typeck/astconv.rs | 26 ++++++++++----------- src/librustc_typeck/check/compare_method.rs | 3 ++- src/librustc_typeck/check/wfcheck.rs | 3 ++- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5daae6d55ee..b93a3dc9ffc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -19,7 +19,6 @@ 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}; @@ -1415,9 +1414,10 @@ pub enum ExplicitSelf<'tcx> { impl<'tcx> ExplicitSelf<'tcx> { /// Categorizes an explicit self declaration like `self: SomeType` /// into either `self`, `&self`, `&mut self`, `Box`, or - /// `Other` (meaning the arbitrary_self_types feature is used). - /// We do this here via a combination of pattern matching and - /// `can_eq`. A more precise check is done in `check_method_receiver()`. + /// `Other`. + /// This is mainly used to require the arbitrary_self_types feature + /// in the case of `Other`, to improve error messages in the common cases, + /// and to make `Other` non-object-safe. /// /// Examples: /// @@ -1436,21 +1436,19 @@ impl<'tcx> ExplicitSelf<'tcx> { /// } /// ``` /// - pub fn determine<'a, 'gcx>( - infcx: &InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - self_ty: Ty<'tcx>, - self_arg_ty: Ty<'tcx> + pub fn determine<'a, 'gcx, P>( + self_arg_ty: Ty<'tcx>, + is_self_ty: P ) -> ExplicitSelf<'tcx> + where + P: Fn(Ty<'tcx>) -> bool { use self::ExplicitSelf::*; - 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, + _ if is_self_ty(self_arg_ty) => ByValue, + ty::TyRef(region, ty::TypeAndMut { ty, mutbl}) if is_self_ty(ty) => ByReference(region, mutbl), + ty::TyAdt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox, _ => Other } } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e2e8868e8f3..b5e7109efdd 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -506,7 +506,8 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let param_env = ty::ParamEnv::empty(Reveal::All); tcx.infer_ctxt().enter(|infcx| { - match ExplicitSelf::determine(&infcx, param_env, untransformed_self_ty, self_arg_ty) { + let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); + match ExplicitSelf::determine(self_arg_ty, can_eq_self) { ExplicitSelf::ByValue => "self".to_string(), ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 89dbd20b699..1718b2043a8 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -495,7 +495,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { } } - let self_kind = ExplicitSelf::determine(fcx, fcx.param_env, self_ty, self_arg_ty); + let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); + let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); if let ExplicitSelf::Other = self_kind { if !fcx.tcx.sess.features.borrow().arbitrary_self_types {