Skip to content

Commit ba0e1cd

Browse files
committed
Auto merge of #25609 - nikomatsakis:const-fn, r=pnkfelix
This is a port of @eddyb's `const-fn` branch. I rebased it, tweaked a few things, and added tests as well as a feature gate. The set of tests is still pretty rudimentary, I'd appreciate suggestions on new tests to write. Also, a double-check that the feature-gate covers all necessary cases. One question: currently, the feature-gate allows the *use* of const functions from stable code, just not the definition. This seems to fit our usual strategy, and implies that we might (perhaps) allow some constant functions in libstd someday, even before stabilizing const-fn, if we were willing to commit to the existence of const fns but found some details of their impl unsatisfactory. r? @pnkfelix
2 parents cc56c20 + 82ded3c commit ba0e1cd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+848
-212
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/common.rs

+2
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,5 @@ pub const tag_item_super_predicates: usize = 0xa3;
262262
pub const tag_defaulted_trait: usize = 0xa4;
263263

264264
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
265+
266+
pub const tag_items_data_item_constness: usize = 0xa6;

src/librustc/metadata/csearch.rs

+5
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,11 @@ pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
384384
decoder::is_typedef(&*cdata, did.node)
385385
}
386386

387+
pub fn is_const_fn(cstore: &cstore::CStore, did: ast::DefId) -> bool {
388+
let cdata = cstore.get_crate_data(did.krate);
389+
decoder::is_const_fn(&*cdata, did.node)
390+
}
391+
387392
pub fn get_stability(cstore: &cstore::CStore,
388393
def: ast::DefId)
389394
-> Option<attr::Stability> {

src/librustc/metadata/decoder.rs

+21
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,19 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
178178
}
179179
}
180180

181+
fn fn_constness(item: rbml::Doc) -> ast::Constness {
182+
match reader::maybe_get_doc(item, tag_items_data_item_constness) {
183+
None => ast::Constness::NotConst,
184+
Some(constness_doc) => {
185+
match reader::doc_as_u8(constness_doc) as char {
186+
'c' => ast::Constness::Const,
187+
'n' => ast::Constness::NotConst,
188+
_ => panic!("unknown constness character")
189+
}
190+
}
191+
}
192+
}
193+
181194
fn item_sort(item: rbml::Doc) -> Option<char> {
182195
let mut ret = None;
183196
reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
@@ -1525,6 +1538,14 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
15251538
}
15261539
}
15271540

1541+
pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
1542+
let item_doc = lookup_item(id, cdata.data());
1543+
match fn_constness(item_doc) {
1544+
ast::Constness::Const => true,
1545+
ast::Constness::NotConst => false,
1546+
}
1547+
}
1548+
15281549
fn doc_generics<'tcx>(base_doc: rbml::Doc,
15291550
tcx: &ty::ctxt<'tcx>,
15301551
cdata: Cmd,

src/librustc/metadata/encoder.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,16 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
581581
rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
582582
}
583583

584+
fn encode_constness(rbml_w: &mut Encoder, constness: ast::Constness) {
585+
rbml_w.start_tag(tag_items_data_item_constness);
586+
let ch = match constness {
587+
ast::Constness::Const => 'c',
588+
ast::Constness::NotConst => 'n',
589+
};
590+
rbml_w.wr_str(&ch.to_string());
591+
rbml_w.end_tag();
592+
}
593+
584594
fn encode_explicit_self(rbml_w: &mut Encoder,
585595
explicit_self: &ty::ExplicitSelfCategory) {
586596
let tag = tag_item_trait_method_explicit_self;
@@ -867,10 +877,13 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
867877
encode_attributes(rbml_w, &impl_item.attrs);
868878
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
869879
let any_types = !scheme.generics.types.is_empty();
870-
if any_types || is_default_impl || attr::requests_inline(&impl_item.attrs) {
880+
let needs_inline = any_types || is_default_impl ||
881+
attr::requests_inline(&impl_item.attrs);
882+
if needs_inline || sig.constness == ast::Constness::Const {
871883
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
872884
impl_item));
873885
}
886+
encode_constness(rbml_w, sig.constness);
874887
if !any_types {
875888
encode_symbol(ecx, rbml_w, m.def_id.node);
876889
}
@@ -1049,7 +1062,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10491062
encode_stability(rbml_w, stab);
10501063
rbml_w.end_tag();
10511064
}
1052-
ast::ItemFn(ref decl, _, _, ref generics, _) => {
1065+
ast::ItemFn(ref decl, _, constness, _, ref generics, _) => {
10531066
add_to_index(item, rbml_w, index);
10541067
rbml_w.start_tag(tag_items_data_item);
10551068
encode_def_id(rbml_w, def_id);
@@ -1059,12 +1072,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
10591072
encode_name(rbml_w, item.ident.name);
10601073
encode_path(rbml_w, path);
10611074
encode_attributes(rbml_w, &item.attrs);
1062-
if tps_len > 0 || attr::requests_inline(&item.attrs) {
1075+
let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
1076+
if needs_inline || constness == ast::Constness::Const {
10631077
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
10641078
}
10651079
if tps_len == 0 {
10661080
encode_symbol(ecx, rbml_w, item.id);
10671081
}
1082+
encode_constness(rbml_w, constness);
10681083
encode_visibility(rbml_w, vis);
10691084
encode_stability(rbml_w, stab);
10701085
encode_method_argument_names(rbml_w, &**decl);
@@ -1967,7 +1982,7 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
19671982

19681983
for id in ecx.reachable {
19691984
if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1970-
if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1985+
if let ast::ItemFn(_, _, _, abi, ref generics, _) = i.node {
19711986
if abi != abi::Rust && !generics.is_type_parameterized() {
19721987
rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
19731988
}

0 commit comments

Comments
 (0)