Skip to content

Commit 1e15bf8

Browse files
committed
---
yaml --- r: 83830 b: refs/heads/try c: facefa7 h: refs/heads/master v: v3
1 parent 7cdfd44 commit 1e15bf8

File tree

14 files changed

+1281
-150
lines changed

14 files changed

+1281
-150
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 0e4d1fc8cae42e15e00f71d9f439b01bb25a86ae
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 6c08cc2db4f98e9f07ae7d50338396c4123c2f0a
5-
refs/heads/try: b0f6c29b4f10bafa59723714161a393a204f9c13
5+
refs/heads/try: facefa7c8d1adf6c851dca88fcf4f5d26f72caa9
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/compiletest/procsrv.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub fn run(lib_path: &str,
5757
});
5858

5959
for input in input.iter() {
60-
proc.input().write_str(*input);
60+
proc.input().write(input.as_bytes());
6161
}
6262
let output = proc.finish_with_output();
6363

branches/try/src/librustc/driver/driver.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
263263
method_map, ty_cx));
264264

265265
let maps = (external_exports, last_private_map);
266-
let exported_items =
267-
time(time_passes, "privacy checking", maps, |(a, b)|
268-
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
269-
a, b, crate));
266+
time(time_passes, "privacy checking", maps, |(a, b)|
267+
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
268+
a, b, crate));
270269

271270
time(time_passes, "effect checking", (), |_|
272271
middle::effect::check_crate(ty_cx, method_map, crate));
@@ -301,8 +300,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
301300

302301
let reachable_map =
303302
time(time_passes, "reachability checking", (), |_|
304-
reachable::find_reachable(ty_cx, method_map, exp_map2,
305-
&exported_items));
303+
reachable::find_reachable(ty_cx, method_map, crate));
306304

307305
time(time_passes, "lint checking", (), |_|
308306
lint::check_crate(ty_cx, crate));

branches/try/src/librustc/middle/privacy.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ use syntax::visit::Visitor;
3131

3232
type Context<'self> = (&'self method_map, &'self resolve::ExportMap2);
3333

34-
// A set of all nodes in the ast which can be considered "publicly exported" in
35-
// the sense that they are accessible from anywhere in any hierarchy.
36-
pub type ExportedItems = HashSet<ast::NodeId>;
37-
3834
// This visitor is used to determine the parent of all nodes in question when it
3935
// comes to privacy. This is used to determine later on if a usage is actually
4036
// valid or not.
@@ -141,7 +137,7 @@ impl<'self> Visitor<()> for ParentVisitor<'self> {
141137
// This visitor is used to determine which items of the ast are embargoed,
142138
// otherwise known as not exported.
143139
struct EmbargoVisitor<'self> {
144-
exported_items: &'self mut ExportedItems,
140+
exported_items: &'self mut HashSet<ast::NodeId>,
145141
exp_map2: &'self resolve::ExportMap2,
146142
path_all_public: bool,
147143
}
@@ -243,7 +239,7 @@ struct PrivacyVisitor<'self> {
243239
curitem: ast::NodeId,
244240

