]> git.lizzy.rs Git - rust.git/commitdiff
modify ExplicitSelf::determine to take an `is_self_type` predicate closure, instead...
authorMichael Hewson <michael@michaelhewson.ca>
Wed, 8 Nov 2017 09:31:48 +0000 (04:31 -0500)
committerMichael Hewson <michael@michaelhewson.ca>
Wed, 8 Nov 2017 09:31:48 +0000 (04:31 -0500)
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/wfcheck.rs

index 5daae6d55eed2cdf5f201bc218d0be452b3442ad..b93a3dc9ffc3df2fd30aa9800788d261c3e861c4 100644 (file)
@@ -19,7 +19,6 @@
 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<self>`, 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
         }
     }
index e2e8868e8f33691975518c63f78d5d29b01e0dff..b5e7109efdd3b9075103a80da5458f22e594d7c3 100644 (file)
@@ -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(),
index 89dbd20b699d97b9574c91b59ee260892ad5d8e9..1718b2043a89e9c5c46ebd093a8ee5bde474f54e 100644 (file)
@@ -495,7 +495,8 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
             }
         }
 
-        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 {