Skip to content

Commit 3a56ab2

Browse files
committedAug 23, 2013
Correctly encode item visibility in metadata
This fixes private statics and functions from being usable cross-crates
1 parent 95c542e commit 3a56ab2

16 files changed

+260
-28
lines changed
 

‎src/librustc/driver/driver.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ pub fn phase_2_configure_and_expand(sess: Session,
195195

196196
pub struct CrateAnalysis {
197197
exp_map2: middle::resolve::ExportMap2,
198+
exported_items: @mut middle::resolve::ExportedItems,
198199
ty_cx: ty::ctxt,
199200
maps: astencode::Maps,
200201
reachable: @mut HashSet<ast::NodeId>
@@ -223,7 +224,8 @@ pub fn phase_3_run_analysis_passes(sess: Session,
223224
let middle::resolve::CrateMap {
224225
def_map: def_map,
225226
exp_map2: exp_map2,
226-
trait_map: trait_map
227+
trait_map: trait_map,
228+
exported_items: exported_items
227229
} =
228230
time(time_passes, ~"resolution", ||
229231
middle::resolve::resolve_crate(sess, lang_items, crate));
@@ -298,6 +300,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
298300

299301
CrateAnalysis {
300302
exp_map2: exp_map2,
303+
exported_items: exported_items,
301304
ty_cx: ty_cx,
302305
maps: astencode::Maps {
303306
root_map: root_map,

‎src/librustc/metadata/csearch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ use syntax::diagnostic::expect;
2727
pub struct StaticMethodInfo {
2828
ident: ast::ident,
2929
def_id: ast::def_id,
30-
purity: ast::purity
30+
purity: ast::purity,
31+
vis: ast::visibility,
3132
}
3233

3334
pub fn get_symbol(cstore: @mut cstore::CStore, def: ast::def_id) -> ~str {

‎src/librustc/metadata/decoder.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ impl<'self> EachItemContext<'self> {
525525
fn process_item_and_pop_name(&mut self,
526526
doc: ebml::Doc,
527527
def_id: ast::def_id,
528-
old_len: uint)
528+
old_len: uint,
529+
vis: ast::visibility)
529530
-> bool {
530531
let def_like = item_to_def_like(doc, def_id, self.cdata.cnum);
531532
match def_like {
@@ -544,8 +545,6 @@ impl<'self> EachItemContext<'self> {
544545
}
545546
}
546547

547-
let vis = item_visibility(doc);
548-
549548
let mut continue = (self.callback)(*self.path_builder, def_like, vis);
550549

551550
let family = item_family(doc);
@@ -634,9 +633,12 @@ impl<'self> EachItemContext<'self> {
634633
self.push_name(token::ident_to_str(&child_name));
635634

636635
// Process this item.
636+
637+
let vis = item_visibility(child_item_doc);
637638
continue = self.process_item_and_pop_name(child_item_doc,
638639
child_def_id,
639-
old_len);
640+
old_len,
641+
vis);
640642
}
641643
}
642644
continue
@@ -682,12 +684,13 @@ impl<'self> EachItemContext<'self> {
682684

683685
// Get the item.
684686
match maybe_find_item(def_id.node, other_crates_items) {
685-
None => {}
687+
None => { self.pop_name(old_len); }
686688
Some(reexported_item_doc) => {
687689
continue = self.process_item_and_pop_name(
688690
reexported_item_doc,
689691
def_id,
690-
old_len);
692+
old_len,
693+
ast::public);
691694
}
692695
}
693696

@@ -1007,7 +1010,8 @@ pub fn get_static_methods_if_impl(intr: @ident_interner,
10071010
static_impl_methods.push(StaticMethodInfo {
10081011
ident: item_name(intr, impl_method_doc),
10091012
def_id: item_def_id(impl_method_doc, cdata),
1010-
purity: purity
1013+
purity: purity,
1014+
vis: item_visibility(impl_method_doc),
10111015
});
10121016
}
10131017
_ => {}

‎src/librustc/metadata/encoder.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use metadata::cstore;
1616
use metadata::decoder;
1717
use metadata::tyencode;
1818
use middle::ty::{node_id_to_type, lookup_item_type};
19+
use middle::astencode;
1920
use middle::ty;
2021
use middle::typeck;
21-
use middle::astencode;
2222
use middle;
2323

2424
use std::hash::HashUtil;
@@ -58,6 +58,7 @@ pub struct EncodeParams<'self> {
5858
diag: @mut span_handler,
5959
tcx: ty::ctxt,
6060
reexports2: middle::resolve::ExportMap2,
61+
exported_items: @mut middle::resolve::ExportedItems,
6162
item_symbols: &'self HashMap<ast::NodeId, ~str>,
6263
discrim_symbols: &'self HashMap<ast::NodeId, @str>,
6364
link_meta: &'self LinkMeta,
@@ -86,6 +87,7 @@ pub struct EncodeContext<'self> {
8687
tcx: ty::ctxt,
8788
stats: @mut Stats,
8889
reexports2: middle::resolve::ExportMap2,
90+
exported_items: @mut middle::resolve::ExportedItems,
8991
item_symbols: &'self HashMap<ast::NodeId, ~str>,
9092
discrim_symbols: &'self HashMap<ast::NodeId, @str>,
9193
link_meta: &'self LinkMeta,
@@ -808,7 +810,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
808810
ebml_w: &mut writer::Encoder,
809811
item: @item,
810812
index: @mut ~[entry<i64>],
811-
path: &[ast_map::path_elt]) {
813+
path: &[ast_map::path_elt],
814+
vis: ast::visibility) {
812815
let tcx = ecx.tcx;
813816

814817
fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
@@ -836,6 +839,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
836839
encode_name(ecx, ebml_w, item.ident);
837840
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
838841
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
842+
encode_visibility(ebml_w, vis);
839843
ebml_w.end_tag();
840844
}
841845
item_fn(_, purity, _, ref generics, _) => {
@@ -853,6 +857,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
853857
} else {
854858
encode_symbol(ecx, ebml_w, item.id);
855859
}
860+
encode_visibility(ebml_w, vis);
856861
ebml_w.end_tag();
857862
}
858863
item_mod(ref m) => {
@@ -879,7 +884,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
879884
ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
880885
ebml_w.end_tag();
881886
}
882-
887+
encode_visibility(ebml_w, vis);
883888
ebml_w.end_tag();
884889
}
885890
item_ty(*) => {
@@ -891,6 +896,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
891896
encode_name(ecx, ebml_w, item.ident);
892897
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
893898
encode_region_param(ecx, ebml_w, item);
899+
encode_visibility(ebml_w, vis);
894900
ebml_w.end_tag();
895901
}
896902
item_enum(ref enum_definition, ref generics) => {
@@ -907,6 +913,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
907913
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
908914
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
909915
encode_region_param(ecx, ebml_w, item);
916+
encode_visibility(ebml_w, vis);
910917
ebml_w.end_tag();
911918

912919
encode_enum_variant_info(ecx,
@@ -938,6 +945,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
938945
encode_attributes(ebml_w, item.attrs);
939946
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
940947
encode_region_param(ecx, ebml_w, item);
948+
encode_visibility(ebml_w, vis);
941949

942950
/* Encode def_ids for each field and method
943951
for methods, write all the stuff get_trait_method
@@ -1187,7 +1195,12 @@ fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
11871195
let mut ebml_w = ebml_w.clone();
11881196
// See above
11891197
let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1190-
encode_info_for_item(ecx, &mut ebml_w, i, index, *pt);
1198+
let vis = if ecx.exported_items.contains(&i.id) {
1199+
ast::public
1200+
} else {
1201+
ast::inherited
1202+
};
1203+
encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, vis);
11911204
}
11921205
_ => fail!("bad item")
11931206
}
@@ -1592,6 +1605,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
15921605
diag,
15931606
tcx,
15941607
reexports2,
1608+
exported_items,
15951609
discrim_symbols,
15961610
cstore,
15971611
encode_inlined_item,
@@ -1606,6 +1620,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
16061620
tcx: tcx,
16071621
stats: stats,
16081622
reexports2: reexports2,
1623+
exported_items: exported_items,
16091624
item_symbols: item_symbols,
16101625
discrim_symbols: discrim_symbols,
16111626
link_meta: link_meta,

‎src/librustc/metadata/filesearch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn make_target_lib_path(sysroot: &Path,
128128
sysroot.push_rel(&relative_target_lib_path(target_triple))
129129
}
130130

131-
fn get_or_default_sysroot() -> Path {
131+
pub fn get_or_default_sysroot() -> Path {
132132
match os::self_exe_path() {
133133
option::Some(ref p) => (*p).pop(),
134134
option::None => fail!("can't determine value for sysroot")

‎src/librustc/middle/privacy.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,12 @@ impl PrivacyVisitor {
261261
fmt!("function `%s` is private",
262262
token::ident_to_str(path.idents.last())));
263263
}
264-
} else if csearch::get_item_visibility(self.tcx.sess.cstore,
265-
def_id) != public {
266-
self.tcx.sess.span_err(span,
267-
fmt!("function `%s` is private",
268-
token::ident_to_str(path.idents.last())));
269264
}
265+
// If this is a function from a non-local crate, then the
266+
// privacy check is enforced during resolve. All public items
267+
// will be tagged as such in the crate metadata and then usage
268+
// of the private items will be blocked during resolve. Hence,
269+
// if this isn't from the local crate, nothing to check.
270270
}
271271
_ => {}
272272
}

‎src/librustc/middle/resolve.rs

+42-6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ pub struct Export2 {
6565
reexport: bool, // Whether this is a reexport.
6666
}
6767

68+
// This set is a set of all item nodes which can be used by external crates if
69+
// we're building a library. The necessary qualifications for this are that all
70+
// items leading down to the current item (excluding an `impl`) must be `pub`.
71+
pub type ExportedItems = HashSet<NodeId>;
72+
6873
#[deriving(Eq)]
6974
pub enum PatternBindingMode {
7075
RefutableMode,
@@ -818,6 +823,7 @@ pub fn Resolver(session: Session,
818823

819824
xray_context: NoXray,
820825
current_trait_refs: None,
826+
path_all_public: true,
821827

822828
self_ident: special_idents::self_,
823829
type_self_ident: special_idents::type_self,
@@ -830,6 +836,7 @@ pub fn Resolver(session: Session,
830836
export_map2: @mut HashMap::new(),
831837
trait_map: HashMap::new(),
832838
used_imports: HashSet::new(),
839+
exported_items: @mut HashSet::new(),
833840

834841
emit_errors: true,
835842
intr: session.intr()
@@ -874,6 +881,13 @@ pub struct Resolver {
874881
// The trait that the current context can refer to.
875882
current_trait_refs: Option<~[def_id]>,
876883

884+
// A set of all items which are re-exported to be used across crates
885+
exported_items: @mut ExportedItems,
886+
887+
// When determinining the list of exported items, this is relevant for
888+
// determining if `pub` uses should be re-exported across crates
889+
path_all_public: bool,
890+
877891
// The ident for the keyword "self".
878892
self_ident: ident,
879893
// The ident for the non-keyword "Self".
@@ -1780,8 +1794,8 @@ impl Resolver {
17801794
|path_string, def_like, visibility| {
17811795

17821796
debug!("(building reduced graph for external crate) found path \
1783-
entry: %s (%?)",
1784-
path_string, def_like);
1797+
entry: %s (%?, %?)",
1798+
path_string, def_like, visibility);
17851799

17861800
let mut pieces: ~[&str] = path_string.split_str_iter("::").collect();
17871801
let final_ident_str = pieces.pop();
@@ -1927,8 +1941,10 @@ impl Resolver {
19271941
let def = def_fn(
19281942
static_method_info.def_id,
19291943
static_method_info.purity);
1944+
let p = visibility_to_privacy(
1945+
static_method_info.vis);
19301946
method_name_bindings.define_value(
1931-
Public, def, dummy_sp());
1947+
p, def, dummy_sp());
19321948
}
19331949
}
19341950

@@ -3252,14 +3268,15 @@ impl Resolver {
32523268
match (namebindings.def_for_namespace(ns),
32533269
namebindings.privacy_for_namespace(ns)) {
32543270
(Some(d), Some(Public)) => {
3271+
let def = def_id_of_def(d);
32553272
debug!("(computing exports) YES: %s '%s' => %?",
32563273
if reexport { ~"reexport" } else { ~"export"},
32573274
self.session.str_of(ident),
3258-
def_id_of_def(d));
3275+
def);
32593276
exports2.push(Export2 {
32603277
reexport: reexport,
32613278
name: self.session.str_of(ident),
3262-
def_id: def_id_of_def(d)
3279+
def_id: def,
32633280
});
32643281
}
32653282
(Some(_), Some(privacy)) => {
@@ -3511,6 +3528,13 @@ impl Resolver {
35113528
self.xray_context = Xray;
35123529
}
35133530

3531+
let orig_path_all_public = self.path_all_public;
3532+
self.path_all_public = self.path_all_public && item.vis == ast::public;
3533+
3534+
if self.path_all_public {
3535+
self.exported_items.insert(item.id);
3536+
}
3537+
35143538
match item.node {
35153539

35163540
// enum item: resolve all the variants' discrs,
@@ -3550,6 +3574,10 @@ impl Resolver {
35503574
ref implemented_traits,
35513575
ref self_type,
35523576
ref methods) => {
3577+
self.path_all_public = orig_path_all_public;
3578+
if self.path_all_public {
3579+
self.exported_items.insert(item.id);
3580+
}
35533581
self.resolve_implementation(item.id,
35543582
generics,
35553583
implemented_traits,
@@ -3634,6 +3662,11 @@ impl Resolver {
36343662
}
36353663

36363664
item_foreign_mod(ref foreign_module) => {
3665+
self.path_all_public = orig_path_all_public;
3666+
if self.path_all_public {
3667+
self.exported_items.insert(item.id);
3668+
}
3669+
36373670
do self.with_scope(Some(item.ident)) {
36383671
for foreign_item in foreign_module.items.iter() {
36393672
match foreign_item.node {
@@ -3681,6 +3714,7 @@ impl Resolver {
36813714
}
36823715

36833716
self.xray_context = orig_xray_flag;
3717+
self.path_all_public = orig_path_all_public;
36843718
}
36853719

36863720
pub fn with_type_parameter_rib(@mut self,
@@ -5464,8 +5498,9 @@ impl Resolver {
54645498

54655499
pub struct CrateMap {
54665500
def_map: DefMap,
5501+
trait_map: TraitMap,
54675502
exp_map2: ExportMap2,
5468-
trait_map: TraitMap
5503+
exported_items: @mut ExportedItems,
54695504
}
54705505

54715506
/// Entry point to crate resolution.
@@ -5478,6 +5513,7 @@ pub fn resolve_crate(session: Session,
54785513
CrateMap {
54795514
def_map: resolver.def_map,
54805515
exp_map2: resolver.export_map2,
5516+
exported_items: resolver.exported_items,
54815517
trait_map: resolver.trait_map.clone(),
54825518
}
54835519
}

4 commit comments

Comments
 (4)

bors commented on Aug 23, 2013

@bors
Collaborator

saw approval from pcwalton
at alexcrichton@3a56ab2

bors commented on Aug 23, 2013

@bors
Collaborator

merging alexcrichton/rust/correct-item-visibility = 3a56ab2 into auto

bors commented on Aug 23, 2013

@bors
Collaborator

alexcrichton/rust/correct-item-visibility = 3a56ab2 merged ok, testing candidate = 62e39942

Please sign in to comment.