mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-13 09:05:00 +00:00
Extend middle::reachable to also consider provided trait methods.
This commit is contained in:
parent
209308439a
commit
d602d7b97e
@ -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<ast::NodeId>,
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
33
src/test/run-pass/auxiliary/issue_38226_aux.rs
Normal file
33
src/test/run-pass/auxiliary/issue_38226_aux.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>() {
|
||||
let _: Box<SomeTrait> = 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 {}
|
24
src/test/run-pass/issue-38226.rs
Normal file
24
src/test/run-pass/issue-38226.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<()>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user