1
Fork 0

Rollup merge of #35480 - KiChjang:e0379-bonus, r=nikomatsakis

Move E0379 check from typeck to ast validation

Part of #35233.
Extension of #35338, #35364.
Fixes #35404.
This commit is contained in:
Jeffrey Seyfried 2016-08-28 10:32:45 +00:00
commit bd38e890ee
21 changed files with 133 additions and 68 deletions

View file

@ -804,8 +804,8 @@ impl<'a> LoweringContext<'a> {
} }
} }
fn lower_constness(&mut self, c: Constness) -> hir::Constness { fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
match c { match c.node {
Constness::Const => hir::Constness::Const, Constness::Const => hir::Constness::Const,
Constness::NotConst => hir::Constness::NotConst, Constness::NotConst => hir::Constness::NotConst,
} }

View file

@ -23,13 +23,13 @@
pub use self::Code::*; pub use self::Code::*;
use hir::map::{self, Node};
use syntax::abi;
use hir::{Block, FnDecl};
use syntax::ast::{Attribute, Name, NodeId};
use hir as ast; use hir as ast;
use syntax_pos::Span; use hir::map::{self, Node};
use hir::{Block, FnDecl};
use hir::intravisit::FnKind; use hir::intravisit::FnKind;
use syntax::abi;
use syntax::ast::{Attribute, Name, NodeId};
use syntax_pos::Span;
/// An FnLikeNode is a Node that is like a fn, in that it has a decl /// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc). /// and a body (as well as a NodeId, a span, etc).

View file

@ -1030,7 +1030,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
= node_inner.expect("expect item fn"); = node_inner.expect("expect item fn");
let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver); let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
let (fn_decl, generics) = rebuilder.rebuild(); let (fn_decl, generics) = rebuilder.rebuild();
self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name, &generics, span); self.give_expl_lifetime_param(
err, &fn_decl, unsafety, constness, name, &generics, span);
} }
pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) { pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {

View file

@ -20,6 +20,7 @@ use rustc::lint;
use rustc::session::Session; use rustc::session::Session;
use syntax::ast::*; use syntax::ast::*;
use syntax::attr; use syntax::attr;
use syntax::codemap::Spanned;
use syntax::parse::token::{self, keywords}; use syntax::parse::token::{self, keywords};
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
use syntax_pos::Span; use syntax_pos::Span;
@ -69,6 +70,18 @@ impl<'a> AstValidator<'a> {
} }
} }
} }
fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
match constness.node {
Constness::Const => {
struct_span_err!(self.session, constness.span, E0379,
"trait fns cannot be declared const")
.span_label(constness.span, &format!("trait fns cannot be const"))
.emit();
}
_ => {}
}
}
} }
impl<'a> Visitor for AstValidator<'a> { impl<'a> Visitor for AstValidator<'a> {
@ -146,6 +159,9 @@ impl<'a> Visitor for AstValidator<'a> {
self.invalid_visibility(&item.vis, item.span, None); self.invalid_visibility(&item.vis, item.span, None);
for impl_item in impl_items { for impl_item in impl_items {
self.invalid_visibility(&impl_item.vis, impl_item.span, None); self.invalid_visibility(&impl_item.vis, impl_item.span, None);
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
self.check_trait_fn_not_const(sig.constness);
}
} }
} }
ItemKind::Impl(_, _, _, None, _, _) => { ItemKind::Impl(_, _, _, None, _, _) => {
@ -169,6 +185,13 @@ impl<'a> Visitor for AstValidator<'a> {
} }
} }
} }
ItemKind::Trait(_, _, _, ref trait_items) => {
for trait_item in trait_items {
if let TraitItemKind::Method(ref sig, _) = trait_item.node {
self.check_trait_fn_not_const(sig.constness);
}
}
}
ItemKind::Mod(_) => { ItemKind::Mod(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584). // Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path"); attr::first_attr_value_str_by_name(&item.attrs, "path");

View file

@ -147,7 +147,8 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
} }
let mode = match fk { let mode = match fk {
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => Mode::ConstFn, FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _)
=> Mode::ConstFn,
FnKind::Method(_, m, _, _) => { FnKind::Method(_, m, _, _) => {
if m.constness == hir::Constness::Const { if m.constness == hir::Constness::Const {
Mode::ConstFn Mode::ConstFn

View file

@ -176,6 +176,13 @@ fn some_func() {
``` ```
"##, "##,
E0379: r##"
Trait methods cannot be declared `const` by design. For more information, see
[RFC 911].
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
"##,
E0449: r##" E0449: r##"
A visibility qualifier was used when it was unnecessary. Erroneous code A visibility qualifier was used when it was unnecessary. Erroneous code
examples: examples:

View file

@ -836,13 +836,9 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
check_const(ccx, &expr, trait_item.id) check_const(ccx, &expr, trait_item.id)
} }
hir::MethodTraitItem(ref sig, Some(ref body)) => { hir::MethodTraitItem(ref sig, Some(ref body)) => {
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
check_bare_fn(ccx, &sig.decl, body, trait_item.id); check_bare_fn(ccx, &sig.decl, body, trait_item.id);
} }
hir::MethodTraitItem(ref sig, None) => { hir::MethodTraitItem(_, None) |
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
}
hir::ConstTraitItem(_, None) | hir::ConstTraitItem(_, None) |
hir::TypeTraitItem(..) => { hir::TypeTraitItem(..) => {
// Nothing to do. // Nothing to do.
@ -854,22 +850,6 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
} }
} }
fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
span: Span,
constness: hir::Constness)
{
match constness {
hir::Constness::NotConst => {
// good
}
hir::Constness::Const => {
struct_span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const")
.span_label(span, &format!("trait fns cannot be const"))
.emit()
}
}
}
fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def_id: DefId, def_id: DefId,
item: &hir::Item) { item: &hir::Item) {
@ -1027,9 +1007,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
err.emit() err.emit()
} }
} }
hir::ImplItemKind::Method(ref sig, ref body) => { hir::ImplItemKind::Method(_, ref body) => {
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
let impl_method = match ty_impl_item { let impl_method = match ty_impl_item {
ty::MethodTraitItem(ref mti) => mti, ty::MethodTraitItem(ref mti) => mti,
_ => span_bug!(impl_item.span, "non-method impl-item for method") _ => span_bug!(impl_item.span, "non-method impl-item for method")

View file

@ -3422,13 +3422,6 @@ containing the unsized type is the last and only unsized type field in the
struct. struct.
"##, "##,
E0379: r##"
Trait methods cannot be declared `const` by design. For more information, see
[RFC 911].
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
"##,
E0380: r##" E0380: r##"
Default impls are only allowed for traits with no methods or associated items. Default impls are only allowed for traits with no methods or associated items.
For more information see the [opt-in builtin traits RFC](https://github.com/rust For more information see the [opt-in builtin traits RFC](https://github.com/rust

View file

@ -1122,7 +1122,7 @@ pub struct MutTy {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MethodSig { pub struct MethodSig {
pub unsafety: Unsafety, pub unsafety: Unsafety,
pub constness: Constness, pub constness: Spanned<Constness>,
pub abi: Abi, pub abi: Abi,
pub decl: P<FnDecl>, pub decl: P<FnDecl>,
pub generics: Generics, pub generics: Generics,
@ -1820,7 +1820,7 @@ pub enum ItemKind {
/// A function declaration (`fn` or `pub fn`). /// A function declaration (`fn` or `pub fn`).
/// ///
/// E.g. `fn foo(bar: usize) -> usize { .. }` /// E.g. `fn foo(bar: usize) -> usize { .. }`
Fn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>), Fn(P<FnDecl>, Unsafety, Spanned<Constness>, Abi, Generics, P<Block>),
/// A module declaration (`mod` or `pub mod`). /// A module declaration (`mod` or `pub mod`).
/// ///
/// E.g. `mod foo;` or `mod foo { .. }` /// E.g. `mod foo;` or `mod foo { .. }`

View file

@ -12,7 +12,7 @@ use abi::Abi;
use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
use attr; use attr;
use syntax_pos::{Span, DUMMY_SP, Pos}; use syntax_pos::{Span, DUMMY_SP, Pos};
use codemap::{respan, Spanned}; use codemap::{dummy_spanned, respan, Spanned};
use ext::base::ExtCtxt; use ext::base::ExtCtxt;
use parse::token::{self, keywords, InternedString}; use parse::token::{self, keywords, InternedString};
use ptr::P; use ptr::P;
@ -1016,7 +1016,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
Vec::new(), Vec::new(),
ast::ItemKind::Fn(self.fn_decl(inputs, output), ast::ItemKind::Fn(self.fn_decl(inputs, output),
ast::Unsafety::Normal, ast::Unsafety::Normal,
ast::Constness::NotConst, dummy_spanned(ast::Constness::NotConst),
Abi::Rust, Abi::Rust,
generics, generics,
body)) body))

View file

@ -30,7 +30,7 @@ use ast::{NodeId, PatKind};
use ast; use ast;
use attr; use attr;
use attr::AttrMetaMethods; use attr::AttrMetaMethods;
use codemap::CodeMap; use codemap::{CodeMap, Spanned};
use syntax_pos::Span; use syntax_pos::Span;
use errors::Handler; use errors::Handler;
use visit::{self, FnKind, Visitor}; use visit::{self, FnKind, Visitor};
@ -1046,7 +1046,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
_node_id: NodeId) { _node_id: NodeId) {
// check for const fn declarations // check for const fn declarations
match fn_kind { match fn_kind {
FnKind::ItemFn(_, _, _, ast::Constness::Const, _, _) => { FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _) => {
gate_feature_post!(&self, const_fn, span, "const fn is unstable"); gate_feature_post!(&self, const_fn, span, "const fn is unstable");
} }
_ => { _ => {
@ -1078,7 +1078,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
if block.is_none() { if block.is_none() {
self.check_abi(sig.abi, ti.span); self.check_abi(sig.abi, ti.span);
} }
if sig.constness == ast::Constness::Const { if sig.constness.node == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
} }
} }
@ -1105,7 +1105,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
"associated constants are experimental") "associated constants are experimental")
} }
ast::ImplItemKind::Method(ref sig, _) => { ast::ImplItemKind::Method(ref sig, _) => {
if sig.constness == ast::Constness::Const { if sig.constness.node == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
} }
} }

View file

@ -937,7 +937,10 @@ mod tests {
variadic: false variadic: false
}), }),
ast::Unsafety::Normal, ast::Unsafety::Normal,
ast::Constness::NotConst, Spanned {
span: sp(0,2),
node: ast::Constness::NotConst,
},
Abi::Rust, Abi::Rust,
ast::Generics{ // no idea on either of these: ast::Generics{ // no idea on either of these:
lifetimes: Vec::new(), lifetimes: Vec::new(),

View file

@ -39,7 +39,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause}; use ast::{Visibility, WhereClause};
use ast::{BinOpKind, UnOp}; use ast::{BinOpKind, UnOp};
use ast; use ast;
use codemap::{self, CodeMap, Spanned, spanned}; use codemap::{self, CodeMap, Spanned, spanned, respan};
use syntax_pos::{self, Span, BytePos, mk_sp}; use syntax_pos::{self, Span, BytePos, mk_sp};
use errors::{self, DiagnosticBuilder}; use errors::{self, DiagnosticBuilder};
use ext::tt::macro_parser; use ext::tt::macro_parser;
@ -4770,7 +4770,7 @@ impl<'a> Parser<'a> {
/// Parse an item-position function declaration. /// Parse an item-position function declaration.
fn parse_item_fn(&mut self, fn parse_item_fn(&mut self,
unsafety: Unsafety, unsafety: Unsafety,
constness: Constness, constness: Spanned<Constness>,
abi: abi::Abi) abi: abi::Abi)
-> PResult<'a, ItemInfo> { -> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?; let (ident, mut generics) = self.parse_fn_header()?;
@ -4796,18 +4796,21 @@ impl<'a> Parser<'a> {
/// - `extern fn` /// - `extern fn`
/// - etc /// - etc
pub fn parse_fn_front_matter(&mut self) pub fn parse_fn_front_matter(&mut self)
-> PResult<'a, (ast::Constness, ast::Unsafety, abi::Abi)> { -> PResult<'a, (Spanned<ast::Constness>,
ast::Unsafety,
abi::Abi)> {
let is_const_fn = self.eat_keyword(keywords::Const); let is_const_fn = self.eat_keyword(keywords::Const);
let const_span = self.last_span;
let unsafety = self.parse_unsafety()?; let unsafety = self.parse_unsafety()?;
let (constness, unsafety, abi) = if is_const_fn { let (constness, unsafety, abi) = if is_const_fn {
(Constness::Const, unsafety, Abi::Rust) (respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else { } else {
let abi = if self.eat_keyword(keywords::Extern) { let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C) self.parse_opt_abi()?.unwrap_or(Abi::C)
} else { } else {
Abi::Rust Abi::Rust
}; };
(Constness::NotConst, unsafety, abi) (respan(self.last_span, Constness::NotConst), unsafety, abi)
}; };
self.expect_keyword(keywords::Fn)?; self.expect_keyword(keywords::Fn)?;
Ok((constness, unsafety, abi)) Ok((constness, unsafety, abi))
@ -5706,9 +5709,12 @@ impl<'a> Parser<'a> {
if self.eat_keyword(keywords::Fn) { if self.eat_keyword(keywords::Fn) {
// EXTERN FUNCTION ITEM // EXTERN FUNCTION ITEM
let fn_span = self.last_span;
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) =
self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi)?; self.parse_item_fn(Unsafety::Normal,
respan(fn_span, 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,
@ -5742,6 +5748,7 @@ impl<'a> Parser<'a> {
return Ok(Some(item)); return Ok(Some(item));
} }
if self.eat_keyword(keywords::Const) { if self.eat_keyword(keywords::Const) {
let const_span = self.last_span;
if self.check_keyword(keywords::Fn) if self.check_keyword(keywords::Fn)
|| (self.check_keyword(keywords::Unsafe) || (self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) { && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
@ -5753,7 +5760,9 @@ impl<'a> Parser<'a> {
}; };
self.bump(); self.bump();
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety, Constness::Const, Abi::Rust)?; self.parse_item_fn(unsafety,
respan(const_span, Constness::Const),
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,
@ -5817,8 +5826,11 @@ impl<'a> Parser<'a> {
if self.check_keyword(keywords::Fn) { if self.check_keyword(keywords::Fn) {
// FUNCTION ITEM // FUNCTION ITEM
self.bump(); self.bump();
let fn_span = self.last_span;
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal, Constness::NotConst, Abi::Rust)?; self.parse_item_fn(Unsafety::Normal,
respan(fn_span, 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,
@ -5838,8 +5850,11 @@ impl<'a> Parser<'a> {
Abi::Rust Abi::Rust
}; };
self.expect_keyword(keywords::Fn)?; self.expect_keyword(keywords::Fn)?;
let fn_span = self.last_span;
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Unsafe, Constness::NotConst, abi)?; self.parse_item_fn(Unsafety::Unsafe,
respan(fn_span, 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

@ -1185,7 +1185,7 @@ impl<'a> State<'a> {
try!(self.print_fn( try!(self.print_fn(
decl, decl,
unsafety, unsafety,
constness, constness.node,
abi, abi,
Some(item.ident), Some(item.ident),
typarams, typarams,
@ -1519,7 +1519,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.constness.node,
m.abi, m.abi,
Some(ident), Some(ident),
&m.generics, &m.generics,

View file

@ -24,7 +24,7 @@ use attr;
use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos}; use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
use std::rc::Rc; use std::rc::Rc;
use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute}; use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned};
use errors; use errors;
use errors::snippet::{SnippetData}; use errors::snippet::{SnippetData};
use config; use config;
@ -485,7 +485,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
let main_body = ecx.block(sp, vec![call_test_main]); let main_body = ecx.block(sp, vec![call_test_main]);
let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty), let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty),
ast::Unsafety::Normal, ast::Unsafety::Normal,
ast::Constness::NotConst, dummy_spanned(ast::Constness::NotConst),
::abi::Abi::Rust, ast::Generics::default(), main_body); ::abi::Abi::Rust, ast::Generics::default(), main_body);
let main = P(ast::Item { let main = P(ast::Item {
ident: token::str_to_ident("main"), ident: token::str_to_ident("main"),

View file

@ -31,7 +31,7 @@ use codemap::Spanned;
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo() /// fn foo() or extern "Abi" fn foo()
ItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, &'a Visibility), ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility),
/// fn foo(&self) /// fn foo(&self)
Method(Ident, &'a MethodSig, Option<&'a Visibility>), Method(Ident, &'a MethodSig, Option<&'a Visibility>),

View file

@ -197,7 +197,7 @@ use syntax::attr;
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder; use syntax::ext::build::AstBuilder;
use syntax::codemap::{self, respan}; use syntax::codemap::{self, dummy_spanned, respan};
use syntax::util::move_map::MoveMap; use syntax::util::move_map::MoveMap;
use syntax::parse::token::{InternedString, keywords}; use syntax::parse::token::{InternedString, keywords};
use syntax::ptr::P; use syntax::ptr::P;
@ -902,7 +902,8 @@ impl<'a> MethodDef<'a> {
generics: fn_generics, generics: fn_generics,
abi: abi, abi: abi,
unsafety: unsafety, unsafety: unsafety,
constness: ast::Constness::NotConst, constness:
dummy_spanned(ast::Constness::NotConst),
decl: fn_decl, decl: fn_decl,
}, },
body_block), body_block),

View file

@ -21,7 +21,7 @@ trait Foo {
impl Foo for u32 { impl Foo for u32 {
const fn f() -> u32 { 22 } const fn f() -> u32 { 22 }
//~^ ERROR E0379 //~^ ERROR trait fns cannot be declared const
//~| NOTE trait fns cannot be const //~| NOTE trait fns cannot be const
} }

View file

@ -14,8 +14,12 @@
#![feature(const_fn)] #![feature(const_fn)]
trait Foo { trait Foo {
const fn f() -> u32; //~ ERROR trait fns cannot be declared const const fn f() -> u32;
const fn g() -> u32 { 0 } //~ ERROR trait fns cannot be declared const //~^ ERROR trait fns cannot be declared const
//~| NOTE trait fns cannot be const
const fn g() -> u32 { 0 }
//~^ ERROR trait fns cannot be declared const
//~| NOTE trait fns cannot be const
} }
fn main() { } fn main() { }

View file

@ -0,0 +1,25 @@
// Copyright 2015 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.
// rustc-env:RUST_NEW_ERROR_FORMAT
#![feature(const_fn)]
trait Foo {
fn f() -> u32;
const fn g();
}
impl Foo for u32 {
const fn f() -> u32 { 22 }
fn g() {}
}
fn main() { }

View file

@ -0,0 +1,14 @@
error[E0379]: trait fns cannot be declared const
--> $DIR/const-fn-in-trait.rs:17:5
|
17 | const fn g();
| ^^^^^ trait fns cannot be const
error[E0379]: trait fns cannot be declared const
--> $DIR/const-fn-in-trait.rs:21:5
|
21 | const fn f() -> u32 { 22 }
| ^^^^^ trait fns cannot be const
error: aborting due to 2 previous errors