Skip to content

Commit 243a524

Browse files
committed
Fix for middle::reachable + better comments and tests
In `middle::reachable` mark default impl of a trait method as reachable if this trait method is used from inlinable code
1 parent 8cef018 commit 243a524

File tree

4 files changed

+65
-60
lines changed

4 files changed

+65
-60
lines changed

src/librustc/middle/reachable.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
125125
hir::ExprMethodCall(..) => {
126126
let method_call = ty::MethodCall::expr(expr.id);
127127
let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
128-
match self.tcx.impl_or_trait_item(def_id).container() {
129-
ty::ImplContainer(_) => {
130-
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
131-
if self.def_id_represents_local_inlined_item(def_id) {
132-
self.worklist.push(node_id)
133-
}
134-
self.reachable_symbols.insert(node_id);
135-
}
128+
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
129+
if self.def_id_represents_local_inlined_item(def_id) {
130+
self.worklist.push(node_id)
136131
}
137-
ty::TraitContainer(_) => {}
132+
self.reachable_symbols.insert(node_id);
138133
}
139134
}
140135
_ => {}

src/librustc_privacy/lib.rs

+13-51
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,6 @@ struct EmbargoVisitor<'a, 'tcx: 'a> {
183183
}
184184

185185
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
186-
// There are checks inside of privacy which depend on knowing whether a
187-
// trait should be exported or not. The two current consumers of this are:
188-
//
189-
// 1. Should default methods of a trait be exported?
190-
// 2. Should the methods of an implementation of a trait be exported?
191-
//
192-
// The answer to both of these questions partly rely on whether the trait
193-
// itself is exported or not. If the trait is somehow exported, then the
194-
// answers to both questions must be yes. Right now this question involves
195-
// more analysis than is currently done in rustc, so we conservatively
196-
// answer "yes" so that all traits need to be exported.
197-
fn exported_trait(&self, _id: ast::NodeId) -> bool {
198-
true
199-
}
200-
201186
// Returns tuple (is_public, is_exported) for a type
202187
fn is_public_exported_ty(&self, ty: &hir::Ty) -> (bool, bool) {
203188
if let hir::TyPath(..) = ty.node {
@@ -247,15 +232,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
247232
// added to public/exported sets based on inherited publicity.
248233
hir::ItemImpl(..) | hir::ItemDefaultImpl(..) | hir::ItemForeignMod(..) => {}
249234

250-
// Traits are a little special in that even if they themselves are
251-
// not public they may still be exported.
252-
hir::ItemTrait(..) => {
253-
self.prev_public = self.prev_public && item.vis == hir::Public;
254-
self.prev_exported = self.exported_trait(item.id);
255-
256-
self.maybe_insert_id(item.id);
257-
}
258-
259235
// Private by default, hence we only retain the "public chain" if
260236
// `pub` is explicitly listed.
261237
_ => {
@@ -284,9 +260,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
284260
}
285261
}
286262

287-
// * Inherent impls for public types only have public methods exported
288-
// * Inherent impls for private types do not need to export their methods
289-
// * Inherent impls themselves are not exported, they are nothing more than
263+
// Public items in inherent impls for public/exported types are public/exported
264+
// Inherent impls themselves are not public/exported, they are nothing more than
290265
// containers for other items
291266
hir::ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
292267
let (public_ty, exported_ty) = self.is_public_exported_ty(&ty);
@@ -303,42 +278,29 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
303278
}
304279
}
305280

306-
// Implementations are a little tricky to determine what's exported
307-
// out of them. Here's a few cases which are currently defined:
308-
//
309-
// * Public trait impls for public types must have all methods
310-
// exported.
311-
//
312-
// * Private trait impls for public types can be ignored
313-
//
314-
// * Public trait impls for private types have their methods
315-
// exported. I'm not entirely certain that this is the correct
316-
// thing to do, but I have seen use cases of where this will cause
317-
// undefined symbols at linkage time if this case is not handled.
318-
//
319-
// * Private trait impls for private types can be completely ignored
281+
// It's not known until monomorphization if a trait impl item should be reachable
282+
// from external crates or not. So, we conservatively mark all of them exported and
283+
// the reachability pass (middle::reachable) marks all exported items as reachable.
284+
// For example of private trait impl for private type that shoud be reachable see
285+
// src/test/auxiliary/issue-11225-3.rs
320286
hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, ref impl_items) => {
321287
let (public_ty, _exported_ty) = self.is_public_exported_ty(&ty);
322-
let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
288+
let (public_trait, _exported_trait) = self.is_public_exported_trait(trait_ref);
323289

324290
if public_ty && public_trait {
325291
self.public_items.insert(item.id);
326292
}
327-
if exported_trait {
328-
self.exported_items.insert(item.id);
329-
}
293+
self.exported_items.insert(item.id);
330294

331295
for impl_item in impl_items {
332296
if public_ty && public_trait {
333297
self.public_items.insert(impl_item.id);
334298
}
335-
if exported_trait {
336-
self.exported_items.insert(impl_item.id);
337-
}
299+
self.exported_items.insert(impl_item.id);
338300
}
339301
}
340302

341-
// Default trait impls are exported for public traits
303+
// Default trait impls are public/exported for public/exported traits
342304
hir::ItemDefaultImpl(_, ref trait_ref) => {
343305
let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
344306

@@ -350,8 +312,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
350312
}
351313
}
352314

353-
// Default methods on traits are all public so long as the trait
354-
// is public
315+
// Default methods on traits are all public/exported so long as the trait
316+
// is public/exported
355317
hir::ItemTrait(_, _, _, ref trait_items) => {
356318
for trait_item in trait_items {
357319
self.maybe_insert_id(trait_item.id);

src/test/auxiliary/issue-11225-3.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2015 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+
trait PrivateTrait {
12+
fn private_trait_method(&self);
13+
}
14+
15+
struct PrivateStruct;
16+
17+
impl PrivateStruct {
18+
fn private_inherent_method(&self) { }
19+
}
20+
21+
impl PrivateTrait for PrivateStruct {
22+
fn private_trait_method(&self) { }
23+
}
24+
25+
#[inline]
26+
pub fn public_generic_function() {
27+
PrivateStruct.private_trait_method();
28+
PrivateStruct.private_inherent_method();
29+
}

src/test/run-pass/issue-11225-3.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 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+
// aux-build:issue-11225-3.rs
12+
13+
// pretty-expanded FIXME #23616
14+
15+
extern crate issue_11225_3;
16+
17+
pub fn main() {
18+
issue_11225_3::public_generic_function();
19+
}

0 commit comments

Comments
 (0)