245241
// Results of previous analyses necessary for privacy checking.
246-
exported_items: &'self ExportedItems,
242+
exported_items: &'self HashSet<ast::NodeId>,
247243
method_map: &'self method_map,
248244
parents: &'self HashMap<ast::NodeId, ast::NodeId>,
249245
external_exports: resolve::ExternalExports,
@@ -789,7 +785,7 @@ pub fn check_crate(tcx: ty::ctxt,
789785
exp_map2: &resolve::ExportMap2,
790786
external_exports: resolve::ExternalExports,
791787
last_private_map: resolve::LastPrivateMap,
792-
crate: &ast::Crate) -> ExportedItems {
788+
crate: &ast::Crate) {
793789
let mut parents = HashMap::new();
794790
let mut exported_items = HashSet::new();
795791

@@ -806,7 +802,7 @@ pub fn check_crate(tcx: ty::ctxt,
806802
{
807803
// Initialize the exported items with resolve's id for the "root crate"
808804
// to resolve references to `super` leading to the root and such.
809-
exported_items.insert(ast::CRATE_NODE_ID);
805+
exported_items.insert(0);
810806
let mut visitor = EmbargoVisitor {
811807
exported_items: &mut exported_items,
812808
exp_map2: exp_map2,
@@ -828,5 +824,4 @@ pub fn check_crate(tcx: ty::ctxt,
828824
};
829825
visit::walk_crate(&mut visitor, crate, ());
830826
}
831-
return exported_items;
832827
}

branches/try/src/librustc/middle/reachable.rs

Lines changed: 138 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@
1717

1818
use middle::ty;
1919
use middle::typeck;
20-
use middle::privacy;
21-
use middle::resolve;
2220

2321
use std::hashmap::HashSet;
2422
use syntax::ast::*;
2523
use syntax::ast_map;
26-
use syntax::ast_util::{def_id_of_def, is_local};
24+
use syntax::ast_util::def_id_of_def;
2725
use syntax::attr;
2826
use syntax::parse::token;
2927
use syntax::visit::Visitor;
@@ -73,6 +71,15 @@ fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool {
7371
}
7472
}
7573

74+
// The context we're in. If we're in a public context, then public symbols are
75+
// marked reachable. If we're in a private context, then only trait
76+
// implementations are marked reachable.
77+
#[deriving(Clone, Eq)]
78+
enum PrivacyContext {
79+
PublicContext,
80+
PrivateContext,
81+
}
82+
7683
// Information needed while computing reachability.
7784
struct ReachableContext {
7885
// The type context.
@@ -85,8 +92,108 @@ struct ReachableContext {
8592
// A worklist of item IDs. Each item ID in this worklist will be inlined
8693
// and will be scanned for further references.
8794
worklist: @mut ~[NodeId],
88-
// Known reexports of modules
89-
exp_map2: resolve::ExportMap2,
95+
}
96+
97+
struct ReachableVisitor {
98+
reachable_symbols: @mut HashSet<NodeId>,
99+
worklist: @mut ~[NodeId],
100+
}
101+
102+
impl Visitor<PrivacyContext> for ReachableVisitor {
103+
104+
fn visit_item(&mut self, item:@item, privacy_context:PrivacyContext) {
105+
106+
match item.node {
107+
item_fn(*) => {
108+
if privacy_context == PublicContext {
109+
self.reachable_symbols.insert(item.id);
110+
}
111+
if item_might_be_inlined(item) {
112+
self.worklist.push(item.id)
113+
}
114+
}
115+
item_struct(ref struct_def, _) => {
116+
match struct_def.ctor_id {
117+
Some(ctor_id) if
118+
privacy_context == PublicContext => {
119+
self.reachable_symbols.insert(ctor_id);
120+
}
121+
Some(_) | None => {}
122+
}
123+
}
124+
item_enum(ref enum_def, _) => {
125+
if privacy_context == PublicContext {
126+
for variant in enum_def.variants.iter() {
127+
self.reachable_symbols.insert(variant.node.id);
128+
}
129+
}
130+
}
131+
item_impl(ref generics, ref trait_ref, _, ref methods) => {
132+
// XXX(pcwalton): We conservatively assume any methods
133+
// on a trait implementation are reachable, when this
134+
// is not the case. We could be more precise by only
135+
// treating implementations of reachable or cross-
136+
// crate traits as reachable.
137+
138+
let should_be_considered_public = |method: @method| {
139+
(method.vis == public &&
140+
privacy_context == PublicContext) ||
141+
trait_ref.is_some()
142+
};
143+
144+
// Mark all public methods as reachable.
145+
for &method in methods.iter() {
146+
if should_be_considered_public(method) {
147+
self.reachable_symbols.insert(method.id);
148+
}
149+
}
150+
151+
if generics_require_inlining(generics) {
152+
// If the impl itself has generics, add all public
153+
// symbols to the worklist.
154+
for &method in methods.iter() {
155+
if should_be_considered_public(method) {
156+
self.worklist.push(method.id)
157+
}
158+
}
159+
} else {
160+
// Otherwise, add only public methods that have
161+
// generics to the worklist.
162+
for method in methods.iter() {
163+
let generics = &method.generics;
164+
let attrs = &method.attrs;
165+
if generics_require_inlining(generics) ||
166+
attributes_specify_inlining(*attrs) ||
167+
should_be_considered_public(*method) {
168+
self.worklist.push(method.id)
169+
}
170+
}
171+
}
172+
}
173+
item_trait(_, _, ref trait_methods) => {
174+
// Mark all provided methods as reachable.
175+
if privacy_context == PublicContext {
176+
for trait_method in trait_methods.iter() {
177+
match *trait_method {
178+
provided(method) => {
179+
self.reachable_symbols.insert(method.id);
180+
self.worklist.push(method.id)
181+
}
182+
required(_) => {}
183+
}
184+
}
185+
}
186+
}
187+
_ => {}
188+
}
189+
190+
if item.vis == public && privacy_context == PublicContext {
191+
visit::walk_item(self, item, PublicContext)
192+
} else {
193+
visit::walk_item(self, item, PrivateContext)
194+
}
195+
}
196+
90197
}
91198

92199
struct MarkSymbolVisitor {
@@ -149,17 +256,31 @@ impl Visitor<()> for MarkSymbolVisitor {
149256

150257
impl ReachableContext {
151258
// Creates a new reachability computation context.
152-
fn new(tcx: ty::ctxt, method_map: typeck::method_map,
153-
exp_map2: resolve::ExportMap2) -> ReachableContext {
259+
fn new(tcx: ty::ctxt, method_map: typeck::method_map)
260+
-> ReachableContext {
154261
ReachableContext {
155262
tcx: tcx,
156263
method_map: method_map,
157264
reachable_symbols: @mut HashSet::new(),
158265
worklist: @mut ~[],
159-
exp_map2: exp_map2,
160266
}
161267
}
162268

269+
// Step 1: Mark all public symbols, and add all public symbols that might
270+
// be inlined to a worklist.
271+
fn mark_public_symbols(&self, crate: &Crate) {
272+
let reachable_symbols = self.reachable_symbols;
273+
let worklist = self.worklist;
274+
275+
let mut visitor = ReachableVisitor {
276+
reachable_symbols: reachable_symbols,
277+
worklist: worklist,
278+
};
279+
280+
281+
visit::walk_crate(&mut visitor, crate, PublicContext);
282+
}
283+
163284
// Returns true if the given def ID represents a local item that is
164285
// eligible for inlining and false otherwise.
165286
fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: DefId)
@@ -231,19 +352,6 @@ impl ReachableContext {
231352
}
232353
}
233354

234-
fn propagate_mod(&self, id: NodeId) {
235-
match self.exp_map2.find(&id) {
236-
Some(l) => {
237-
for reexport in l.iter() {
238-
if reexport.reexport && is_local(reexport.def_id) {
239-
self.worklist.push(reexport.def_id.node);
240-
}
241-
}
242-
}
243-
None => {}
244-
}
245-
}
246-
247355
// Step 2: Mark all symbols that the symbols on the worklist touch.
248356
fn propagate(&self) {
249357
let mut visitor = self.init_visitor();
@@ -265,18 +373,6 @@ impl ReachableContext {
265373
item_fn(_, _, _, _, ref search_block) => {
266374
visit::walk_block(&mut visitor, search_block, ())
267375
}
268-
// Our recursion into modules involves looking up their
269-
// public reexports and the destinations of those
270-
// exports. Privacy will put them in the worklist, but
271-
// we won't find them in the ast_map, so this is where
272-
// we deal with publicly re-exported items instead.
273-
item_mod(*) => { self.propagate_mod(item.id); }
274-
// These are normal, nothing reachable about these
275-
// inherently and their children are already in the
276-
// worklist
277-
item_struct(*) | item_impl(*) | item_static(*) |
278-
item_enum(*) | item_ty(*) | item_trait(*) |
279-
item_foreign_mod(*) => {}
280376
_ => {
281377
self.tcx.sess.span_bug(item.span,
282378
"found non-function item \
@@ -286,8 +382,10 @@ impl ReachableContext {
286382
}
287383
Some(&ast_map::node_trait_method(trait_method, _, _)) => {
288384
match *trait_method {
289-
required(*) => {
290-
// Keep going, nothing to get exported
385+
required(ref ty_method) => {
386+
self.tcx.sess.span_bug(ty_method.span,
387+
"found required method in \
388+
worklist?!")
291389
}
292390
provided(ref method) => {
293391
visit::walk_block(&mut visitor, &method.body, ())
@@ -297,10 +395,6 @@ impl ReachableContext {
297395
Some(&ast_map::node_method(ref method, _, _)) => {
298396
visit::walk_block(&mut visitor, &method.body, ())
299397
}
300-
// Nothing to recurse on for these
301-
Some(&ast_map::node_foreign_item(*)) |
302-
Some(&ast_map::node_variant(*)) |
303-
Some(&ast_map::node_struct_ctor(*)) => {}
304398
Some(_) => {
305399
let ident_interner = token::get_ident_interner();
306400
let desc = ast_map::node_id_to_str(self.tcx.items,
@@ -310,9 +404,6 @@ impl ReachableContext {
310404
worklist: {}",
311405
desc))
312406
}
313-
None if search_item == CRATE_NODE_ID => {
314-
self.propagate_mod(search_item);
315-
}
316407
None => {
317408
self.tcx.sess.bug(format!("found unmapped ID in worklist: \
318409
{}",
@@ -338,8 +429,7 @@ impl ReachableContext {
338429

339430
pub fn find_reachable(tcx: ty::ctxt,
340431
method_map: typeck::method_map,
341-
exp_map2: resolve::ExportMap2,
342-
exported_items: &privacy::ExportedItems)
432+
crate: &Crate)
343433
-> @mut HashSet<NodeId> {
344434
// XXX(pcwalton): We only need to mark symbols that are exported. But this
345435
// is more complicated than just looking at whether the symbol is `pub`,
@@ -352,13 +442,11 @@ pub fn find_reachable(tcx: ty::ctxt,
352442
// is to have the name resolution pass mark all targets of a `pub use` as
353443
// "must be reachable".
354444

355-
let reachable_context = ReachableContext::new(tcx, method_map, exp_map2);
445+
let reachable_context = ReachableContext::new(tcx, method_map);
356446

357-
// Step 1: Seed the worklist with all nodes which were found to be public as
358-
// a result of the privacy pass
359-
for &id in exported_items.iter() {
360-
reachable_context.worklist.push(id);
361-
}
447+
// Step 1: Mark all public symbols, and add all public symbols that might
448+
// be inlined to a worklist.
449+
reachable_context.mark_public_symbols(crate);
362450

363451
// Step 2: Mark all symbols that the symbols on the worklist touch.
364452
reachable_context.propagate();

branches/try/src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,6 +2535,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
25352535
let (v, inlineable) = consts::const_expr(ccx, expr);
25362536
ccx.const_values.insert(id, v);
25372537
let mut inlineable = inlineable;
2538+
exprt = true;
25382539

25392540
unsafe {
25402541
let llty = llvm::LLVMTypeOf(v);

branches/try/src/libstd/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use option::{Option, Some, None};
3939
pub use result::{Result, Ok, Err};
4040

4141
// Reexported functions
42-
pub use io::{print, println};
42+
pub use rt::io::stdio::{print, println};
4343
pub use iter::range;
4444
pub use from_str::from_str;
4545

0 commit comments

Comments
 (0)