From d602d7b97e737c461fdd0ff724d092ec53707157 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 8 Dec 2016 16:55:51 -0500 Subject: [PATCH 1/2] Extend middle::reachable to also consider provided trait methods. --- src/librustc/middle/reachable.rs | 25 ++++++++++++-- .../run-pass/auxiliary/issue_38226_aux.rs | 33 +++++++++++++++++++ src/test/run-pass/issue-38226.rs | 24 ++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/auxiliary/issue_38226_aux.rs create mode 100644 src/test/run-pass/issue-38226.rs diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 9798b2d587dbf..2c4710f1e452b 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -323,19 +323,37 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // items of non-exported traits (or maybe all local traits?) unless their respective // trait items are used from inlinable code through method call syntax or UFCS, or their // trait is a lang item. -struct CollectPrivateImplItemsVisitor<'a> { +struct CollectPrivateImplItemsVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a privacy::AccessLevels, worklist: &'a mut Vec, } -impl<'a, 'v> ItemLikeVisitor<'v> for CollectPrivateImplItemsVisitor<'a> { +impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { // We need only trait impls here, not inherent impls, and only non-exported ones - if let hir::ItemImpl(.., Some(_), _, ref impl_item_refs) = item.node { + if let hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { if !self.access_levels.is_reachable(item.id) { for impl_item_ref in impl_item_refs { self.worklist.push(impl_item_ref.id.node_id); } + + let trait_def_id = match trait_ref.path.def { + Def::Trait(def_id) => def_id, + _ => unreachable!() + }; + + if !trait_def_id.is_local() { + return + } + + for default_method in self.tcx.provided_trait_methods(trait_def_id) { + let node_id = self.tcx + .map + .as_local_node_id(default_method.def_id) + .unwrap(); + self.worklist.push(node_id); + } } } } @@ -369,6 +387,7 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } { let mut collect_private_impl_items = CollectPrivateImplItemsVisitor { + tcx: tcx, access_levels: access_levels, worklist: &mut reachable_context.worklist, }; diff --git a/src/test/run-pass/auxiliary/issue_38226_aux.rs b/src/test/run-pass/auxiliary/issue_38226_aux.rs new file mode 100644 index 0000000000000..d48a973368501 --- /dev/null +++ b/src/test/run-pass/auxiliary/issue_38226_aux.rs @@ -0,0 +1,33 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="rlib"] + +#[inline(never)] +pub fn foo() { + let _: Box = Box::new(SomeTraitImpl); +} + +pub fn bar() { + SomeTraitImpl.bar(); +} + +mod submod { + pub trait SomeTrait { + fn bar(&self) { + panic!("NO") + } + } +} + +use self::submod::SomeTrait; + +pub struct SomeTraitImpl; +impl SomeTrait for SomeTraitImpl {} diff --git a/src/test/run-pass/issue-38226.rs b/src/test/run-pass/issue-38226.rs new file mode 100644 index 0000000000000..33604212af951 --- /dev/null +++ b/src/test/run-pass/issue-38226.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test makes sure that we don't run into a linker error because of the +// middle::reachable pass missing trait methods with default impls. + +// aux-build:issue_38226_aux.rs + +// Need -Cno-prepopulate-passes to really disable inlining, otherwise the faulty +// code gets optimized out: +// compile-flags: -Cno-prepopulate-passes + +extern crate issue_38226_aux; + +fn main() { + issue_38226_aux::foo::<()>(); +} From 5d35dfb01edd8f53862ac30e1eaec2cea40bace9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 8 Dec 2016 16:57:34 -0500 Subject: [PATCH 2/2] Improve debug output in trans::back::symbol_export. --- src/librustc_trans/back/symbol_export.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index f99f543d9b7df..eef464eb7f4dc 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -51,8 +51,10 @@ impl ExportedSymbols { scx.tcx().map.local_def_id(node_id) }) .map(|def_id| { - (symbol_for_def_id(scx, def_id, symbol_map), - export_level(scx, def_id)) + let name = symbol_for_def_id(scx, def_id, symbol_map); + let export_level = export_level(scx, def_id); + debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); + (name, export_level) }) .collect(); @@ -90,9 +92,10 @@ impl ExportedSymbols { .exported_symbols(cnum) .iter() .map(|&def_id| { - debug!("EXTERN-SYMBOL: {:?}", def_id); let name = Instance::mono(scx, def_id).symbol_name(scx); - (name, export_level(scx, def_id)) + let export_level = export_level(scx, def_id); + debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); + (name, export_level) }) .collect();