diff --git a/.travis.yml b/.travis.yml index f36ad67b11103..63831cd596122 100644 --- a/.travis.yml +++ b/.travis.yml @@ -176,6 +176,8 @@ matrix: if: branch = auto - env: IMAGE=x86_64-gnu-distcheck if: branch = auto + - env: IMAGE=mingw-check + if: type = pull_request OR branch = auto - stage: publish toolstate if: branch = master AND type = push diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 3dd9b6840591b..b6ae824c37601 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -247,9 +247,6 @@ fn main() { // When running miri tests, we need to generate MIR for all libraries if env::var("TEST_MIRI").ok().map_or(false, |val| val == "true") { cmd.arg("-Zalways-encode-mir"); - if stage != "0" { - cmd.arg("-Zmiri"); - } cmd.arg("-Zmir-emit-validate=1"); } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c175d2c69016f..29c8cd1568a39 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -459,7 +459,7 @@ impl Step for RustdocTheme { } fn run(self, builder: &Builder) { - let rustdoc = builder.rustdoc(self.compiler.host); + let rustdoc = builder.out.join("bootstrap/debug/rustdoc"); let mut cmd = builder.tool_cmd(Tool::RustdocTheme); cmd.arg(rustdoc.to_str().unwrap()) .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap()) @@ -875,7 +875,7 @@ impl Step for Compiletest { if build.config.rust_debuginfo_tests { flags.push("-g".to_string()); } - flags.push("-Zmiri -Zunstable-options".to_string()); + flags.push("-Zunstable-options".to_string()); flags.push(build.config.cmd.rustc_args().join(" ")); if let Some(linker) = build.linker(target) { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 5fc92611e6529..97507bc08698a 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -564,7 +564,8 @@ tool_extended!((self, builder), target: self.target, extra_features: Vec::new(), }); - if clippy.is_some() { + let channel = &builder.config.channel; + if clippy.is_some() && channel != "stable" && channel != "beta" { self.extra_features.push("clippy".to_owned()); } builder.ensure(native::Openssl { diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile new file mode 100644 index 0000000000000..ae4641009cf1d --- /dev/null +++ b/src/ci/docker/mingw-check/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + libssl-dev \ + pkg-config \ + mingw-w64 + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index 15c9fc2e504a1..5b106275ac9d2 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -18,7 +18,7 @@ sample usage: src/etc/generate-deriving-span-tests.py """ -import sys, os, datetime, stat +import sys, os, datetime, stat, re TEST_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), '../test/compile-fail')) @@ -87,16 +87,25 @@ def create_test_case(type, trait, super_traits, error_count): def write_file(name, string): test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name) + with open(test_file) as f: + old_str = f.read() + old_str_ignoring_date = re.sub(r'^// Copyright \d+', + '// Copyright {year}'.format(year = YEAR), old_str) + if old_str_ignoring_date == string: + # if all we're doing is updating the copyright year, ignore it + return 0 + # set write permission if file exists, so it can be changed if os.path.exists(test_file): os.chmod(test_file, stat.S_IWUSR) - with open(test_file, 'wt') as f: + with open(test_file, 'w') as f: f.write(string) # mark file read-only os.chmod(test_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + return 1 ENUM = 1 @@ -120,11 +129,15 @@ def write_file(name, string): ('Hash', [], 1)]: traits[trait] = (ALL, supers, errs) +files = 0 + for (trait, (types, super_traits, error_count)) in traits.items(): mk = lambda ty: create_test_case(ty, trait, super_traits, error_count) if types & ENUM: - write_file(trait + '-enum', mk(ENUM_TUPLE)) - write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT)) + files += write_file(trait + '-enum', mk(ENUM_TUPLE)) + files += write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT)) if types & STRUCT: - write_file(trait + '-struct', mk(STRUCT_FIELDS)) - write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE)) + files += write_file(trait + '-struct', mk(STRUCT_FIELDS)) + files += write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE)) + +print('Generated {files} deriving span test{}.'.format('s' if files != 1 else '', files = files)) diff --git a/src/libcore/heap.rs b/src/libcore/heap.rs index fe19c923a58d1..3df8fd5fc615e 100644 --- a/src/libcore/heap.rs +++ b/src/libcore/heap.rs @@ -125,7 +125,14 @@ impl Layout { /// Constructs a `Layout` suitable for holding a value of type `T`. pub fn new() -> Self { let (size, align) = size_align::(); - Layout::from_size_align(size, align).unwrap() + // Note that the align is guaranteed by rustc to be a power of two and + // the size+align combo is guaranteed to fit in our address space. As a + // result use the unchecked constructor here to avoid inserting code + // that panics if it isn't optimized well enough. + debug_assert!(Layout::from_size_align(size, align).is_some()); + unsafe { + Layout::from_size_align_unchecked(size, align) + } } /// Produces layout describing a record that could be used to @@ -133,7 +140,11 @@ impl Layout { /// or other unsized type like a slice). pub fn for_value(t: &T) -> Self { let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); - Layout::from_size_align(size, align).unwrap() + // See rationale in `new` for why this us using an unsafe variant below + debug_assert!(Layout::from_size_align(size, align).is_some()); + unsafe { + Layout::from_size_align_unchecked(size, align) + } } /// Creates a layout describing the record that can hold a value @@ -212,12 +223,7 @@ impl Layout { pub fn repeat(&self, n: usize) -> Option<(Self, usize)> { let padded_size = self.size.checked_add(self.padding_needed_for(self.align))?; let alloc_size = padded_size.checked_mul(n)?; - - // We can assume that `self.align` is a power-of-two. - // Furthermore, `alloc_size` has already been rounded up - // to a multiple of `self.align`; therefore, the call to - // `Layout::from_size_align` below should never panic. - Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size)) + Some((Layout::from_size_align(alloc_size, self.align)?, padded_size)) } /// Creates a layout describing the record for `self` followed by diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index d336934ec7214..62e0979c5fefc 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1425,8 +1425,8 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110); doc_comment! { concat!("Fetches the value, and applies a function to it that returns an optional -new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the -previous value. +new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else +`Err(previous_value)`. Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns `Some(_)`, but the function will have been applied diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e6080fad91d59..f471ffb072d67 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2277,6 +2277,7 @@ bitflags! { const NAKED = 0b0001_0000; const NO_MANGLE = 0b0010_0000; const RUSTC_STD_INTERNAL_SYMBOL = 0b0100_0000; + const NO_DEBUG = 0b1000_0000; } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 41cfac2674be6..21623b82f1b83 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1387,6 +1387,7 @@ impl<'a, 'tcx> HashStable> for traits::DomainGoal<'tcx> FromEnv(where_clause) => where_clause.hash_stable(hcx, hasher), WellFormedTy(ty) => ty.hash_stable(hcx, hasher), + Normalize(projection) => projection.hash_stable(hcx, hasher), FromEnvTy(ty) => ty.hash_stable(hcx, hasher), RegionOutlives(predicate) => predicate.hash_stable(hcx, hasher), TypeOutlives(predicate) => predicate.hash_stable(hcx, hasher), diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8b6a8fea4cabb..d309026212bfa 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1227,8 +1227,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some statistics about MIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), - miri: bool = (false, parse_bool, [TRACKED], - "check the miri const evaluator against the old ctfe"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the macOS linker"), sanitizer: Option = (None, parse_sanitizer, [TRACKED], diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b30fb2ce016df..bf81cd197bf01 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -267,6 +267,7 @@ pub enum DomainGoal<'tcx> { WellFormed(WhereClauseAtom<'tcx>), FromEnv(WhereClauseAtom<'tcx>), WellFormedTy(Ty<'tcx>), + Normalize(ty::ProjectionPredicate<'tcx>), FromEnvTy(Ty<'tcx>), RegionOutlives(ty::RegionOutlivesPredicate<'tcx>), TypeOutlives(ty::TypeOutlivesPredicate<'tcx>), diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 865a9a34aaa25..e8d31d401847e 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -449,6 +449,7 @@ impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> { FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref), FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection), WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty), + Normalize(projection) => write!(fmt, "Normalize({})", projection), FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty), RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate), TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate), @@ -537,6 +538,7 @@ EnumTypeFoldableImpl! { (traits::DomainGoal::WellFormed)(wc), (traits::DomainGoal::FromEnv)(wc), (traits::DomainGoal::WellFormedTy)(ty), + (traits::DomainGoal::Normalize)(projection), (traits::DomainGoal::FromEnvTy)(ty), (traits::DomainGoal::RegionOutlives)(predicate), (traits::DomainGoal::TypeOutlives)(predicate), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 76ec8c21743e0..52818ee855240 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -61,7 +61,7 @@ use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{Lrc, Lock}; use std::any::Any; use std::borrow::Borrow; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::cmp::Ordering; use std::collections::hash_map::{self, Entry}; use std::hash::{Hash, Hasher}; @@ -890,7 +890,7 @@ pub struct GlobalCtxt<'tcx> { maybe_unused_extern_crates: Vec<(DefId, Span)>, // Internal cache for metadata decoding. No need to track deps on this. - pub rcache: RefCell>>, + pub rcache: Lock>>, /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. @@ -1286,7 +1286,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir, def_path_hash_to_def_id, maps: maps::Maps::new(providers), - rcache: RefCell::new(FxHashMap()), + rcache: Lock::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 4d78703613e94..9ea4b21c55221 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -17,7 +17,7 @@ use hir::map::definitions::DefPathHash; use ich::{CachingCodemapView, Fingerprint}; use mir::{self, interpret}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque, SpecializedDecoder, SpecializedEncoder, @@ -57,17 +57,17 @@ pub struct OnDiskCache<'sess> { // This field collects all Diagnostics emitted during the current // compilation session. - current_diagnostics: RefCell>>, + current_diagnostics: Lock>>, prev_cnums: Vec<(u32, String, CrateDisambiguator)>, - cnum_map: RefCell>>>, + cnum_map: Once>>, codemap: &'sess CodeMap, file_index_to_stable_id: FxHashMap, // These two fields caches that are populated lazily during decoding. - file_index_to_file: RefCell>>, - synthetic_expansion_infos: RefCell>, + file_index_to_file: Lock>>, + synthetic_expansion_infos: Lock>, // A map from dep-node to the position of the cached query result in // `serialized_data`. @@ -140,14 +140,14 @@ impl<'sess> OnDiskCache<'sess> { OnDiskCache { serialized_data: data, file_index_to_stable_id: footer.file_index_to_stable_id, - file_index_to_file: RefCell::new(FxHashMap()), + file_index_to_file: Lock::new(FxHashMap()), prev_cnums: footer.prev_cnums, - cnum_map: RefCell::new(None), + cnum_map: Once::new(), codemap: sess.codemap(), - current_diagnostics: RefCell::new(FxHashMap()), + current_diagnostics: Lock::new(FxHashMap()), query_result_index: footer.query_result_index.into_iter().collect(), prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(), - synthetic_expansion_infos: RefCell::new(FxHashMap()), + synthetic_expansion_infos: Lock::new(FxHashMap()), interpret_alloc_cache: RefCell::new(FxHashMap::default()), interpret_alloc_size: RefCell::new(FxHashMap::default()), } @@ -157,14 +157,14 @@ impl<'sess> OnDiskCache<'sess> { OnDiskCache { serialized_data: Vec::new(), file_index_to_stable_id: FxHashMap(), - file_index_to_file: RefCell::new(FxHashMap()), + file_index_to_file: Lock::new(FxHashMap()), prev_cnums: vec![], - cnum_map: RefCell::new(None), + cnum_map: Once::new(), codemap, - current_diagnostics: RefCell::new(FxHashMap()), + current_diagnostics: Lock::new(FxHashMap()), query_result_index: FxHashMap(), prev_diagnostics_index: FxHashMap(), - synthetic_expansion_infos: RefCell::new(FxHashMap()), + synthetic_expansion_infos: Lock::new(FxHashMap()), interpret_alloc_cache: RefCell::new(FxHashMap::default()), interpret_alloc_size: RefCell::new(FxHashMap::default()), } @@ -383,18 +383,16 @@ impl<'sess> OnDiskCache<'sess> { return None }; - // Initialize the cnum_map if it is not initialized yet. - if self.cnum_map.borrow().is_none() { - let mut cnum_map = self.cnum_map.borrow_mut(); - *cnum_map = Some(Self::compute_cnum_map(tcx, &self.prev_cnums[..])); - } - let cnum_map = self.cnum_map.borrow(); + // Initialize the cnum_map using the value from the thread which finishes the closure first + self.cnum_map.init_nonlocking_same(|| { + Self::compute_cnum_map(tcx, &self.prev_cnums[..]) + }); let mut decoder = CacheDecoder { tcx, opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), codemap: self.codemap, - cnum_map: cnum_map.as_ref().unwrap(), + cnum_map: self.cnum_map.get(), file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, synthetic_expansion_infos: &self.synthetic_expansion_infos, @@ -458,8 +456,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> { opaque: opaque::Decoder<'x>, codemap: &'x CodeMap, cnum_map: &'x IndexVec>, - synthetic_expansion_infos: &'x RefCell>, - file_index_to_file: &'x RefCell>>, + synthetic_expansion_infos: &'x Lock>, + file_index_to_file: &'x Lock>>, file_index_to_stable_id: &'x FxHashMap, interpret_alloc_cache: &'x RefCell>, interpret_alloc_size: &'x RefCell>, @@ -557,7 +555,8 @@ impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, } let ty = or_insert_with(self)?; - tcx.rcache.borrow_mut().insert(cache_key, ty); + // This may overwrite the entry, but it should overwrite with the same value + tcx.rcache.borrow_mut().insert_same(cache_key, ty); Ok(ty) } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 3dec84d174dd8..df01c1279e881 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -25,6 +25,7 @@ #![feature(slice_sort_by_cached_key)] #![feature(set_stdio)] #![feature(rustc_stack_internals)] +#![feature(no_debug)] extern crate arena; extern crate getopts; @@ -230,6 +231,9 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box { pub fn get_trans(sess: &Session) -> Box { static INIT: Once = ONCE_INIT; + + #[allow(deprecated)] + #[no_debug] static mut LOAD: fn() -> Box = || unreachable!(); INIT.call_once(|| { diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 3d24b087c5958..5068662651ac6 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -106,6 +106,7 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | + Normalize(..) | RegionOutlives(..) | TypeOutlives(..) => self, } @@ -116,10 +117,20 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI -> Lrc>> { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let item = tcx.hir.expect_item(node_id); - match item.node { - hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id), - hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id), + let node = tcx.hir.find(node_id).unwrap(); + match node { + hir::map::Node::NodeItem(item) => match item.node { + hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id), + hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id), + _ => Lrc::new(vec![]), + } + hir::map::Node::NodeImplItem(item) => { + if let hir::ImplItemKind::Type(..) = item.node { + program_clauses_for_associated_type_value(tcx, def_id) + } else { + Lrc::new(vec![]) + } + }, // FIXME: other constructions e.g. traits, associated types... _ => Lrc::new(vec![]), @@ -229,6 +240,56 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))]) } +pub fn program_clauses_for_associated_type_value<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: DefId, +) -> Lrc>> { + // Rule Normalize-From-Impl (see rustc guide) + // + // ```impl Trait for A0 + // { + // type AssocType where WC = T; + // }``` + // + // ``` + // forall { + // forall { + // Normalize(>::AssocType -> T) :- + // Implemented(A0: Trait) && WC + // } + // } + // ``` + + let item = tcx.associated_item(item_id); + debug_assert_eq!(item.kind, ty::AssociatedKind::Type); + let impl_id = if let ty::AssociatedItemContainer::ImplContainer(impl_id) = item.container { + impl_id + } else { + bug!() + }; + // `A0 as Trait` + let trait_ref = tcx.impl_trait_ref(impl_id).unwrap(); + // `T` + let ty = tcx.type_of(item_id); + // `Implemented(A0: Trait)` + let trait_implemented = ty::Binder::dummy(ty::TraitPredicate { trait_ref }.lower()); + // `WC` + let item_where_clauses = tcx.predicates_of(item_id).predicates.lower(); + // `Implemented(A0: Trait) && WC` + let mut where_clauses = vec![trait_implemented]; + where_clauses.extend(item_where_clauses); + // `>::AssocType` + let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.name); + // `Normalize(>::AssocType -> T)` + let normalize_goal = DomainGoal::Normalize(ty::ProjectionPredicate { projection_ty, ty }); + // `Normalize(... -> T) :- ...` + let clause = ProgramClause { + goal: normalize_goal, + hypotheses: where_clauses.into_iter().map(|wc| wc.into()).collect(), + }; + Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))]) +} + pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { if !tcx.features().rustc_attrs { return; diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 4ffc71ba4703e..97683840172d2 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -149,8 +149,9 @@ pub(crate) fn link_binary(sess: &Session, let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { // Ignore executable crates if we have -Z no-trans, as they will error. - if (sess.opts.debugging_opts.no_trans || - !sess.opts.output_types.should_trans()) && + let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); + if (sess.opts.debugging_opts.no_trans || !sess.opts.output_types.should_trans()) && + !output_metadata && crate_type == config::CrateTypeExecutable { continue; } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index f3d95cf794bab..eb550d7a605c5 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -23,6 +23,7 @@ use llvm::{self, ValueRef}; use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags}; +use rustc::hir::TransFnAttrFlags; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ty::fold::TypeVisitor; @@ -41,7 +42,7 @@ use std::ffi::CString; use std::fmt::Write; use std::ptr; use std::path::{Path, PathBuf}; -use syntax::{ast, attr}; +use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; use syntax_pos::{self, Span, FileName}; @@ -1644,11 +1645,17 @@ pub fn create_global_var_metadata(cx: &CodegenCx, } let tcx = cx.tcx; - let no_mangle = attr::contains_name(&tcx.get_attrs(def_id), "no_mangle"); + let attrs = tcx.trans_fn_attrs(def_id); + + if attrs.flags.contains(TransFnAttrFlags::NO_DEBUG) { + return; + } + + let no_mangle = attrs.flags.contains(TransFnAttrFlags::NO_MANGLE); // We may want to remove the namespace scope if we're in an extern block, see: // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952 let var_scope = get_namespace_for_item(cx, def_id); - let span = cx.tcx.def_span(def_id); + let span = tcx.def_span(def_id); let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP { let loc = span_start(cx, span); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 28311018ee7d7..5594400c03cbc 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -23,6 +23,7 @@ use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}; +use rustc::hir::TransFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum}; use rustc::ty::subst::Substs; @@ -30,7 +31,7 @@ use abi::Abi; use common::CodegenCx; use builder::Builder; use monomorphize::Instance; -use rustc::ty::{self, ParamEnv, Ty}; +use rustc::ty::{self, ParamEnv, Ty, InstanceDef}; use rustc::mir; use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; @@ -210,13 +211,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return FunctionDebugContext::DebugInfoDisabled; } - for attr in instance.def.attrs(cx.tcx).iter() { - if attr.check_name("no_debug") { - return FunctionDebugContext::FunctionWithoutDebugInfo; - } + let def_id = if let InstanceDef::Item(def_id) = instance.def { + def_id + } else { + return FunctionDebugContext::FunctionWithoutDebugInfo; + }; + + if cx.tcx.trans_fn_attrs(def_id).flags.contains(TransFnAttrFlags::NO_DEBUG) { + return FunctionDebugContext::FunctionWithoutDebugInfo; } - let containing_scope = get_containing_scope(cx, instance); let span = mir.span; // This can be the case for functions inlined from another crate @@ -225,7 +229,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return FunctionDebugContext::FunctionWithoutDebugInfo; } - let def_id = instance.def_id(); + let containing_scope = get_containing_scope(cx, instance); let loc = span_start(cx, span); let file_metadata = file_metadata(cx, &loc.file.name, def_id.krate); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3939c3a06270e..959bbf8b99f97 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1790,6 +1790,8 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt trans_fn_attrs.flags |= TransFnAttrFlags::NO_MANGLE; } else if attr.check_name("rustc_std_internal_symbol") { trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; + } else if attr.check_name("no_debug") { + trans_fn_attrs.flags |= TransFnAttrFlags::NO_DEBUG; } else if attr.check_name("inline") { trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { if attr.path != "inline" { diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs index 2083ada6d2de5..671d77efbea3a 100644 --- a/src/test/ui/chalkify/lower_impl.rs +++ b/src/test/ui/chalkify/lower_impl.rs @@ -15,6 +15,15 @@ trait Foo { } #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- impl Foo for T where T: Iterator { } +trait Bar { + type Assoc; +} + +impl Bar for T where T: Iterator { + #[rustc_dump_program_clauses] //~ ERROR Normalize(::Assoc == std::vec::Vec) :- + type Assoc = Vec; +} + fn main() { println!("hello"); } diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr index b5d791d640ada..f253f9847d162 100644 --- a/src/test/ui/chalkify/lower_impl.stderr +++ b/src/test/ui/chalkify/lower_impl.stderr @@ -4,5 +4,11 @@ error: Implemented(T: Foo) :- ProjectionEq(::Item == i LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: Normalize(::Assoc == std::vec::Vec) :- Implemented(T: Bar). + --> $DIR/lower_impl.rs:23:5 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Normalize(::Assoc == std::vec::Vec) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors