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:
commit
bd38e890ee
21 changed files with 133 additions and 68 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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]) {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 { .. }`
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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>),
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() { }
|
||||||
|
|
25
src/test/ui/mismatched_types/const-fn-in-trait.rs
Normal file
25
src/test/ui/mismatched_types/const-fn-in-trait.rs
Normal 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() { }
|
14
src/test/ui/mismatched_types/const-fn-in-trait.stderr
Normal file
14
src/test/ui/mismatched_types/const-fn-in-trait.stderr
Normal 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue