Skip to content

Commit

Permalink
Auto merge of #25609 - nikomatsakis:const-fn, r=pnkfelix
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed May 24, 2015
2 parents cc56c20 + 82ded3c commit ba0e1cd
Show file tree
Hide file tree
Showing 55 changed files with 848 additions and 212 deletions.
3 changes: 2 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,5 +845,6 @@ register_diagnostics! {
E0314, // closure outlives stack frame
E0315, // cannot invoke closure outside of its lifetime
E0316, // nested quantification of lifetimes
E0370 // discriminant overflow
E0370, // discriminant overflow
E0378 // method calls limited to constant inherent methods
}
2 changes: 2 additions & 0 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,5 @@ pub const tag_item_super_predicates: usize = 0xa3;
pub const tag_defaulted_trait: usize = 0xa4;

pub const tag_impl_coerce_unsized_kind: usize = 0xa5;

pub const tag_items_data_item_constness: usize = 0xa6;
5 changes: 5 additions & 0 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,11 @@ pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
decoder::is_typedef(&*cdata, did.node)
}

pub fn is_const_fn(cstore: &cstore::CStore, did: ast::DefId) -> bool {
let cdata = cstore.get_crate_data(did.krate);
decoder::is_const_fn(&*cdata, did.node)
}

pub fn get_stability(cstore: &cstore::CStore,
def: ast::DefId)
-> Option<attr::Stability> {
Expand Down
21 changes: 21 additions & 0 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,19 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
}
}

fn fn_constness(item: rbml::Doc) -> ast::Constness {
match reader::maybe_get_doc(item, tag_items_data_item_constness) {
None => ast::Constness::NotConst,
Some(constness_doc) => {
match reader::doc_as_u8(constness_doc) as char {
'c' => ast::Constness::Const,
'n' => ast::Constness::NotConst,
_ => panic!("unknown constness character")
}
}
}
}

fn item_sort(item: rbml::Doc) -> Option<char> {
let mut ret = None;
reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
Expand Down Expand Up @@ -1525,6 +1538,14 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
}
}

pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
let item_doc = lookup_item(id, cdata.data());
match fn_constness(item_doc) {
ast::Constness::Const => true,
ast::Constness::NotConst => false,
}
}

fn doc_generics<'tcx>(base_doc: rbml::Doc,
tcx: &ty::ctxt<'tcx>,
cdata: Cmd,
Expand Down
23 changes: 19 additions & 4 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,16 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
}

fn encode_constness(rbml_w: &mut Encoder, constness: ast::Constness) {
rbml_w.start_tag(tag_items_data_item_constness);
let ch = match constness {
ast::Constness::Const => 'c',
ast::Constness::NotConst => 'n',
};
rbml_w.wr_str(&ch.to_string());
rbml_w.end_tag();
}

fn encode_explicit_self(rbml_w: &mut Encoder,
explicit_self: &ty::ExplicitSelfCategory) {
let tag = tag_item_trait_method_explicit_self;
Expand Down Expand Up @@ -867,10 +877,13 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_attributes(rbml_w, &impl_item.attrs);
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
let any_types = !scheme.generics.types.is_empty();
if any_types || is_default_impl || attr::requests_inline(&impl_item.attrs) {
let needs_inline = any_types || is_default_impl ||
attr::requests_inline(&impl_item.attrs);
if needs_inline || sig.constness == ast::Constness::Const {
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
impl_item));
}
encode_constness(rbml_w, sig.constness);
if !any_types {
encode_symbol(ecx, rbml_w, m.def_id.node);
}
Expand Down Expand Up @@ -1049,7 +1062,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_stability(rbml_w, stab);
rbml_w.end_tag();
}
ast::ItemFn(ref decl, _, _, ref generics, _) => {
ast::ItemFn(ref decl, _, constness, _, ref generics, _) => {
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
Expand All @@ -1059,12 +1072,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_name(rbml_w, item.ident.name);
encode_path(rbml_w, path);
encode_attributes(rbml_w, &item.attrs);
if tps_len > 0 || attr::requests_inline(&item.attrs) {
let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
if needs_inline || constness == ast::Constness::Const {
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
}
if tps_len == 0 {
encode_symbol(ecx, rbml_w, item.id);
}
encode_constness(rbml_w, constness);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
encode_method_argument_names(rbml_w, &**decl);
Expand Down Expand Up @@ -1967,7 +1982,7 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {

for id in ecx.reachable {
if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
if let ast::ItemFn(_, _, _, abi, ref generics, _) = i.node {
if abi != abi::Rust && !generics.is_type_parameterized() {
rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
}
Expand Down
Loading

0 comments on commit ba0e1cd

Please sign in to comment.