Skip to content

Commit

Permalink
Rollup merge of rust-lang#35480 - KiChjang:e0379-bonus, r=nikomatsakis
Browse files Browse the repository at this point in the history
Move E0379 check from typeck to ast validation

Part of rust-lang#35233.
Extension of rust-lang#35338, rust-lang#35364.
Fixes rust-lang#35404.
  • Loading branch information
jseyfried committed Aug 28, 2016
2 parents 37f3017 + e46b09a commit bd38e89
Show file tree
Hide file tree
Showing 21 changed files with 131 additions and 66 deletions.
4 changes: 2 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,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) |
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) => {
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 @@ -1122,7 +1122,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 @@ -1820,7 +1820,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 @@ -4770,7 +4770,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 @@ -4796,18 +4796,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 @@ -5706,9 +5709,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 @@ -5742,6 +5748,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 @@ -5753,7 +5760,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 @@ -5817,8 +5826,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 @@ -5838,8 +5850,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 @@ -1185,7 +1185,7 @@ impl<'a> State<'a> {
try!(self.print_fn(
decl,
unsafety,
constness,
constness.node,
abi,
Some(item.ident),
typarams,
Expand Down Expand Up @@ -1519,7 +1519,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

0 comments on commit bd38e89

Please sign in to comment.