Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c6337f2

Browse files
committedOct 22, 2013
auto merge of #10003 : alexcrichton/rust/issue-fixes, r=brson
Commits have all the fun details.
2 parents 886a4dd + 41f6e97 commit c6337f2

File tree

7 files changed

+235
-64
lines changed

7 files changed

+235
-64
lines changed
 

‎src/librustc/middle/reachable.rs

+72-35
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,36 @@ use middle::privacy;
2121
use middle::resolve;
2222

2323
use std::hashmap::HashSet;
24-
use syntax::ast::*;
24+
use syntax::ast;
2525
use syntax::ast_map;
26-
use syntax::ast_util::{def_id_of_def, is_local};
26+
use syntax::ast_util::{def_id_of_def, is_local, local_def};
2727
use syntax::attr;
2828
use syntax::parse::token;
2929
use syntax::visit::Visitor;
3030
use syntax::visit;
3131

3232
// Returns true if the given set of attributes contains the `#[inline]`
3333
// attribute.
34-
fn attributes_specify_inlining(attrs: &[Attribute]) -> bool {
34+
fn attributes_specify_inlining(attrs: &[ast::Attribute]) -> bool {
3535
attr::contains_name(attrs, "inline")
3636
}
3737

3838
// Returns true if the given set of generics implies that the item it's
3939
// associated with must be inlined.
40-
fn generics_require_inlining(generics: &Generics) -> bool {
40+
fn generics_require_inlining(generics: &ast::Generics) -> bool {
4141
!generics.ty_params.is_empty()
4242
}
4343

4444
// Returns true if the given item must be inlined because it may be
4545
// monomorphized or it was marked with `#[inline]`. This will only return
4646
// true for functions.
47-
fn item_might_be_inlined(item: @item) -> bool {
47+
fn item_might_be_inlined(item: @ast::item) -> bool {
4848
if attributes_specify_inlining(item.attrs) {
4949
return true
5050
}
5151

5252
match item.node {
53-
item_fn(_, _, _, ref generics, _) => {
53+
ast::item_fn(_, _, _, ref generics, _) => {
5454
generics_require_inlining(generics)
5555
}
5656
_ => false,
@@ -59,17 +59,17 @@ fn item_might_be_inlined(item: @item) -> bool {
5959

6060
// Returns true if the given type method must be inlined because it may be
6161
// monomorphized or it was marked with `#[inline]`.
62-
fn ty_method_might_be_inlined(ty_method: &TypeMethod) -> bool {
62+
fn ty_method_might_be_inlined(ty_method: &ast::TypeMethod) -> bool {
6363
attributes_specify_inlining(ty_method.attrs) ||
6464
generics_require_inlining(&ty_method.generics)
6565
}
6666

6767
// Returns true if the given trait method must be inlined because it may be
6868
// monomorphized or it was marked with `#[inline]`.
69-
fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool {
69+
fn trait_method_might_be_inlined(trait_method: &ast::trait_method) -> bool {
7070
match *trait_method {
71-
required(ref ty_method) => ty_method_might_be_inlined(ty_method),
72-
provided(_) => true
71+
ast::required(ref ty_method) => ty_method_might_be_inlined(ty_method),
72+
ast::provided(_) => true
7373
}
7474
}
7575

@@ -81,27 +81,27 @@ struct ReachableContext {
8181
// methods they've been resolved to.
8282
method_map: typeck::method_map,
8383
// The set of items which must be exported in the linkage sense.
84-
reachable_symbols: @mut HashSet<NodeId>,
84+
reachable_symbols: @mut HashSet<ast::NodeId>,
8585
// A worklist of item IDs. Each item ID in this worklist will be inlined
8686
// and will be scanned for further references.
87-
worklist: @mut ~[NodeId],
87+
worklist: @mut ~[ast::NodeId],
8888
// Known reexports of modules
8989
exp_map2: resolve::ExportMap2,
9090
}
9191

9292
struct MarkSymbolVisitor {
93-
worklist: @mut ~[NodeId],
93+
worklist: @mut ~[ast::NodeId],
9494
method_map: typeck::method_map,
9595
tcx: ty::ctxt,
96-
reachable_symbols: @mut HashSet<NodeId>,
96+
reachable_symbols: @mut HashSet<ast::NodeId>,
9797
}
9898

9999
impl Visitor<()> for MarkSymbolVisitor {
100100

101-
fn visit_expr(&mut self, expr:@Expr, _:()) {
101+
fn visit_expr(&mut self, expr:@ast::Expr, _:()) {
102102

103103
match expr.node {
104-
ExprPath(_) => {
104+
ast::ExprPath(_) => {
105105
let def = match self.tcx.def_map.find(&expr.id) {
106106
Some(&def) => def,
107107
None => {
@@ -118,7 +118,7 @@ impl Visitor<()> for MarkSymbolVisitor {
118118
}
119119
self.reachable_symbols.insert(def_id.node);
120120
}
121-
ExprMethodCall(*) => {
121+
ast::ExprMethodCall(*) => {
122122
match self.method_map.find(&expr.id) {
123123
Some(&typeck::method_map_entry {
124124
origin: typeck::method_static(def_id),
@@ -162,24 +162,24 @@ impl ReachableContext {
162162

163163
// Returns true if the given def ID represents a local item that is
164164
// eligible for inlining and false otherwise.
165-
fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: DefId)
165+
fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: ast::DefId)
166166
-> bool {
167-
if def_id.crate != LOCAL_CRATE {
167+
if def_id.crate != ast::LOCAL_CRATE {
168168
return false
169169
}
170170

171171
let node_id = def_id.node;
172172
match tcx.items.find(&node_id) {
173173
Some(&ast_map::node_item(item, _)) => {
174174
match item.node {
175-
item_fn(*) => item_might_be_inlined(item),
175+
ast::item_fn(*) => item_might_be_inlined(item),
176176
_ => false,
177177
}
178178
}
179179
Some(&ast_map::node_trait_method(trait_method, _, _)) => {
180180
match *trait_method {
181-
required(_) => false,
182-
provided(_) => true,
181+
ast::required(_) => false,
182+
ast::provided(_) => true,
183183
}
184184
}
185185
Some(&ast_map::node_method(method, impl_did, _)) => {
@@ -189,11 +189,11 @@ impl ReachableContext {
189189
} else {
190190
// Check the impl. If the generics on the self type of the
191191
// impl require inlining, this method does too.
192-
assert!(impl_did.crate == LOCAL_CRATE);
192+
assert!(impl_did.crate == ast::LOCAL_CRATE);
193193
match tcx.items.find(&impl_did.node) {
194194
Some(&ast_map::node_item(item, _)) => {
195195
match item.node {
196-
item_impl(ref generics, _, _, _) => {
196+
ast::item_impl(ref generics, _, _, _) => {
197197
generics_require_inlining(generics)
198198
}
199199
_ => false
@@ -231,7 +231,7 @@ impl ReachableContext {
231231
}
232232
}
233233

234-
fn propagate_mod(&self, id: NodeId) {
234+
fn propagate_mod(&self, id: ast::NodeId) {
235235
match self.exp_map2.find(&id) {
236236
Some(l) => {
237237
for reexport in l.iter() {
@@ -262,21 +262,58 @@ impl ReachableContext {
262262
match self.tcx.items.find(&search_item) {
263263
Some(&ast_map::node_item(item, _)) => {
264264
match item.node {
265-
item_fn(_, _, _, _, ref search_block) => {
265+
ast::item_fn(_, _, _, _, ref search_block) => {
266266
visit::walk_block(&mut visitor, search_block, ())
267267
}
268268
// Our recursion into modules involves looking up their
269269
// public reexports and the destinations of those
270270
// exports. Privacy will put them in the worklist, but
271271
// we won't find them in the ast_map, so this is where
272272
// we deal with publicly re-exported items instead.
273-
item_mod(*) => { self.propagate_mod(item.id); }
273+
ast::item_mod(*) => self.propagate_mod(item.id),
274+
275+
// Implementations of exported structs/enums need to get
276+
// added to the worklist (as all their methods should be
277+
// accessible)
278+
ast::item_struct(*) | ast::item_enum(*) => {
279+
let def = local_def(item.id);
280+
let impls = match self.tcx.inherent_impls.find(&def) {
281+
Some(&impls) => impls,
282+
None => continue
283+
};
284+
for imp in impls.iter() {
285+
if is_local(imp.did) {
286+
self.worklist.push(imp.did.node);
287+
}
288+
}
289+
}
290+
291+
// Propagate through this impl
292+
ast::item_impl(_, _, _, ref methods) => {
293+
for method in methods.iter() {
294+
self.worklist.push(method.id);
295+
}
296+
}
297+
298+
// Default methods of exported traits need to all be
299+
// accessible.
300+
ast::item_trait(_, _, ref methods) => {
301+
for method in methods.iter() {
302+
match *method {
303+
ast::required(*) => {}
304+
ast::provided(ref method) => {
305+
self.worklist.push(method.id);
306+
}
307+
}
308+
}
309+
}
310+
274311
// These are normal, nothing reachable about these
275312
// inherently and their children are already in the
276313
// worklist
277-
item_struct(*) | item_impl(*) | item_static(*) |
278-
item_enum(*) | item_ty(*) | item_trait(*) |
279-
item_foreign_mod(*) => {}
314+
ast::item_static(*) | ast::item_ty(*) |
315+
ast::item_foreign_mod(*) => {}
316+
280317
_ => {
281318
self.tcx.sess.span_bug(item.span,
282319
"found non-function item \
@@ -286,10 +323,10 @@ impl ReachableContext {
286323
}
287324
Some(&ast_map::node_trait_method(trait_method, _, _)) => {
288325
match *trait_method {
289-
required(*) => {
326+
ast::required(*) => {
290327
// Keep going, nothing to get exported
291328
}
292-
provided(ref method) => {
329+
ast::provided(ref method) => {
293330
visit::walk_block(&mut visitor, &method.body, ())
294331
}
295332
}
@@ -310,7 +347,7 @@ impl ReachableContext {
310347
worklist: {}",
311348
desc))
312349
}
313-
None if search_item == CRATE_NODE_ID => {
350+
None if search_item == ast::CRATE_NODE_ID => {
314351
self.propagate_mod(search_item);
315352
}
316353
None => {
@@ -329,7 +366,7 @@ impl ReachableContext {
329366
// reachability, which might result in a compile time loss.
330367
fn mark_destructors_reachable(&self) {
331368
for (_, destructor_def_id) in self.tcx.destructor_for_type.iter() {
332-
if destructor_def_id.crate == LOCAL_CRATE {
369+
if destructor_def_id.crate == ast::LOCAL_CRATE {
333370
self.reachable_symbols.insert(destructor_def_id.node);
334371
}
335372
}
@@ -340,7 +377,7 @@ pub fn find_reachable(tcx: ty::ctxt,
340377
method_map: typeck::method_map,
341378
exp_map2: resolve::ExportMap2,
342379
exported_items: &privacy::ExportedItems)
343-
-> @mut HashSet<NodeId> {
380+
-> @mut HashSet<ast::NodeId> {
344381
// XXX(pcwalton): We only need to mark symbols that are exported. But this
345382
// is more complicated than just looking at whether the symbol is `pub`,
346383
// because it might be the target of a `pub use` somewhere. For now, I

‎src/librustdoc/html/render.rs

+56-29
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,9 @@ pub struct Cache {
149149

150150
/// This map contains information about all known traits of this crate.
151151
/// Implementations of a crate should inherit the documentation of the
152-
/// parent trait if no extra documentation is specified, and this map is
153-
/// keyed on trait id with a value of a 'method name => documentation'
154-
/// mapping.
155-
traits: HashMap<ast::NodeId, HashMap<~str, ~str>>,
152+
/// parent trait if no extra documentation is specified, and default methods
153+
/// should show up in documentation about trait implementations.
154+
traits: HashMap<ast::NodeId, clean::Trait>,
156155

157156
/// When rendering traits, it's often useful to be able to list all
158157
/// implementors of the trait, and this mapping is exactly, that: a mapping
@@ -488,18 +487,7 @@ impl DocFolder for Cache {
488487
// trait
489488
match item.inner {
490489
clean::TraitItem(ref t) => {
491-
let mut dox = HashMap::new();
492-
for meth in t.methods.iter() {
493-
let it = meth.item();
494-
match it.doc_value() {
495-
None => {}
496-
Some(s) => {
497-
dox.insert(it.name.get_ref().to_owned(),
498-
s.to_owned());
499-
}
500-
}
501-
}
502-
self.traits.insert(item.id, dox);
490+
self.traits.insert(item.id, t.clone());
503491
}
504492
_ => {}
505493
}
@@ -1480,18 +1468,25 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
14801468
}
14811469
None => {}
14821470
}
1483-
write!(w, "<div class='methods'>");
1484-
for meth in i.methods.iter() {
1471+
1472+
fn docmeth(w: &mut io::Writer, item: &clean::Item) -> bool {
14851473
write!(w, "<h4 id='method.{}' class='method'><code>",
1486-
*meth.name.get_ref());
1487-
render_method(w, meth, false);
1474+
*item.name.get_ref());
1475+
render_method(w, item, false);
14881476
write!(w, "</code></h4>\n");
1489-
match meth.doc_value() {
1477+
match item.doc_value() {
14901478
Some(s) => {
14911479
write!(w, "<div class='docblock'>{}</div>", Markdown(s));
1492-
continue
1480+
true
14931481
}
1494-
None => {}
1482+
None => false
1483+
}
1484+
}
1485+
1486+
write!(w, "<div class='methods'>");
1487+
for meth in i.methods.iter() {
1488+
if docmeth(w, meth) {
1489+
continue
14951490
}
14961491

14971492
// No documentation? Attempt to slurp in the trait's documentation
@@ -1501,13 +1496,19 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
15011496
};
15021497
do local_data::get(cache_key) |cache| {
15031498
do cache.unwrap().read |cache| {
1504-
let name = meth.name.get_ref().as_slice();
15051499
match cache.traits.find(&trait_id) {
1506-
Some(m) => {
1507-
match m.find_equiv(&name) {
1508-
Some(s) => {
1509-
write!(w, "<div class='docblock'>{}</div>",
1510-
Markdown(s.as_slice()));
1500+
Some(t) => {
1501+
let name = meth.name.clone();
1502+
match t.methods.iter().find(|t| t.item().name == name) {
1503+
Some(method) => {
1504+
match method.item().doc_value() {
1505+
Some(s) => {
1506+
write!(w,
1507+
"<div class='docblock'>{}</div>",
1508+
Markdown(s));
1509+
}
1510+
None => {}
1511+
}
15111512
}
15121513
None => {}
15131514
}
@@ -1517,6 +1518,32 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
15171518
}
15181519
}
15191520
}
1521+
1522+
// If we've implemented a trait, then also emit documentation for all
1523+
// default methods which weren't overridden in the implementation block.
1524+
match trait_id {
1525+
None => {}
1526+
Some(id) => {
1527+
do local_data::get(cache_key) |cache| {
1528+
do cache.unwrap().read |cache| {
1529+
match cache.traits.find(&id) {
1530+
Some(t) => {
1531+
for method in t.methods.iter() {
1532+
let n = method.item().name.clone();
1533+
match i.methods.iter().find(|m| m.name == n) {
1534+
Some(*) => continue,
1535+
None => {}
1536+
}
1537+
1538+
docmeth(w, method.item());
1539+
}
1540+
}
1541+
None => {}
1542+
}
1543+
}
1544+
}
1545+
}
1546+
}
15201547
write!(w, "</div>");
15211548
}
15221549

‎src/librustdoc/html/static/main.css

+7
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ nav.sub {
9797
margin-bottom: 10px;
9898
}
9999
.block h2 { margin-top: 0; }
100+
.block a {
101+
display: inline-block;
102+
width: 100%;
103+
text-overflow: ellipsis;
104+
overflow: hidden;
105+
line-height: 15px;
106+
}
100107

101108
.content {
102109
background: #f3f3f3;

‎src/test/auxiliary/issue-9906.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast windows doesn't like extern mod
12+
// aux-build:issue-9906.rs
13+
14+
pub use other::FooBar;
15+
pub use other::foo;
16+
17+
mod other {
18+
pub struct FooBar{value: int}
19+
impl FooBar{
20+
pub fn new(val: int) -> FooBar {
21+
FooBar{value: val}
22+
}
23+
}
24+
25+
pub fn foo(){
26+
1+1;
27+
}
28+
}

‎src/test/auxiliary/issue-9968.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub use internal::core::{Trait, Struct};
12+
13+
mod internal {
14+
pub mod core {
15+
pub struct Struct;
16+
impl Struct {
17+
pub fn init() -> Struct {
18+
Struct
19+
}
20+
}
21+
22+
pub trait Trait {
23+
fn test(&self) {
24+
private();
25+
}
26+
}
27+
28+
impl Trait for Struct {}
29+
30+
fn private() { }
31+
}
32+
}

‎src/test/run-pass/issue-9906.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast windows doesn't like extern mod
12+
// aux-build:issue-9906.rs
13+
14+
extern mod testmod(name = "issue-9906");
15+
16+
fn main() {
17+
testmod::foo();
18+
testmod::FooBar::new(1);
19+
}

‎src/test/run-pass/issue-9968.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast windows doesn't like extern mod
12+
// aux-build:issue-9968.rs
13+
14+
extern mod lib(name = "issue-9968");
15+
16+
use lib::{Trait, Struct};
17+
18+
fn main()
19+
{
20+
Struct::init().test();
21+
}

0 commit comments

Comments
 (0)
Please sign in to comment.