Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move E0379 check from typeck to ast validation #35480

Merged
merged 3 commits into from
Aug 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,8 +809,8 @@ impl<'a> LoweringContext<'a> {
}
}

fn lower_constness(&mut self, c: Constness) -> hir::Constness {
match c {
fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
match c.node {
Constness::Const => hir::Constness::Const,
Constness::NotConst => hir::Constness::NotConst,
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/hir/map/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@

pub use self::Code::*;

use hir as ast;
use hir::map::{self, Node};
use syntax::abi;
use hir::{Block, FnDecl};
use hir::intravisit::FnKind;
use syntax::abi;
use syntax::ast::{Attribute, Name, NodeId};
use hir as ast;
use syntax_pos::Span;
use hir::intravisit::FnKind;

/// 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).
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
= node_inner.expect("expect item fn");
let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
let (fn_decl, generics) = rebuilder.rebuild();
self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name, &generics, span);
self.give_expl_lifetime_param(
err, &fn_decl, unsafety, constness, name, &generics, span);
}

pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
Expand Down
23 changes: 23 additions & 0 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rustc::lint;
use rustc::session::Session;
use syntax::ast::*;
use syntax::attr;
use syntax::codemap::Spanned;
use syntax::parse::token::{self, keywords};
use syntax::visit::{self, Visitor};
use syntax_pos::Span;
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -146,6 +159,9 @@ impl<'a> Visitor for AstValidator<'a> {
self.invalid_visibility(&item.vis, item.span, None);
for impl_item in impl_items {
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, _, _) => {
Expand All @@ -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(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path");
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_passes/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
}

let mode = match fk {
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => Mode::ConstFn,
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _)
=> Mode::ConstFn,
FnKind::Method(_, m, _, _) => {
if m.constness == hir::Constness::Const {
Mode::ConstFn
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_passes/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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##"
A visibility qualifier was used when it was unnecessary. Erroneous code
examples:
Expand Down
26 changes: 2 additions & 24 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
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);
}
hir::MethodTraitItem(ref sig, None) => {
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
}
hir::MethodTraitItem(_, None) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertion here too

hir::ConstTraitItem(_, None) |
hir::TypeTraitItem(..) => {
// Nothing to do.
Expand All @@ -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>,
def_id: DefId,
item: &hir::Item) {
Expand Down Expand Up @@ -1027,9 +1007,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
err.emit()
}
}
hir::ImplItemKind::Method(ref sig, ref body) => {
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);

hir::ImplItemKind::Method(_, ref body) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertion here too

let impl_method = match ty_impl_item {
ty::MethodTraitItem(ref mti) => mti,
_ => span_bug!(impl_item.span, "non-method impl-item for method")
Expand Down
7 changes: 0 additions & 7 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3422,13 +3422,6 @@ containing the unsized type is the last and only unsized type field in the
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##"
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
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ pub struct MutTy {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MethodSig {
pub unsafety: Unsafety,
pub constness: Constness,
pub constness: Spanned<Constness>,
pub abi: Abi,
pub decl: P<FnDecl>,
pub generics: Generics,
Expand Down Expand Up @@ -1846,7 +1846,7 @@ pub enum ItemKind {
/// A function declaration (`fn` or `pub fn`).
///
/// 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`).
///
/// E.g. `mod foo;` or `mod foo { .. }`
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use abi::Abi;
use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
use attr;
use syntax_pos::{Span, DUMMY_SP, Pos};
use codemap::{respan, Spanned};
use codemap::{dummy_spanned, respan, Spanned};
use ext::base::ExtCtxt;
use parse::token::{self, keywords, InternedString};
use ptr::P;
Expand Down Expand Up @@ -1016,7 +1016,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
Vec::new(),
ast::ItemKind::Fn(self.fn_decl(inputs, output),
ast::Unsafety::Normal,
ast::Constness::NotConst,
dummy_spanned(ast::Constness::NotConst),
Abi::Rust,
generics,
body))
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use ast::{NodeId, PatKind};
use ast;
use attr;
use attr::AttrMetaMethods;
use codemap::CodeMap;
use codemap::{CodeMap, Spanned};
use syntax_pos::Span;
use errors::Handler;
use visit::{self, FnKind, Visitor};
Expand Down Expand Up @@ -1046,7 +1046,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
_node_id: NodeId) {
// check for const fn declarations
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");
}
_ => {
Expand Down Expand Up @@ -1078,7 +1078,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
if block.is_none() {
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");
}
}
Expand All @@ -1105,7 +1105,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
"associated constants are experimental")
}
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");
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,10 @@ mod tests {
variadic: false
}),
ast::Unsafety::Normal,
ast::Constness::NotConst,
Spanned {
span: sp(0,2),
node: ast::Constness::NotConst,
},
Abi::Rust,
ast::Generics{ // no idea on either of these:
lifetimes: Vec::new(),
Expand Down
33 changes: 24 additions & 9 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause};
use ast::{BinOpKind, UnOp};
use ast;
use codemap::{self, CodeMap, Spanned, spanned};
use codemap::{self, CodeMap, Spanned, spanned, respan};
use syntax_pos::{self, Span, BytePos, mk_sp};
use errors::{self, DiagnosticBuilder};
use ext::tt::macro_parser;
Expand Down Expand Up @@ -4768,7 +4768,7 @@ impl<'a> Parser<'a> {
/// Parse an item-position function declaration.
fn parse_item_fn(&mut self,
unsafety: Unsafety,
constness: Constness,
constness: Spanned<Constness>,
abi: abi::Abi)
-> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?;
Expand All @@ -4794,18 +4794,21 @@ impl<'a> Parser<'a> {
/// - `extern fn`
/// - etc
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 const_span = self.last_span;
let unsafety = self.parse_unsafety()?;
let (constness, unsafety, abi) = if is_const_fn {
(Constness::Const, unsafety, Abi::Rust)
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
Abi::Rust
};
(Constness::NotConst, unsafety, abi)
(respan(self.last_span, Constness::NotConst), unsafety, abi)
};
self.expect_keyword(keywords::Fn)?;
Ok((constness, unsafety, abi))
Expand Down Expand Up @@ -5704,9 +5707,12 @@ impl<'a> Parser<'a> {

if self.eat_keyword(keywords::Fn) {
// EXTERN FUNCTION ITEM
let fn_span = self.last_span;
let abi = opt_abi.unwrap_or(Abi::C);
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 item = self.mk_item(lo,
last_span.hi,
Expand Down Expand Up @@ -5740,6 +5746,7 @@ impl<'a> Parser<'a> {
return Ok(Some(item));
}
if self.eat_keyword(keywords::Const) {
let const_span = self.last_span;
if self.check_keyword(keywords::Fn)
|| (self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
Expand All @@ -5751,7 +5758,9 @@ impl<'a> Parser<'a> {
};
self.bump();
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 item = self.mk_item(lo,
last_span.hi,
Expand Down Expand Up @@ -5815,8 +5824,11 @@ impl<'a> Parser<'a> {
if self.check_keyword(keywords::Fn) {
// FUNCTION ITEM
self.bump();
let fn_span = self.last_span;
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 item = self.mk_item(lo,
last_span.hi,
Expand All @@ -5836,8 +5848,11 @@ impl<'a> Parser<'a> {
Abi::Rust
};
self.expect_keyword(keywords::Fn)?;
let fn_span = self.last_span;
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 item = self.mk_item(lo,
last_span.hi,
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ impl<'a> State<'a> {
try!(self.print_fn(
decl,
unsafety,
constness,
constness.node,
abi,
Some(item.ident),
typarams,
Expand Down Expand Up @@ -1518,7 +1518,7 @@ impl<'a> State<'a> {
-> io::Result<()> {
self.print_fn(&m.decl,
m.unsafety,
m.constness,
m.constness.node,
m.abi,
Some(ident),
&m.generics,
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use attr;
use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
use std::rc::Rc;

use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute};
use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned};
use errors;
use errors::snippet::{SnippetData};
use config;
Expand Down Expand Up @@ -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 = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty),
ast::Unsafety::Normal,
ast::Constness::NotConst,
dummy_spanned(ast::Constness::NotConst),
::abi::Abi::Rust, ast::Generics::default(), main_body);
let main = P(ast::Item {
ident: token::str_to_ident("main"),
Expand Down
Loading