From 212d5d43524123a45c6a88174fd3c771057faf47 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 May 2016 21:18:21 +0300 Subject: [PATCH 1/3] syntax: Refactor parsing of method declarations Fix spans and expected token lists, fix #33413 + other cosmetic improvements Add test for #33413 Convert between `Arg` and `ExplicitSelf` precisely Simplify pretty-printing for methods --- src/libsyntax/ast.rs | 83 ++++++-- src/libsyntax/parse/parser.rs | 246 +++++++++------------- src/libsyntax/print/pprust.rs | 51 ++--- src/libsyntax_ext/deriving/generic/mod.rs | 5 +- src/test/parse-fail/issue-33413.rs | 16 ++ src/test/parse-fail/no-unsafe-self.rs | 10 +- 6 files changed, 206 insertions(+), 205 deletions(-) create mode 100644 src/test/parse-fail/issue-33413.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d1ad330c58ce8..f6a794bd8cd73 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -16,13 +16,12 @@ pub use self::ViewPath_::*; pub use self::PathParameters::*; use attr::ThinAttributes; -use codemap::{Span, Spanned, DUMMY_SP, ExpnId}; +use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId}; use abi::Abi; use errors; use ext::base; use ext::tt::macro_parser; -use parse::token::InternedString; -use parse::token; +use parse::token::{self, keywords, InternedString}; use parse::lexer; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use print::pprust; @@ -1674,7 +1673,25 @@ pub struct Arg { pub id: NodeId, } +/// Represents the kind of 'self' associated with a method. +/// String representation of `Ident` here is always "self", but hygiene contexts may differ. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum SelfKind { + /// No self + Static, + /// `self`, `mut self` + Value(Ident), + /// `&'lt self`, `&'lt mut self` + Region(Option, Mutability, Ident), + /// `self: TYPE`, `mut self: TYPE` + Explicit(P, Ident), +} + +pub type ExplicitSelf = Spanned; + impl Arg { + #[unstable(feature = "rustc_private", issue = "27812")] + #[rustc_deprecated(since = "1.10.0", reason = "use `from_self` instead")] pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg { let path = Spanned{span:span,node:self_ident}; Arg { @@ -1692,6 +1709,51 @@ impl Arg { id: DUMMY_NODE_ID } } + + pub fn to_self(&self) -> Option { + if let PatKind::Ident(_, ident, _) = self.pat.node { + if ident.node.name == keywords::SelfValue.name() { + return match self.ty.node { + TyKind::Infer => Some(respan(self.pat.span, SelfKind::Value(ident.node))), + TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::Infer => { + Some(respan(self.pat.span, SelfKind::Region(lt, mutbl, ident.node))) + } + _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi), + SelfKind::Explicit(self.ty.clone(), ident.node))), + } + } + } + None + } + + pub fn from_self(eself: ExplicitSelf, ident_sp: Span, mutbl: Mutability) -> Arg { + let pat = |ident, span| P(Pat { + id: DUMMY_NODE_ID, + node: PatKind::Ident(BindingMode::ByValue(mutbl), respan(ident_sp, ident), None), + span: span, + }); + let infer_ty = P(Ty { + id: DUMMY_NODE_ID, + node: TyKind::Infer, + span: DUMMY_SP, + }); + let arg = |ident, ty, span| Arg { + pat: pat(ident, span), + ty: ty, + id: DUMMY_NODE_ID, + }; + match eself.node { + SelfKind::Static => panic!("bug: `Arg::from_self` is called \ + with `SelfKind::Static` argument"), + SelfKind::Explicit(ty, ident) => arg(ident, ty, mk_sp(eself.span.lo, ident_sp.hi)), + SelfKind::Value(ident) => arg(ident, infer_ty, eself.span), + SelfKind::Region(lt, mutbl, ident) => arg(ident, P(Ty { + id: DUMMY_NODE_ID, + node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }), + span: DUMMY_SP, + }), eself.span), + } + } } /// Represents the header (not the body) of a function declaration @@ -1772,21 +1834,6 @@ impl FunctionRetTy { } } -/// Represents the kind of 'self' associated with a method -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum SelfKind { - /// No self - Static, - /// `self` - Value(Ident), - /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability, Ident), - /// `self: TYPE` - Explicit(P, Ident), -} - -pub type ExplicitSelf = Spanned; - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 48368cc025c85..fc62cee92fdbc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2036,7 +2036,7 @@ impl<'a> Parser<'a> { } } - /// Parse mutability declaration (mut/const/imm) + /// Parse mutability (`mut` or nothing). pub fn parse_mutability(&mut self) -> PResult<'a, Mutability> { if self.eat_keyword(keywords::Mut) { Ok(Mutability::Mutable) @@ -4616,184 +4616,142 @@ impl<'a> Parser<'a> { })) } - fn expect_self_ident(&mut self) -> PResult<'a, ast::Ident> { - match self.token { - token::Ident(id) if id.name == keywords::SelfValue.name() => { - self.bump(); - // The hygiene context of `id` needs to be preserved here, - // so we can't just return `SelfValue.ident()`. - Ok(id) - }, - _ => { - let token_str = self.this_token_to_string(); - return Err(self.fatal(&format!("expected `self`, found `{}`", - token_str))) - } - } - } - - /// Parse the argument list and result type of a function - /// that may have a self type. + /// Parse the parameter list and result type of a function that may have a `self` parameter. fn parse_fn_decl_with_self(&mut self, - parse_arg_fn: F) -> PResult<'a, (ExplicitSelf, P)> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, + parse_arg_fn: F) + -> PResult<'a, (ExplicitSelf, P)> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, { - fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>) - -> PResult<'b, ast::SelfKind> { - // The following things are possible to see here: - // - // fn(&mut self) - // fn(&mut self) - // fn(&'lt self) - // fn(&'lt mut self) - // - // We already know that the current token is `&`. - - if this.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { - this.bump(); - Ok(SelfKind::Region(None, Mutability::Immutable, this.expect_self_ident()?)) - } else if this.look_ahead(1, |t| t.is_mutability()) && - this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { - this.bump(); - let mutability = this.parse_mutability()?; - Ok(SelfKind::Region(None, mutability, this.expect_self_ident()?)) - } else if this.look_ahead(1, |t| t.is_lifetime()) && - this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { - this.bump(); - let lifetime = this.parse_lifetime()?; - let ident = this.expect_self_ident()?; - Ok(SelfKind::Region(Some(lifetime), Mutability::Immutable, ident)) - } else if this.look_ahead(1, |t| t.is_lifetime()) && - this.look_ahead(2, |t| t.is_mutability()) && - this.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) { - this.bump(); - let lifetime = this.parse_lifetime()?; - let mutability = this.parse_mutability()?; - Ok(SelfKind::Region(Some(lifetime), mutability, this.expect_self_ident()?)) - } else { - Ok(SelfKind::Static) - } - } + let expect_ident = |this: &mut Self| match this.token { + token::Ident(ident) => { this.bump(); ident } // Preserve hygienic context. + _ => unreachable!() + }; self.expect(&token::OpenDelim(token::Paren))?; - // A bit of complexity and lookahead is needed here in order to be - // backwards compatible. - let lo = self.span.lo; - let mut self_ident_lo = self.span.lo; - let mut self_ident_hi = self.span.hi; - - let mut mutbl_self = Mutability::Immutable; - let explicit_self = match self.token { + // Parse optional self parameter of a method. + // Only a limited set of initial token sequences is considered self parameters, anything + // else is parsed as a normal function parameter list, so some lookahead is required. + let eself_lo = self.span.lo; + let mut eself_mutbl = Mutability::Immutable; + let (eself, eself_ident_sp) = match self.token { token::BinOp(token::And) => { - let eself = maybe_parse_borrowed_explicit_self(self)?; - self_ident_lo = self.last_span.lo; - self_ident_hi = self.last_span.hi; - eself + // &self + // &mut self + // &'lt self + // &'lt mut self + // ¬_self + if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { + self.bump(); + (SelfKind::Region(None, Mutability::Immutable, expect_ident(self)), + self.last_span) + } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && + self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { + self.bump(); + self.bump(); + (SelfKind::Region(None, Mutability::Mutable, expect_ident(self)), + self.last_span) + } else if self.look_ahead(1, |t| t.is_lifetime()) && + self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { + self.bump(); + let lt = self.parse_lifetime()?; + (SelfKind::Region(Some(lt), Mutability::Immutable, expect_ident(self)), + self.last_span) + } else if self.look_ahead(1, |t| t.is_lifetime()) && + self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) && + self.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) { + self.bump(); + let lt = self.parse_lifetime()?; + self.bump(); + (SelfKind::Region(Some(lt), Mutability::Mutable, expect_ident(self)), + self.last_span) + } else { + (SelfKind::Static, codemap::DUMMY_SP) + } } token::BinOp(token::Star) => { - // Possibly "*self" or "*mut self" -- not supported. Try to avoid - // emitting cryptic "unexpected token" errors. - self.bump(); - let _mutability = if self.token.is_mutability() { - self.parse_mutability()? - } else { - Mutability::Immutable - }; - if self.token.is_keyword(keywords::SelfValue) { - let span = self.span; - self.span_err(span, "cannot pass self by raw pointer"); + // *self + // *const self + // *mut self + // *not_self + // Emit special error for `self` cases. + if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); + self.span_err(self.span, "cannot pass `self` by raw pointer"); + (SelfKind::Value(expect_ident(self)), self.last_span) + } else if self.look_ahead(1, |t| t.is_mutability()) && + self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { + self.bump(); + self.bump(); + self.span_err(self.span, "cannot pass `self` by raw pointer"); + (SelfKind::Value(expect_ident(self)), self.last_span) + } else { + (SelfKind::Static, codemap::DUMMY_SP) } - // error case, making bogus self ident: - SelfKind::Value(keywords::SelfValue.ident()) } token::Ident(..) => { if self.token.is_keyword(keywords::SelfValue) { - let self_ident = self.expect_self_ident()?; - - // Determine whether this is the fully explicit form, `self: - // TYPE`. + // self + // self: TYPE + let eself_ident = expect_ident(self); + let eself_ident_sp = self.last_span; if self.eat(&token::Colon) { - SelfKind::Explicit(self.parse_ty_sum()?, self_ident) + (SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp) } else { - SelfKind::Value(self_ident) + (SelfKind::Value(eself_ident), eself_ident_sp) } - } else if self.token.is_mutability() && + } else if self.token.is_keyword(keywords::Mut) && self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { - mutbl_self = self.parse_mutability()?; - let self_ident = self.expect_self_ident()?; - - // Determine whether this is the fully explicit form, - // `self: TYPE`. + // mut self + // mut self: TYPE + eself_mutbl = Mutability::Mutable; + self.bump(); + let eself_ident = expect_ident(self); + let eself_ident_sp = self.last_span; if self.eat(&token::Colon) { - SelfKind::Explicit(self.parse_ty_sum()?, self_ident) + (SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp) } else { - SelfKind::Value(self_ident) + (SelfKind::Value(eself_ident), eself_ident_sp) } } else { - SelfKind::Static + (SelfKind::Static, codemap::DUMMY_SP) } } - _ => SelfKind::Static, + _ => (SelfKind::Static, codemap::DUMMY_SP) }; + let mut eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself); - let explicit_self_sp = mk_sp(self_ident_lo, self_ident_hi); - - // shared fall-through for the three cases below. borrowing prevents simply - // writing this as a closure - macro_rules! parse_remaining_arguments { - ($self_id:ident) => - { - // If we parsed a self type, expect a comma before the argument list. - match self.token { - token::Comma => { + // Parse the rest of the function parameter list. + let sep = SeqSep::trailing_allowed(token::Comma); + let fn_inputs = match eself.node { + SelfKind::Static => { + eself.span = codemap::DUMMY_SP; + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) + } + SelfKind::Value(..) | SelfKind::Region(..) | SelfKind::Explicit(..) => { + if self.check(&token::CloseDelim(token::Paren)) { + vec![Arg::from_self(eself.clone(), eself_ident_sp, eself_mutbl)] + } else if self.check(&token::Comma) { self.bump(); - let sep = SeqSep::trailing_allowed(token::Comma); - let mut fn_inputs = self.parse_seq_to_before_end( - &token::CloseDelim(token::Paren), - sep, - parse_arg_fn + let mut fn_inputs = vec![Arg::from_self(eself.clone(), eself_ident_sp, + eself_mutbl)]; + fn_inputs.append(&mut self.parse_seq_to_before_end( + &token::CloseDelim(token::Paren), sep, parse_arg_fn) ); - fn_inputs.insert(0, Arg::new_self(explicit_self_sp, mutbl_self, $self_id)); fn_inputs - } - token::CloseDelim(token::Paren) => { - vec!(Arg::new_self(explicit_self_sp, mutbl_self, $self_id)) - } - _ => { - let token_str = self.this_token_to_string(); - return Err(self.fatal(&format!("expected `,` or `)`, found `{}`", - token_str))) + } else { + return self.unexpected(); } } - } - } - - let fn_inputs = match explicit_self { - SelfKind::Static => { - let sep = SeqSep::trailing_allowed(token::Comma); - self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) - } - SelfKind::Value(id) => parse_remaining_arguments!(id), - SelfKind::Region(_,_,id) => parse_remaining_arguments!(id), - SelfKind::Explicit(_,id) => parse_remaining_arguments!(id), }; - + // Parse closing paren and return type. self.expect(&token::CloseDelim(token::Paren))?; - - let hi = self.span.hi; - - let ret_ty = self.parse_ret_ty()?; - - let fn_decl = P(FnDecl { + Ok((eself, P(FnDecl { inputs: fn_inputs, - output: ret_ty, + output: self.parse_ret_ty()?, variadic: false - }); - - Ok((spanned(lo, hi, explicit_self), fn_decl)) + }))) } // parse the |arg, arg| header on a lambda diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7bfc58e85c259..ebb4927d69c0b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1522,7 +1522,7 @@ impl<'a> State<'a> { m.abi, Some(ident), &m.generics, - Some(&m.explicit_self.node), + None, vis) } @@ -2656,36 +2656,9 @@ impl<'a> State<'a> { } pub fn print_fn_args(&mut self, decl: &ast::FnDecl, - opt_explicit_self: Option<&ast::SelfKind>, + _: Option<&ast::SelfKind>, is_closure: bool) -> io::Result<()> { - // It is unfortunate to duplicate the commasep logic, but we want the - // self type and the args all in the same box. - self.rbox(0, Inconsistent)?; - let mut first = true; - if let Some(explicit_self) = opt_explicit_self { - let m = match *explicit_self { - ast::SelfKind::Static => ast::Mutability::Immutable, - _ => match decl.inputs[0].pat.node { - PatKind::Ident(ast::BindingMode::ByValue(m), _, _) => m, - _ => ast::Mutability::Immutable - } - }; - first = !self.print_explicit_self(explicit_self, m)?; - } - - // HACK(eddyb) ignore the separately printed self argument. - let args = if first { - &decl.inputs[..] - } else { - &decl.inputs[1..] - }; - - for arg in args { - if first { first = false; } else { self.word_space(",")?; } - self.print_arg(arg, is_closure)?; - } - - self.end() + self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, is_closure)) } pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl, @@ -2956,18 +2929,24 @@ impl<'a> State<'a> { match input.ty.node { ast::TyKind::Infer if is_closure => self.print_pat(&input.pat)?, _ => { - match input.pat.node { - PatKind::Ident(_, ref path1, _) - if path1.node.name == keywords::Invalid.name() => { - // Do nothing. + let (mutbl, invalid) = match input.pat.node { + PatKind::Ident(ast::BindingMode::ByValue(mutbl), ident, _) | + PatKind::Ident(ast::BindingMode::ByRef(mutbl), ident, _) => { + (mutbl, ident.node.name == keywords::Invalid.name()) } - _ => { + _ => (ast::Mutability::Immutable, false) + }; + + if let Some(eself) = input.to_self() { + self.print_explicit_self(&eself.node, mutbl)?; + } else { + if !invalid { self.print_pat(&input.pat)?; word(&mut self.s, ":")?; space(&mut self.s)?; } + self.print_type(&input.ty)?; } - self.print_type(&input.ty)?; } } self.end() diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1d5fc13c72008..161edcca5b283 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -864,9 +864,8 @@ impl<'a> MethodDef<'a> { let self_arg = match explicit_self.node { ast::SelfKind::Static => None, // creating fresh self id - _ => Some(ast::Arg::new_self(trait_.span, - ast::Mutability::Immutable, - keywords::SelfValue.ident())) + _ => Some(ast::Arg::from_self(explicit_self.clone(), trait_.span, + ast::Mutability::Immutable)), }; let args = { let args = arg_types.into_iter().map(|(name, ty)| { diff --git a/src/test/parse-fail/issue-33413.rs b/src/test/parse-fail/issue-33413.rs new file mode 100644 index 0000000000000..699af8ca7ab4f --- /dev/null +++ b/src/test/parse-fail/issue-33413.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +impl S { + fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*` + //~^ ERROR expected one of `)`, `-`, `box`, `false`, `mut`, `ref`, or `true`, found `*` +} diff --git a/src/test/parse-fail/no-unsafe-self.rs b/src/test/parse-fail/no-unsafe-self.rs index cbdf50a7521ac..22baf88b43f5a 100644 --- a/src/test/parse-fail/no-unsafe-self.rs +++ b/src/test/parse-fail/no-unsafe-self.rs @@ -11,14 +11,16 @@ // compile-flags: -Z parse-only -Z continue-parse-after-error trait A { - fn foo(*mut self); //~ ERROR cannot pass self by raw pointer - fn bar(*self); //~ ERROR cannot pass self by raw pointer + fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer + fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer + fn bar(*self); //~ ERROR cannot pass `self` by raw pointer } struct X; impl A for X { - fn foo(*mut self) { } //~ ERROR cannot pass self by raw pointer - fn bar(*self) { } //~ ERROR cannot pass self by raw pointer + fn foo(*mut self) { } //~ ERROR cannot pass `self` by raw pointer + fn baz(*const self) { } //~ ERROR cannot pass `self` by raw pointer + fn bar(*self) { } //~ ERROR cannot pass `self` by raw pointer } fn main() { } From 766f9b5a2ff2973bc18eddc91b988a2fe476b0a1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 May 2016 21:19:29 +0300 Subject: [PATCH 2/3] Remove ExplicitSelf from HIR --- src/librustc/hir/fold.rs | 32 ------ src/librustc/hir/intravisit.rs | 22 ----- src/librustc/hir/lowering.rs | 23 ----- src/librustc/hir/mod.rs | 79 ++++++++------- src/librustc/hir/print.rs | 112 ++++++--------------- src/librustc/infer/error_reporting.rs | 58 ++--------- src/librustc/lint/context.rs | 5 - src/librustc/middle/resolve_lifetime.rs | 1 - src/librustc_incremental/calculate_svh.rs | 5 - src/librustc_privacy/lib.rs | 4 +- src/librustc_resolve/lib.rs | 1 - src/librustc_typeck/astconv.rs | 77 +++++++-------- src/librustdoc/clean/inline.rs | 3 +- src/librustdoc/clean/mod.rs | 113 +++++++++------------- src/librustdoc/html/format.rs | 42 ++++---- src/librustdoc/html/render.rs | 50 +++------- 16 files changed, 196 insertions(+), 431 deletions(-) diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs index fa391538b9c60..740d72f4c3e3c 100644 --- a/src/librustc/hir/fold.rs +++ b/src/librustc/hir/fold.rs @@ -158,14 +158,6 @@ pub trait Folder : Sized { noop_fold_local(l, self) } - fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf { - noop_fold_explicit_self(es, self) - } - - fn fold_explicit_self_underscore(&mut self, es: ExplicitSelf_) -> ExplicitSelf_ { - noop_fold_explicit_self_underscore(es, self) - } - fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { noop_fold_lifetime(l, self) } @@ -495,29 +487,6 @@ pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Option(es: ExplicitSelf_, - fld: &mut T) - -> ExplicitSelf_ { - match es { - SelfStatic | SelfValue(_) => es, - SelfRegion(lifetime, m, name) => { - SelfRegion(fld.fold_opt_lifetime(lifetime), m, name) - } - SelfExplicit(typ, name) => { - SelfExplicit(fld.fold_ty(typ), name) - } - } -} - -pub fn noop_fold_explicit_self(Spanned { span, node }: ExplicitSelf, - fld: &mut T) - -> ExplicitSelf { - Spanned { - node: fld.fold_explicit_self_underscore(node), - span: fld.new_span(span), - } -} - pub fn noop_fold_meta_item(mi: P, fld: &mut T) -> P { mi.map(|Spanned { node, span }| { Spanned { @@ -941,7 +910,6 @@ pub fn noop_fold_method_sig(sig: MethodSig, folder: &mut T) -> Method MethodSig { generics: folder.fold_generics(sig.generics), abi: sig.abi, - explicit_self: folder.fold_explicit_self(sig.explicit_self), unsafety: sig.unsafety, constness: sig.constness, decl: folder.fold_fn_decl(sig.decl), diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index ec9b465521b97..b387ced48228c 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -180,9 +180,6 @@ pub trait Visitor<'v> : Sized { fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { walk_lifetime_def(self, lifetime) } - fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { - walk_explicit_self(self, es) - } fn visit_path(&mut self, path: &'v Path, _id: NodeId) { walk_path(self, path) } @@ -258,23 +255,6 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); } -pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) { - match explicit_self.node { - SelfStatic => {} - SelfValue(name) => { - visitor.visit_name(explicit_self.span, name) - } - SelfRegion(ref opt_lifetime, _, name) => { - visitor.visit_name(explicit_self.span, name); - walk_list!(visitor, visit_lifetime, opt_lifetime); - } - SelfExplicit(ref typ, name) => { - visitor.visit_name(explicit_self.span, name); - visitor.visit_ty(typ) - } - } -} - pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef, _modifier: &'v TraitBoundModifier) @@ -620,7 +600,6 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' } FnKind::Method(_, sig, _, _) => { visitor.visit_generics(&sig.generics); - visitor.visit_explicit_self(&sig.explicit_self); } FnKind::Closure(_) => {} } @@ -645,7 +624,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai walk_list!(visitor, visit_expr, default); } MethodTraitItem(ref sig, None) => { - visitor.visit_explicit_self(&sig.explicit_self); visitor.visit_generics(&sig.generics); walk_fn_decl(visitor, &sig.decl); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5ca99a7db67f5..d6a29b0376428 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -388,21 +388,6 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_explicit_self_underscore(&mut self, es: &SelfKind) -> hir::ExplicitSelf_ { - match *es { - SelfKind::Static => hir::SelfStatic, - SelfKind::Value(v) => hir::SelfValue(v.name), - SelfKind::Region(ref lifetime, m, ident) => { - hir::SelfRegion(self.lower_opt_lifetime(lifetime), - self.lower_mutability(m), - ident.name) - } - SelfKind::Explicit(ref typ, ident) => { - hir::SelfExplicit(self.lower_ty(typ), ident.name) - } - } - } - fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { match m { Mutability::Mutable => hir::MutMutable, @@ -410,13 +395,6 @@ impl<'a> LoweringContext<'a> { } } - fn lower_explicit_self(&mut self, s: &ExplicitSelf) -> hir::ExplicitSelf { - Spanned { - node: self.lower_explicit_self_underscore(&s.node), - span: s.span, - } - } - fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { hir::Arg { id: arg.id, @@ -800,7 +778,6 @@ impl<'a> LoweringContext<'a> { hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, - explicit_self: self.lower_explicit_self(&sig.explicit_self), unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), decl: self.lower_fn_decl(&sig.decl), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 97c4388381908..eb38458a3acfa 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -15,7 +15,6 @@ pub use self::BinOp_::*; pub use self::BlockCheckMode::*; pub use self::CaptureClause::*; pub use self::Decl_::*; -pub use self::ExplicitSelf_::*; pub use self::Expr_::*; pub use self::FunctionRetTy::*; pub use self::ForeignItem_::*; @@ -37,12 +36,12 @@ use hir::def::Def; use hir::def_id::DefId; use util::nodemap::{NodeMap, FnvHashSet}; -use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId}; +use syntax::codemap::{self, mk_sp, respan, Span, Spanned, ExpnId}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; use syntax::attr::{ThinAttributes, ThinAttributesExt}; -use syntax::parse::token::InternedString; +use syntax::parse::token::{keywords, InternedString}; use syntax::ptr::P; use std::collections::BTreeMap; @@ -1055,7 +1054,6 @@ pub struct MethodSig { pub abi: Abi, pub decl: P, pub generics: Generics, - pub explicit_self: ExplicitSelf, } /// Represents an item declaration within a trait declaration, @@ -1196,25 +1194,41 @@ 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 new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg { - let path = Spanned { - span: span, - node: self_ident, - }; - Arg { - // HACK(eddyb) fake type for the self argument. - ty: P(Ty { - id: DUMMY_NODE_ID, - node: TyInfer, - span: DUMMY_SP, - }), - pat: P(Pat { - id: DUMMY_NODE_ID, - node: PatKind::Ident(BindByValue(mutability), path, None), - span: span, - }), - id: DUMMY_NODE_ID, + pub fn to_self(&self) -> Option { + if let PatKind::Ident(BindByValue(mutbl), ident, _) = self.pat.node { + if ident.node.unhygienic_name == 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 { + if let PatKind::Ident(_, ident, _) = self.pat.node { + ident.node.unhygienic_name == keywords::SelfValue.name() + } else { + false } } } @@ -1227,6 +1241,12 @@ pub struct FnDecl { pub variadic: bool, } +impl FnDecl { + pub fn has_self(&self) -> bool { + self.inputs.get(0).map(Arg::is_self).unwrap_or(false) + } +} + #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Unsafety { Unsafe, @@ -1308,21 +1328,6 @@ impl FunctionRetTy { } } -/// Represents the kind of 'self' associated with a method -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ExplicitSelf_ { - /// No self - SelfStatic, - /// `self` - SelfValue(Name), - /// `&'lt self`, `&'lt mut self` - SelfRegion(Option, Mutability, Name), - /// `self: TYPE` - SelfExplicit(P, Name), -} - -pub type ExplicitSelf = Spanned; - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index db179c1cc1bf6..c3617cb768d56 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -23,7 +23,7 @@ use syntax::print::pprust::{self as ast_pp, PrintState}; use syntax::ptr::P; use hir; -use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; +use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier}; use std::io::{self, Write, Read}; @@ -281,7 +281,6 @@ pub fn fun_to_string(decl: &hir::FnDecl, unsafety: hir::Unsafety, constness: hir::Constness, name: ast::Name, - opt_explicit_self: Option<&hir::ExplicitSelf_>, generics: &hir::Generics) -> String { to_string(|s| { @@ -292,7 +291,6 @@ pub fn fun_to_string(decl: &hir::FnDecl, Abi::Rust, Some(name), generics, - opt_explicit_self, &hir::Inherited)?; s.end()?; // Close the head box s.end() // Close the outer box @@ -309,10 +307,6 @@ pub fn block_to_string(blk: &hir::Block) -> String { }) } -pub fn explicit_self_to_string(explicit_self: &hir::ExplicitSelf_) -> String { - to_string(|s| s.print_explicit_self(explicit_self, hir::MutImmutable).map(|_| {})) -} - pub fn variant_to_string(var: &hir::Variant) -> String { to_string(|s| s.print_variant(var)) } @@ -526,7 +520,7 @@ impl<'a> State<'a> { predicates: hir::HirVec::new(), }, }; - self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics, None)?; + self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?; } hir::TyPath(None, ref path) => { self.print_path(path, false, 0)?; @@ -573,7 +567,6 @@ impl<'a> State<'a> { Abi::Rust, Some(item.name), generics, - None, &item.vis)?; self.end()?; // end head-ibox word(&mut self.s, ";")?; @@ -710,7 +703,6 @@ impl<'a> State<'a> { abi, Some(item.name), typarams, - None, &item.vis)?; word(&mut self.s, " ")?; self.print_block_with_attrs(&body, &item.attrs)?; @@ -976,7 +968,6 @@ impl<'a> State<'a> { m.abi, Some(name), &m.generics, - Some(&m.explicit_self.node), vis) } @@ -1881,32 +1872,25 @@ impl<'a> State<'a> { self.end() // close enclosing cbox } - // Returns whether it printed anything - fn print_explicit_self(&mut self, - explicit_self: &hir::ExplicitSelf_, - mutbl: hir::Mutability) - -> io::Result { - self.print_mutability(mutbl)?; - match *explicit_self { - hir::SelfStatic => { - return Ok(false); - } - hir::SelfValue(_) => { - word(&mut self.s, "self")?; + 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") } - hir::SelfRegion(ref lt, m, _) => { + SelfKind::Region(ref lt, m) => { word(&mut self.s, "&")?; self.print_opt_lifetime(lt)?; self.print_mutability(m)?; - word(&mut self.s, "self")?; + word(&mut self.s, "self") } - hir::SelfExplicit(ref typ, _) => { + SelfKind::Explicit(ref typ, m) => { + self.print_mutability(m)?; word(&mut self.s, "self")?; self.word_space(":")?; - self.print_type(&typ)?; + self.print_type(&typ) } } - return Ok(true); } pub fn print_fn(&mut self, @@ -1916,7 +1900,6 @@ impl<'a> State<'a> { abi: Abi, name: Option, generics: &hir::Generics, - opt_explicit_self: Option<&hir::ExplicitSelf_>, vis: &hir::Visibility) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -1926,55 +1909,13 @@ impl<'a> State<'a> { self.print_name(name)?; } self.print_generics(generics)?; - self.print_fn_args_and_ret(decl, opt_explicit_self)?; + self.print_fn_args_and_ret(decl)?; self.print_where_clause(&generics.where_clause) } - pub fn print_fn_args(&mut self, - decl: &hir::FnDecl, - opt_explicit_self: Option<&hir::ExplicitSelf_>, - is_closure: bool) - -> io::Result<()> { - // It is unfortunate to duplicate the commasep logic, but we want the - // self type and the args all in the same box. - self.rbox(0, Inconsistent)?; - let mut first = true; - if let Some(explicit_self) = opt_explicit_self { - let m = match explicit_self { - &hir::SelfStatic => hir::MutImmutable, - _ => match decl.inputs[0].pat.node { - PatKind::Ident(hir::BindByValue(m), _, _) => m, - _ => hir::MutImmutable, - }, - }; - first = !self.print_explicit_self(explicit_self, m)?; - } - - // HACK(eddyb) ignore the separately printed self argument. - let args = if first { - &decl.inputs[..] - } else { - &decl.inputs[1..] - }; - - for arg in args { - if first { - first = false; - } else { - self.word_space(",")?; - } - self.print_arg(arg, is_closure)?; - } - - self.end() - } - - pub fn print_fn_args_and_ret(&mut self, - decl: &hir::FnDecl, - opt_explicit_self: Option<&hir::ExplicitSelf_>) - -> io::Result<()> { + pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> { self.popen()?; - self.print_fn_args(decl, opt_explicit_self, false)?; + self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; if decl.variadic { word(&mut self.s, ", ...")?; } @@ -1985,7 +1926,7 @@ impl<'a> State<'a> { pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> { word(&mut self.s, "|")?; - self.print_fn_args(decl, None, true)?; + self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; word(&mut self.s, "|")?; if let hir::DefaultReturn(..) = decl.output { @@ -2207,18 +2148,21 @@ impl<'a> State<'a> { match input.ty.node { hir::TyInfer if is_closure => self.print_pat(&input.pat)?, _ => { - match input.pat.node { - PatKind::Ident(_, ref path1, _) - if path1.node.name == keywords::Invalid.name() => { - // Do nothing. - } - _ => { + if let Some(eself) = input.to_self() { + self.print_explicit_self(&eself)?; + } else { + let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node { + ident.node.name == 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)?; } - self.print_type(&input.ty)?; } } self.end() @@ -2250,8 +2194,7 @@ impl<'a> State<'a> { unsafety: hir::Unsafety, decl: &hir::FnDecl, name: Option, - generics: &hir::Generics, - opt_explicit_self: Option<&hir::ExplicitSelf_>) + generics: &hir::Generics) -> io::Result<()> { self.ibox(indent_unit)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { @@ -2272,7 +2215,6 @@ impl<'a> State<'a> { abi, name, &generics, - opt_explicit_self, &hir::Inherited)?; self.end() } diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 3900fab2d930a..cabc004a65d7d 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -976,8 +976,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ast_map::NodeItem(ref item) => { match item.node { hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => { - Some((fn_decl, gen, unsafety, constness, - item.name, None, item.span)) + Some((fn_decl, gen, unsafety, constness, item.name, item.span)) }, _ => None } @@ -990,7 +989,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sig.unsafety, sig.constness, item.name, - Some(&sig.explicit_self.node), item.span)) } _ => None, @@ -1004,7 +1002,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sig.unsafety, sig.constness, item.name, - Some(&sig.explicit_self.node), item.span)) } _ => None @@ -1014,13 +1011,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, None => None }; - let (fn_decl, generics, unsafety, constness, name, expl_self, span) + let (fn_decl, generics, unsafety, constness, name, span) = node_inner.expect("expect item fn"); - let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, - generics, same_regions, &life_giver); - let (fn_decl, expl_self, generics) = rebuilder.rebuild(); - self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name, - expl_self.as_ref(), &generics, span); + let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver); + let (fn_decl, generics) = rebuilder.rebuild(); + self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name, &generics, span); } } @@ -1038,7 +1033,6 @@ struct RebuildPathInfo<'a> { struct Rebuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, fn_decl: &'a hir::FnDecl, - expl_self_opt: Option<&'a hir::ExplicitSelf_>, generics: &'a hir::Generics, same_regions: &'a [SameRegions], life_giver: &'a LifeGiver, @@ -1054,7 +1048,6 @@ enum FreshOrKept { impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn_decl: &'a hir::FnDecl, - expl_self_opt: Option<&'a hir::ExplicitSelf_>, generics: &'a hir::Generics, same_regions: &'a [SameRegions], life_giver: &'a LifeGiver) @@ -1062,7 +1055,6 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { Rebuilder { tcx: tcx, fn_decl: fn_decl, - expl_self_opt: expl_self_opt, generics: generics, same_regions: same_regions, life_giver: life_giver, @@ -1071,9 +1063,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { } } - fn rebuild(&self) - -> (hir::FnDecl, Option, hir::Generics) { - let mut expl_self_opt = self.expl_self_opt.cloned(); + fn rebuild(&self) -> (hir::FnDecl, hir::Generics) { let mut inputs = self.fn_decl.inputs.clone(); let mut output = self.fn_decl.output.clone(); let mut ty_params = self.generics.ty_params.clone(); @@ -1089,8 +1079,6 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { Kept => { kept_lifetimes.insert(lifetime.name); } _ => () } - expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime, - &anon_nums, ®ion_names); inputs = self.rebuild_args_ty(&inputs[..], lifetime, &anon_nums, ®ion_names); output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names); @@ -1110,7 +1098,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { output: output, variadic: self.fn_decl.variadic }; - (new_fn_decl, expl_self_opt, generics) + (new_fn_decl, generics) } fn pick_lifetime(&self, @@ -1250,34 +1238,6 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { }).collect() } - fn rebuild_expl_self(&self, - expl_self_opt: Option, - lifetime: hir::Lifetime, - anon_nums: &HashSet, - region_names: &HashSet) - -> Option { - match expl_self_opt { - Some(ref expl_self) => match *expl_self { - hir::SelfRegion(lt_opt, muta, id) => match lt_opt { - Some(lt) => if region_names.contains(<.name) { - return Some(hir::SelfRegion(Some(lifetime), muta, id)); - }, - None => { - let anon = self.cur_anon.get(); - self.inc_and_offset_cur_anon(1); - if anon_nums.contains(&anon) { - self.track_anon(anon); - return Some(hir::SelfRegion(Some(lifetime), muta, id)); - } - } - }, - _ => () - }, - None => () - } - expl_self_opt - } - fn rebuild_generics(&self, generics: &hir::Generics, add: &Vec, @@ -1575,11 +1535,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { unsafety: hir::Unsafety, constness: hir::Constness, name: ast::Name, - opt_explicit_self: Option<&hir::ExplicitSelf_>, generics: &hir::Generics, span: Span) { - let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, - opt_explicit_self, generics); + let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, generics); let msg = format!("consider using an explicit lifetime \ parameter as shown: {}", suggested_fn); err.span_help(span, &msg[..]); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a4b9b5f45563f..0801f8f4ac7ef 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -889,11 +889,6 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { run_lints!(self, check_lifetime_def, late_passes, lt); } - fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) { - run_lints!(self, check_explicit_self, late_passes, es); - hir_visit::walk_explicit_self(self, es); - } - fn visit_path(&mut self, p: &hir::Path, id: ast::NodeId) { run_lints!(self, check_path, late_passes, p, id); hir_visit::walk_path(self, p); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 5c06231631010..932f2882b4963 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -483,7 +483,6 @@ impl<'a> LifetimeContext<'a> { FnKind::Method(_, sig, _, _) => { intravisit::walk_fn_decl(self, fd); self.visit_generics(&sig.generics); - self.visit_explicit_self(&sig.explicit_self); } FnKind::Closure(_) => { intravisit::walk_fn_decl(self, fd); diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs index ef3ac4c342690..e914c38963cab 100644 --- a/src/librustc_incremental/calculate_svh.rs +++ b/src/librustc_incremental/calculate_svh.rs @@ -172,7 +172,6 @@ mod svh_visitor { SawImplItem, SawStructField, SawVariant, - SawExplicitSelf, SawPath, SawBlock, SawPat, @@ -391,10 +390,6 @@ mod svh_visitor { SawStructField.hash(self.st); visit::walk_struct_field(self, s) } - fn visit_explicit_self(&mut self, es: &'a ExplicitSelf) { - SawExplicitSelf.hash(self.st); visit::walk_explicit_self(self, es) - } - fn visit_path(&mut self, path: &'a Path, _: ast::NodeId) { SawPath.hash(self.st); visit::walk_path(self, path) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0b2763baf4f67..f1e744098b960 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -831,8 +831,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> } } hir::ImplItemKind::Method(ref sig, _) => { - if sig.explicit_self.node == hir::SelfStatic && - self.item_is_public(&impl_item.id, &impl_item.vis) { + if !sig.decl.has_self() && + self.item_is_public(&impl_item.id, &impl_item.vis) { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9cec3a5179496..60c8724b8db6e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -582,7 +582,6 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> { } FnKind::Method(_, sig, _) => { self.visit_generics(&sig.generics); - self.visit_explicit_self(&sig.explicit_self); MethodRibKind } FnKind::Closure => ClosureRibKind(node_id), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c8e247fb9181c..4faefb610562d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -75,7 +75,7 @@ use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::parse::token::{self, keywords}; use rustc::hir::print as pprust; -use rustc::hir; +use rustc::hir::{self, SelfKind}; use rustc_back::slice; pub trait AstConv<'gcx, 'tcx> { @@ -166,11 +166,6 @@ struct ConvertedBinding<'tcx> { span: Span, } -struct SelfInfo<'a, 'tcx> { - untransformed_self_ty: Ty<'tcx>, - explicit_self: &'a hir::ExplicitSelf, -} - type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime) @@ -1719,33 +1714,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { sig: &hir::MethodSig, untransformed_self_ty: Ty<'tcx>) -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) { - let self_info = Some(SelfInfo { - untransformed_self_ty: untransformed_self_ty, - explicit_self: &sig.explicit_self, - }); let (bare_fn_ty, optional_explicit_self_category) = self.ty_of_method_or_bare_fn(sig.unsafety, sig.abi, - self_info, + Some(untransformed_self_ty), &sig.decl); - (bare_fn_ty, optional_explicit_self_category.unwrap()) + (bare_fn_ty, optional_explicit_self_category) } pub fn ty_of_bare_fn(&self, - unsafety: hir::Unsafety, abi: abi::Abi, + unsafety: hir::Unsafety, + abi: abi::Abi, decl: &hir::FnDecl) -> &'tcx ty::BareFnTy<'tcx> { - let (bare_fn_ty, _) = self.ty_of_method_or_bare_fn(unsafety, abi, None, decl); - bare_fn_ty + self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0 } fn ty_of_method_or_bare_fn<'a>(&self, unsafety: hir::Unsafety, abi: abi::Abi, - opt_self_info: Option>, + opt_untransformed_self_ty: Option>, decl: &hir::FnDecl) - -> (&'tcx ty::BareFnTy<'tcx>, - Option) + -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) { debug!("ty_of_method_or_bare_fn"); @@ -1758,9 +1748,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // 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_category) = match opt_self_info { - None => (None, None), - Some(self_info) => self.determine_self_type(&rb, self_info) + let explicit_self = decl.inputs.get(0).and_then(hir::Arg::to_self); + let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, explicit_self) { + (Some(untransformed_self_ty), Some(explicit_self)) => { + let self_type = self.determine_self_type(&rb, untransformed_self_ty, + &explicit_self); + (Some(self_type.0), self_type.1) + } + _ => (None, ty::ExplicitSelfCategory::Static), }; // HACK(eddyb) replace the fake self type in the AST with the actual type. @@ -1778,7 +1773,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // reference) in the arguments, then any anonymous regions in the output // have that lifetime. let implied_output_region = match explicit_self_category { - Some(ty::ExplicitSelfCategory::ByReference(region, _)) => Ok(region), + ty::ExplicitSelfCategory::ByReference(region, _) => Ok(region), _ => self.find_implied_output_region(&arg_tys, arg_pats) }; @@ -1803,29 +1798,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn determine_self_type<'a>(&self, rscope: &RegionScope, - self_info: SelfInfo<'a, 'tcx>) - -> (Option>, Option) + untransformed_self_ty: Ty<'tcx>, + explicit_self: &hir::ExplicitSelf) + -> (Ty<'tcx>, ty::ExplicitSelfCategory) { - let self_ty = self_info.untransformed_self_ty; - return match self_info.explicit_self.node { - hir::SelfStatic => (None, Some(ty::ExplicitSelfCategory::Static)), - hir::SelfValue(_) => { - (Some(self_ty), Some(ty::ExplicitSelfCategory::ByValue)) + return match explicit_self.node { + SelfKind::Value(..) => { + (untransformed_self_ty, ty::ExplicitSelfCategory::ByValue) } - hir::SelfRegion(ref lifetime, mutability, _) => { + SelfKind::Region(ref lifetime, mutability) => { let region = - self.opt_ast_region_to_region(rscope, - self_info.explicit_self.span, - lifetime); - (Some(self.tcx().mk_ref( + self.opt_ast_region_to_region( + rscope, + explicit_self.span, + lifetime); + (self.tcx().mk_ref( self.tcx().mk_region(region), ty::TypeAndMut { - ty: self_ty, + ty: untransformed_self_ty, mutbl: mutability - })), - Some(ty::ExplicitSelfCategory::ByReference(region, mutability))) + }), + ty::ExplicitSelfCategory::ByReference(region, mutability)) } - hir::SelfExplicit(ref ast_type, _) => { + SelfKind::Explicit(ref ast_type, _) => { let explicit_type = self.ast_ty_to_ty(rscope, &ast_type); // We wish to (for now) categorize an explicit self @@ -1857,13 +1852,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // type has two, so we end up with // ExplicitSelfCategory::ByReference. - let impl_modifiers = count_modifiers(self_info.untransformed_self_ty); + let impl_modifiers = count_modifiers(untransformed_self_ty); let method_modifiers = count_modifiers(explicit_type); debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \ explicit_type={:?} \ modifiers=({},{})", - self_info.untransformed_self_ty, + untransformed_self_ty, explicit_type, impl_modifiers, method_modifiers); @@ -1878,7 +1873,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }; - (Some(explicit_type), Some(category)) + (explicit_type, category) } }; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c9df54dfef267..f5d54123f37b5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -361,7 +361,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, let mut item = method.clean(cx); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { - unsafety, decl, self_, generics, abi + unsafety, decl, generics, abi }) => { let constness = if tcx.sess.cstore.is_const_fn(did) { hir::Constness::Const @@ -373,7 +373,6 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, unsafety: unsafety, constness: constness, decl: decl, - self_: self_, generics: generics, abi: abi }) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a89609fad6b6e..7c7a2cfc21cc9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1025,7 +1025,6 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Method { pub generics: Generics, - pub self_: SelfTy, pub unsafety: hir::Unsafety, pub constness: hir::Constness, pub decl: FnDecl, @@ -1034,14 +1033,9 @@ pub struct Method { impl Clean for hir::MethodSig { fn clean(&self, cx: &DocContext) -> Method { - let all_inputs = &self.decl.inputs; - let inputs = match self.explicit_self.node { - hir::SelfStatic => &**all_inputs, - _ => &all_inputs[1..] - }; let decl = FnDecl { inputs: Arguments { - values: inputs.clean(cx), + values: self.decl.inputs.clean(cx), }, output: self.decl.output.clean(cx), variadic: false, @@ -1049,7 +1043,6 @@ impl Clean for hir::MethodSig { }; Method { generics: self.generics.clean(cx), - self_: self.explicit_self.node.clean(cx), unsafety: self.unsafety, constness: self.constness, decl: decl, @@ -1063,19 +1056,14 @@ pub struct TyMethod { pub unsafety: hir::Unsafety, pub decl: FnDecl, pub generics: Generics, - pub self_: SelfTy, pub abi: Abi, } impl Clean for hir::MethodSig { fn clean(&self, cx: &DocContext) -> TyMethod { - let inputs = match self.explicit_self.node { - hir::SelfStatic => &*self.decl.inputs, - _ => &self.decl.inputs[1..] - }; let decl = FnDecl { inputs: Arguments { - values: inputs.clean(cx), + values: self.decl.inputs.clean(cx), }, output: self.decl.output.clean(cx), variadic: false, @@ -1084,34 +1072,12 @@ impl Clean for hir::MethodSig { TyMethod { unsafety: self.unsafety.clone(), decl: decl, - self_: self.explicit_self.node.clean(cx), generics: self.generics.clean(cx), abi: self.abi } } } -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] -pub enum SelfTy { - SelfStatic, - SelfValue, - SelfBorrowed(Option, Mutability), - SelfExplicit(Type), -} - -impl Clean for hir::ExplicitSelf_ { - fn clean(&self, cx: &DocContext) -> SelfTy { - match *self { - hir::SelfStatic => SelfStatic, - hir::SelfValue(_) => SelfValue, - hir::SelfRegion(ref lt, ref mt, _) => { - SelfBorrowed(lt.clean(cx), mt.clean(cx)) - } - hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)), - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Function { pub decl: FnDecl, @@ -1150,6 +1116,12 @@ pub struct FnDecl { pub attrs: Vec, } +impl FnDecl { + pub fn has_self(&self) -> bool { + return self.inputs.values.len() > 0 && self.inputs.values[0].name == "self"; + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub struct Arguments { pub values: Vec, @@ -1185,9 +1157,6 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { } else { cx.tcx().sess.cstore.method_arg_names(did).into_iter() }.peekable(); - if let Some("self") = names.peek().map(|s| &s[..]) { - let _ = names.next(); - } FnDecl { output: Return(sig.0.output.clean(cx)), attrs: Vec::new(), @@ -1212,6 +1181,29 @@ pub struct Argument { pub id: ast::NodeId, } +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] +pub enum SelfTy { + SelfValue, + SelfBorrowed(Option, Mutability), + SelfExplicit(Type), +} + +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())) + } + } else { + None + } + } +} + impl Clean for hir::Arg { fn clean(&self, cx: &DocContext) -> Argument { Argument { @@ -1346,36 +1338,21 @@ impl Clean for hir::ImplItem { impl<'tcx> Clean for ty::Method<'tcx> { fn clean(&self, cx: &DocContext) -> Item { - let (self_, sig) = match self.explicit_self { - ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx), - self.fty.sig.clone()), - s => { - let sig = ty::Binder(ty::FnSig { - inputs: self.fty.sig.0.inputs[1..].to_vec(), - ..self.fty.sig.0.clone() - }); - let s = match s { - ty::ExplicitSelfCategory::ByValue => SelfValue, - ty::ExplicitSelfCategory::ByReference(..) => { - match self.fty.sig.0.inputs[0].sty { - ty::TyRef(r, mt) => { - SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx)) - } - _ => unreachable!(), - } - } - ty::ExplicitSelfCategory::ByBox => { - SelfExplicit(self.fty.sig.0.inputs[0].clean(cx)) - } - ty::ExplicitSelfCategory::Static => unreachable!(), - }; - (s, sig) - } - }; - let generics = (&self.generics, &self.predicates, subst::FnSpace).clean(cx); - let decl = (self.def_id, &sig).clean(cx); + let mut decl = (self.def_id, &self.fty.sig).clean(cx); + match self.explicit_self { + ty::ExplicitSelfCategory::ByValue => { + decl.inputs.values[0].type_ = Infer; + } + ty::ExplicitSelfCategory::ByReference(..) => { + match decl.inputs.values[0].type_ { + BorrowedRef{ref mut type_, ..} => **type_ = Infer, + _ => unreachable!(), + } + } + _ => {} + } let provided = match self.container { ty::ImplContainer(..) => false, ty::TraitContainer(did) => { @@ -1388,7 +1365,6 @@ impl<'tcx> Clean for ty::Method<'tcx> { MethodItem(Method { unsafety: self.fty.unsafety, generics: generics, - self_: self_, decl: decl, abi: self.fty.abi, @@ -1399,7 +1375,6 @@ impl<'tcx> Clean for ty::Method<'tcx> { TyMethodItem(TyMethod { unsafety: self.fty.unsafety, generics: generics, - self_: self_, decl: decl, abi: self.fty.abi, }) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7af5322e7bdf1..95bf66ed30db2 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -43,7 +43,7 @@ pub struct UnsafetySpace(pub hir::Unsafety); #[derive(Copy, Clone)] pub struct ConstnessSpace(pub hir::Constness); /// Wrapper struct for properly emitting a method declaration. -pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); +pub struct Method<'a>(pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); @@ -642,29 +642,31 @@ impl fmt::Display for clean::FnDecl { impl<'a> fmt::Display for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Method(selfty, d) = *self; + let decl = self.0; let mut args = String::new(); - match *selfty { - clean::SelfStatic => {}, - clean::SelfValue => args.push_str("self"), - clean::SelfBorrowed(Some(ref lt), mtbl) => { - args.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl))); - } - clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("&{}self", MutableSpace(mtbl))); - } - clean::SelfExplicit(ref typ) => { - args.push_str(&format!("self: {}", *typ)); - } - } - for (i, input) in d.inputs.values.iter().enumerate() { + for (i, input) in decl.inputs.values.iter().enumerate() { if i > 0 || !args.is_empty() { args.push_str(", "); } - if !input.name.is_empty() { - args.push_str(&format!("{}: ", input.name)); + if let Some(selfty) = input.to_self() { + match selfty { + clean::SelfValue => args.push_str("self"), + clean::SelfBorrowed(Some(ref lt), mtbl) => { + args.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl))); + } + clean::SelfBorrowed(None, mtbl) => { + args.push_str(&format!("&{}self", MutableSpace(mtbl))); + } + clean::SelfExplicit(ref typ) => { + args.push_str(&format!("self: {}", *typ)); + } + } + } else { + if !input.name.is_empty() { + args.push_str(&format!("{}: ", input.name)); + } + args.push_str(&format!("{}", input.type_)); } - args.push_str(&format!("{}", input.type_)); } - write!(f, "({args}){arrow}", args = args, arrow = d.output) + write!(f, "({args}){arrow}", args = args, arrow = decl.output) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index da0520ebcb84a..005e25b07d42d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -62,7 +62,7 @@ use rustc::middle::stability; use rustc::session::config::get_unstable_features_setting; use rustc::hir; -use clean::{self, SelfTy, Attributes, GetDefId}; +use clean::{self, Attributes, GetDefId}; use doctree; use fold::DocFolder; use html::escape::Escape; @@ -592,8 +592,6 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { for &(did, ref item) in orphan_methods { match paths.get(&did) { Some(&(ref fqp, _)) => { - // Needed to determine `self` type. - let parent_basename = Some(fqp[fqp.len() - 1].clone()); search_index.push(IndexItem { ty: shortty(item), name: item.name.clone().unwrap(), @@ -601,7 +599,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { desc: Escape(&shorter(item.doc_value())).to_string(), parent: Some(did), parent_idx: None, - search_type: get_index_search_type(&item, parent_basename), + search_type: get_index_search_type(&item), }); }, None => {} @@ -1081,13 +1079,6 @@ impl DocFolder for Cache { match parent { (parent, Some(path)) if is_method || (!self.stripped_mod) => { - // Needed to determine `self` type. - let parent_basename = self.parent_stack.first().and_then(|parent| { - match self.paths.get(parent) { - Some(&(ref fqp, _)) => Some(fqp[fqp.len() - 1].clone()), - _ => None - } - }); debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, @@ -1101,7 +1092,7 @@ impl DocFolder for Cache { desc: Escape(&shorter(item.doc_value())).to_string(), parent: parent, parent_idx: None, - search_type: get_index_search_type(&item, parent_basename), + search_type: get_index_search_type(&item), }); } } @@ -2167,7 +2158,6 @@ fn render_assoc_item(w: &mut fmt::Formatter, constness: hir::Constness, abi: abi::Abi, g: &clean::Generics, - selfty: &clean::SelfTy, d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result { @@ -2201,18 +2191,18 @@ fn render_assoc_item(w: &mut fmt::Formatter, href = href, name = name, generics = *g, - decl = Method(selfty, d), + decl = Method(d), where_clause = WhereClause(g)) } match item.inner { clean::StrippedItem(..) => Ok(()), clean::TyMethodItem(ref m) => { method(w, item, m.unsafety, hir::Constness::NotConst, - m.abi, &m.generics, &m.self_, &m.decl, link) + m.abi, &m.generics, &m.decl, link) } clean::MethodItem(ref m) => { method(w, item, m.unsafety, m.constness, - m.abi, &m.generics, &m.self_, &m.decl, + m.abi, &m.generics, &m.decl, link) } clean::AssociatedConstItem(ref ty, ref default) => { @@ -2570,8 +2560,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi let name = item.name.as_ref().unwrap(); let is_static = match item.inner { - clean::MethodItem(ref method) => method.self_ == SelfTy::SelfStatic, - clean::TyMethodItem(ref method) => method.self_ == SelfTy::SelfStatic, + clean::MethodItem(ref method) => !method.decl.has_self(), + clean::TyMethodItem(ref method) => !method.decl.has_self(), _ => false }; @@ -2760,27 +2750,15 @@ fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) } -fn get_index_search_type(item: &clean::Item, - parent: Option) -> Option { - let (decl, selfty) = match item.inner { - clean::FunctionItem(ref f) => (&f.decl, None), - clean::MethodItem(ref m) => (&m.decl, Some(&m.self_)), - clean::TyMethodItem(ref m) => (&m.decl, Some(&m.self_)), +fn get_index_search_type(item: &clean::Item) -> Option { + let decl = match item.inner { + clean::FunctionItem(ref f) => &f.decl, + clean::MethodItem(ref m) => &m.decl, + clean::TyMethodItem(ref m) => &m.decl, _ => return None }; - let mut inputs = Vec::new(); - - // Consider `self` an argument as well. - match parent.and_then(|p| selfty.map(|s| (p, s)) ) { - Some((_, &clean::SelfStatic)) | None => (), - Some((name, _)) => inputs.push(Type { name: Some(name.to_ascii_lowercase()) }), - } - - inputs.extend(&mut decl.inputs.values.iter().map(|arg| { - get_index_type(&arg.type_) - })); - + let inputs = decl.inputs.values.iter().map(|arg| get_index_type(&arg.type_)).collect(); let output = match decl.output { clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)), _ => None From a62a6903268a68e793407aca05a64e89b8b22f1b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 May 2016 21:19:29 +0300 Subject: [PATCH 3/3] Add checks for `self: _` and `self: &_` --- src/librustc/hir/lowering.rs | 10 ++++++++++ src/test/compile-fail/self-infer.rs | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/compile-fail/self-infer.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d6a29b0376428..0c3c190064b08 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -775,6 +775,16 @@ impl<'a> LoweringContext<'a> { } fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { + // Check for `self: _` and `self: &_` + if let SelfKind::Explicit(ref ty, _) = sig.explicit_self.node { + match sig.decl.inputs.get(0).and_then(Arg::to_self).map(|eself| eself.node) { + Some(SelfKind::Value(..)) | Some(SelfKind::Region(..)) => { + self.id_assigner.diagnostic().span_err(ty.span, + "the type placeholder `_` is not allowed within types on item signatures"); + } + _ => {} + } + } hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, diff --git a/src/test/compile-fail/self-infer.rs b/src/test/compile-fail/self-infer.rs new file mode 100644 index 0000000000000..fd011318a4800 --- /dev/null +++ b/src/test/compile-fail/self-infer.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig + fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig +} + +fn main() {}