From 48ede3f031ee81be017923708e5a6e77160e09c3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Apr 2018 16:54:30 -0700 Subject: [PATCH] Fix another circulare deps link args issue It turns out that the support in #49316 wasn't enough to handle all cases notably the example in #48661. The underlying bug was connected to panic=abort where lang items were listed in the `missing_lang_items` sets but didn't actually exist anywhere. This caused the linker backend to deduce that start-group/end-group wasn't needed because not all items were defined. Instead the missing lang items that don't actually need to have a definition are filtered out and not considered for the start-group/end-group arguments Closes #48661 --- src/librustc/middle/weak_lang_items.rs | 29 ++++++++++++------- src/librustc_trans/base.rs | 8 +++++ src/librustc_trans/lib.rs | 2 +- .../run-make-fulldeps/std-core-cycle/Makefile | 1 + 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 95e75b4f064..e19f4483f65 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -64,6 +64,24 @@ pub fn link_name(attrs: &[ast::Attribute]) -> Option { }) } +/// Returns whether the specified `lang_item` doesn't actually need to be +/// present for this compilation. +/// +/// Not all lang items are always required for each compilation, particularly in +/// the case of panic=abort. In these situations some lang items are injected by +/// crates and don't actually need to be defined in libstd. +pub fn whitelisted(tcx: TyCtxt, lang_item: lang_items::LangItem) -> bool { + // If we're not compiling with unwinding, we won't actually need these + // symbols. Other panic runtimes ensure that the relevant symbols are + // available to link things together, but they're never exercised. + if tcx.sess.panic_strategy() != PanicStrategy::Unwind { + return lang_item == lang_items::EhPersonalityLangItem || + lang_item == lang_items::EhUnwindResumeLangItem + } + + false +} + fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, items: &lang_items::LanguageItems) { // We only need to check for the presence of weak lang items if we're @@ -89,18 +107,9 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - // If we're not compiling with unwinding, we won't actually need these - // symbols. Other panic runtimes ensure that the relevant symbols are - // available to link things together, but they're never exercised. - let mut whitelisted = HashSet::new(); - if tcx.sess.panic_strategy() != PanicStrategy::Unwind { - whitelisted.insert(lang_items::EhPersonalityLangItem); - whitelisted.insert(lang_items::EhUnwindResumeLangItem); - } - $( if missing.contains(&lang_items::$item) && - !whitelisted.contains(&lang_items::$item) && + !whitelisted(tcx, lang_items::$item) && items.$name().is_none() { tcx.sess.err(&format!("language item required, but not found: `{}`", stringify!($name))); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 7ab3499ead3..bea195f4f70 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -36,6 +36,7 @@ use llvm; use metadata; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::middle::lang_items::StartFnLangItem; +use rustc::middle::weak_lang_items; use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::{self, Ty, TyCtxt}; @@ -1137,6 +1138,13 @@ impl CrateInfo { info.lang_item_to_crate.insert(item, id.krate); } } + + // No need to look for lang items that are whitelisted and don't + // actually need to exist. + let missing = missing.iter() + .cloned() + .filter(|&l| !weak_lang_items::whitelisted(tcx, l)) + .collect(); info.missing_lang_items.insert(cnum, missing); } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index e8a1eb3071a..6ceddc1be60 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -407,7 +407,7 @@ struct CrateInfo { wasm_custom_sections: BTreeMap>, wasm_imports: FxHashMap, lang_item_to_crate: FxHashMap, - missing_lang_items: FxHashMap>>, + missing_lang_items: FxHashMap>, } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } diff --git a/src/test/run-make-fulldeps/std-core-cycle/Makefile b/src/test/run-make-fulldeps/std-core-cycle/Makefile index adc5be8016c..ce3b2d46bbc 100644 --- a/src/test/run-make-fulldeps/std-core-cycle/Makefile +++ b/src/test/run-make-fulldeps/std-core-cycle/Makefile @@ -13,3 +13,4 @@ endif all: $(RUSTC) bar.rs $(RUSTC) foo.rs $(FLAGS) + $(RUSTC) foo.rs $(FLAGS) -C panic=abort