1
Fork 0

syntax: parse const fn for free functions and inherent methods.

This commit is contained in:
Eduard Burtescu 2015-02-25 22:05:07 +02:00 committed by Niko Matsakis
parent bc6318d2be
commit af3795721c
34 changed files with 218 additions and 88 deletions

View file

@ -1049,7 +1049,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_stability(rbml_w, stab); encode_stability(rbml_w, stab);
rbml_w.end_tag(); rbml_w.end_tag();
} }
ast::ItemFn(ref decl, _, _, ref generics, _) => { ast::ItemFn(ref decl, _, _, _, ref generics, _) => {
add_to_index(item, rbml_w, index); add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item); rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id); encode_def_id(rbml_w, def_id);
@ -1967,7 +1967,7 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
for id in ecx.reachable { for id in ecx.reachable {
if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) { if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
if let ast::ItemFn(_, _, abi, ref generics, _) = i.node { if let ast::ItemFn(_, _, _, abi, ref generics, _) = i.node {
if abi != abi::Rust && !generics.is_type_parameterized() { if abi != abi::Rust && !generics.is_type_parameterized() {
rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id); rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
} }

View file

@ -87,8 +87,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
block: &'v ast::Block, span: Span, _: ast::NodeId) { block: &'v ast::Block, span: Span, _: ast::NodeId) {
let (is_item_fn, is_unsafe_fn) = match fn_kind { let (is_item_fn, is_unsafe_fn) = match fn_kind {
visit::FkItemFn(_, _, fn_style, _, _) => visit::FkItemFn(_, _, unsafety, _, _) =>
(true, fn_style == ast::Unsafety::Unsafe), (true, unsafety == ast::Unsafety::Unsafe),
visit::FkMethod(_, sig, _) => visit::FkMethod(_, sig, _) =>
(true, sig.unsafety == ast::Unsafety::Unsafe), (true, sig.unsafety == ast::Unsafety::Unsafe),
_ => (false, false), _ => (false, false),

View file

@ -158,6 +158,7 @@ trait ErrorReportingHelpers<'tcx> {
fn give_expl_lifetime_param(&self, fn give_expl_lifetime_param(&self,
decl: &ast::FnDecl, decl: &ast::FnDecl,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
constness: ast::Constness,
ident: ast::Ident, ident: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>, opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics, generics: &ast::Generics,
@ -826,8 +827,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
Some(ref node) => match *node { Some(ref node) => match *node {
ast_map::NodeItem(ref item) => { ast_map::NodeItem(ref item) => {
match item.node { match item.node {
ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => { ast::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
Some((fn_decl, gen, pur, item.ident, None, item.span)) Some((fn_decl, gen, unsafety, constness,
item.ident, None, item.span))
}, },
_ => None _ => None
} }
@ -838,6 +840,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
Some((&sig.decl, Some((&sig.decl,
&sig.generics, &sig.generics,
sig.unsafety, sig.unsafety,
sig.constness,
item.ident, item.ident,
Some(&sig.explicit_self.node), Some(&sig.explicit_self.node),
item.span)) item.span))
@ -852,6 +855,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
Some((&sig.decl, Some((&sig.decl,
&sig.generics, &sig.generics,
sig.unsafety, sig.unsafety,
sig.constness,
item.ident, item.ident,
Some(&sig.explicit_self.node), Some(&sig.explicit_self.node),
item.span)) item.span))
@ -863,12 +867,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
}, },
None => None None => None
}; };
let (fn_decl, generics, unsafety, ident, expl_self, span) let (fn_decl, generics, unsafety, constness, ident, expl_self, span)
= node_inner.expect("expect item fn"); = node_inner.expect("expect item fn");
let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
generics, same_regions, &life_giver); generics, same_regions, &life_giver);
let (fn_decl, expl_self, generics) = rebuilder.rebuild(); let (fn_decl, expl_self, generics) = rebuilder.rebuild();
self.give_expl_lifetime_param(&fn_decl, unsafety, ident, self.give_expl_lifetime_param(&fn_decl, unsafety, constness, ident,
expl_self.as_ref(), &generics, span); expl_self.as_ref(), &generics, span);
} }
} }
@ -1423,12 +1427,13 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
fn give_expl_lifetime_param(&self, fn give_expl_lifetime_param(&self,
decl: &ast::FnDecl, decl: &ast::FnDecl,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
constness: ast::Constness,
ident: ast::Ident, ident: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>, opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics, generics: &ast::Generics,
span: codemap::Span) { span: codemap::Span) {
let suggested_fn = pprust::fun_to_string(decl, unsafety, ident, let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, ident,
opt_explicit_self, generics); opt_explicit_self, generics);
let msg = format!("consider using an explicit lifetime \ let msg = format!("consider using an explicit lifetime \
parameter as shown: {}", suggested_fn); parameter as shown: {}", suggested_fn);
self.tcx.sess.span_help(span, &msg[..]); self.tcx.sess.span_help(span, &msg[..]);
@ -1710,7 +1715,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
let method_id_opt = match tcx.map.find(parent) { let method_id_opt = match tcx.map.find(parent) {
Some(node) => match node { Some(node) => match node {
ast_map::NodeItem(item) => match item.node { ast_map::NodeItem(item) => match item.node {
ast::ItemFn(_, _, _, ref gen, _) => { ast::ItemFn(_, _, _, _, ref gen, _) => {
taken.push_all(&gen.lifetimes); taken.push_all(&gen.lifetimes);
None None
}, },

View file

@ -46,7 +46,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
match item.node { match item.node {
ast::ItemImpl(_, _, ref generics, _, _, _) | ast::ItemImpl(_, _, ref generics, _, _, _) |
ast::ItemFn(_, _, _, ref generics, _) => { ast::ItemFn(_, _, _, _, ref generics, _) => {
generics_require_inlining(generics) generics_require_inlining(generics)
} }
_ => false, _ => false,
@ -256,7 +256,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// but all other rust-only interfaces can be private (they will not // but all other rust-only interfaces can be private (they will not
// participate in linkage after this product is produced) // participate in linkage after this product is produced)
if let ast_map::NodeItem(item) = *node { if let ast_map::NodeItem(item) = *node {
if let ast::ItemFn(_, _, abi, _, _) = item.node { if let ast::ItemFn(_, _, _, abi, _, _) = item.node {
if abi != abi::Rust { if abi != abi::Rust {
self.reachable_symbols.insert(search_item); self.reachable_symbols.insert(search_item);
} }
@ -273,7 +273,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
match *node { match *node {
ast_map::NodeItem(item) => { ast_map::NodeItem(item) => {
match item.node { match item.node {
ast::ItemFn(_, _, _, _, ref search_block) => { ast::ItemFn(_, _, _, _, _, ref search_block) => {
if item_might_be_inlined(&*item) { if item_might_be_inlined(&*item) {
visit::walk_block(self, &**search_block) visit::walk_block(self, &**search_block)
} }

View file

@ -154,7 +154,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
b: &'v ast::Block, s: Span, _: ast::NodeId) { b: &'v ast::Block, s: Span, _: ast::NodeId) {
match fk { match fk {
visit::FkItemFn(_, generics, _, _, _) => { visit::FkItemFn(_, generics, _, _, _, _) => {
self.visit_early_late(subst::FnSpace, generics, |this| { self.visit_early_late(subst::FnSpace, generics, |this| {
this.walk_fn(fk, fd, b, s) this.walk_fn(fk, fd, b, s)
}) })

View file

@ -23,7 +23,7 @@ use syntax::{attr, visit};
use syntax::ast; use syntax::ast;
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant}; use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
use syntax::ast::{Item, Generics, StructField}; use syntax::ast::{Item, Generics, StructField};
use syntax::ast_util::is_local; use syntax::ast_util::{is_local, PostExpansionMethod};
use syntax::attr::{Stability, AttrMetaMethods}; use syntax::attr::{Stability, AttrMetaMethods};
use syntax::visit::{FnKind, Visitor}; use syntax::visit::{FnKind, Visitor};
use syntax::feature_gate::emit_feature_err; use syntax::feature_gate::emit_feature_err;

View file

@ -2428,7 +2428,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
} }
Some(ast_map::NodeItem(item)) => { Some(ast_map::NodeItem(item)) => {
match item.node { match item.node {
ast::ItemFn(_, _, _, _, ref body) => { ast::ItemFn(_, _, _, _, _, ref body) => {
// We assume this is a function. // We assume this is a function.
let fn_def_id = ast_util::local_def(id); let fn_def_id = ast_util::local_def(id);
let fn_scheme = lookup_item_type(cx, fn_def_id); let fn_scheme = lookup_item_type(cx, fn_def_id);

View file

@ -977,7 +977,7 @@ impl LintPass for NonSnakeCase {
}, },
_ => (), _ => (),
}, },
visit::FkItemFn(ident, _, _, _, _) => { visit::FkItemFn(ident, _, _, _, _, _) => {
self.check_snake_case(cx, "function", &token::get_ident(ident), Some(span)) self.check_snake_case(cx, "function", &token::get_ident(ident), Some(span))
}, },
_ => (), _ => (),
@ -1853,7 +1853,7 @@ impl LintPass for UnconditionalRecursion {
ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
let (name, checker) = match fn_kind { let (name, checker) = match fn_kind {
visit::FkItemFn(name, _, _, _, _) => (name, id_refers_to_this_fn as F), visit::FkItemFn(name, _, _, _, _, _) => (name, id_refers_to_this_fn as F),
visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F), visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
// closures can't recur, so they don't matter. // closures can't recur, so they don't matter.
visit::FkFnBlock => return visit::FkFnBlock => return

View file

@ -425,7 +425,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
.define_value(DefConst(local_def(item.id)), sp, modifiers); .define_value(DefConst(local_def(item.id)), sp, modifiers);
parent.clone() parent.clone()
} }
ItemFn(_, _, _, _, _) => { ItemFn(_, _, _, _, _, _) => {
let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp); let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
let def = DefFn(local_def(item.id), false); let def = DefFn(local_def(item.id), false);

View file

@ -1809,7 +1809,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ItemRibKind), ItemRibKind),
|this| visit::walk_item(this, item)); |this| visit::walk_item(this, item));
} }
ItemFn(_, _, _, ref generics, _) => { ItemFn(_, _, _, _, ref generics, _) => {
self.with_type_parameter_rib(HasTypeParameters(generics, self.with_type_parameter_rib(HasTypeParameters(generics,
FnSpace, FnSpace,
ItemRibKind), ItemRibKind),

View file

@ -1073,7 +1073,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
let blk = match tcx.map.find(id) { let blk = match tcx.map.find(id) {
Some(ast_map::NodeItem(i)) => { Some(ast_map::NodeItem(i)) => {
match i.node { match i.node {
ast::ItemFn(_, _, _, _, ref blk) => { ast::ItemFn(_, _, _, _, _, ref blk) => {
blk blk
} }
_ => tcx.sess.bug("unexpected item variant in has_nested_returns") _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
@ -1966,7 +1966,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
let from_external = ccx.external_srcs().borrow().contains_key(&item.id); let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
match item.node { match item.node {
ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => { ast::ItemFn(ref decl, _, _, abi, ref generics, ref body) => {
if !generics.is_type_parameterized() { if !generics.is_type_parameterized() {
let trans_everywhere = attr::requests_inline(&item.attrs); let trans_everywhere = attr::requests_inline(&item.attrs);
// Ignore `trans_everywhere` for cross-crate inlined items // Ignore `trans_everywhere` for cross-crate inlined items
@ -2336,7 +2336,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
} }
} }
ast::ItemFn(_, _, abi, _, _) => { ast::ItemFn(_, _, _, abi, _, _) => {
let sym = sym(); let sym = sym();
let llfn = if abi == Rust { let llfn = if abi == Rust {
register_fn(ccx, i.span, sym, i.id, ty) register_fn(ccx, i.span, sym, i.id, ty)

View file

@ -55,7 +55,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
trans_item(ccx, &**item); trans_item(ccx, &**item);
let linkage = match item.node { let linkage = match item.node {
ast::ItemFn(_, _, _, ref generics, _) => { ast::ItemFn(_, _, _, _, ref generics, _) => {
if generics.is_type_parameterized() { if generics.is_type_parameterized() {
// Generics have no symbol, so they can't be given any // Generics have no symbol, so they can't be given any
// linkage. // linkage.

View file

@ -177,7 +177,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ast_map::NodeItem(i) => { ast_map::NodeItem(i) => {
match *i { match *i {
ast::Item { ast::Item {
node: ast::ItemFn(ref decl, _, abi, _, ref body), node: ast::ItemFn(ref decl, _, _, abi, _, ref body),
.. ..
} => { } => {
let d = mk_lldecl(abi); let d = mk_lldecl(abi);

View file

@ -741,7 +741,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
&enum_definition.variants, &enum_definition.variants,
it.id); it.id);
} }
ast::ItemFn(_, _, _, _, _) => {} // entirely within check_item_body ast::ItemFn(..) => {} // entirely within check_item_body
ast::ItemImpl(_, _, _, _, _, ref impl_items) => { ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) { match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
@ -796,7 +796,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
ty::item_path_str(ccx.tcx, local_def(it.id))); ty::item_path_str(ccx.tcx, local_def(it.id)));
let _indenter = indenter(); let _indenter = indenter();
match it.node { match it.node {
ast::ItemFn(ref decl, _, _, _, ref body) => { ast::ItemFn(ref decl, _, _, _, _, ref body) => {
let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env); check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);

View file

@ -1440,7 +1440,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t); let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
ty::TypeScheme { ty: ty, generics: ty::Generics::empty() } ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
} }
ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty()); let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl); let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd)); let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
@ -1492,7 +1492,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ast::ItemStatic(..) | ast::ItemConst(..) => { ast::ItemStatic(..) | ast::ItemConst(..) => {
ty::GenericPredicates::empty() ty::GenericPredicates::empty()
} }
ast::ItemFn(_, _, _, ref ast_generics, _) => { ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
} }
ast::ItemTy(_, ref generics) => { ast::ItemTy(_, ref generics) => {

View file

@ -215,7 +215,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
match tcx.map.find(main_id) { match tcx.map.find(main_id) {
Some(ast_map::NodeItem(it)) => { Some(ast_map::NodeItem(it)) => {
match it.node { match it.node {
ast::ItemFn(_, _, _, ref ps, _) ast::ItemFn(_, _, _, _, ref ps, _)
if ps.is_parameterized() => { if ps.is_parameterized() => {
span_err!(ccx.tcx.sess, main_span, E0131, span_err!(ccx.tcx.sess, main_span, E0131,
"main function is not allowed to have type parameters"); "main function is not allowed to have type parameters");
@ -262,7 +262,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
match tcx.map.find(start_id) { match tcx.map.find(start_id) {
Some(ast_map::NodeItem(it)) => { Some(ast_map::NodeItem(it)) => {
match it.node { match it.node {
ast::ItemFn(_,_,_,ref ps,_) ast::ItemFn(_,_,_,_,ref ps,_)
if ps.is_parameterized() => { if ps.is_parameterized() => {
span_err!(tcx.sess, start_span, E0132, span_err!(tcx.sess, start_span, E0132,
"start function is not allowed to have type parameters"); "start function is not allowed to have type parameters");

View file

@ -175,6 +175,7 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) ->
decl: decl, decl: decl,
generics: (&t.generics, &predicates, subst::FnSpace).clean(cx), generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
unsafety: style, unsafety: style,
constness: ast::Constness::NotConst,
abi: abi, abi: abi,
} }
} }
@ -348,6 +349,7 @@ pub fn build_impl(cx: &DocContext,
}) => { }) => {
clean::MethodItem(clean::Method { clean::MethodItem(clean::Method {
unsafety: unsafety, unsafety: unsafety,
constness: ast::Constness::NotConst,
decl: decl, decl: decl,
self_: self_, self_: self_,
generics: generics, generics: generics,

View file

@ -989,6 +989,7 @@ pub struct Method {
pub generics: Generics, pub generics: Generics,
pub self_: SelfTy, pub self_: SelfTy,
pub unsafety: ast::Unsafety, pub unsafety: ast::Unsafety,
pub constness: ast::Constness,
pub decl: FnDecl, pub decl: FnDecl,
pub abi: abi::Abi pub abi: abi::Abi
} }
@ -1010,7 +1011,8 @@ impl Clean<Method> for ast::MethodSig {
Method { Method {
generics: self.generics.clean(cx), generics: self.generics.clean(cx),
self_: self.explicit_self.node.clean(cx), self_: self.explicit_self.node.clean(cx),
unsafety: self.unsafety.clone(), unsafety: self.unsafety,
constness: self.constness,
decl: decl, decl: decl,
abi: self.abi abi: self.abi
} }
@ -1075,7 +1077,8 @@ pub struct Function {
pub decl: FnDecl, pub decl: FnDecl,
pub generics: Generics, pub generics: Generics,
pub unsafety: ast::Unsafety, pub unsafety: ast::Unsafety,
pub abi: abi::Abi pub constness: ast::Constness,
pub abi: abi::Abi,
} }
impl Clean<Item> for doctree::Function { impl Clean<Item> for doctree::Function {
@ -1091,6 +1094,7 @@ impl Clean<Item> for doctree::Function {
decl: self.decl.clean(cx), decl: self.decl.clean(cx),
generics: self.generics.clean(cx), generics: self.generics.clean(cx),
unsafety: self.unsafety, unsafety: self.unsafety,
constness: self.constness,
abi: self.abi, abi: self.abi,
}), }),
} }
@ -2453,6 +2457,7 @@ impl Clean<Item> for ast::ForeignItem {
generics: generics.clean(cx), generics: generics.clean(cx),
unsafety: ast::Unsafety::Unsafe, unsafety: ast::Unsafety::Unsafe,
abi: abi::Rust, abi: abi::Rust,
constness: ast::Constness::NotConst,
}) })
} }
ast::ForeignItemStatic(ref ty, mutbl) => { ast::ForeignItemStatic(ref ty, mutbl) => {

View file

@ -133,6 +133,7 @@ pub struct Function {
pub vis: ast::Visibility, pub vis: ast::Visibility,
pub stab: Option<attr::Stability>, pub stab: Option<attr::Stability>,
pub unsafety: ast::Unsafety, pub unsafety: ast::Unsafety,
pub constness: ast::Constness,
pub whence: Span, pub whence: Span,
pub generics: ast::Generics, pub generics: ast::Generics,
pub abi: abi::Abi, pub abi: abi::Abi,

View file

@ -35,6 +35,10 @@ pub struct VisSpace(pub Option<ast::Visibility>);
/// space after it. /// space after it.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct UnsafetySpace(pub ast::Unsafety); pub struct UnsafetySpace(pub ast::Unsafety);
/// Similarly to VisSpace, this structure is used to render a function constness
/// with a space after it.
#[derive(Copy)]
pub struct ConstnessSpace(pub ast::Constness);
/// Wrapper struct for properly emitting a method declaration. /// 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::SelfTy, pub &'a clean::FnDecl);
/// Similar to VisSpace, but used for mutability /// Similar to VisSpace, but used for mutability
@ -63,6 +67,12 @@ impl UnsafetySpace {
} }
} }
impl ConstnessSpace {
pub fn get(&self) -> ast::Constness {
let ConstnessSpace(v) = *self; v
}
}
impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, item) in self.0.iter().enumerate() { for (i, item) in self.0.iter().enumerate() {
@ -607,6 +617,15 @@ impl fmt::Display for UnsafetySpace {
} }
} }
impl fmt::Display for ConstnessSpace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.get() {
ast::Constness::Const => write!(f, "const "),
ast::Constness::NotConst => Ok(())
}
}
}
impl fmt::Display for clean::Import { impl fmt::Display for clean::Import {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {

View file

@ -63,6 +63,7 @@ use clean;
use doctree; use doctree;
use fold::DocFolder; use fold::DocFolder;
use html::escape::Escape; use html::escape::Escape;
use html::format::{ConstnessSpace};
use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; use html::format::{TyParamBounds, WhereClause, href, AbiSpace};
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
use html::highlight; use html::highlight;
@ -1753,11 +1754,12 @@ fn item_static(w: &mut fmt::Formatter, it: &clean::Item,
fn item_function(w: &mut fmt::Formatter, it: &clean::Item, fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
f: &clean::Function) -> fmt::Result { f: &clean::Function) -> fmt::Result {
try!(write!(w, "<pre class='rust fn'>{vis}{unsafety}{abi}fn \ try!(write!(w, "<pre class='rust fn'>{vis}{unsafety}{abi}{constness}fn \
{name}{generics}{decl}{where_clause}</pre>", {name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(it.visibility), vis = VisSpace(it.visibility),
unsafety = UnsafetySpace(f.unsafety), unsafety = UnsafetySpace(f.unsafety),
abi = AbiSpace(f.abi), abi = AbiSpace(f.abi),
constness = ConstnessSpace(f.constness),
name = it.name.as_ref().unwrap(), name = it.name.as_ref().unwrap(),
generics = f.generics, generics = f.generics,
where_clause = WhereClause(&f.generics), where_clause = WhereClause(&f.generics),
@ -1957,10 +1959,16 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
link: AssocItemLink) -> fmt::Result { link: AssocItemLink) -> fmt::Result {
fn method(w: &mut fmt::Formatter, it: &clean::Item, fn method(w: &mut fmt::Formatter,
unsafety: ast::Unsafety, abi: abi::Abi, it: &clean::Item,
g: &clean::Generics, selfty: &clean::SelfTy, unsafety: ast::Unsafety,
d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result { constness: ast::Constness,
abi: abi::Abi,
g: &clean::Generics,
selfty: &clean::SelfTy,
d: &clean::FnDecl,
link: AssocItemLink)
-> fmt::Result {
use syntax::abi::Abi; use syntax::abi::Abi;
let name = it.name.as_ref().unwrap(); let name = it.name.as_ref().unwrap();
@ -1971,12 +1979,10 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
} }
}; };
write!(w, "{}{}fn <a href='{href}' class='fnname'>{name}</a>\ write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
{generics}{decl}{where_clause}", {generics}{decl}{where_clause}",
match unsafety { UnsafetySpace(unsafety),
ast::Unsafety::Unsafe => "unsafe ", ConstnessSpace(constness),
_ => "",
},
match abi { match abi {
Abi::Rust => String::new(), Abi::Rust => String::new(),
a => format!("extern {} ", a.to_string()) a => format!("extern {} ", a.to_string())
@ -1989,11 +1995,12 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
} }
match meth.inner { match meth.inner {
clean::TyMethodItem(ref m) => { clean::TyMethodItem(ref m) => {
method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl, method(w, meth, m.unsafety, ast::Constness::NotConst,
link) m.abi, &m.generics, &m.self_, &m.decl, link)
} }
clean::MethodItem(ref m) => { clean::MethodItem(ref m) => {
method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl, method(w, meth, m.unsafety, m.constness,
m.abi, &m.generics, &m.self_, &m.decl,
link) link)
} }
clean::AssociatedConstItem(ref ty, ref default) => { clean::AssociatedConstItem(ref ty, ref default) => {

View file

@ -123,7 +123,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
pub fn visit_fn(&mut self, item: &ast::Item, pub fn visit_fn(&mut self, item: &ast::Item,
name: ast::Ident, fd: &ast::FnDecl, name: ast::Ident, fd: &ast::FnDecl,
unsafety: &ast::Unsafety, abi: &abi::Abi, unsafety: &ast::Unsafety,
constness: ast::Constness,
_abi: &abi::Abi,
gen: &ast::Generics) -> Function { gen: &ast::Generics) -> Function {
debug!("Visiting fn"); debug!("Visiting fn");
Function { Function {
@ -136,6 +138,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span, whence: item.span,
generics: gen.clone(), generics: gen.clone(),
unsafety: *unsafety, unsafety: *unsafety,
constness: constness,
abi: *abi, abi: *abi,
} }
} }
@ -291,8 +294,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
om.enums.push(self.visit_enum_def(item, name, ed, gen)), om.enums.push(self.visit_enum_def(item, name, ed, gen)),
ast::ItemStruct(ref sd, ref gen) => ast::ItemStruct(ref sd, ref gen) =>
om.structs.push(self.visit_struct_def(item, name, &**sd, gen)), om.structs.push(self.visit_struct_def(item, name, &**sd, gen)),
ast::ItemFn(ref fd, ref pur, ref abi, ref gen, _) => ast::ItemFn(ref fd, unsafety, constness, ref abi, ref gen, _) =>
om.fns.push(self.visit_fn(item, name, &**fd, pur, abi, gen)), om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
constness, abi, gen)),
ast::ItemTy(ref ty, ref gen) => { ast::ItemTy(ref ty, ref gen) => {
let t = Typedef { let t = Typedef {
ty: ty.clone(), ty: ty.clone(),

View file

@ -1475,6 +1475,12 @@ pub enum Unsafety {
Normal, Normal,
} }
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Constness {
Const,
NotConst,
}
impl fmt::Display for Unsafety { impl fmt::Display for Unsafety {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(match *self { fmt::Display::fmt(match *self {
@ -1543,6 +1549,7 @@ pub enum ExplicitSelf_ {
pub type ExplicitSelf = Spanned<ExplicitSelf_>; pub type ExplicitSelf = Spanned<ExplicitSelf_>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
Constness,
pub struct Mod { pub struct Mod {
/// A span from the first token past `{` to the last token until `}`. /// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token /// For `mod foo;`, the inner span ranges from the first token
@ -1761,7 +1768,7 @@ pub enum Item_ {
/// A `const` item /// A `const` item
ItemConst(P<Ty>, P<Expr>), ItemConst(P<Ty>, P<Expr>),
/// A function declaration /// A function declaration
ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>), ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
/// A module /// A module
ItemMod(Mod), ItemMod(Mod),
/// An external module /// An external module

View file

@ -120,6 +120,7 @@ struct ItemFnParts<'a> {
ident: ast::Ident, ident: ast::Ident,
decl: &'a ast::FnDecl, decl: &'a ast::FnDecl,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
constness: ast::Constness,
abi: abi::Abi, abi: abi::Abi,
vis: ast::Visibility, vis: ast::Visibility,
generics: &'a ast::Generics, generics: &'a ast::Generics,
@ -180,7 +181,7 @@ impl<'a> FnLikeNode<'a> {
pub fn kind(self) -> visit::FnKind<'a> { pub fn kind(self) -> visit::FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> {
visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi, p.vis) visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi, p.constness, p.vis)
}; };
let closure = |_: ClosureParts| { let closure = |_: ClosureParts| {
visit::FkFnBlock visit::FkFnBlock
@ -204,10 +205,19 @@ impl<'a> FnLikeNode<'a> {
{ {
match self.node { match self.node {
ast_map::NodeItem(i) => match i.node { ast_map::NodeItem(i) => match i.node {
ast::ItemFn(ref decl, unsafety, abi, ref generics, ref block) => ast::ItemFn(ref decl, unsafety, constness, ref abi, ref generics, ref block) =>
item_fn(ItemFnParts{ item_fn(ItemFnParts {
ident: i.ident, decl: &**decl, unsafety: unsafety, body: &**block, id: i.id,
generics: generics, abi: abi, vis: i.vis, id: i.id, span: i.span ident: i.ident,
decl: &**decl,
unsafety: unsafety,
constness: constness,
body: &**block,
generics: generics,
abi: abi,
vis: i.vis,
constness: constness,
span: i.span
}), }),
_ => panic!("item FnLikeNode that is not fn-like"), _ => panic!("item FnLikeNode that is not fn-like"),
}, },

View file

@ -251,6 +251,7 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident
token::gensym_ident(&pretty[..]) token::gensym_ident(&pretty[..])
} }
_,
pub fn struct_field_visibility(field: ast::StructField) -> Visibility { pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
match field.node.kind { match field.node.kind {
ast::NamedField(_, v) | ast::UnnamedField(v) => v ast::NamedField(_, v) | ast::UnnamedField(v) => v

View file

@ -1034,6 +1034,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
Vec::new(), Vec::new(),
ast::ItemFn(self.fn_decl(inputs, output), ast::ItemFn(self.fn_decl(inputs, output),
ast::Unsafety::Normal, ast::Unsafety::Normal,
ast::Constness::NotConst,
abi::Rust, abi::Rust,
generics, generics,
body)) body))

View file

@ -880,6 +880,7 @@ impl<'a> MethodDef<'a> {
abi: abi, abi: abi,
explicit_self: explicit_self, explicit_self: explicit_self,
unsafety: unsafety, unsafety: unsafety,
constness: ast::Constness::NotConst,
decl: fn_decl decl: fn_decl
}, body_block) }, body_block)
}) })

View file

@ -513,11 +513,12 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
/// Expand item_underscore /// Expand item_underscore
fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ { fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ {
match item { match item {
ast::ItemFn(decl, fn_style, abi, generics, body) => { ast::ItemFn(decl, unsafety, constness, abi, generics, body) => {
let (rewritten_fn_decl, rewritten_body) let (rewritten_fn_decl, rewritten_body)
= expand_and_rename_fn_decl_and_block(decl, body, fld); = expand_and_rename_fn_decl_and_block(decl, body, fld);
let expanded_generics = fold::noop_fold_generics(generics,fld); let expanded_generics = fold::noop_fold_generics(generics,fld);
ast::ItemFn(rewritten_fn_decl, fn_style, abi, expanded_generics, rewritten_body) ast::ItemFn(rewritten_fn_decl, unsafety, constness, abi,
expanded_generics, rewritten_body)
} }
_ => noop_fold_item_underscore(item, fld) _ => noop_fold_item_underscore(item, fld)
} }

View file

@ -641,12 +641,12 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
span: Span, span: Span,
_node_id: NodeId) { _node_id: NodeId) {
match fn_kind { match fn_kind {
visit::FkItemFn(_, _, _, abi, _) if abi == Abi::RustIntrinsic => { visit::FkItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => {
self.gate_feature("intrinsics", self.gate_feature("intrinsics",
span, span,
"intrinsics are subject to change") "intrinsics are subject to change")
} }
visit::FkItemFn(_, _, _, abi, _) | visit::FkItemFn(_, _, _, _, abi, _) |
visit::FkMethod(_, &ast::MethodSig { abi, .. }, _) if abi == Abi::RustCall => { visit::FkMethod(_, &ast::MethodSig { abi, .. }, _) if abi == Abi::RustCall => {
self.gate_feature("unboxed_closures", self.gate_feature("unboxed_closures",
span, span,

View file

@ -917,10 +917,11 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
ItemConst(t, e) => { ItemConst(t, e) => {
ItemConst(folder.fold_ty(t), folder.fold_expr(e)) ItemConst(folder.fold_ty(t), folder.fold_expr(e))
} }
ItemFn(decl, unsafety, abi, generics, body) => { ItemFn(decl, unsafety, constness, abi, generics, body) => {
ItemFn( ItemFn(
folder.fold_fn_decl(decl), folder.fold_fn_decl(decl),
unsafety, unsafety,
constness,
abi, abi,
folder.fold_generics(generics), folder.fold_generics(generics),
folder.fold_block(body) folder.fold_block(body)
@ -1126,6 +1127,8 @@ pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> Method
unsafety: sig.unsafety, unsafety: sig.unsafety,
decl: folder.fold_fn_decl(sig.decl) decl: folder.fold_fn_decl(sig.decl)
} }
constness,
constness,
} }
pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {

View file

@ -17,7 +17,7 @@ use ast::{Public, Unsafety};
use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block}; use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block};
use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause}; use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
use ast::{ConstImplItem, ConstTraitItem, Crate, CrateConfig}; use ast::{Constness, ConstImplItem, ConstTraitItem, Crate, CrateConfig};
use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn}; use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn};
use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf}; use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
@ -1175,7 +1175,7 @@ impl<'a> Parser<'a> {
}; };
(ident, ConstTraitItem(ty, default)) (ident, ConstTraitItem(ty, default))
} else { } else {
let style = try!(p.parse_unsafety()); let unsafety = try!(p.parse_unsafety());
let abi = if try!(p.eat_keyword(keywords::Extern)) { let abi = if try!(p.eat_keyword(keywords::Extern)) {
try!(p.parse_opt_abi()).unwrap_or(abi::C) try!(p.parse_opt_abi()).unwrap_or(abi::C)
} else { } else {
@ -1195,7 +1195,8 @@ impl<'a> Parser<'a> {
generics.where_clause = try!(p.parse_where_clause()); generics.where_clause = try!(p.parse_where_clause());
let sig = ast::MethodSig { let sig = ast::MethodSig {
unsafety: style, unsafety: unsafety,
constness: ast::Constness::NotConst;
decl: d, decl: d,
generics: generics, generics: generics,
abi: abi, abi: abi,
@ -4359,12 +4360,16 @@ impl<'a> Parser<'a> {
} }
/// Parse an item-position function declaration. /// Parse an item-position function declaration.
fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> PResult<ItemInfo> { fn parse_item_fn(&mut self,
unsafety: Unsafety,
constness: Constness,
abi: abi::Abi)
-> PResult<ItemInfo> {
let (ident, mut generics) = try!(self.parse_fn_header()); let (ident, mut generics) = try!(self.parse_fn_header());
let decl = try!(self.parse_fn_decl(false)); let decl = try!(self.parse_fn_decl(false));
generics.where_clause = try!(self.parse_where_clause()); generics.where_clause = try!(self.parse_where_clause());
let (inner_attrs, body) = try!(self.parse_inner_attrs_and_block()); let (inner_attrs, body) = try!(self.parse_inner_attrs_and_block());
Ok((ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs))) Ok((ident, ItemFn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs)))
} }
/// Parse an impl item. /// Parse an impl item.
@ -4445,11 +4450,17 @@ impl<'a> Parser<'a> {
} }
Ok((token::special_idents::invalid, vec![], ast::MacImplItem(m))) Ok((token::special_idents::invalid, vec![], ast::MacImplItem(m)))
} else { } else {
let unsafety = try!(self.parse_unsafety()); let is_const_fn = !is_trait_impl && self.eat_keyword(keywords::Const);
let abi = if try!(self.eat_keyword(keywords::Extern)) { let (constness, unsafety, abi) = if is_const_fn {
try!(self.parse_opt_abi()).unwrap_or(abi::C) (Constness::Const, Unsafety::Normal, abi::Rust)
} else { } else {
abi::Rust let unsafety = try!(self.parse_unsafety());
let abi = if try!(self.eat_keyword(keywords::Extern)) {
try!(self.parse_opt_abi()).unwrap_or(abi::C)
} else {
abi::Rust
};
(Constness::NotConst, unsafety, abi)
}; };
try!(self.expect_keyword(keywords::Fn)); try!(self.expect_keyword(keywords::Fn));
let ident = try!(self.parse_ident()); let ident = try!(self.parse_ident());
@ -4464,6 +4475,7 @@ impl<'a> Parser<'a> {
abi: abi, abi: abi,
explicit_self: explicit_self, explicit_self: explicit_self,
unsafety: unsafety, unsafety: unsafety,
constness: constness;
decl: decl decl: decl
}, body))) }, body)))
} }
@ -5252,7 +5264,7 @@ impl<'a> Parser<'a> {
// EXTERN FUNCTION ITEM // EXTERN FUNCTION ITEM
let abi = opt_abi.unwrap_or(abi::C); let abi = opt_abi.unwrap_or(abi::C);
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
try!(self.parse_item_fn(Unsafety::Normal, abi)); try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi));
let last_span = self.last_span; let last_span = self.last_span;
let item = self.mk_item(lo, let item = self.mk_item(lo,
last_span.hi, last_span.hi,
@ -5287,6 +5299,21 @@ impl<'a> Parser<'a> {
return Ok(Some(item)); return Ok(Some(item));
} }
if try!(self.eat_keyword(keywords::Const) ){ if try!(self.eat_keyword(keywords::Const) ){
if self.check_keyword(keywords::Fn) {
// CONST FUNCTION ITEM
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust);
let last_span = self.last_span;
let item = self.mk_item(lo,
last_span.hi,
ident,
item_,
visibility,
maybe_append(attrs, extra_attrs));
return Ok(item);
}
// CONST ITEM // CONST ITEM
if try!(self.eat_keyword(keywords::Mut) ){ if try!(self.eat_keyword(keywords::Mut) ){
let last_span = self.last_span; let last_span = self.last_span;
@ -5340,7 +5367,7 @@ impl<'a> Parser<'a> {
// FUNCTION ITEM // FUNCTION ITEM
try!(self.bump()); try!(self.bump());
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
try!(self.parse_item_fn(Unsafety::Normal, abi::Rust)); try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi::Rust));
let last_span = self.last_span; let last_span = self.last_span;
let item = self.mk_item(lo, let item = self.mk_item(lo,
last_span.hi, last_span.hi,
@ -5361,7 +5388,7 @@ impl<'a> Parser<'a> {
}; };
try!(self.expect_keyword(keywords::Fn)); try!(self.expect_keyword(keywords::Fn));
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
try!(self.parse_item_fn(Unsafety::Unsafe, abi)); try!(self.parse_item_fn(Unsafety::Unsafe, Constness::NotConst, abi));
let last_span = self.last_span; let last_span = self.last_span;
let item = self.mk_item(lo, let item = self.mk_item(lo,
last_span.hi, last_span.hi,

View file

@ -378,12 +378,28 @@ pub fn ident_to_string(id: &ast::Ident) -> String {
to_string(|s| s.print_ident(*id)) to_string(|s| s.print_ident(*id))
} }
<<<<<<< HEAD
pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident, pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>, opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics) -> String { generics: &ast::Generics) -> String {
to_string(|s| { to_string(|s| {
||||||| parent of 61a958e... syntax: parse `const fn` for free functions and inherent methods.
pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics) -> String {
$to_string(|s| {
=======
pub fn fun_to_string(decl: &ast::FnDecl,
unsafety: ast::Unsafety,
constness: ast::Constness,
name: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics)
-> String {
$to_string(|s| {
>>>>>>> 61a958e... syntax: parse `const fn` for free functions and inherent methods.
try!(s.head("")); try!(s.head(""));
try!(s.print_fn(decl, unsafety, abi::Rust, Some(name), try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name),
generics, opt_explicit_self, ast::Inherited)); generics, opt_explicit_self, ast::Inherited));
try!(s.end()); // Close the head box try!(s.end()); // Close the head box
s.end() // Close the outer box s.end() // Close the outer box
@ -740,7 +756,8 @@ impl<'a> State<'a> {
match item.node { match item.node {
ast::ForeignItemFn(ref decl, ref generics) => { ast::ForeignItemFn(ref decl, ref generics) => {
try!(self.head("")); try!(self.head(""));
try!(self.print_fn(&**decl, ast::Unsafety::Normal, try!(self.print_fn(decl, ast::Unsafety::Normal,
ast::Constness::NotConst,
abi::Rust, Some(item.ident), abi::Rust, Some(item.ident),
generics, None, item.vis)); generics, None, item.vis));
try!(self.end()); // end head-ibox try!(self.end()); // end head-ibox
@ -866,11 +883,12 @@ impl<'a> State<'a> {
try!(word(&mut self.s, ";")); try!(word(&mut self.s, ";"));
try!(self.end()); // end the outer cbox try!(self.end()); // end the outer cbox
} }
ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => { ast::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
try!(self.head("")); try!(self.head(""));
try!(self.print_fn( try!(self.print_fn(
decl, decl,
unsafety, unsafety,
constness,
abi, abi,
Some(item.ident), Some(item.ident),
typarams, typarams,
@ -1241,6 +1259,7 @@ impl<'a> State<'a> {
-> io::Result<()> { -> io::Result<()> {
self.print_fn(&m.decl, self.print_fn(&m.decl,
m.unsafety, m.unsafety,
m.constness,
m.abi, m.abi,
Some(ident), Some(ident),
&m.generics, &m.generics,
@ -2335,12 +2354,13 @@ impl<'a> State<'a> {
pub fn print_fn(&mut self, pub fn print_fn(&mut self,
decl: &ast::FnDecl, decl: &ast::FnDecl,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
constness: ast::Constness,
abi: abi::Abi, abi: abi::Abi,
name: Option<ast::Ident>, name: Option<ast::Ident>,
generics: &ast::Generics, generics: &ast::Generics,
opt_explicit_self: Option<&ast::ExplicitSelf_>, opt_explicit_self: Option<&ast::ExplicitSelf_>,
vis: ast::Visibility) -> io::Result<()> { vis: ast::Visibility) -> io::Result<()> {
try!(self.print_fn_header_info(unsafety, abi, vis)); try!(self.print_fn_header_info(unsafety, constness, abi, vis));
if let Some(name) = name { if let Some(name) = name {
try!(self.nbsp()); try!(self.nbsp());
@ -2726,8 +2746,13 @@ impl<'a> State<'a> {
predicates: Vec::new(), predicates: Vec::new(),
}, },
}; };
try!(self.print_fn(decl, unsafety, abi, name, try!(self.print_fn(decl,
&generics, opt_explicit_self, unsafety,
ast::Constness::NotConst,
abi,
name,
generics,
opt_explicit_self,
ast::Inherited)); ast::Inherited));
self.end() self.end()
} }
@ -2976,11 +3001,17 @@ impl<'a> State<'a> {
pub fn print_fn_header_info(&mut self, pub fn print_fn_header_info(&mut self,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
constness: ast::Constness,
abi: abi::Abi, abi: abi::Abi,
vis: ast::Visibility) -> io::Result<()> { vis: ast::Visibility) -> io::Result<()> {
try!(word(&mut self.s, &visibility_qualified(vis, ""))); try!(word(&mut self.s, &visibility_qualified(vis, "")));
try!(self.print_unsafety(unsafety)); try!(self.print_unsafety(unsafety));
match constness {
ast::Constness::NotConst => {}
ast::Constness::Const => try!(self.word_nbsp("unsafe"))
}
if abi != abi::Rust { if abi != abi::Rust {
try!(self.word_nbsp("extern")); try!(self.word_nbsp("extern"));
try!(self.word_nbsp(&abi.to_string())); try!(self.word_nbsp(&abi.to_string()));
@ -3018,8 +3049,10 @@ mod tests {
variadic: false variadic: false
}; };
let generics = ast_util::empty_generics(); let generics = ast_util::empty_generics();
assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, abba_ident, assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
None, &generics), ast::Constness::NotConst,
abba_ident,
None, &generics),
"fn abba()"); "fn abba()");
} }

View file

@ -123,7 +123,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
let i = if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { let i = if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) {
match i.node { match i.node {
ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => { ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _, _) => {
let diag = self.cx.span_diagnostic; let diag = self.cx.span_diagnostic;
panic!(diag.span_fatal(i.span, "unsafe functions cannot be used for tests")); panic!(diag.span_fatal(i.span, "unsafe functions cannot be used for tests"));
} }
@ -320,7 +320,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
fn has_test_signature(i: &ast::Item) -> HasTestSignature { fn has_test_signature(i: &ast::Item) -> HasTestSignature {
match &i.node { match &i.node {
&ast::ItemFn(ref decl, _, _, ref generics, _) => { &ast::ItemFn(ref decl, _, _, _, ref generics, _) => {
let no_output = match decl.output { let no_output = match decl.output {
ast::DefaultReturn(..) => true, ast::DefaultReturn(..) => true,
ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true, ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
@ -356,7 +356,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
fn has_test_signature(i: &ast::Item) -> bool { fn has_test_signature(i: &ast::Item) -> bool {
match i.node { match i.node {
ast::ItemFn(ref decl, _, _, ref generics, _) => { ast::ItemFn(ref decl, _, _, _, ref generics, _) => {
let input_cnt = decl.inputs.len(); let input_cnt = decl.inputs.len();
let no_output = match decl.output { let no_output = match decl.output {
ast::DefaultReturn(..) => true, ast::DefaultReturn(..) => true,
@ -469,7 +469,9 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
let main_ret_ty = ecx.ty(sp, ast::TyTup(vec![])); let main_ret_ty = ecx.ty(sp, ast::TyTup(vec![]));
let main_body = ecx.block_all(sp, vec![call_test_main], None); let main_body = ecx.block_all(sp, vec![call_test_main], None);
let main = ast::ItemFn(ecx.fn_decl(vec![], main_ret_ty), let main = ast::ItemFn(ecx.fn_decl(vec![], main_ret_ty),
ast::Unsafety::Normal, ::abi::Rust, empty_generics(), main_body); ast::Unsafety::Normal,
ast::Constness::NotConst,
::abi::Rust, empty_generics(), main_body);
let main = P(ast::Item { let main = P(ast::Item {
ident: token::str_to_ident("main"), ident: token::str_to_ident("main"),
attrs: vec![main_attr], attrs: vec![main_attr],

View file

@ -35,7 +35,7 @@ use owned_slice::OwnedSlice;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo() /// fn foo() or extern "Abi" fn foo()
FkItemFn(Ident, &'a Generics, Unsafety, Abi, Visibility), FkItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, Visibility),
/// fn foo(&self) /// fn foo(&self)
FkMethod(Ident, &'a MethodSig, Option<Visibility>), FkMethod(Ident, &'a MethodSig, Option<Visibility>),
@ -246,8 +246,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_ty(&**typ); visitor.visit_ty(&**typ);
visitor.visit_expr(&**expr); visitor.visit_expr(&**expr);
} }
ItemFn(ref declaration, fn_style, abi, ref generics, ref body) => { ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
visitor.visit_fn(FkItemFn(item.ident, generics, fn_style, abi, item.vis), visitor.visit_fn(FkItemFn(item.ident, generics, unsafety,
constness, abi, item.vis),
&**declaration, &**declaration,
&**body, &**body,
item.span, item.span,