diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1cf5e35a0957f..d1fe19364b409 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -259,7 +259,7 @@ impl<'a> LoweringContext<'a> { P(hir::Ty { id: t.id, node: match t.node { - TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer, + TyKind::Infer => hir::TyInfer, TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)), TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)), TyKind::Rptr(ref region, ref mt) => { @@ -283,6 +283,16 @@ impl<'a> LoweringContext<'a> { TyKind::Path(ref qself, ref path) => { hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit)) } + TyKind::ImplicitSelf => { + hir::TyPath(hir::QPath::Resolved(None, P(hir::Path { + def: self.expect_full_def(t.id), + segments: hir_vec![hir::PathSegment { + name: keywords::SelfType.name(), + parameters: hir::PathParameters::none() + }], + span: t.span, + }))) + } TyKind::ObjectSum(ref ty, ref bounds) => { hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) } @@ -976,7 +986,7 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Const(..) => hir::AssociatedItemKind::Const, ImplItemKind::Type(..) => hir::AssociatedItemKind::Type, ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method { - has_self: sig.decl.get_self().is_some(), + has_self: sig.decl.has_self(), }, ImplItemKind::Macro(..) => unimplemented!(), }, @@ -1051,24 +1061,13 @@ impl<'a> LoweringContext<'a> { } fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { - let hir_sig = hir::MethodSig { + hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), decl: self.lower_fn_decl(&sig.decl), - }; - // Check for `self: _` and `self: &_` - if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { - match hir_sig.decl.get_self().map(|eself| eself.node) { - Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { - self.diagnostic().span_err(sig.decl.inputs[0].ty.span, - "the type placeholder `_` is not allowed within types on item signatures"); - } - _ => {} - } } - hir_sig } fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4eee76d466ac1..d135762ae8204 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -35,8 +35,8 @@ use hir::def_id::DefId; use util::nodemap::{NodeMap, FxHashSet}; use rustc_data_structures::fnv::FnvHashMap; -use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP}; -use syntax::codemap::{self, respan, Spanned}; +use syntax_pos::{Span, ExpnId, DUMMY_SP}; +use syntax::codemap::{self, Spanned}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; @@ -1234,37 +1234,8 @@ pub struct Arg { pub id: NodeId, } -/// Alternative representation for `Arg`s describing `self` parameter of methods. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum SelfKind { - /// `self`, `mut self` - Value(Mutability), - /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability), - /// `self: TYPE`, `mut self: TYPE` - Explicit(P, Mutability), -} - -pub type ExplicitSelf = Spanned; - impl Arg { - pub fn to_self(&self) -> Option { - if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node { - if name.node == keywords::SelfValue.name() { - return match self.ty.node { - TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyRptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyInfer => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) - } - _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi), - SelfKind::Explicit(self.ty.clone(), mutbl))) - } - } - } - None - } - - pub fn is_self(&self) -> bool { + fn is_self(&self) -> bool { if let PatKind::Binding(_, _, name, _) = self.pat.node { name.node == keywords::SelfValue.name() } else { @@ -1282,9 +1253,6 @@ pub struct FnDecl { } impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) - } pub fn has_self(&self) -> bool { self.inputs.get(0).map(Arg::is_self).unwrap_or(false) } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 100e344d94180..eaed62e4dce91 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -25,7 +25,7 @@ use syntax_pos::{self, BytePos}; use errors; use hir; -use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier}; +use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use std::io::{self, Write, Read}; @@ -1954,27 +1954,6 @@ impl<'a> State<'a> { self.end() // close enclosing cbox } - fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> { - match explicit_self.node { - SelfKind::Value(m) => { - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Region(ref lt, m) => { - word(&mut self.s, "&")?; - self.print_opt_lifetime(lt)?; - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Explicit(ref typ, m) => { - self.print_mutability(m)?; - word(&mut self.s, "self")?; - self.word_space(":")?; - self.print_type(&typ) - } - } - } - pub fn print_fn(&mut self, decl: &hir::FnDecl, unsafety: hir::Unsafety, @@ -2185,21 +2164,17 @@ impl<'a> State<'a> { match input.ty.node { hir::TyInfer if is_closure => self.print_pat(&input.pat)?, _ => { - if let Some(eself) = input.to_self() { - self.print_explicit_self(&eself)?; + let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node { + name.node == keywords::Invalid.name() } else { - let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node { - name.node == keywords::Invalid.name() - } else { - false - }; - if !invalid { - self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; - } - self.print_type(&input.ty)?; + false + }; + if !invalid { + self.print_pat(&input.pat)?; + word(&mut self.s, ":")?; + space(&mut self.s)?; } + self.print_type(&input.ty)?; } } self.end() diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2ab10d0446b2a..180141d674aa7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2127,7 +2127,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let (kind, has_self, has_value) = match trait_item.node { hir::MethodTraitItem(ref sig, ref body) => { - (AssociatedKind::Method, sig.decl.get_self().is_some(), + (AssociatedKind::Method, sig.decl.has_self(), body.is_some()) } hir::ConstTraitItem(_, ref value) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a0af4c4565359..63bcbfeb23d8a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -571,6 +571,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_ty(&mut self, ty: &'tcx Ty) { if let TyKind::Path(ref qself, ref path) = ty.node { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); + } else if let TyKind::ImplicitSelf = ty.node { + let self_ty = keywords::SelfType.ident(); + let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span)) + .map_or(Def::Err, |d| d.def()); + self.record_def(ty.id, PathResolution::new(def)); } visit::walk_ty(self, ty); } @@ -741,6 +746,13 @@ impl<'a> LexicalScopeBinding<'a> { _ => None, } } + + fn def(self) -> Def { + match self { + LexicalScopeBinding::Item(binding) => binding.def(), + LexicalScopeBinding::Def(def) => def, + } + } } #[derive(Clone)] diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 598003a392512..7ccb0fffb7d95 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -50,7 +50,7 @@ use rustc_const_eval::eval_length; use rustc_data_structures::accumulate_vec::AccumulateVec; -use hir::{self, SelfKind}; +use hir; use hir::def::Def; use hir::def_id::DefId; use hir::print as pprust; @@ -1743,36 +1743,33 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // declaration are bound to that function type. let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope); - // `implied_output_region` is the region that will be assumed for any - // region parameters in the return type. In accordance with the rules for - // lifetime elision, we can determine it in two ways. First (determined - // here), if self is by-reference, then the implied output region is the - // region of the self parameter. - let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) { - (Some(untransformed_self_ty), Some(explicit_self)) => { - let self_type = self.determine_self_type(&rb, untransformed_self_ty, - &explicit_self); - (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type))) - } - _ => (None, None), - }; + let input_tys: Vec = + decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect(); - // HACK(eddyb) replace the fake self type in the AST with the actual type. - let arg_params = if self_ty.is_some() { - &decl.inputs[1..] - } else { - &decl.inputs[..] + let has_self = decl.has_self(); + let explicit_self = match (opt_untransformed_self_ty, has_self) { + (Some(untransformed_self_ty), true) => { + Some(ExplicitSelf::determine(untransformed_self_ty, input_tys[0])) + } + _ => None }; - let arg_tys: Vec = - arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect(); - // Second, if there was exactly one lifetime (either a substitution or a - // reference) in the arguments, then any anonymous regions in the output - // have that lifetime. let implied_output_region = match explicit_self { + // `implied_output_region` is the region that will be assumed for any + // region parameters in the return type. In accordance with the rules for + // lifetime elision, we can determine it in two ways. First (determined + // here), if self is by-reference, then the implied output region is the + // region of the self parameter. Some(ExplicitSelf::ByReference(region, _)) => Ok(*region), + + // Second, if there was exactly one lifetime (either a substitution or a + // reference) in the arguments, then any anonymous regions in the output + // have that lifetime. _ => { - self.find_implied_output_region(&arg_tys, + let arg_params = &decl.inputs[has_self as usize..]; + let arg_tys = &input_tys[has_self as usize..]; + + self.find_implied_output_region(arg_tys, arg_params.iter() .map(|a| pprust::pat_to_string(&a.pat))) @@ -1793,37 +1790,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { unsafety: unsafety, abi: abi, sig: ty::Binder(self.tcx().mk_fn_sig( - self_ty.into_iter().chain(arg_tys), + input_tys.into_iter(), output_ty, decl.variadic )), }) } - fn determine_self_type<'a>(&self, - rscope: &RegionScope, - untransformed_self_ty: Ty<'tcx>, - explicit_self: &hir::ExplicitSelf) - -> Ty<'tcx> - { - match explicit_self.node { - SelfKind::Value(..) => untransformed_self_ty, - SelfKind::Region(ref lifetime, mutability) => { - let region = - self.opt_ast_region_to_region( - rscope, - explicit_self.span, - lifetime); - self.tcx().mk_ref(region, - ty::TypeAndMut { - ty: untransformed_self_ty, - mutbl: mutability - }) - } - SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type) - } - } - pub fn ty_of_closure(&self, unsafety: hir::Unsafety, decl: &hir::FnDecl, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 478de1673170f..1536aa6def7eb 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; +use rustc::hir::{self, ImplItemKind, TraitItem_}; use rustc::infer::{self, InferOk}; use rustc::middle::free_region::FreeRegionMap; use rustc::ty; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; -use rustc::hir::{ImplItemKind, TraitItem_, Ty_}; use rustc::util::common::ErrorReported; use syntax::ast; @@ -456,31 +455,18 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a _ => bug!("{:?} is not a MethodTraitItem", trait_m), }; - impl_m_iter.zip(trait_m_iter) - .find(|&(ref impl_arg, ref trait_arg)| { - match (&impl_arg.ty.node, &trait_arg.ty.node) { - (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) | - (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) => { - impl_mt.mutbl != trait_mt.mutbl - } - _ => false, - } - }) - .map(|(ref impl_arg, ref trait_arg)| { - match (impl_arg.to_self(), trait_arg.to_self()) { - (Some(impl_self), Some(trait_self)) => { - (impl_self.span, Some(trait_self.span)) - } - (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)), - _ => { - bug!("impl and trait fns have different first args, impl: \ - {:?}, trait: {:?}", - impl_arg, - trait_arg) - } - } - }) - .unwrap_or((cause.span, tcx.map.span_if_local(trait_m.def_id))) + impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| { + match (&impl_arg.ty.node, &trait_arg.ty.node) { + (&hir::TyRptr(_, ref impl_mt), &hir::TyRptr(_, ref trait_mt)) | + (&hir::TyPtr(ref impl_mt), &hir::TyPtr(ref trait_mt)) => { + impl_mt.mutbl != trait_mt.mutbl + } + _ => false, + } + }).map(|(ref impl_arg, ref trait_arg)| { + (impl_arg.ty.span, Some(trait_arg.ty.span)) + }) + .unwrap_or_else(|| (cause.span, tcx.map.span_if_local(trait_m.def_id))) } else { (cause.span, tcx.map.span_if_local(trait_m.def_id)) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fdbd2f3647c0c..a0071fe25cb1f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1184,16 +1184,17 @@ pub enum SelfTy { impl Argument { pub fn to_self(&self) -> Option { - if self.name == "self" { - match self.type_ { - Infer => Some(SelfValue), - BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => { - Some(SelfBorrowed(lifetime.clone(), mutability)) - } - _ => Some(SelfExplicit(self.type_.clone())) + if self.name != "self" { + return None; + } + if self.type_.is_self_type() { + return Some(SelfValue); + } + match self.type_ { + BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => { + Some(SelfBorrowed(lifetime.clone(), mutability)) } - } else { - None + _ => Some(SelfExplicit(self.type_.clone())) } } } @@ -1353,11 +1354,13 @@ impl<'tcx> Clean for ty::AssociatedItem { }; let self_arg_ty = *fty.sig.input(0).skip_binder(); if self_arg_ty == self_ty { - decl.inputs.values[0].type_ = Infer; + decl.inputs.values[0].type_ = Generic(String::from("Self")); } else if let ty::TyRef(_, mt) = self_arg_ty.sty { if mt.ty == self_ty { match decl.inputs.values[0].type_ { - BorrowedRef{ref mut type_, ..} => **type_ = Infer, + BorrowedRef{ref mut type_, ..} => { + **type_ = Generic(String::from("Self")) + } _ => unreachable!(), } } @@ -1568,6 +1571,13 @@ impl Type { _ => false, } } + + pub fn is_self_type(&self) -> bool { + match *self { + Generic(ref name) => name == "Self", + _ => false + } + } } impl GetDefId for Type { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a5abdd922d63f..f72985fd91a3e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1471,12 +1471,13 @@ impl Arg { } pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg { + let span = mk_sp(eself.span.lo, eself_ident.span.hi); let infer_ty = P(Ty { id: DUMMY_NODE_ID, node: TyKind::ImplicitSelf, - span: DUMMY_SP, + span: span, }); - let arg = |mutbl, ty, span| Arg { + let arg = |mutbl, ty| Arg { pat: P(Pat { id: DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), @@ -1486,15 +1487,13 @@ impl Arg { id: DUMMY_NODE_ID, }; match eself.node { - SelfKind::Explicit(ty, mutbl) => { - arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi)) - } - SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span), + SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), + SelfKind::Value(mutbl) => arg(mutbl, infer_ty), SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }), - span: DUMMY_SP, - }), eself.span), + span: span, + })), } } } diff --git a/src/test/run-make/pretty-print-path-suffix/foo_method.pp b/src/test/run-make/pretty-print-path-suffix/foo_method.pp index 696e0544fdc57..fae134986872e 100644 --- a/src/test/run-make/pretty-print-path-suffix/foo_method.pp +++ b/src/test/run-make/pretty-print-path-suffix/foo_method.pp @@ -12,5 +12,6 @@ -fn foo_method(&self) -> &'static str { return "i am very similar to foo."; } -/* nest::{{impl}}::foo_method */ +fn foo_method(self: &Self) + -> &'static str { return "i am very similar to foo."; } /* +nest::{{impl}}::foo_method */