Auto merge of #33505 - petrochenkov:self, r=nrc
Remove ExplicitSelf from HIR `self` argument is already kept in the argument list and can be retrieved from there if necessary, so there's no need for the duplication. The same changes can be applied to AST, I'll make them in the next breaking batch. The first commit also improves parsing of method declarations and fixes https://github.com/rust-lang/rust/issues/33413. r? @eddyb
This commit is contained in:
commit
e87cd7e380
@ -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<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attr
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_explicit_self_underscore<T: Folder>(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<T: Folder>(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<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
|
||||
mi.map(|Spanned { node, span }| {
|
||||
Spanned {
|
||||
@ -941,7 +910,6 @@ pub fn noop_fold_method_sig<T: Folder>(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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
@ -797,10 +775,19 @@ 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,
|
||||
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),
|
||||
|
@ -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<FnDecl>,
|
||||
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<Lifetime>, Mutability),
|
||||
/// `self: TYPE`, `mut self: TYPE`
|
||||
Explicit(P<Ty>, Mutability),
|
||||
}
|
||||
|
||||
pub type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
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<ExplicitSelf> {
|
||||
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<Lifetime>, Mutability, Name),
|
||||
/// `self: TYPE`
|
||||
SelfExplicit(P<Ty>, Name),
|
||||
}
|
||||
|
||||
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct Mod {
|
||||
/// A span from the first token past `{` to the last token until `}`.
|
||||
|
@ -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<bool> {
|
||||
self.print_mutability(mutbl)?;
|
||||
match *explicit_self {
|
||||
hir::SelfStatic => {
|
||||
return Ok(false);
|
||||
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::SelfValue(_) => {
|
||||
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<ast::Name>,
|
||||
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<ast::Name>,
|
||||
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()
|
||||
}
|
||||
|
@ -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::ExplicitSelf_>, 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<hir::ExplicitSelf_>,
|
||||
lifetime: hir::Lifetime,
|
||||
anon_nums: &HashSet<u32>,
|
||||
region_names: &HashSet<ast::Name>)
|
||||
-> Option<hir::ExplicitSelf_> {
|
||||
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<hir::Lifetime>,
|
||||
@ -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[..]);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -596,7 +596,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),
|
||||
|
@ -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<ty::PolyProjectionPredicate<'tcx>>);
|
||||
|
||||
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<SelfInfo<'a, 'tcx>>,
|
||||
opt_untransformed_self_ty: Option<Ty<'tcx>>,
|
||||
decl: &hir::FnDecl)
|
||||
-> (&'tcx ty::BareFnTy<'tcx>,
|
||||
Option<ty::ExplicitSelfCategory>)
|
||||
-> (&'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<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
|
||||
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)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -1025,7 +1025,6 @@ impl<'a, 'tcx> Clean<Generics> 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<Method> 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<Method> 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<TyMethod> 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<TyMethod> 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<Lifetime>, Mutability),
|
||||
SelfExplicit(Type),
|
||||
}
|
||||
|
||||
impl Clean<SelfTy> 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<Attribute>,
|
||||
}
|
||||
|
||||
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<Argument>,
|
||||
@ -1185,9 +1157,6 @@ impl<'a, 'tcx> Clean<FnDecl> 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<Lifetime>, Mutability),
|
||||
SelfExplicit(Type),
|
||||
}
|
||||
|
||||
impl Argument {
|
||||
pub fn to_self(&self) -> Option<SelfTy> {
|
||||
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<Argument> for hir::Arg {
|
||||
fn clean(&self, cx: &DocContext) -> Argument {
|
||||
Argument {
|
||||
@ -1346,36 +1338,21 @@ impl Clean<Item> for hir::ImplItem {
|
||||
|
||||
impl<'tcx> Clean<Item> 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<Item> 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<Item> for ty::Method<'tcx> {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: self.fty.unsafety,
|
||||
generics: generics,
|
||||
self_: self_,
|
||||
decl: decl,
|
||||
abi: self.fty.abi,
|
||||
})
|
||||
|
@ -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);
|
||||
@ -648,29 +648,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<String>) -> Option<IndexItemFunctionType> {
|
||||
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<IndexItemFunctionType> {
|
||||
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
|
||||
|
@ -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<Lifetime>, Mutability, Ident),
|
||||
/// `self: TYPE`, `mut self: TYPE`
|
||||
Explicit(P<Ty>, Ident),
|
||||
}
|
||||
|
||||
pub type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
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<ExplicitSelf> {
|
||||
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<Lifetime>, Mutability, Ident),
|
||||
/// `self: TYPE`
|
||||
Explicit(P<Ty>, Ident),
|
||||
}
|
||||
|
||||
pub type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct Mod {
|
||||
/// A span from the first token past `{` to the last token until `}`.
|
||||
|
@ -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<F>(&mut self,
|
||||
parse_arg_fn: F) -> PResult<'a, (ExplicitSelf, P<FnDecl>)> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
|
||||
parse_arg_fn: F)
|
||||
-> PResult<'a, (ExplicitSelf, P<FnDecl>)>
|
||||
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 => {
|
||||
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
|
||||
);
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let fn_inputs = match explicit_self {
|
||||
SelfKind::Static => {
|
||||
let sep = SeqSep::trailing_allowed(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(id) => parse_remaining_arguments!(id),
|
||||
SelfKind::Region(_,_,id) => parse_remaining_arguments!(id),
|
||||
SelfKind::Explicit(_,id) => parse_remaining_arguments!(id),
|
||||
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 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
|
||||
} else {
|
||||
return self.unexpected();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
|
@ -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()
|
||||
|
@ -867,9 +867,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)| {
|
||||
|
18
src/test/compile-fail/self-infer.rs
Normal file
18
src/test/compile-fail/self-infer.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
|
16
src/test/parse-fail/issue-33413.rs
Normal file
16
src/test/parse-fail/issue-33413.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 `*`
|
||||
}
|
@ -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() { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user