Skip to content

Commit df93dea

Browse files
committed
Make various fixes:
- add feature gate - add basic tests - adjust parser to eliminate conflict between `const fn` and associated constants - allow `const fn` in traits/trait-impls, but forbid later in type check - correct some merge conflicts
1 parent fb206bf commit df93dea

36 files changed

+322
-108
lines changed

src/librustc/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -845,5 +845,6 @@ register_diagnostics! {
845845
E0314, // closure outlives stack frame
846846
E0315, // cannot invoke closure outside of its lifetime
847847
E0316, // nested quantification of lifetimes
848-
E0370 // discriminant overflow
848+
E0370, // discriminant overflow
849+
E0378 // method calls limited to constant inherent methods
849850
}

src/librustc/metadata/encoder.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -879,12 +879,11 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
879879
let any_types = !scheme.generics.types.is_empty();
880880
let needs_inline = any_types || is_default_impl ||
881881
attr::requests_inline(&impl_item.attrs);
882-
let constness = ast_method.pe_constness();
883-
if needs_inline || constness == ast::Constness::Const {
882+
if needs_inline || sig.constness == ast::Constness::Const {
884883
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
885884
impl_item));
886885
}
887-
encode_constness(rbml_w, constness);
886+
encode_constness(rbml_w, sig.constness);
888887
if !any_types {
889888
encode_symbol(ecx, rbml_w, m.def_id.node);
890889
}

src/librustc/middle/check_const.rs

+11-24
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use util::nodemap::NodeMap;
3636
use util::ppaux::Repr;
3737

3838
use syntax::ast;
39-
use syntax::ast_util::PostExpansionMethod;
4039
use syntax::codemap::Span;
4140
use syntax::visit::{self, Visitor};
4241

@@ -149,16 +148,16 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
149148
Entry::Occupied(entry) => return *entry.get(),
150149
Entry::Vacant(entry) => {
151150
// Prevent infinite recursion on re-entry.
152-
entry.insert(PURE_CONST);
151+
entry.insert(ConstQualif::empty());
153152
}
154153
}
155154

