From a6ca302097ff30c0eb7746c5ef642fa4af4b6285 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 28 Jun 2017 23:50:24 +0300 Subject: [PATCH] add comments --- src/librustc_trans/collector.rs | 4 ++++ src/librustc_trans/trans_item.rs | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 3536dcf16e5..55a2c281403 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -304,7 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, scx.tcx().hir.krate().visit_all_item_likes(&mut visitor); } + // We can only translate items that are instantiable - items all of + // whose predicates hold. Luckily, items that aren't instantiable + // can't actually be used, so we can just skip translating them. roots.retain(|root| root.is_instantiable(scx.tcx())); + roots } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 6e8b2e0a2a6..192e23a66a1 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -253,6 +253,29 @@ impl<'a, 'tcx> TransItem<'tcx> { /// Returns whether this instance is instantiable - whether it has no unsatisfied /// predicates. + /// + /// In order to translate an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we translate collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be translated, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { debug!("is_instantiable({:?})", self); let (def_id, substs) = match *self {