Auto merge of #78697 - JohnTitor:rollup-q0fchpv, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #78376 (Treat trailing semicolon as a statement in macro call) - #78400 (Fix unindent in doc comments) - #78575 (Add a test for compiletest rustc-env & unset-rustc-env directives) - #78616 (Document -Zinstrument-coverage) - #78663 (Fix ICE when a future-incompat-report has its command-line level capped) - #78664 (Fix intrinsic size_of stable link) - #78668 (inliner: Remove redundant loop) - #78676 (add mipsel-unknown-none target) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d662f80855
27 changed files with 584 additions and 191 deletions
|
@ -905,6 +905,13 @@ pub struct Stmt {
|
|||
}
|
||||
|
||||
impl Stmt {
|
||||
pub fn has_trailing_semicolon(&self) -> bool {
|
||||
match &self.kind {
|
||||
StmtKind::Semi(_) => true,
|
||||
StmtKind::MacCall(mac) => matches!(mac.style, MacStmtStyle::Semicolon),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn add_trailing_semicolon(mut self) -> Self {
|
||||
self.kind = match self.kind {
|
||||
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
||||
|
|
|
@ -310,8 +310,44 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
|||
};
|
||||
|
||||
if style == ast::MacStmtStyle::Semicolon {
|
||||
// Implement the proposal described in
|
||||
// https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
|
||||
//
|
||||
// The macro invocation expands to the list of statements.
|
||||
// If the list of statements is empty, then 'parse'
|
||||
// the trailing semicolon on the original invocation
|
||||
// as an empty statement. That is:
|
||||
//
|
||||
// `empty();` is parsed as a single `StmtKind::Empty`
|
||||
//
|
||||
// If the list of statements is non-empty, see if the
|
||||
// final statement alreayd has a trailing semicolon.
|
||||
//
|
||||
// If it doesn't have a semicolon, then 'parse' the trailing semicolon
|
||||
// from the invocation as part of the final statement,
|
||||
// using `stmt.add_trailing_semicolon()`
|
||||
//
|
||||
// If it does have a semicolon, then 'parse' the trailing semicolon
|
||||
// from the invocation as a new StmtKind::Empty
|
||||
|
||||
// FIXME: We will need to preserve the original
|
||||
// semicolon token and span as part of #15701
|
||||
let empty_stmt = ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::StmtKind::Empty,
|
||||
span: DUMMY_SP,
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
if let Some(stmt) = stmts.pop() {
|
||||
stmts.push(stmt.add_trailing_semicolon());
|
||||
if stmt.has_trailing_semicolon() {
|
||||
stmts.push(stmt);
|
||||
stmts.push(empty_stmt);
|
||||
} else {
|
||||
stmts.push(stmt.add_trailing_semicolon());
|
||||
}
|
||||
} else {
|
||||
stmts.push(empty_stmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
|
||||
for &(ref lint_name, level) in &sess.opts.lint_opts {
|
||||
store.check_lint_name_cmdline(sess, &lint_name, level);
|
||||
let orig_level = level;
|
||||
|
||||
// If the cap is less than this specified level, e.g., if we've got
|
||||
// `--cap-lints allow` but we've also got `-D foo` then we ignore
|
||||
|
@ -88,7 +89,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
};
|
||||
for id in ids {
|
||||
self.check_gated_lint(id, DUMMY_SP);
|
||||
let src = LintSource::CommandLine(lint_flag_val);
|
||||
let src = LintSource::CommandLine(lint_flag_val, orig_level);
|
||||
specs.insert(id, (level, src));
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
diag_builder.note(&rationale.as_str());
|
||||
}
|
||||
}
|
||||
LintSource::CommandLine(_) => {
|
||||
LintSource::CommandLine(_, _) => {
|
||||
diag_builder.note("`forbid` lint level was set on command line");
|
||||
}
|
||||
}
|
||||
|
@ -422,7 +423,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
let forbidden_lint_name = match forbid_src {
|
||||
LintSource::Default => id.to_string(),
|
||||
LintSource::Node(name, _, _) => name.to_string(),
|
||||
LintSource::CommandLine(name) => name.to_string(),
|
||||
LintSource::CommandLine(name, _) => name.to_string(),
|
||||
};
|
||||
let (lint_attr_name, lint_attr_span) = match *src {
|
||||
LintSource::Node(name, span, _) => (name, span),
|
||||
|
@ -446,7 +447,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
diag_builder.note(&rationale.as_str());
|
||||
}
|
||||
}
|
||||
LintSource::CommandLine(_) => {
|
||||
LintSource::CommandLine(_, _) => {
|
||||
diag_builder.note("`forbid` lint level was set on command line");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,11 @@ impl EarlyLintPass for RedundantSemicolons {
|
|||
|
||||
fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, bool)>) {
|
||||
if let Some((span, multiple)) = seq.take() {
|
||||
// FIXME: Find a better way of ignoring the trailing
|
||||
// semicolon from macro expansion
|
||||
if span == rustc_span::DUMMY_SP {
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
|
||||
let (msg, rem) = if multiple {
|
||||
("unnecessary trailing semicolons", "remove these semicolons")
|
||||
|
|
|
@ -22,7 +22,9 @@ pub enum LintSource {
|
|||
Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),
|
||||
|
||||
/// Lint level was set by a command-line flag.
|
||||
CommandLine(Symbol),
|
||||
/// The provided `Level` is the level specified on the command line -
|
||||
/// the actual level may be lower due to `--cap-lints`
|
||||
CommandLine(Symbol, Level),
|
||||
}
|
||||
|
||||
impl LintSource {
|
||||
|
@ -30,7 +32,7 @@ impl LintSource {
|
|||
match *self {
|
||||
LintSource::Default => symbol::kw::Default,
|
||||
LintSource::Node(name, _, _) => name,
|
||||
LintSource::CommandLine(name) => name,
|
||||
LintSource::CommandLine(name, _) => name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +40,7 @@ impl LintSource {
|
|||
match *self {
|
||||
LintSource::Default => DUMMY_SP,
|
||||
LintSource::Node(_, span, _) => span,
|
||||
LintSource::CommandLine(_) => DUMMY_SP,
|
||||
LintSource::CommandLine(_, _) => DUMMY_SP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,12 +281,12 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
&format!("`#[{}({})]` on by default", level.as_str(), name),
|
||||
);
|
||||
}
|
||||
LintSource::CommandLine(lint_flag_val) => {
|
||||
let flag = match level {
|
||||
LintSource::CommandLine(lint_flag_val, orig_level) => {
|
||||
let flag = match orig_level {
|
||||
Level::Warn => "-W",
|
||||
Level::Deny => "-D",
|
||||
Level::Forbid => "-F",
|
||||
Level::Allow => panic!(),
|
||||
Level::Allow => "-A",
|
||||
};
|
||||
let hyphen_case_lint_name = name.replace("_", "-");
|
||||
if lint_flag_val.as_str() == name {
|
||||
|
|
|
@ -93,96 +93,79 @@ impl Inliner<'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut local_change;
|
||||
let mut changed = false;
|
||||
while let Some(callsite) = callsites.pop_front() {
|
||||
debug!("checking whether to inline callsite {:?}", callsite);
|
||||
|
||||
loop {
|
||||
local_change = false;
|
||||
while let Some(callsite) = callsites.pop_front() {
|
||||
debug!("checking whether to inline callsite {:?}", callsite);
|
||||
|
||||
if let InstanceDef::Item(_) = callsite.callee.def {
|
||||
if !self.tcx.is_mir_available(callsite.callee.def_id()) {
|
||||
debug!(
|
||||
"checking whether to inline callsite {:?} - MIR unavailable",
|
||||
callsite,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if let InstanceDef::Item(_) = callsite.callee.def {
|
||||
if !self.tcx.is_mir_available(callsite.callee.def_id()) {
|
||||
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite,);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let callee_body = if let Some(callee_def_id) = callsite.callee.def_id().as_local() {
|
||||
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
||||
// Avoid a cycle here by only using `instance_mir` only if we have
|
||||
// a lower `HirId` than the callee. This ensures that the callee will
|
||||
// not inline us. This trick only works without incremental compilation.
|
||||
// So don't do it if that is enabled. Also avoid inlining into generators,
|
||||
// since their `optimized_mir` is used for layout computation, which can
|
||||
// create a cycle, even when no attempt is made to inline the function
|
||||
// in the other direction.
|
||||
if !self.tcx.dep_graph.is_fully_enabled()
|
||||
&& self_hir_id < callee_hir_id
|
||||
&& caller_body.generator_kind.is_none()
|
||||
{
|
||||
self.tcx.instance_mir(callsite.callee.def)
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// This cannot result in a cycle since the callee MIR is from another crate
|
||||
// and is already optimized.
|
||||
let callee_body = if let Some(callee_def_id) = callsite.callee.def_id().as_local() {
|
||||
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
||||
// Avoid a cycle here by only using `instance_mir` only if we have
|
||||
// a lower `HirId` than the callee. This ensures that the callee will
|
||||
// not inline us. This trick only works without incremental compilation.
|
||||
// So don't do it if that is enabled. Also avoid inlining into generators,
|
||||
// since their `optimized_mir` is used for layout computation, which can
|
||||
// create a cycle, even when no attempt is made to inline the function
|
||||
// in the other direction.
|
||||
if !self.tcx.dep_graph.is_fully_enabled()
|
||||
&& self_hir_id < callee_hir_id
|
||||
&& caller_body.generator_kind.is_none()
|
||||
{
|
||||
self.tcx.instance_mir(callsite.callee.def)
|
||||
};
|
||||
|
||||
let callee_body: &Body<'tcx> = &*callee_body;
|
||||
|
||||
let callee_body = if self.consider_optimizing(callsite, callee_body) {
|
||||
self.tcx.subst_and_normalize_erasing_regions(
|
||||
&callsite.callee.substs,
|
||||
self.param_env,
|
||||
callee_body,
|
||||
)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `subst_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(
|
||||
callee_body.required_consts.iter().copied().filter(|&constant| {
|
||||
matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _))
|
||||
}),
|
||||
);
|
||||
|
||||
let start = caller_body.basic_blocks().len();
|
||||
debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body);
|
||||
if !self.inline_call(callsite, caller_body, callee_body) {
|
||||
debug!("attempting to inline callsite {:?} - failure", callsite);
|
||||
continue;
|
||||
}
|
||||
debug!("attempting to inline callsite {:?} - success", callsite);
|
||||
} else {
|
||||
// This cannot result in a cycle since the callee MIR is from another crate
|
||||
// and is already optimized.
|
||||
self.tcx.instance_mir(callsite.callee.def)
|
||||
};
|
||||
|
||||
// Add callsites from inlined function
|
||||
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) {
|
||||
if let Some(new_callsite) =
|
||||
self.get_valid_function_call(bb, bb_data, caller_body)
|
||||
{
|
||||
// Don't inline the same function multiple times.
|
||||
if callsite.callee != new_callsite.callee {
|
||||
callsites.push_back(new_callsite);
|
||||
}
|
||||
let callee_body: &Body<'tcx> = &*callee_body;
|
||||
|
||||
let callee_body = if self.consider_optimizing(callsite, callee_body) {
|
||||
self.tcx.subst_and_normalize_erasing_regions(
|
||||
&callsite.callee.substs,
|
||||
self.param_env,
|
||||
callee_body,
|
||||
)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `subst_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter(
|
||||
|&constant| matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)),
|
||||
));
|
||||
|
||||
let start = caller_body.basic_blocks().len();
|
||||
debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body);
|
||||
if !self.inline_call(callsite, caller_body, callee_body) {
|
||||
debug!("attempting to inline callsite {:?} - failure", callsite);
|
||||
continue;
|
||||
}
|
||||
debug!("attempting to inline callsite {:?} - success", callsite);
|
||||
|
||||
// Add callsites from inlined function
|
||||
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) {
|
||||
if let Some(new_callsite) = self.get_valid_function_call(bb, bb_data, caller_body) {
|
||||
// Don't inline the same function multiple times.
|
||||
if callsite.callee != new_callsite.callee {
|
||||
callsites.push_back(new_callsite);
|
||||
}
|
||||
}
|
||||
|
||||
local_change = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if !local_change {
|
||||
break;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Simplify if we inlined anything.
|
||||
|
|
42
compiler/rustc_target/src/spec/mipsel_unknown_none.rs
Normal file
42
compiler/rustc_target/src/spec/mipsel_unknown_none.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
//! Bare MIPS32r2, little endian, softfloat, O32 calling convention
|
||||
//!
|
||||
//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
|
||||
|
||||
use crate::spec::abi::Abi;
|
||||
use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
|
||||
use crate::spec::{PanicStrategy, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "mipsel-unknown-none".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
pointer_width: 32,
|
||||
target_c_int_width: "32".to_string(),
|
||||
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
|
||||
arch: "mips".to_string(),
|
||||
target_os: "none".to_string(),
|
||||
target_env: String::new(),
|
||||
target_vendor: String::new(),
|
||||
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
|
||||
|
||||
options: TargetOptions {
|
||||
cpu: "mips32r2".to_string(),
|
||||
features: "+mips32r2,+soft-float,+noabicalls".to_string(),
|
||||
max_atomic_width: Some(32),
|
||||
executables: true,
|
||||
linker: Some("rust-lld".to_owned()),
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
relocation_model: RelocModel::Static,
|
||||
unsupported_abis: vec![
|
||||
Abi::Stdcall,
|
||||
Abi::Fastcall,
|
||||
Abi::Vectorcall,
|
||||
Abi::Thiscall,
|
||||
Abi::Win64,
|
||||
Abi::SysV64,
|
||||
],
|
||||
emit_debug_gdb_scripts: false,
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
|
@ -653,6 +653,7 @@ supported_targets! {
|
|||
("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
|
||||
|
||||
("mipsel-sony-psp", mipsel_sony_psp),
|
||||
("mipsel-unknown-none", mipsel_unknown_none),
|
||||
("thumbv4t-none-eabi", thumbv4t_none_eabi),
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue