From 9ae85e19dfb6172692908c514f4b4613fe8fe792 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Apr 2020 14:07:13 +0200 Subject: [PATCH 01/12] Unify lints handling in rustdoc --- src/librustdoc/core.rs | 96 ++++++++++++++++++++++++++---------------- src/librustdoc/test.rs | 42 ++++-------------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 91e60f81cec53..07996587fb532 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -205,6 +205,56 @@ pub fn new_handler( ) } +/// This function is used to setup the lint initialization. By default, in rustdoc, everything +/// is "allowed". Depending if we run in test mode or not, we want some of them to be at their +/// default level. For example, the "INVALID_CODEBLOCK_ATTRIBUTE" lint is activated in both +/// modes. +/// +/// A little detail easy to forget is that there is a way to set the lint level for all lints +/// through the "WARNINGS" lint. To prevent this to happen, we set it back to its "normal" level +/// inside this function. +/// +/// It returns a tuple containing: +/// * Vector of tuples of lints' name and their associated "max" level +/// * HashMap of lint id with their associated "max" level +pub fn init_lints( + mut whitelisted_lints: Vec, + lint_opts: Vec<(String, lint::Level)>, + filter_call: F, +) -> (Vec<(String, lint::Level)>, FxHashMap) +where + F: Fn(&lint::Lint) -> Option<(String, lint::Level)>, +{ + let warnings_lint_name = lint::builtin::WARNINGS.name; + + whitelisted_lints.push(warnings_lint_name.to_owned()); + whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); + + let lints = || { + lint::builtin::HardwiredLints::get_lints() + .into_iter() + .chain(rustc_lint::SoftLints::get_lints().into_iter()) + }; + + let lint_opts = lints() + .filter_map(|lint| if lint.name == warnings_lint_name { None } else { filter_call(lint) }) + .chain(lint_opts.into_iter()) + .collect::>(); + + let lint_caps = lints() + .filter_map(|lint| { + // We don't want to whitelist *all* lints so let's + // ignore those ones. + if whitelisted_lints.iter().any(|l| lint.name == l) { + None + } else { + Some((lint::LintId::of(lint), lint::Allow)) + } + }) + .collect(); + (lint_opts, lint_caps) +} + pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) { // Parse, resolve, and typecheck the given crate. @@ -248,7 +298,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let input = Input::File(input); let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name; - let warnings_lint_name = lint::builtin::WARNINGS.name; let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; @@ -257,8 +306,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // In addition to those specific lints, we also need to whitelist those given through // command line, otherwise they'll get ignored and we don't want that. - let mut whitelisted_lints = vec![ - warnings_lint_name.to_owned(), + let whitelisted_lints = vec![ intra_link_resolution_failure_name.to_owned(), missing_docs.to_owned(), missing_doc_example.to_owned(), @@ -267,39 +315,15 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt invalid_codeblock_attribute_name.to_owned(), ]; - whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); - - let lints = || { - lint::builtin::HardwiredLints::get_lints() - .into_iter() - .chain(rustc_lint::SoftLints::get_lints().into_iter()) - }; - - let lint_opts = lints() - .filter_map(|lint| { - if lint.name == warnings_lint_name - || lint.name == intra_link_resolution_failure_name - || lint.name == invalid_codeblock_attribute_name - { - None - } else { - Some((lint.name_lower(), lint::Allow)) - } - }) - .chain(lint_opts.into_iter()) - .collect::>(); - - let lint_caps = lints() - .filter_map(|lint| { - // We don't want to whitelist *all* lints so let's - // ignore those ones. - if whitelisted_lints.iter().any(|l| lint.name == l) { - None - } else { - Some((lint::LintId::of(lint), lint::Allow)) - } - }) - .collect(); + let (lint_opts, lint_caps) = init_lints(whitelisted_lints, lint_opts, |lint| { + if lint.name == intra_link_resolution_failure_name + || lint.name == invalid_codeblock_attribute_name + { + None + } else { + Some((lint.name_lower(), lint::Allow)) + } + }); let crate_types = if proc_macro_crate { vec![config::CrateType::ProcMacro] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e2940efd49c0d..1cb249d0f867e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -26,6 +26,7 @@ use tempfile::Builder as TempFileBuilder; use crate::clean::Attributes; use crate::config::Options; +use crate::core::init_lints; use crate::html::markdown::{self, ErrorCodes, Ignore, LangString}; use crate::passes::span_of_attrs; @@ -43,44 +44,19 @@ pub struct TestOptions { pub fn run(options: Options) -> i32 { let input = config::Input::File(options.input.clone()); - let warnings_lint_name = lint::builtin::WARNINGS.name; let invalid_codeblock_attribute_name = rustc_lint::builtin::INVALID_CODEBLOCK_ATTRIBUTE.name; // In addition to those specific lints, we also need to whitelist those given through // command line, otherwise they'll get ignored and we don't want that. - let mut whitelisted_lints = - vec![warnings_lint_name.to_owned(), invalid_codeblock_attribute_name.to_owned()]; + let whitelisted_lints = vec![invalid_codeblock_attribute_name.to_owned()]; - whitelisted_lints.extend(options.lint_opts.iter().map(|(lint, _)| lint).cloned()); - - let lints = || { - lint::builtin::HardwiredLints::get_lints() - .into_iter() - .chain(rustc_lint::SoftLints::get_lints().into_iter()) - }; - - let lint_opts = lints() - .filter_map(|lint| { - if lint.name == warnings_lint_name || lint.name == invalid_codeblock_attribute_name { - None - } else { - Some((lint.name_lower(), lint::Allow)) - } - }) - .chain(options.lint_opts.clone().into_iter()) - .collect::>(); - - let lint_caps = lints() - .filter_map(|lint| { - // We don't want to whitelist *all* lints so let's - // ignore those ones. - if whitelisted_lints.iter().any(|l| lint.name == l) { - None - } else { - Some((lint::LintId::of(lint), lint::Allow)) - } - }) - .collect(); + let (lint_opts, lint_caps) = init_lints(whitelisted_lints, options.lint_opts.clone(), |lint| { + if lint.name == invalid_codeblock_attribute_name { + None + } else { + Some((lint.name_lower(), lint::Allow)) + } + }); let crate_types = if options.proc_macro_crate { vec![config::CrateType::ProcMacro] From cd4c30940fdbc6755d5e10f2b6f74f6959f1d867 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 30 Apr 2020 06:28:23 -0700 Subject: [PATCH 02/12] Test for zero-sized function items not ICEing --- .../unsized-locals/issue-30276-feature-flagged.rs | 7 +++++++ .../issue-30276-feature-flagged.stderr | 14 ++++++++++++++ src/test/ui/unsized-locals/issue-30276.rs | 5 +++++ src/test/ui/unsized-locals/issue-30276.stderr | 14 ++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 src/test/ui/unsized-locals/issue-30276-feature-flagged.rs create mode 100644 src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr create mode 100644 src/test/ui/unsized-locals/issue-30276.rs create mode 100644 src/test/ui/unsized-locals/issue-30276.stderr diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs new file mode 100644 index 0000000000000..4193210b8bd3b --- /dev/null +++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs @@ -0,0 +1,7 @@ +#![feature(unsized_locals)] + +struct Test([i32]); + +fn main() { + let _x: fn(_) -> Test = Test; +} //~^the size for values of type `[i32]` cannot be known at compilation time diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr new file mode 100644 index 0000000000000..35f63a91b2b53 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276-feature-flagged.rs:6:29 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^ doesn't have a size known at compile-time + | + = help: within `Test`, the trait `std::marker::Sized` is not implemented for `[i32]` + = note: to learn more, visit + = note: required because it appears within the type `Test` + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/issue-30276.rs b/src/test/ui/unsized-locals/issue-30276.rs new file mode 100644 index 0000000000000..9c4bf062a40e9 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-30276.rs @@ -0,0 +1,5 @@ +struct Test([i32]); + +fn main() { + let _x: fn(_) -> Test = Test; +} //~^the size for values of type `[i32]` cannot be known at compilation time diff --git a/src/test/ui/unsized-locals/issue-30276.stderr b/src/test/ui/unsized-locals/issue-30276.stderr new file mode 100644 index 0000000000000..d42fddb3a4a26 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-30276.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276.rs:4:29 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[i32]` + = note: to learn more, visit + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From cbc577fc719e00f60004c8b22db0256f4c9da4b2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 7 May 2020 15:03:45 +1000 Subject: [PATCH 03/12] Reduce `TypedArena` creations in `check_match`. `check_match` creates a new `TypedArena` for every call to `create_and_enter`. DHAT tells me that each `TypedArena` typically is barely used, with typically a single allocation per arena. This commit moves the `TypedArena` creation outwards a bit, into `check_match`, and then passes it into `create_and_enter`. This reduces the number of arenas created by about 4-5x, for a very small perf win. (Moving the arena creation further outwards is hard because `check_match` is a query.) --- src/librustc_mir_build/hair/pattern/_match.rs | 7 +++---- .../hair/pattern/check_match.rs | 20 ++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index de3ae2e961f42..4e8ec6152e358 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -588,12 +588,11 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { crate fn create_and_enter( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + pattern_arena: &'a TypedArena>, module: DefId, - f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>) -> R, + f: impl FnOnce(MatchCheckCtxt<'a, 'tcx>) -> R, ) -> R { - let pattern_arena = TypedArena::default(); - - f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &pattern_arena }) + f(MatchCheckCtxt { tcx, param_env, module, pattern_arena }) } fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index c90634e511bb1..eda694ee2cba5 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -1,9 +1,9 @@ use super::_match::Usefulness::*; use super::_match::WitnessPreference::*; use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}; - use super::{PatCtxt, PatKind, PatternError}; +use arena::TypedArena; use rustc_ast::ast::Mutability; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -17,7 +17,6 @@ use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERN use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::{sym, Span}; - use std::slice; crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { @@ -26,8 +25,12 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { Some(id) => tcx.hir().body_owned_by(tcx.hir().as_local_hir_id(id)), }; - let mut visitor = - MatchVisitor { tcx, tables: tcx.body_tables(body_id), param_env: tcx.param_env(def_id) }; + let mut visitor = MatchVisitor { + tcx, + tables: tcx.body_tables(body_id), + param_env: tcx.param_env(def_id), + pattern_arena: TypedArena::default(), + }; visitor.visit_body(tcx.hir().body(body_id)); } @@ -39,6 +42,7 @@ struct MatchVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, + pattern_arena: TypedArena>, } impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { @@ -145,7 +149,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { let module = self.tcx.parent_module(hir_id); - MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx)); + MatchCheckCtxt::create_and_enter( + self.tcx, + self.param_env, + &self.pattern_arena, + module.to_def_id(), + f, + ); } fn check_match( From 342aad1d1b88a37361bf3a704750217b4fb4039d Mon Sep 17 00:00:00 2001 From: Tom Karpiniec Date: Thu, 7 May 2020 12:26:18 +1000 Subject: [PATCH 04/12] Force embed-bitcode on non-simulator iOS/tvOS targets At this time Apple recommends Bitcode be included for iOS apps, and requires it for tvOS. It is unlikely that a developer would want to disable bitcode when building for these targets, yet by default it will not be generated. This presents a papercut for developers on those platforms. Introduces a new TargetOption boolean key for specific triples to indicate that bitcode should be generated, even if cargo attempts to optimise with -Cembed-bitcode=no. --- src/librustc_codegen_ssa/back/write.rs | 2 ++ src/librustc_target/spec/aarch64_apple_ios.rs | 1 + src/librustc_target/spec/aarch64_apple_tvos.rs | 1 + src/librustc_target/spec/mod.rs | 5 +++++ 4 files changed, 9 insertions(+) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 5c3444eff0a11..72c4539e82908 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -147,6 +147,8 @@ impl ModuleConfig { || sess.opts.cg.linker_plugin_lto.enabled() { EmitObj::Bitcode + } else if sess.target.target.options.forces_embed_bitcode { + EmitObj::ObjectCode(BitcodeSection::Full) } else if need_crate_bitcode_for_rlib(sess) { let force_full = need_crate_bitcode_for_rlib(sess); match sess.opts.optimize { diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index e896b46da9a62..3ecedd769fae4 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -19,6 +19,7 @@ pub fn target() -> TargetResult { eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), + forces_embed_bitcode: true, ..base }, }) diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index 794bc7900e747..f1cd14ffd11a6 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -19,6 +19,7 @@ pub fn target() -> TargetResult { eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), + forces_embed_bitcode: true, ..base }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e853c07632f90..8b319a0e38113 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -783,6 +783,8 @@ pub struct TargetOptions { // If we give emcc .o files that are actually .bc files it // will 'just work'. pub obj_is_bitcode: bool, + /// Whether the target requires that emitted object code includes bitcode. + pub forces_embed_bitcode: bool, /// Don't use this field; instead use the `.min_atomic_width()` method. pub min_atomic_width: Option, @@ -939,6 +941,7 @@ impl Default for TargetOptions { allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, + forces_embed_bitcode: false, min_atomic_width: None, max_atomic_width: None, atomic_cas: true, @@ -1278,6 +1281,7 @@ impl Target { key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); + key!(forces_embed_bitcode, bool); key!(max_atomic_width, Option); key!(min_atomic_width, Option); key!(atomic_cas, bool); @@ -1505,6 +1509,7 @@ impl ToJson for Target { target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); + target_option_val!(forces_embed_bitcode); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(atomic_cas); From a390803782218807966b0999a698795b0fc5b281 Mon Sep 17 00:00:00 2001 From: Tom Karpiniec Date: Thu, 7 May 2020 15:34:31 +1000 Subject: [PATCH 05/12] Provide configurable LLVM cmdline section via target spec The App Store performs certain sanity checks on bitcode, including that an acceptable set of command line arguments was used when compiling a given module. For Rust code to be distributed on the app store with bitcode rustc must pretend to have the same command line arguments. --- src/librustc_codegen_llvm/back/write.rs | 14 ++++++++------ src/librustc_codegen_ssa/back/write.rs | 2 ++ src/librustc_target/spec/aarch64_apple_ios.rs | 11 +++++++++++ src/librustc_target/spec/mod.rs | 5 +++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 394e2f332cb21..d8faa82a8944d 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -651,10 +651,10 @@ pub(crate) unsafe fn codegen( "LLVM_module_codegen_embed_bitcode", &module.name[..], ); - embed_bitcode(cgcx, llcx, llmod, Some(data)); + embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, Some(data)); } } else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) { - embed_bitcode(cgcx, llcx, llmod, None); + embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, None); } if config.emit_ir { @@ -777,8 +777,8 @@ pub(crate) unsafe fn codegen( /// * __LLVM,__cmdline /// /// It appears *both* of these sections are necessary to get the linker to -/// recognize what's going on. For us though we just always throw in an empty -/// cmdline section. +/// recognize what's going on. A suitable cmdline value is taken from the +/// target spec. /// /// Furthermore debug/O1 builds don't actually embed bitcode but rather just /// embed an empty section. @@ -789,6 +789,7 @@ unsafe fn embed_bitcode( cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module, + cmdline: &str, bitcode: Option<&[u8]>, ) { let llconst = common::bytes_in_context(llcx, bitcode.unwrap_or(&[])); @@ -800,14 +801,15 @@ unsafe fn embed_bitcode( llvm::LLVMSetInitializer(llglobal, llconst); let is_apple = cgcx.opts.target_triple.triple().contains("-ios") - || cgcx.opts.target_triple.triple().contains("-darwin"); + || cgcx.opts.target_triple.triple().contains("-darwin") + || cgcx.opts.target_triple.triple().contains("-tvos"); let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); - let llconst = common::bytes_in_context(llcx, &[]); + let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 72c4539e82908..cae99f630c35b 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -101,6 +101,7 @@ pub struct ModuleConfig { pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: EmitObj, + pub bc_cmdline: String, // Miscellaneous flags. These are mostly copied from command-line // options. @@ -213,6 +214,7 @@ impl ModuleConfig { false ), emit_obj, + bc_cmdline: sess.target.target.options.bitcode_llvm_cmdline.clone(), verify_llvm_ir: sess.verify_llvm_ir(), no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index 3ecedd769fae4..eac2c3e6aa40c 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -20,6 +20,17 @@ pub fn target() -> TargetResult { max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), forces_embed_bitcode: true, + // Taken from a clang build on Xcode 11.4.1. + // These arguments are not actually invoked - they just have + // to look right to pass App Store validation. + bitcode_llvm_cmdline: "-triple\0\ + arm64-apple-ios11.0.0\0\ + -emit-obj\0\ + -disable-llvm-passes\0\ + -target-abi\0\ + darwinpcs\0\ + -Os\0" + .to_string(), ..base }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 8b319a0e38113..51dce9e144caa 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -785,6 +785,8 @@ pub struct TargetOptions { pub obj_is_bitcode: bool, /// Whether the target requires that emitted object code includes bitcode. pub forces_embed_bitcode: bool, + /// Content of the LLVM cmdline section associated with embedded bitcode. + pub bitcode_llvm_cmdline: String, /// Don't use this field; instead use the `.min_atomic_width()` method. pub min_atomic_width: Option, @@ -942,6 +944,7 @@ impl Default for TargetOptions { has_elf_tls: false, obj_is_bitcode: false, forces_embed_bitcode: false, + bitcode_llvm_cmdline: String::new(), min_atomic_width: None, max_atomic_width: None, atomic_cas: true, @@ -1282,6 +1285,7 @@ impl Target { key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(forces_embed_bitcode, bool); + key!(bitcode_llvm_cmdline); key!(max_atomic_width, Option); key!(min_atomic_width, Option); key!(atomic_cas, bool); @@ -1510,6 +1514,7 @@ impl ToJson for Target { target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(forces_embed_bitcode); + target_option_val!(bitcode_llvm_cmdline); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(atomic_cas); From 95f600d6b9aa892000c8d525a5f5cee9f89b6d1d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 8 May 2020 07:42:49 +1000 Subject: [PATCH 06/12] Remove `MatchCheckCtxt::create_and_enter`. It has a single call site. --- src/librustc_mir_build/hair/pattern/_match.rs | 12 +----------- src/librustc_mir_build/hair/pattern/check_match.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 4e8ec6152e358..cdafb63f1ebc1 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -580,21 +580,11 @@ crate struct MatchCheckCtxt<'a, 'tcx> { /// outside it's module and should not be matchable with an empty match /// statement. crate module: DefId, - param_env: ty::ParamEnv<'tcx>, + crate param_env: ty::ParamEnv<'tcx>, crate pattern_arena: &'a TypedArena>, } impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { - crate fn create_and_enter( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - pattern_arena: &'a TypedArena>, - module: DefId, - f: impl FnOnce(MatchCheckCtxt<'a, 'tcx>) -> R, - ) -> R { - f(MatchCheckCtxt { tcx, param_env, module, pattern_arena }) - } - fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env) diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index eda694ee2cba5..c3e853c0b2d12 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -149,13 +149,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { let module = self.tcx.parent_module(hir_id); - MatchCheckCtxt::create_and_enter( - self.tcx, - self.param_env, - &self.pattern_arena, - module.to_def_id(), - f, - ); + let cx = MatchCheckCtxt { + tcx: self.tcx, + param_env: self.param_env, + module: module.to_def_id(), + pattern_arena: &self.pattern_arena, + }; + f(cx); } fn check_match( From d26d187ff83b0b10687a3c380114cda1590d9e26 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 8 May 2020 07:51:10 +1000 Subject: [PATCH 07/12] Replace `MatchVisitor::check_in_cx` with `MatchVisitor::new_cx`. The closure isn't necessary. --- .../hair/pattern/check_match.rs | 155 +++++++++--------- 1 file changed, 75 insertions(+), 80 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index c3e853c0b2d12..0f22288437ca1 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -147,15 +147,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { (pattern, pattern_ty) } - fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { - let module = self.tcx.parent_module(hir_id); - let cx = MatchCheckCtxt { + fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'_, 'tcx> { + MatchCheckCtxt { tcx: self.tcx, param_env: self.param_env, - module: module.to_def_id(), + module: self.tcx.parent_module(hir_id).to_def_id(), pattern_arena: &self.pattern_arena, - }; - f(cx); + } } fn check_match( @@ -169,91 +167,88 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { self.check_patterns(arm.guard.is_some(), &arm.pat); } - self.check_in_cx(scrut.hir_id, |ref mut cx| { - let mut have_errors = false; + let mut cx = self.new_cx(scrut.hir_id); - let inlined_arms: Vec<_> = arms - .iter() - .map(|hir::Arm { pat, guard, .. }| { - (self.lower_pattern(cx, pat, &mut have_errors).0, pat.hir_id, guard.is_some()) - }) - .collect(); + let mut have_errors = false; - // Bail out early if inlining failed. - if have_errors { - return; - } + let inlined_arms: Vec<_> = arms + .iter() + .map(|hir::Arm { pat, guard, .. }| { + (self.lower_pattern(&mut cx, pat, &mut have_errors).0, pat.hir_id, guard.is_some()) + }) + .collect(); - // Fourth, check for unreachable arms. - let matrix = check_arms(cx, &inlined_arms, source); + // Bail out early if inlining failed. + if have_errors { + return; + } + + // Fourth, check for unreachable arms. + let matrix = check_arms(&mut cx, &inlined_arms, source); - // Fifth, check if the match is exhaustive. - let scrut_ty = self.tables.node_type(scrut.hir_id); - // Note: An empty match isn't the same as an empty matrix for diagnostics purposes, - // since an empty matrix can occur when there are arms, if those arms all have guards. - let is_empty_match = inlined_arms.is_empty(); - check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match); - }) + // Fifth, check if the match is exhaustive. + let scrut_ty = self.tables.node_type(scrut.hir_id); + // Note: An empty match isn't the same as an empty matrix for diagnostics purposes, + // since an empty matrix can occur when there are arms, if those arms all have guards. + let is_empty_match = inlined_arms.is_empty(); + check_exhaustive(&mut cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match); } fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option) { - self.check_in_cx(pat.hir_id, |ref mut cx| { - let (pattern, pattern_ty) = self.lower_pattern(cx, pat, &mut false); - let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect(); - - let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) { - Ok(_) => return, - Err(err) => err, - }; - - let joined_patterns = joined_uncovered_patterns(&witnesses); - let mut err = struct_span_err!( - self.tcx.sess, - pat.span, - E0005, - "refutable pattern in {}: {} not covered", - origin, - joined_patterns - ); - let suggest_if_let = match &pat.kind { - hir::PatKind::Path(hir::QPath::Resolved(None, path)) - if path.segments.len() == 1 && path.segments[0].args.is_none() => - { - const_not_var(&mut err, cx.tcx, pat, path); - false - } - _ => { - err.span_label( - pat.span, - pattern_not_covered_label(&witnesses, &joined_patterns), - ); - true - } - }; + let mut cx = self.new_cx(pat.hir_id); - if let (Some(span), true) = (sp, suggest_if_let) { - err.note( - "`let` bindings require an \"irrefutable pattern\", like a `struct` or \ - an `enum` with only one variant", - ); - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "you might want to use `if let` to ignore the variant that isn't matched", - format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), - Applicability::HasPlaceholders, - ); - } - err.note( - "for more information, visit \ - https://doc.rust-lang.org/book/ch18-02-refutability.html", + let (pattern, pattern_ty) = self.lower_pattern(&mut cx, pat, &mut false); + let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect(); + + let witnesses = match check_not_useful(&mut cx, pattern_ty, &pats, pat.hir_id) { + Ok(_) => return, + Err(err) => err, + }; + + let joined_patterns = joined_uncovered_patterns(&witnesses); + let mut err = struct_span_err!( + self.tcx.sess, + pat.span, + E0005, + "refutable pattern in {}: {} not covered", + origin, + joined_patterns + ); + let suggest_if_let = match &pat.kind { + hir::PatKind::Path(hir::QPath::Resolved(None, path)) + if path.segments.len() == 1 && path.segments[0].args.is_none() => + { + const_not_var(&mut err, cx.tcx, pat, path); + false + } + _ => { + err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns)); + true + } + }; + + if let (Some(span), true) = (sp, suggest_if_let) { + err.note( + "`let` bindings require an \"irrefutable pattern\", like a `struct` or \ + an `enum` with only one variant", + ); + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "you might want to use `if let` to ignore the variant that isn't matched", + format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), + Applicability::HasPlaceholders, ); } + err.note( + "for more information, visit \ + https://doc.rust-lang.org/book/ch18-02-refutability.html", + ); + } - adt_defined_here(cx, &mut err, pattern_ty, &witnesses); - err.note(&format!("the matched value is of type `{}`", pattern_ty)); - err.emit(); - }); + adt_defined_here(&mut cx, &mut err, pattern_ty, &witnesses); + err.note(&format!("the matched value is of type `{}`", pattern_ty)); + err.emit(); } } From 4fea9cdd2400f60439f96999f423f92a711b984d Mon Sep 17 00:00:00 2001 From: Tom Karpiniec Date: Fri, 8 May 2020 09:48:30 +1000 Subject: [PATCH 08/12] Simplify bitcode embedding - either None or Full --- src/librustc_codegen_llvm/back/write.rs | 8 +++----- src/librustc_codegen_ssa/back/write.rs | 22 ++++++---------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index d8faa82a8944d..e261ac6544679 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -651,10 +651,8 @@ pub(crate) unsafe fn codegen( "LLVM_module_codegen_embed_bitcode", &module.name[..], ); - embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, Some(data)); + embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); } - } else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) { - embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, None); } if config.emit_ir { @@ -790,9 +788,9 @@ unsafe fn embed_bitcode( llcx: &llvm::Context, llmod: &llvm::Module, cmdline: &str, - bitcode: Option<&[u8]>, + bitcode: &[u8], ) { - let llconst = common::bytes_in_context(llcx, bitcode.unwrap_or(&[])); + let llconst = common::bytes_in_context(llcx, bitcode); let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index cae99f630c35b..21eb56f12b971 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -68,10 +68,6 @@ pub enum BitcodeSection { // No bitcode section. None, - // An empty bitcode section (to placate tools such as the iOS linker that - // require this section even if they don't use it). - Marker, - // A full, uncompressed bitcode section. Full, } @@ -148,16 +144,8 @@ impl ModuleConfig { || sess.opts.cg.linker_plugin_lto.enabled() { EmitObj::Bitcode - } else if sess.target.target.options.forces_embed_bitcode { + } else if need_bitcode_in_object(sess) { EmitObj::ObjectCode(BitcodeSection::Full) - } else if need_crate_bitcode_for_rlib(sess) { - let force_full = need_crate_bitcode_for_rlib(sess); - match sess.opts.optimize { - config::OptLevel::No | config::OptLevel::Less if !force_full => { - EmitObj::ObjectCode(BitcodeSection::Marker) - } - _ => EmitObj::ObjectCode(BitcodeSection::Full), - } } else { EmitObj::ObjectCode(BitcodeSection::None) }; @@ -376,10 +364,12 @@ pub struct CompiledModules { pub allocator_module: Option, } -fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { - sess.opts.cg.embed_bitcode +fn need_bitcode_in_object(sess: &Session) -> bool { + let requested_for_rlib = sess.opts.cg.embed_bitcode && sess.crate_types.borrow().contains(&CrateType::Rlib) - && sess.opts.output_types.contains_key(&OutputType::Exe) + && sess.opts.output_types.contains_key(&OutputType::Exe); + let forced_by_target = sess.target.target.options.forces_embed_bitcode; + requested_for_rlib || forced_by_target } fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool { From 60c66e3f8245072a0b4f8a16260933cc0828eb44 Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Thu, 7 May 2020 22:13:50 -0600 Subject: [PATCH 09/12] allow wasm target for rustc-ap-rustc_span --- src/librustc_span/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 060ad604369fb..78661cd61a39a 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -14,6 +14,9 @@ #![feature(optin_builtin_traits)] #![feature(specialization)] +// allow wasm target for rustc-ap-rustc_span +extern crate rustc_macros; + use rustc_data_structures::AtomicRef; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; From 74f00e2f63bc1596eb7e5fe916b68b9e819362bc Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Thu, 7 May 2020 22:30:14 -0600 Subject: [PATCH 10/12] #[allow(unused)] --- src/librustc_span/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 78661cd61a39a..1c3bca6608f53 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -15,6 +15,7 @@ #![feature(specialization)] // allow wasm target for rustc-ap-rustc_span +#[allow(unused)] extern crate rustc_macros; use rustc_data_structures::AtomicRef; From 732eaf81b7e95dc724b3d71ed2f87bd7b91e052b Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Fri, 8 May 2020 07:56:53 -0600 Subject: [PATCH 11/12] FIXME comment --- src/librustc_span/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 1c3bca6608f53..dd7ba5cb6fc0c 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -14,7 +14,7 @@ #![feature(optin_builtin_traits)] #![feature(specialization)] -// allow wasm target for rustc-ap-rustc_span +// FIXME(#56935): Work around ICEs during cross-compilation. #[allow(unused)] extern crate rustc_macros; From 0d60c46faa638ab8ceb543765d39269f4402c4a0 Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Fri, 8 May 2020 09:38:18 -0600 Subject: [PATCH 12/12] Work around ICEs during cross-compilation --- src/librustc_ast/lib.rs | 4 ++++ src/librustc_attr/lib.rs | 4 ++++ src/librustc_target/lib.rs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs index f81622d091400..cb3118cba23dd 100644 --- a/src/librustc_ast/lib.rs +++ b/src/librustc_ast/lib.rs @@ -19,6 +19,10 @@ #![feature(unicode_internals)] #![recursion_limit = "256"] +// FIXME(#56935): Work around ICEs during cross-compilation. +#[allow(unused)] +extern crate rustc_macros; + #[macro_export] macro_rules! unwrap_or { ($opt:expr, $default:expr) => { diff --git a/src/librustc_attr/lib.rs b/src/librustc_attr/lib.rs index 66c4495c5afc8..5754bb48d24e1 100644 --- a/src/librustc_attr/lib.rs +++ b/src/librustc_attr/lib.rs @@ -6,6 +6,10 @@ #![feature(or_patterns)] +// FIXME(#56935): Work around ICEs during cross-compilation. +#[allow(unused)] +extern crate rustc_macros; + mod builtin; pub use builtin::*; diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index b2965fb880681..a0229a5daf0dc 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -17,6 +17,10 @@ #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] +// FIXME(#56935): Work around ICEs during cross-compilation. +#[allow(unused)] +extern crate rustc_macros; + #[macro_use] extern crate log;