156155
let mode = match fk {
157-
visit::FkItemFn(_, _, _, ast::Constness::Const, _) => {
156+
visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
158157
Mode::ConstFn
159158
}
160-
visit::FkMethod(_, _, m) => {
161-
if m.pe_constness() == ast::Constness::Const {
159+
visit::FkMethod(_, m, _) => {
160+
if m.constness == ast::Constness::Const {
162161
Mode::ConstFn
163162
} else {
164163
Mode::Var
@@ -189,7 +188,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
189188

190189
// Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
191190
// and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
192-
let qualif = qualif & (NON_ZERO_SIZED | PREFER_IN_PLACE);
191+
let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
193192

194193
self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
195194
qualif
@@ -210,7 +209,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
210209
self.add_qualif(qualif);
211210

212211
if ty::type_contents(self.tcx, ret_ty).interior_unsafe() {
213-
self.add_qualif(MUTABLE_MEM);
212+
self.add_qualif(ConstQualif::MUTABLE_MEM);
214213
}
215214

216215
true
@@ -366,7 +365,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
366365
macro in const?!")
367366
}
368367
};
369-
self.add_qualif(NOT_CONST);
368+
self.add_qualif(ConstQualif::NOT_CONST);
370369
if self.mode != Mode::Var {
371370
span_err!(self.tcx.sess, span, E0016,
372371
"blocks in {}s are limited to items and \
@@ -602,7 +601,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
602601
}
603602
Some(def::DefLocal(_)) if v.mode == Mode::ConstFn => {
604603
// Sadly, we can't determine whether the types are zero-sized.
605-
v.add_qualif(NOT_CONST | NON_ZERO_SIZED);
604+
v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
606605
}
607606
def => {
608607
v.add_qualif(ConstQualif::NOT_CONST);
@@ -651,20 +650,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
651650
}
652651
}
653652
}
654-
ast::ExprBlock(ref block) => {
655-
// Check all statements in the block
656-
let mut block_span_err = |span| {
657-
v.add_qualif(ConstQualif::NOT_CONST);
658-
if v.mode != Mode::Var {
659-
span_err!(v.tcx.sess, e.span, E0015,
660-
"function calls in {}s are limited to \
661-
constant functions, \
662-
struct and enum constructors", v.msg());
663-
}
664-
}
665-
}
666653
ast::ExprMethodCall(..) => {
667-
let method_did = match v.tcx.method_map.borrow()[method_call].origin {
654+
let method_did = match v.tcx.method_map.borrow()[&method_call].origin {
668655
ty::MethodStatic(did) => Some(did),
669656
_ => None
670657
};
@@ -673,9 +660,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
673660
None => false
674661
};
675662
if !is_const {
676-
v.add_qualif(NOT_CONST);
663+
v.add_qualif(ConstQualif::NOT_CONST);
677664
if v.mode != Mode::Var {
678-
span_err!(v.tcx.sess, e.span, E0021,
665+
span_err!(v.tcx.sess, e.span, E0378,
679666
"method calls in {}s are limited to \
680667
constant inherent methods", v.msg());
681668
}

src/librustc/middle/const_eval.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use util::ppaux::Repr;
2525

2626
use syntax::ast::{self, Expr};
2727
use syntax::ast_map::blocks::FnLikeNode;
28-
use syntax::ast_util::{self, PostExpansionMethod};
28+
use syntax::ast_util;
2929
use syntax::codemap::Span;
3030
use syntax::feature_gate;
3131
use syntax::parse::token::InternedString;
@@ -216,17 +216,17 @@ fn inline_const_fn_from_external_crate(tcx: &ty::ctxt, def_id: ast::DefId)
216216
let fn_id = match csearch::maybe_get_item_ast(tcx, def_id,
217217
box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
218218
csearch::FoundAst::Found(&ast::IIItem(ref item)) => Some(item.id),
219-
csearch::FoundAst::Found(&ast::IIImplItem(_, ast::MethodImplItem(ref m))) => Some(m.id),
219+
csearch::FoundAst::Found(&ast::IIImplItem(_, ref item)) => Some(item.id),
220220
_ => None
221221
};
222222
tcx.extern_const_fns.borrow_mut().insert(def_id,
223223
fn_id.unwrap_or(ast::DUMMY_NODE_ID));
224224
fn_id
225225
}
226226

227-
pub fn lookup_const_fn_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
228-
-> Option<FnLikeNode<'a>> {
229-
227+
pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: ast::DefId)
228+
-> Option<FnLikeNode<'tcx>>
229+
{
230230
let fn_id = if !ast_util::is_local(def_id) {
231231
if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) {
232232
fn_id
@@ -243,11 +243,11 @@ pub fn lookup_const_fn_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
243243
};
244244

245245
match fn_like.kind() {
246-
visit::FkItemFn(_, _, _, ast::Constness::Const, _) => {
246+
visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
247247
Some(fn_like)
248248
}
249-
visit::FkMethod(_, _, m) => {
250-
if m.pe_constness() == ast::Constness::Const {
249+
visit::FkMethod(_, m, _) => {
250+
if m.constness == ast::Constness::Const {
251251
Some(fn_like)
252252
} else {
253253
None

src/librustc/middle/effect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
8787
block: &'v ast::Block, span: Span, _: ast::NodeId) {
8888

8989
let (is_item_fn, is_unsafe_fn) = match fn_kind {
90-
visit::FkItemFn(_, _, unsafety, _, _) =>
90+
visit::FkItemFn(_, _, unsafety, _, _, _) =>
9191
(true, unsafety == ast::Unsafety::Unsafe),
9292
visit::FkMethod(_, sig, _) =>
9393
(true, sig.unsafety == ast::Unsafety::Unsafe),

src/librustc/middle/resolve_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ impl<'a> LifetimeContext<'a> {
447447
fb: &'b ast::Block,
448448
_span: Span) {
449449
match fk {
450-
visit::FkItemFn(_, generics, _, _, _) => {
450+
visit::FkItemFn(_, generics, _, _, _, _) => {
451451
visit::walk_fn_decl(self, fd);
452452
self.visit_generics(generics);
453453
}

src/librustc/middle/stability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use syntax::{attr, visit};
2323
use syntax::ast;
2424
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
2525
use syntax::ast::{Item, Generics, StructField};
26-
use syntax::ast_util::{is_local, PostExpansionMethod};
26+
use syntax::ast_util::is_local;
2727
use syntax::attr::{Stability, AttrMetaMethods};
2828
use syntax::visit::{FnKind, Visitor};
2929
use syntax::feature_gate::emit_feature_err;

src/librustc_lint/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ impl LintPass for UnsafeCode {
13241324
fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
13251325
_: &ast::Block, span: Span, _: ast::NodeId) {
13261326
match fk {
1327-
visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _, _) =>
1327+
visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _, _, _) =>
13281328
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
13291329

13301330
visit::FkMethod(_, sig, _) => {

src/librustc_resolve/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
245245
_: Span,
246246
node_id: NodeId) {
247247
let rib_kind = match function_kind {
248-
visit::FkItemFn(_, generics, _, _, _) => {
248+
visit::FkItemFn(_, generics, _, _, _, _) => {
249249
self.visit_generics(generics);
250250
ItemRibKind
251251
}

src/librustc_trans/save/dump_csv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
11671167
&location[..],
11681168
self.cur_scope);
11691169
}
1170-
ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
1170+
ast::ItemFn(ref decl, _, _, _, ref ty_params, ref body) =>
11711171
self.process_fn(item, &**decl, ty_params, &**body),
11721172
ast::ItemStatic(ref typ, _, ref expr) =>
11731173
self.process_static_or_const_item(item, typ, expr),

src/librustc_trans/trans/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use syntax::{ast, ast_util};
4141
use syntax::parse::token;
4242
use syntax::ptr::P;
4343

44-
type FnArgMap<'a> = Option<&'a NodeMap<ValueRef>>;
44+
pub type FnArgMap<'a> = Option<&'a NodeMap<ValueRef>>;
4545

4646
pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
4747
-> ValueRef {
@@ -863,7 +863,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
863863
_ => break
864864
};
865865
}
866-
let def = cx.tcx().def_map.borrow()[callee.id].full_def();
866+
let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
867867
let arg_vals = map_list(args);
868868
match def {
869869
def::DefFn(did, _) | def::DefMethod(did, _) => {
@@ -893,7 +893,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
893893
ast::ExprMethodCall(_, _, ref args) => {
894894
let arg_vals = map_list(args);
895895
let method_call = ty::MethodCall::expr(e.id);
896-
let method_did = match cx.tcx().method_map.borrow()[method_call].origin {
896+
let method_did = match cx.tcx().method_map.borrow()[&method_call].origin {
897897
ty::MethodStatic(did) => did,
898898
_ => cx.sess().span_bug(e.span, "expected a const method def")
899899
};

src/librustc_trans/trans/debuginfo/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
232232
}
233233

234234
match item.node {
235-
ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => {
235+
ast::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
236236
(item.ident.name, fn_decl, generics, top_level_block, item.span, true)
237237
}
238238
_ => {

src/librustc_typeck/check/mod.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -830,11 +830,15 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
830830
check_const(ccx, trait_item.span, &*expr, trait_item.id)
831831
}
832832
ast::MethodTraitItem(ref sig, Some(ref body)) => {
833+
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
834+
833835
check_method_body(ccx, &trait_def.generics, sig, body,
834836
trait_item.id, trait_item.span);
835837
}
838+
ast::MethodTraitItem(ref sig, None) => {
839+
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
840+
}
836841
ast::ConstTraitItem(_, None) |
837-
ast::MethodTraitItem(_, None) |
838842
ast::TypeTraitItem(..) => {
839843
// Nothing to do.
840844
}
@@ -845,6 +849,20 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
845849
}
846850
}
847851

852+
fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
853+
span: Span,
854+
constness: ast::Constness)
855+
{
856+
match constness {
857+
ast::Constness::NotConst => {
858+
// good
859+
}
860+
ast::Constness::Const => {
861+
span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
862+
}
863+
}
864+
}
865+
848866
fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
849867
generics: &ast::Generics,
850868
item: &ast::Item) {
@@ -966,7 +984,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
966984
}
967985
}
968986
}
969-
ast::MethodImplItem(_, ref body) => {
987+
ast::MethodImplItem(ref sig, ref body) => {
988+
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
989+
970990
let impl_method_def_id = local_def(impl_item.id);
971991
let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
972992
impl_method_def_id);

src/librustc_typeck/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ register_diagnostics! {
11131113
// fields need coercions
11141114
E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
11151115
// between structures
1116-
E0377 // the trait `CoerceUnsized` may only be implemented for a coercion
1116+
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
11171117
// between structures with the same definition
1118+
E0379 // trait fns cannot be const
11181119
}

src/librustdoc/clean/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1352,15 +1352,18 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
13521352
generics: generics,
13531353
self_: self_,
13541354
decl: decl,
1355-
abi: self.fty.abi
1355+
abi: self.fty.abi,
1356+
1357+
// trait methods canot (currently, at least) be const
1358+
constness: ast::Constness::NotConst,
13561359
})
13571360
} else {
13581361
TyMethodItem(TyMethod {
13591362
unsafety: self.fty.unsafety,
13601363
generics: generics,
13611364
self_: self_,
13621365
decl: decl,
1363-
abi: self.fty.abi
1366+
abi: self.fty.abi,
13641367
})
13651368
};
13661369

src/librustdoc/html/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub struct VisSpace(pub Option<ast::Visibility>);
3737
pub struct UnsafetySpace(pub ast::Unsafety);
3838
/// Similarly to VisSpace, this structure is used to render a function constness
3939
/// with a space after it.
40-
#[derive(Copy)]
40+
#[derive(Copy, Clone)]
4141
pub struct ConstnessSpace(pub ast::Constness);
4242
/// Wrapper struct for properly emitting a method declaration.
4343
pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);

src/librustdoc/visit_ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
125125
name: ast::Ident, fd: &ast::FnDecl,
126126
unsafety: &ast::Unsafety,
127127
constness: ast::Constness,
128-
_abi: &abi::Abi,
128+
abi: &abi::Abi,
129129
gen: &ast::Generics) -> Function {
130130
debug!("Visiting fn");
131131
Function {
@@ -294,7 +294,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
294294
om.enums.push(self.visit_enum_def(item, name, ed, gen)),
295295
ast::ItemStruct(ref sd, ref gen) =>
296296
om.structs.push(self.visit_struct_def(item, name, &**sd, gen)),
297-
ast::ItemFn(ref fd, unsafety, constness, ref abi, ref gen, _) =>
297+
ast::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
298298
om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
299299
constness, abi, gen)),
300300
ast::ItemTy(ref ty, ref gen) => {

src/libsyntax/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,7 @@ pub struct TypeField {
12151215
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
12161216
pub struct MethodSig {
12171217
pub unsafety: Unsafety,
1218+
pub constness: Constness,
12181219
pub abi: Abi,
12191220
pub decl: P<FnDecl>,
12201221
pub generics: Generics,
@@ -1549,7 +1550,6 @@ pub enum ExplicitSelf_ {
15491550
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
15501551

15511552
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
1552-
Constness,
15531553
pub struct Mod {
15541554
/// A span from the first token past `{` to the last token until `}`.
15551555
/// For `mod foo;`, the inner span ranges from the first token

0 commit comments

Comments
 (0)