diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-05-05 08:47:04 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-05-21 11:47:30 -0400 |
| commit | df93deab10850d52252829770895b0249b0d7f1e (patch) | |
| tree | 4e8a7657c0d2714319800a07c485bff473043bad /src/libsyntax | |
| parent | fb206bf34a2463317b9fa1ef3c0ff35d921f8920 (diff) | |
| download | rust-df93deab10850d52252829770895b0249b0d7f1e.tar.gz rust-df93deab10850d52252829770895b0249b0d7f1e.zip | |
Make various fixes:
- add feature gate - add basic tests - adjust parser to eliminate conflict between `const fn` and associated constants - allow `const fn` in traits/trait-impls, but forbid later in type check - correct some merge conflicts
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/blocks.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 68 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
9 files changed, 76 insertions, 50 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bd7fb441bf5..5b03b3bf038 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1215,6 +1215,7 @@ pub struct TypeField { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct MethodSig { pub unsafety: Unsafety, + pub constness: Constness, pub abi: Abi, pub decl: P<FnDecl>, pub generics: Generics, @@ -1549,7 +1550,6 @@ pub enum ExplicitSelf_ { pub type ExplicitSelf = Spanned<ExplicitSelf_>; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] - Constness, pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 58627b37a87..99686d54ce5 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -189,7 +189,7 @@ impl<'a> FnLikeNode<'a> { pub fn kind(self) -> visit::FnKind<'a> { let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { - visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi, p.constness, p.vis) + visit::FkItemFn(p.ident, p.generics, p.unsafety, p.constness, p.abi, p.vis) }; let closure = |_: ClosureParts| { visit::FkFnBlock @@ -213,13 +213,12 @@ impl<'a> FnLikeNode<'a> { { match self.node { ast_map::NodeItem(i) => match i.node { - ast::ItemFn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => + ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) => item_fn(ItemFnParts { id: i.id, ident: i.ident, decl: &**decl, unsafety: unsafety, - constness: constness, body: &**block, generics: generics, abi: abi, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 45db8cc7b25..bb8096f2770 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -251,7 +251,6 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident token::gensym_ident(&pretty[..]) } - _, pub fn struct_field_visibility(field: ast::StructField) -> Visibility { match field.node.kind { ast::NamedField(_, v) | ast::UnnamedField(v) => v @@ -441,7 +440,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { self.operation.visit_id(node_id); match function_kind { - visit::FkItemFn(_, generics, _, _, _) => { + visit::FkItemFn(_, generics, _, _, _, _) => { self.visit_generics_helper(generics) } visit::FkMethod(_, sig, _) => { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 912cc841a64..5f0efd14eec 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1396,6 +1396,7 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>, abi: sig.abi, explicit_self: fld.fold_explicit_self(sig.explicit_self), unsafety: sig.unsafety, + constness: sig.constness, decl: rewritten_fn_decl }, rewritten_body) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 84546679b23..2b749dd890e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -155,6 +155,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // Allows the definition of associated constants in `trait` or `impl` // blocks. ("associated_consts", "1.0.0", Active), + + // Allows the definition of `const fn` functions. + ("const_fn", "1.2.0", Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -640,6 +643,19 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { block: &'v ast::Block, span: Span, _node_id: NodeId) { + // check for const fn declarations + match fn_kind { + visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => { + self.gate_feature("const_fn", span, "const fn is unstable"); + } + _ => { + // stability of const fn methods are covered in + // visit_trait_item and visit_impl_item below; this is + // because default methods don't pass through this + // point. + } + } + match fn_kind { visit::FkItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => { self.gate_feature("intrinsics", @@ -664,6 +680,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { ti.span, "associated constants are experimental") } + ast::MethodTraitItem(ref sig, _) => { + if sig.constness == ast::Constness::Const { + self.gate_feature("const_fn", ti.span, "const fn is unstable"); + } + } _ => {} } visit::walk_trait_item(self, ti); @@ -676,6 +697,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { ii.span, "associated constants are experimental") } + ast::MethodImplItem(ref sig, _) => { + if sig.constness == ast::Constness::Const { + self.gate_feature("const_fn", ii.span, "const fn is unstable"); + } + } _ => {} } visit::walk_impl_item(self, ii); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c2382eaf82e..7806a27c53e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1125,10 +1125,9 @@ pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> Method 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) } - constness, - constness, } pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6fba8fd47fd..eb6420165da 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1160,7 +1160,8 @@ impl<'a> Parser<'a> { let TyParam {ident, bounds, default, ..} = try!(p.parse_ty_param()); try!(p.expect(&token::Semi)); (ident, TypeTraitItem(bounds, default)) - } else if try!(p.eat_keyword(keywords::Const)) { + } else if p.is_const_item() { + try!(p.expect_keyword(keywords::Const)); let ident = try!(p.parse_ident()); try!(p.expect(&token::Colon)); let ty = try!(p.parse_ty_sum()); @@ -1175,13 +1176,7 @@ impl<'a> Parser<'a> { }; (ident, ConstTraitItem(ty, default)) } else { - let unsafety = try!(p.parse_unsafety()); - let abi = if try!(p.eat_keyword(keywords::Extern)) { - try!(p.parse_opt_abi()).unwrap_or(abi::C) - } else { - abi::Rust - }; - try!(p.expect_keyword(keywords::Fn)); + let (constness, unsafety, abi) = try!(p.parse_fn_front_matter()); let ident = try!(p.parse_ident()); let mut generics = try!(p.parse_generics()); @@ -1196,7 +1191,7 @@ impl<'a> Parser<'a> { generics.where_clause = try!(p.parse_where_clause()); let sig = ast::MethodSig { unsafety: unsafety, - constness: ast::Constness::NotConst; + constness: constness, decl: d, generics: generics, abi: abi, @@ -4372,6 +4367,36 @@ impl<'a> Parser<'a> { Ok((ident, ItemFn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs))) } + /// true if we are looking at `const ID`, false for things like `const fn` etc + pub fn is_const_item(&mut self) -> bool { + self.token.is_keyword(keywords::Const) && + !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) + } + + /// parses all the "front matter" for a `fn` declaration, up to + /// and including the `fn` keyword: + /// + /// - `const fn` + /// - `unsafe fn` + /// - `extern fn` + /// - etc + pub fn parse_fn_front_matter(&mut self) -> PResult<(ast::Constness, ast::Unsafety, abi::Abi)> { + let is_const_fn = try!(self.eat_keyword(keywords::Const)); + let (constness, unsafety, abi) = if is_const_fn { + (Constness::Const, Unsafety::Normal, abi::Rust) + } else { + 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)); + Ok((constness, unsafety, abi)) + } + /// Parse an impl item. pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> { maybe_whole!(no_clone self, NtImplItem); @@ -4385,7 +4410,8 @@ impl<'a> Parser<'a> { let typ = try!(self.parse_ty_sum()); try!(self.expect(&token::Semi)); (name, TypeImplItem(typ)) - } else if try!(self.eat_keyword(keywords::Const)) { + } else if self.is_const_item() { + try!(self.expect_keyword(keywords::Const)); let name = try!(self.parse_ident()); try!(self.expect(&token::Colon)); let typ = try!(self.parse_ty_sum()); @@ -4450,19 +4476,7 @@ impl<'a> Parser<'a> { } Ok((token::special_idents::invalid, vec![], ast::MacImplItem(m))) } else { - let is_const_fn = !is_trait_impl && self.eat_keyword(keywords::Const); - let (constness, unsafety, abi) = if is_const_fn { - (Constness::Const, Unsafety::Normal, abi::Rust) - } else { - 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)); + let (constness, unsafety, abi) = try!(self.parse_fn_front_matter()); let ident = try!(self.parse_ident()); let mut generics = try!(self.parse_generics()); let (explicit_self, decl) = try!(self.parse_fn_decl_with_self(|p| { @@ -4475,7 +4489,7 @@ impl<'a> Parser<'a> { abi: abi, explicit_self: explicit_self, unsafety: unsafety, - constness: constness; + constness: constness, decl: decl }, body))) } @@ -5301,9 +5315,9 @@ impl<'a> Parser<'a> { if try!(self.eat_keyword(keywords::Const) ){ if self.check_keyword(keywords::Fn) { // CONST FUNCTION ITEM - self.bump(); + try!(self.bump()); let (ident, item_, extra_attrs) = - self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust); + try!(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, @@ -5311,7 +5325,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Ok(Some(item)); } // CONST ITEM diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5889b968f41..0b211cd0733 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -378,17 +378,6 @@ pub fn ident_to_string(id: &ast::Ident) -> String { to_string(|s| s.print_ident(*id)) } -<<<<<<< HEAD -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| { -||||||| 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, @@ -396,8 +385,7 @@ pub fn fun_to_string(decl: &ast::FnDecl, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics) -> String { - $to_string(|s| { ->>>>>>> 61a958e... syntax: parse `const fn` for free functions and inherent methods. + to_string(|s| { try!(s.head("")); try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name), generics, opt_explicit_self, ast::Inherited)); @@ -2751,7 +2739,7 @@ impl<'a> State<'a> { ast::Constness::NotConst, abi, name, - generics, + &generics, opt_explicit_self, ast::Inherited)); self.end() diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b9b81bd7c6f..61fddd6bed8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -605,7 +605,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, walk_fn_decl(visitor, function_declaration); match function_kind { - FkItemFn(_, generics, _, _, _) => { + FkItemFn(_, generics, _, _, _, _) => { visitor.visit_generics(generics); } FkMethod(_, sig, _) => { |
