Skip to content

Commit

Permalink
Auto merge of #72021 - Dylan-DPC:rollup-1w61ihk, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - #71581 (Unify lints handling in rustdoc)
 - #71710 (Test for zero-sized function items not ICEing)
 - #71970 (Improve bitcode generation for Apple platforms)
 - #71975 (Reduce `TypedArena` creations in `check_match`.)
 - #72003 (allow wasm target for rustc-ap-rustc_span)
 - #72017 (Work around ICEs during cross-compilation for target, ast, & attr)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 8, 2020
2 parents 7b80539 + 827ec49 commit 7ebd87a
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 186 deletions.
4 changes: 4 additions & 0 deletions src/librustc_ast/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_attr/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down
18 changes: 9 additions & 9 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,10 +651,8 @@ 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, data);
}
} else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
embed_bitcode(cgcx, llcx, llmod, None);
}

if config.emit_ir {
Expand Down Expand Up @@ -777,8 +775,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.
Expand All @@ -789,9 +787,10 @@ unsafe fn embed_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
llcx: &llvm::Context,
llmod: &llvm::Module,
bitcode: Option<&[u8]>,
cmdline: &str,
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),
Expand All @@ -800,14 +799,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),
Expand Down
24 changes: 9 additions & 15 deletions src/librustc_codegen_ssa/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -101,6 +97,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.
Expand Down Expand Up @@ -147,14 +144,8 @@ impl ModuleConfig {
|| sess.opts.cg.linker_plugin_lto.enabled()
{
EmitObj::Bitcode
} 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 if need_bitcode_in_object(sess) {
EmitObj::ObjectCode(BitcodeSection::Full)
} else {
EmitObj::ObjectCode(BitcodeSection::None)
};
Expand Down Expand Up @@ -211,6 +202,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,
Expand Down Expand Up @@ -372,10 +364,12 @@ pub struct CompiledModules {
pub allocator_module: Option<CompiledModule>,
}

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 {
Expand Down
13 changes: 1 addition & 12 deletions src/librustc_mir_build/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,22 +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<Pat<'tcx>>,
}

impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
crate fn create_and_enter<R>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
module: DefId,
f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>) -> R,
) -> R {
let pattern_arena = TypedArena::default();

f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &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)
Expand Down
167 changes: 86 additions & 81 deletions src/librustc_mir_build/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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) {
Expand All @@ -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));
}

Expand All @@ -39,6 +42,7 @@ struct MatchVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pattern_arena: TypedArena<super::Pat<'tcx>>,
}

impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
Expand Down Expand Up @@ -143,9 +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);
MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx));
fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'_, 'tcx> {
MatchCheckCtxt {
tcx: self.tcx,
param_env: self.param_env,
module: self.tcx.parent_module(hir_id).to_def_id(),
pattern_arena: &self.pattern_arena,
}
}

fn check_match(
Expand All @@ -159,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();

// Bail out early if inlining failed.
if have_errors {
return;
}

// Fourth, check for unreachable arms.
let matrix = check_arms(cx, &inlined_arms, source);
// 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<Span>) {
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();
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/librustc_span/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#![feature(optin_builtin_traits)]
#![feature(specialization)]

// FIXME(#56935): Work around ICEs during cross-compilation.
#[allow(unused)]
extern crate rustc_macros;

use rustc_data_structures::AtomicRef;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
Expand Down
Loading

0 comments on commit 7ebd87a

Please sign in to comment.