From 1e9e798ccea7f70480c3bcc86e271ca2191b8675 Mon Sep 17 00:00:00 2001
From: Keith Yeung <kungfukeith11@gmail.com>
Date: Sun, 7 Aug 2016 14:33:35 -0700
Subject: [PATCH 1/3] Move E0379 check from typeck to ast validation

---
 src/librustc_passes/ast_validation.rs         | 21 +++++++++++++++
 src/librustc_passes/diagnostics.rs            |  7 +++++
 src/librustc_typeck/check/mod.rs              | 26 ++-----------------
 src/librustc_typeck/diagnostics.rs            |  7 -----
 src/test/compile-fail/const-fn-mismatch.rs    |  2 +-
 .../compile-fail/const-fn-not-in-trait.rs     |  8 ++++--
 6 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 46124d0f97359..f10f1fba4c25e 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -69,6 +69,17 @@ impl<'a> AstValidator<'a> {
             }
         }
     }
+
+    fn check_trait_fn_not_const(&self, span: Span, constness: Constness) {
+        match constness {
+            Constness::Const => {
+                struct_span_err!(self.session, span, E0379, "trait fns cannot be declared const")
+                    .span_label(span, &format!("trait fns cannot be const"))
+                    .emit();
+            }
+            _ => {}
+        }
+    }
 }
 
 impl<'a> Visitor for AstValidator<'a> {
@@ -146,6 +157,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(impl_item.span, sig.constness);
+                    }
                 }
             }
             ItemKind::Impl(_, _, _, None, _, _) => {
@@ -169,6 +183,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(trait_item.span, 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");
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 7049040678e39..89b8aa81411b3 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -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:
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e972a5ca7fb38..c8d2f9144dcc6 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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.
@@ -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) {
@@ -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")
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 8bb5efdcad2c3..3f1374db36936 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -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
diff --git a/src/test/compile-fail/const-fn-mismatch.rs b/src/test/compile-fail/const-fn-mismatch.rs
index 92568b27f7c1d..7ea72e23779ec 100644
--- a/src/test/compile-fail/const-fn-mismatch.rs
+++ b/src/test/compile-fail/const-fn-mismatch.rs
@@ -21,7 +21,7 @@ trait Foo {
 
 impl Foo for u32 {
     const fn f() -> u32 { 22 }
-    //~^ ERROR E0379
+    //~^ ERROR trait fns cannot be declared const
     //~| NOTE trait fns cannot be const
 }
 
diff --git a/src/test/compile-fail/const-fn-not-in-trait.rs b/src/test/compile-fail/const-fn-not-in-trait.rs
index 191f3e025270f..257d4d5ee9921 100644
--- a/src/test/compile-fail/const-fn-not-in-trait.rs
+++ b/src/test/compile-fail/const-fn-not-in-trait.rs
@@ -14,8 +14,12 @@
 #![feature(const_fn)]
 
 trait Foo {
-    const fn f() -> u32; //~ ERROR trait fns cannot be declared const
-    const fn g() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
+    const fn f() -> u32;
+    //~^ 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() { }

From aa5c4bb05d1d5d10a2fdbb80f098ba06e73214b9 Mon Sep 17 00:00:00 2001
From: Keith Yeung <kungfukeith11@gmail.com>
Date: Wed, 10 Aug 2016 16:20:12 -0700
Subject: [PATCH 2/3] Change Constness to Spanned<Constness>

---
 src/librustc/hir/lowering.rs              |  4 +--
 src/librustc/hir/map/blocks.rs            |  6 ++---
 src/librustc/infer/error_reporting.rs     |  3 ++-
 src/librustc_passes/ast_validation.rs     | 14 +++++-----
 src/librustc_passes/consts.rs             |  3 ++-
 src/libsyntax/ast.rs                      |  4 +--
 src/libsyntax/ext/build.rs                |  4 +--
 src/libsyntax/feature_gate.rs             |  8 +++---
 src/libsyntax/parse/mod.rs                |  5 +++-
 src/libsyntax/parse/parser.rs             | 33 ++++++++++++++++-------
 src/libsyntax/print/pprust.rs             |  4 +--
 src/libsyntax/test.rs                     |  4 +--
 src/libsyntax/visit.rs                    |  2 +-
 src/libsyntax_ext/deriving/generic/mod.rs |  5 ++--
 14 files changed, 61 insertions(+), 38 deletions(-)

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b45610c3fe820..be5eb7f83769e 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -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,
         }
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 50e8c6e7ab842..4487234885692 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -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).
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 9169d299e040b..eab7f37382e67 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -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]) {
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index f10f1fba4c25e..dde1a4a759563 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -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;
@@ -70,11 +71,12 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_trait_fn_not_const(&self, span: Span, constness: Constness) {
-        match constness {
+    fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
+        match constness.node {
             Constness::Const => {
-                struct_span_err!(self.session, span, E0379, "trait fns cannot be declared const")
-                    .span_label(span, &format!("trait fns cannot be 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();
             }
             _ => {}
@@ -158,7 +160,7 @@ impl<'a> Visitor for AstValidator<'a> {
                 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(impl_item.span, sig.constness);
+                        self.check_trait_fn_not_const(sig.constness);
                     }
                 }
             }
@@ -186,7 +188,7 @@ 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(trait_item.span, sig.constness);
+                        self.check_trait_fn_not_const(sig.constness);
                     }
                 }
             }
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 4aae6d690c4df..2d1b6e1315f8b 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -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
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f8a5cb0b04a8e..427a44d2e740c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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,
@@ -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 { .. }`
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5d6429f7bdfff..14c7e46246d0d 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -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;
@@ -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))
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index dc68e06463464..9114c31d29816 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -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};
@@ -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");
             }
             _ => {
@@ -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");
                 }
             }
@@ -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");
                 }
             }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index cd1fdcfe9d130..a89dc80df4b08 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -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(),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 1646246069ead..757c0779e352a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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;
@@ -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()?;
@@ -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))
@@ -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,
@@ -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))) {
@@ -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,
@@ -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,
@@ -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,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a77c678248b56..4c83440306306 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1184,7 +1184,7 @@ impl<'a> State<'a> {
                 try!(self.print_fn(
                     decl,
                     unsafety,
-                    constness,
+                    constness.node,
                     abi,
                     Some(item.ident),
                     typarams,
@@ -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,
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index faf6a17a15045..cbf9aa8c6c17f 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -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;
@@ -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"),
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 582412119caa8..d75110b2654ce 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -31,7 +31,7 @@ use codemap::Spanned;
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
     /// 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)
     Method(Ident, &'a MethodSig, Option<&'a Visibility>),
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index cd49e7ec9d2c6..809f444b9936e 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -197,7 +197,7 @@ use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 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::parse::token::{InternedString, keywords};
 use syntax::ptr::P;
@@ -901,7 +901,8 @@ impl<'a> MethodDef<'a> {
                                                 generics: fn_generics,
                                                 abi: abi,
                                                 unsafety: unsafety,
-                                                constness: ast::Constness::NotConst,
+                                                constness:
+                                                    dummy_spanned(ast::Constness::NotConst),
                                                 decl: fn_decl,
                                             },
                                             body_block),

From e46b09a1f9051a65544dee08f4d8d749d474d586 Mon Sep 17 00:00:00 2001
From: Keith Yeung <kungfukeith11@gmail.com>
Date: Fri, 12 Aug 2016 15:47:42 -0700
Subject: [PATCH 3/3] Add UI test for E0379

---
 .../ui/mismatched_types/const-fn-in-trait.rs  | 25 +++++++++++++++++++
 .../mismatched_types/const-fn-in-trait.stderr | 14 +++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 src/test/ui/mismatched_types/const-fn-in-trait.rs
 create mode 100644 src/test/ui/mismatched_types/const-fn-in-trait.stderr

diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.rs b/src/test/ui/mismatched_types/const-fn-in-trait.rs
new file mode 100644
index 0000000000000..5e44030eab71a
--- /dev/null
+++ b/src/test/ui/mismatched_types/const-fn-in-trait.rs
@@ -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() { }
diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
new file mode 100644
index 0000000000000..f7b7635e41aec
--- /dev/null
+++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
@@ -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
+