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:
bors 2016-05-15 23:14:52 -07:00
commit e87cd7e380
23 changed files with 433 additions and 639 deletions

View File

@ -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),

View File

@ -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);
}

View File

@ -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),

View File

@ -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 `}`.

View File

@ -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()
}

View File

@ -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, &region_names);
inputs = self.rebuild_args_ty(&inputs[..], lifetime,
&anon_nums, &region_names);
output = self.rebuild_output(&output, lifetime, &anon_nums, &region_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(&lt.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[..]);

View File

@ -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);

View File

@ -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);

View File

@ -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)
}

View File

@ -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);
}

View File

@ -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),

View File

@ -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)
}
};

View File

@ -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
})

View File

@ -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,
})

View File

@ -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!("&amp;{} {}self", *lt, MutableSpace(mtbl)));
}
clean::SelfBorrowed(None, mtbl) => {
args.push_str(&format!("&amp;{}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!("&amp;{} {}self", *lt, MutableSpace(mtbl)));
}
clean::SelfBorrowed(None, mtbl) => {
args.push_str(&format!("&amp;{}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)
}
}

View File

@ -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

View File

@ -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 `}`.

View File

@ -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
// &not_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

View File

@ -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()

View File

@ -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)| {

View 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() {}

View 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 `*`
}

View File

@ -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() { }