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};
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:
///
/// }
/// ```
///
- 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
}
}
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(),