Auto merge of #123708 - matthiaskrgr:rollup-uf9w1e9, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #121884 (Port exit-code run-make test to use rust) - #122200 (Unconditionally show update nightly hint on ICE) - #123568 (Clean up tests/ui by removing `does-nothing.rs`) - #123609 (Don't use bytepos offsets when computing semicolon span for removal) - #123612 (Set target-abi module flag for RISC-V targets) - #123633 (Store all args in the unsupported Command implementation) - #123668 (async closure coroutine by move body MirPass refactoring) Failed merges: - #123701 (Only assert for child/parent projection compatibility AFTER checking that theyre coming from the same place) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1c77f7378e
@ -346,7 +346,7 @@ impl<'a> AstValidator<'a> {
|
||||
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
|
||||
const_context_label: parent_constness,
|
||||
remove_const_sugg: (
|
||||
self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
|
||||
self.session.source_map().span_extend_while_whitespace(span),
|
||||
match parent_constness {
|
||||
Some(_) => rustc_errors::Applicability::MachineApplicable,
|
||||
None => rustc_errors::Applicability::MaybeIncorrect,
|
||||
|
@ -608,7 +608,7 @@ pub(crate) fn run_pass_manager(
|
||||
"LTOPostLink".as_ptr().cast(),
|
||||
11,
|
||||
) {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
module.module_llvm.llmod(),
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"LTOPostLink".as_ptr().cast(),
|
||||
|
@ -180,13 +180,13 @@ pub unsafe fn create_module<'ll>(
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
}
|
||||
|
||||
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
||||
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
||||
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
@ -197,7 +197,7 @@ pub unsafe fn create_module<'ll>(
|
||||
// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
|
||||
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
@ -208,7 +208,7 @@ pub unsafe fn create_module<'ll>(
|
||||
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
||||
if sess.is_sanitizer_kcfi_enabled() {
|
||||
let kcfi = c"kcfi".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
@ -217,7 +217,7 @@ pub unsafe fn create_module<'ll>(
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
@ -226,7 +226,7 @@ pub unsafe fn create_module<'ll>(
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
@ -238,26 +238,26 @@ pub unsafe fn create_module<'ll>(
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch == "aarch64" {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
@ -273,7 +273,7 @@ pub unsafe fn create_module<'ll>(
|
||||
|
||||
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
|
||||
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
@ -281,7 +281,7 @@ pub unsafe fn create_module<'ll>(
|
||||
)
|
||||
}
|
||||
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
@ -290,7 +290,7 @@ pub unsafe fn create_module<'ll>(
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
@ -300,7 +300,7 @@ pub unsafe fn create_module<'ll>(
|
||||
|
||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||
if sess.opts.unstable_opts.ehcont_guard {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
@ -326,6 +326,22 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
|
||||
// Emit RISC-V specific target-abi metadata
|
||||
// to workaround lld as the LTO plugin not
|
||||
// correctly setting target-abi for the LTO object
|
||||
// FIXME: https://github.com/llvm/llvm-project/issues/50591
|
||||
// If llvm_abiname is empty, emit nothing.
|
||||
let llvm_abiname = &sess.target.options.llvm_abiname;
|
||||
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_ptr().cast(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
}
|
||||
|
||||
// Add module flags specified via -Z llvm_module_flag
|
||||
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
|
||||
let key = format!("{key}\0");
|
||||
@ -341,7 +357,7 @@ pub unsafe fn create_module<'ll>(
|
||||
// We already checked this during option parsing
|
||||
_ => unreachable!(),
|
||||
};
|
||||
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
|
||||
}
|
||||
|
||||
llmod
|
||||
|
@ -110,7 +110,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
.unstable_opts
|
||||
.dwarf_version
|
||||
.unwrap_or(sess.target.default_dwarf_version);
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Dwarf Version".as_ptr().cast(),
|
||||
@ -118,7 +118,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
);
|
||||
} else {
|
||||
// Indicate that we want CodeView debug information on MSVC
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"CodeView".as_ptr().cast(),
|
||||
@ -127,7 +127,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
}
|
||||
|
||||
// Prevent bitcode readers from deleting the debug info.
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Debug Info Version".as_ptr().cast(),
|
||||
|
@ -1801,12 +1801,21 @@ extern "C" {
|
||||
///
|
||||
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
|
||||
/// "compatible" means depends on the merge behaviors involved.
|
||||
pub fn LLVMRustAddModuleFlag(
|
||||
pub fn LLVMRustAddModuleFlagU32(
|
||||
M: &Module,
|
||||
merge_behavior: LLVMModFlagBehavior,
|
||||
name: *const c_char,
|
||||
value: u32,
|
||||
);
|
||||
|
||||
pub fn LLVMRustAddModuleFlagString(
|
||||
M: &Module,
|
||||
merge_behavior: LLVMModFlagBehavior,
|
||||
name: *const c_char,
|
||||
value: *const c_char,
|
||||
value_len: size_t,
|
||||
);
|
||||
|
||||
pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
|
||||
|
@ -1,10 +1,7 @@
|
||||
driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
|
||||
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
||||
driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
|
||||
driver_impl_ice_bug_report_outdated =
|
||||
it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the meantime
|
||||
.update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
||||
.url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
|
||||
driver_impl_ice_bug_report_update_note = please make sure that you have updated to the latest nightly
|
||||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||
|
||||
driver_impl_ice_flags = compiler flags: {$flags}
|
||||
|
@ -61,7 +61,7 @@ use std::str;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::{Instant, SystemTime};
|
||||
use time::{Date, OffsetDateTime, Time};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro do_not_use_print($($t:tt)*) {
|
||||
@ -1385,9 +1385,6 @@ pub fn install_ice_hook(
|
||||
using_internal_features
|
||||
}
|
||||
|
||||
const DATE_FORMAT: &[time::format_description::FormatItem<'static>] =
|
||||
&time::macros::format_description!("[year]-[month]-[day]");
|
||||
|
||||
/// Prints the ICE message, including query stack, but without backtrace.
|
||||
///
|
||||
/// The message will point the user at `bug_report_url` to report the ICE.
|
||||
@ -1416,33 +1413,14 @@ fn report_ice(
|
||||
dcx.emit_err(session_diagnostics::Ice);
|
||||
}
|
||||
|
||||
use time::ext::NumericalDuration;
|
||||
|
||||
// Try to hint user to update nightly if applicable when reporting an ICE.
|
||||
// Attempt to calculate when current version was released, and add 12 hours
|
||||
// as buffer. If the current version's release timestamp is older than
|
||||
// the system's current time + 24 hours + 12 hours buffer if we're on
|
||||
// nightly.
|
||||
if let Some("nightly") = option_env!("CFG_RELEASE_CHANNEL")
|
||||
&& let Some(version) = option_env!("CFG_VERSION")
|
||||
&& let Some(ver_date_str) = option_env!("CFG_VER_DATE")
|
||||
&& let Ok(ver_date) = Date::parse(&ver_date_str, DATE_FORMAT)
|
||||
&& let ver_datetime = OffsetDateTime::new_utc(ver_date, Time::MIDNIGHT)
|
||||
&& let system_datetime = OffsetDateTime::from(SystemTime::now())
|
||||
&& system_datetime.checked_sub(36.hours()).is_some_and(|d| d > ver_datetime)
|
||||
&& !using_internal_features.load(std::sync::atomic::Ordering::Relaxed)
|
||||
{
|
||||
dcx.emit_note(session_diagnostics::IceBugReportOutdated {
|
||||
version,
|
||||
bug_report_url,
|
||||
note_update: (),
|
||||
note_url: (),
|
||||
});
|
||||
if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
|
||||
} else {
|
||||
if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
|
||||
} else {
|
||||
dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
|
||||
// Only emit update nightly hint for users on nightly builds.
|
||||
if rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() {
|
||||
dcx.emit_note(session_diagnostics::UpdateNightlyNote);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,19 +43,12 @@ pub(crate) struct IceBugReport<'a> {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_bug_report_internal_feature)]
|
||||
pub(crate) struct IceBugReportInternalFeature;
|
||||
#[diag(driver_impl_ice_bug_report_update_note)]
|
||||
pub(crate) struct UpdateNightlyNote;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_bug_report_outdated)]
|
||||
pub(crate) struct IceBugReportOutdated<'a> {
|
||||
pub version: &'a str,
|
||||
pub bug_report_url: &'a str,
|
||||
#[note(driver_impl_update)]
|
||||
pub note_update: (),
|
||||
#[note(driver_impl_url)]
|
||||
pub note_url: (),
|
||||
}
|
||||
#[diag(driver_impl_ice_bug_report_internal_feature)]
|
||||
pub(crate) struct IceBugReportInternalFeature;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_version)]
|
||||
|
@ -2023,8 +2023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_extend_while(range_start.span, |c| c.is_whitespace())
|
||||
.unwrap_or(range_start.span)
|
||||
.span_extend_while_whitespace(range_start.span)
|
||||
.shrink_to_hi()
|
||||
.to(range_end.span);
|
||||
|
||||
|
@ -15,7 +15,7 @@ use rustc_middle::traits::{
|
||||
};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
use crate::errors::{
|
||||
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
|
||||
@ -763,8 +763,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
|
||||
self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
|
||||
} else {
|
||||
last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
|
||||
self.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_extend_while_whitespace(last_expr.span)
|
||||
.shrink_to_hi()
|
||||
.with_hi(last_stmt.span.hi())
|
||||
};
|
||||
|
||||
Some((span, needs_box))
|
||||
}
|
||||
|
||||
@ -867,10 +873,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
format!(" {ident} ")
|
||||
};
|
||||
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
|
||||
(
|
||||
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
|
||||
sugg,
|
||||
)
|
||||
(sm.span_extend_while_whitespace(left_span), sugg)
|
||||
};
|
||||
Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
|
||||
}
|
||||
|
@ -215,10 +215,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
|
||||
if let Some(deletion_span) = deletion_span {
|
||||
let msg = "elide the single-use lifetime";
|
||||
let (use_span, replace_lt) = if elide {
|
||||
let use_span = sess
|
||||
.source_map()
|
||||
.span_extend_while(use_span, char::is_whitespace)
|
||||
.unwrap_or(use_span);
|
||||
let use_span = sess.source_map().span_extend_while_whitespace(use_span);
|
||||
(use_span, String::new())
|
||||
} else {
|
||||
(use_span, "'_".to_owned())
|
||||
|
@ -817,7 +817,7 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
|
||||
|
||||
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
||||
|
||||
extern "C" void LLVMRustAddModuleFlag(
|
||||
extern "C" void LLVMRustAddModuleFlagU32(
|
||||
LLVMModuleRef M,
|
||||
Module::ModFlagBehavior MergeBehavior,
|
||||
const char *Name,
|
||||
@ -825,6 +825,16 @@ extern "C" void LLVMRustAddModuleFlag(
|
||||
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustAddModuleFlagString(
|
||||
LLVMModuleRef M,
|
||||
Module::ModFlagBehavior MergeBehavior,
|
||||
const char *Name,
|
||||
const char *Value,
|
||||
size_t ValueLen) {
|
||||
unwrap(M)->addModuleFlag(MergeBehavior, Name,
|
||||
MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
|
||||
}
|
||||
|
||||
extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
|
||||
size_t Len) {
|
||||
return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
|
||||
|
@ -126,59 +126,33 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
|
||||
let mut field_remapping = UnordMap::default();
|
||||
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
let mut parent_captures =
|
||||
tcx.closure_captures(parent_def_id).iter().copied().enumerate().peekable();
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
|
||||
for (child_field_idx, child_capture) in tcx
|
||||
let mut child_captures = tcx
|
||||
.closure_captures(coroutine_def_id)
|
||||
.iter()
|
||||
.copied()
|
||||
// By construction we capture all the args first.
|
||||
.skip(num_args)
|
||||
.enumerate()
|
||||
.peekable();
|
||||
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
for (parent_field_idx, parent_capture) in
|
||||
tcx.closure_captures(parent_def_id).iter().copied().enumerate()
|
||||
{
|
||||
loop {
|
||||
let Some(&(parent_field_idx, parent_capture)) = parent_captures.peek() else {
|
||||
bug!("we ran out of parent captures!")
|
||||
};
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
|
||||
let PlaceBase::Upvar(parent_base) = parent_capture.place.base else {
|
||||
bug!("expected capture to be an upvar");
|
||||
};
|
||||
let PlaceBase::Upvar(child_base) = child_capture.place.base else {
|
||||
bug!("expected capture to be an upvar");
|
||||
};
|
||||
|
||||
assert!(
|
||||
child_capture.place.projections.len() >= parent_capture.place.projections.len()
|
||||
);
|
||||
// A parent matches a child they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
if parent_base.var_path.hir_id != child_base.var_path.hir_id
|
||||
|| !std::iter::zip(
|
||||
&child_capture.place.projections,
|
||||
&parent_capture.place.projections,
|
||||
)
|
||||
.all(|(child, parent)| child.kind == parent.kind)
|
||||
{
|
||||
// Make sure the field was used at least once.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
);
|
||||
field_used_at_least_once = false;
|
||||
// Skip this field.
|
||||
let _ = parent_captures.next().unwrap();
|
||||
continue;
|
||||
}
|
||||
// A parent matches a child if they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
while child_captures.peek().map_or(false, |(_, child_capture)| {
|
||||
child_prefix_matches_parent_projections(parent_capture, child_capture)
|
||||
}) {
|
||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||
|
||||
// Store this set of additional projections (fields and derefs).
|
||||
// We need to re-apply them later.
|
||||
@ -221,15 +195,15 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
);
|
||||
|
||||
field_used_at_least_once = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pop the last parent capture
|
||||
if field_used_at_least_once {
|
||||
let _ = parent_captures.next().unwrap();
|
||||
// Make sure the field was used at least once.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
);
|
||||
}
|
||||
assert_eq!(parent_captures.next(), None, "leftover parent captures?");
|
||||
assert_eq!(child_captures.next(), None, "leftover child captures?");
|
||||
|
||||
if coroutine_kind == ty::ClosureKind::FnOnce {
|
||||
assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len());
|
||||
@ -251,6 +225,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
let mut by_move_body = body.clone();
|
||||
MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
|
||||
dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
|
||||
// FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body.
|
||||
by_move_body.source = mir::MirSource::from_instance(InstanceDef::CoroutineKindShim {
|
||||
coroutine_def_id: coroutine_def_id.to_def_id(),
|
||||
});
|
||||
@ -258,6 +233,23 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
||||
}
|
||||
}
|
||||
|
||||
fn child_prefix_matches_parent_projections(
|
||||
parent_capture: &ty::CapturedPlace<'_>,
|
||||
child_capture: &ty::CapturedPlace<'_>,
|
||||
) -> bool {
|
||||
let PlaceBase::Upvar(parent_base) = parent_capture.place.base else {
|
||||
bug!("expected capture to be an upvar");
|
||||
};
|
||||
let PlaceBase::Upvar(child_base) = child_capture.place.base else {
|
||||
bug!("expected capture to be an upvar");
|
||||
};
|
||||
|
||||
assert!(child_capture.place.projections.len() >= parent_capture.place.projections.len());
|
||||
parent_base.var_path.hir_id == child_base.var_path.hir_id
|
||||
&& std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
|
||||
.all(|(child, parent)| child.kind == parent.kind)
|
||||
}
|
||||
|
||||
struct MakeByMoveBody<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, &'tcx [Projection<'tcx>])>,
|
||||
|
@ -654,6 +654,12 @@ impl SourceMap {
|
||||
})
|
||||
}
|
||||
|
||||
/// Extends the span to include any trailing whitespace, or returns the original
|
||||
/// span if a `SpanSnippetError` was encountered.
|
||||
pub fn span_extend_while_whitespace(&self, span: Span) -> Span {
|
||||
self.span_extend_while(span, char::is_whitespace).unwrap_or(span)
|
||||
}
|
||||
|
||||
/// Extends the given `Span` to previous character while the previous character matches the predicate
|
||||
pub fn span_extend_prev_while(
|
||||
&self,
|
||||
@ -1034,12 +1040,9 @@ impl SourceMap {
|
||||
/// // ^^^^^^ input
|
||||
/// ```
|
||||
pub fn mac_call_stmt_semi_span(&self, mac_call: Span) -> Option<Span> {
|
||||
let span = self.span_extend_while(mac_call, char::is_whitespace).ok()?;
|
||||
let span = span.shrink_to_hi().with_hi(BytePos(span.hi().0.checked_add(1)?));
|
||||
if self.span_to_snippet(span).as_deref() != Ok(";") {
|
||||
return None;
|
||||
}
|
||||
Some(span)
|
||||
let span = self.span_extend_while_whitespace(mac_call);
|
||||
let span = self.next_point(span);
|
||||
if self.span_to_snippet(span).as_deref() == Ok(";") { Some(span) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1592,8 +1592,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_extend_while(expr_span, char::is_whitespace)
|
||||
.unwrap_or(expr_span)
|
||||
.span_extend_while_whitespace(expr_span)
|
||||
.shrink_to_hi()
|
||||
.to(await_expr.span.shrink_to_hi());
|
||||
err.span_suggestion(
|
||||
@ -4851,10 +4850,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
|
||||
let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
|
||||
return None;
|
||||
};
|
||||
let Ok(async_span) = tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace())
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span);
|
||||
|
||||
let future = tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
|
||||
let [hir::GenericBound::Trait(trait_ref, _)] = future.bounds else {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::ffi::OsStr;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::num::NonZero;
|
||||
use crate::path::Path;
|
||||
use crate::sys::fs::File;
|
||||
@ -16,7 +15,14 @@ pub use crate::ffi::OsString as EnvKey;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct Command {
|
||||
program: OsString,
|
||||
args: Vec<OsString>,
|
||||
env: CommandEnv,
|
||||
|
||||
cwd: Option<OsString>,
|
||||
stdin: Option<Stdio>,
|
||||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
}
|
||||
|
||||
// passed back to std::process with the pipes connected to the child, if any
|
||||
@ -27,39 +33,62 @@ pub struct StdioPipes {
|
||||
pub stderr: Option<AnonPipe>,
|
||||
}
|
||||
|
||||
// FIXME: This should be a unit struct, so we can always construct it
|
||||
// The value here should be never used, since we cannot spawn processes.
|
||||
#[derive(Debug)]
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
ParentStdout,
|
||||
ParentStderr,
|
||||
#[allow(dead_code)] // This variant exists only for the Debug impl
|
||||
InheritFile(File),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(_program: &OsStr) -> Command {
|
||||
Command { env: Default::default() }
|
||||
pub fn new(program: &OsStr) -> Command {
|
||||
Command {
|
||||
program: program.to_owned(),
|
||||
args: vec![program.to_owned()],
|
||||
env: Default::default(),
|
||||
cwd: None,
|
||||
stdin: None,
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, _arg: &OsStr) {}
|
||||
pub fn arg(&mut self, arg: &OsStr) {
|
||||
self.args.push(arg.to_owned());
|
||||
}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
&mut self.env
|
||||
}
|
||||
|
||||
pub fn cwd(&mut self, _dir: &OsStr) {}
|
||||
pub fn cwd(&mut self, dir: &OsStr) {
|
||||
self.cwd = Some(dir.to_owned());
|
||||
}
|
||||
|
||||
pub fn stdin(&mut self, _stdin: Stdio) {}
|
||||
pub fn stdin(&mut self, stdin: Stdio) {
|
||||
self.stdin = Some(stdin);
|
||||
}
|
||||
|
||||
pub fn stdout(&mut self, _stdout: Stdio) {}
|
||||
pub fn stdout(&mut self, stdout: Stdio) {
|
||||
self.stdout = Some(stdout);
|
||||
}
|
||||
|
||||
pub fn stderr(&mut self, _stderr: Stdio) {}
|
||||
pub fn stderr(&mut self, stderr: Stdio) {
|
||||
self.stderr = Some(stderr);
|
||||
}
|
||||
|
||||
pub fn get_program(&self) -> &OsStr {
|
||||
panic!("unsupported")
|
||||
&self.program
|
||||
}
|
||||
|
||||
pub fn get_args(&self) -> CommandArgs<'_> {
|
||||
CommandArgs { _p: PhantomData }
|
||||
let mut iter = self.args.iter();
|
||||
iter.next();
|
||||
CommandArgs { iter }
|
||||
}
|
||||
|
||||
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
||||
@ -67,7 +96,7 @@ impl Command {
|
||||
}
|
||||
|
||||
pub fn get_current_dir(&self) -> Option<&Path> {
|
||||
None
|
||||
self.cwd.as_ref().map(|cs| Path::new(cs))
|
||||
}
|
||||
|
||||
pub fn spawn(
|
||||
@ -91,31 +120,83 @@ impl From<AnonPipe> for Stdio {
|
||||
|
||||
impl From<io::Stdout> for Stdio {
|
||||
fn from(_: io::Stdout) -> Stdio {
|
||||
// FIXME: This is wrong.
|
||||
// Instead, the Stdio we have here should be a unit struct.
|
||||
panic!("unsupported")
|
||||
Stdio::ParentStdout
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Stderr> for Stdio {
|
||||
fn from(_: io::Stderr) -> Stdio {
|
||||
// FIXME: This is wrong.
|
||||
// Instead, the Stdio we have here should be a unit struct.
|
||||
panic!("unsupported")
|
||||
Stdio::ParentStderr
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(_file: File) -> Stdio {
|
||||
// FIXME: This is wrong.
|
||||
// Instead, the Stdio we have here should be a unit struct.
|
||||
panic!("unsupported")
|
||||
fn from(file: File) -> Stdio {
|
||||
Stdio::InheritFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(())
|
||||
// show all attributes
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.alternate() {
|
||||
let mut debug_command = f.debug_struct("Command");
|
||||
debug_command.field("program", &self.program).field("args", &self.args);
|
||||
if !self.env.is_unchanged() {
|
||||
debug_command.field("env", &self.env);
|
||||
}
|
||||
|
||||
if self.cwd.is_some() {
|
||||
debug_command.field("cwd", &self.cwd);
|
||||
}
|
||||
|
||||
if self.stdin.is_some() {
|
||||
debug_command.field("stdin", &self.stdin);
|
||||
}
|
||||
if self.stdout.is_some() {
|
||||
debug_command.field("stdout", &self.stdout);
|
||||
}
|
||||
if self.stderr.is_some() {
|
||||
debug_command.field("stderr", &self.stderr);
|
||||
}
|
||||
|
||||
debug_command.finish()
|
||||
} else {
|
||||
if let Some(ref cwd) = self.cwd {
|
||||
write!(f, "cd {cwd:?} && ")?;
|
||||
}
|
||||
if self.env.does_clear() {
|
||||
write!(f, "env -i ")?;
|
||||
// Altered env vars will be printed next, that should exactly work as expected.
|
||||
} else {
|
||||
// Removed env vars need the command to be wrapped in `env`.
|
||||
let mut any_removed = false;
|
||||
for (key, value_opt) in self.get_envs() {
|
||||
if value_opt.is_none() {
|
||||
if !any_removed {
|
||||
write!(f, "env ")?;
|
||||
any_removed = true;
|
||||
}
|
||||
write!(f, "-u {} ", key.to_string_lossy())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Altered env vars can just be added in front of the program.
|
||||
for (key, value_opt) in self.get_envs() {
|
||||
if let Some(value) = value_opt {
|
||||
write!(f, "{}={value:?} ", key.to_string_lossy())?;
|
||||
}
|
||||
}
|
||||
if self.program != self.args[0] {
|
||||
write!(f, "[{:?}] ", self.program)?;
|
||||
}
|
||||
write!(f, "{:?}", self.args[0])?;
|
||||
|
||||
for arg in &self.args[1..] {
|
||||
write!(f, " {:?}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,23 +298,30 @@ impl Process {
|
||||
}
|
||||
|
||||
pub struct CommandArgs<'a> {
|
||||
_p: PhantomData<&'a ()>,
|
||||
iter: crate::slice::Iter<'a, OsString>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CommandArgs<'a> {
|
||||
type Item = &'a OsStr;
|
||||
fn next(&mut self) -> Option<&'a OsStr> {
|
||||
None
|
||||
self.iter.next().map(|os| &**os)
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ExactSizeIterator for CommandArgs<'a> {}
|
||||
impl<'a> ExactSizeIterator for CommandArgs<'a> {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for CommandArgs<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().finish()
|
||||
f.debug_list().entries(self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
@ -294,8 +294,7 @@ fn elision_suggestions(
|
||||
let span = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_extend_while(usage.ident.span, |ch| ch.is_ascii_whitespace())
|
||||
.unwrap_or(usage.ident.span);
|
||||
.span_extend_while_whitespace(usage.ident.span);
|
||||
|
||||
(span, String::new())
|
||||
},
|
||||
|
@ -819,6 +819,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
||||
"needs-dynamic-linking",
|
||||
"needs-git-hash",
|
||||
"needs-llvm-components",
|
||||
"needs-matching-clang",
|
||||
"needs-profiler-support",
|
||||
"needs-relocation-model-pic",
|
||||
"needs-run-enabled",
|
||||
|
@ -86,6 +86,18 @@ impl Rustc {
|
||||
self
|
||||
}
|
||||
|
||||
/// This flag defers LTO optimizations to the linker.
|
||||
pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
|
||||
self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify what happens when the code panics.
|
||||
pub fn panic(&mut self, option: &str) -> &mut Self {
|
||||
self.cmd.arg(format!("-Cpanic={option}"));
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify number of codegen units
|
||||
pub fn codegen_units(&mut self, units: usize) -> &mut Self {
|
||||
self.cmd.arg(format!("-Ccodegen-units={units}"));
|
||||
@ -183,6 +195,18 @@ impl Rustc {
|
||||
output
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if output.status.code().unwrap() != code {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// Inspect what the underlying [`Command`] is up to the current construction.
|
||||
pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
|
||||
f(&self.cmd);
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output};
|
||||
|
||||
@ -58,9 +59,8 @@ impl Rustdoc {
|
||||
self
|
||||
}
|
||||
|
||||
/// Fallback argument provider. Consider adding meaningfully named methods instead of using
|
||||
/// this method.
|
||||
pub fn arg(&mut self, arg: &str) -> &mut Self {
|
||||
/// Generic command argument provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
|
||||
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
|
||||
self.cmd.arg(arg);
|
||||
self
|
||||
}
|
||||
@ -77,4 +77,16 @@ impl Rustdoc {
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if output.status.code().unwrap() != code {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,6 @@ run-make/emit/Makefile
|
||||
run-make/env-dep-info/Makefile
|
||||
run-make/error-found-staticlib-instead-crate/Makefile
|
||||
run-make/error-writing-dependencies/Makefile
|
||||
run-make/exit-code/Makefile
|
||||
run-make/export-executable-symbols/Makefile
|
||||
run-make/extern-diff-internal-name/Makefile
|
||||
run-make/extern-flag-disambiguates/Makefile
|
||||
|
@ -18,7 +18,7 @@ const ENTRY_LIMIT: usize = 900;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1722;
|
||||
const ROOT_ENTRY_LIMIT: usize = 861;
|
||||
const ROOT_ENTRY_LIMIT: usize = 859;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
20
tests/codegen/riscv-target-abi.rs
Normal file
20
tests/codegen/riscv-target-abi.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ revisions:riscv64gc riscv32gc riscv32imac
|
||||
|
||||
//@[riscv64gc] compile-flags: --target=riscv64gc-unknown-linux-gnu
|
||||
//@[riscv64gc] needs-llvm-components: riscv
|
||||
// riscv64gc: !{i32 1, !"target-abi", !"lp64d"}
|
||||
|
||||
//@[riscv32gc] compile-flags: --target=riscv32gc-unknown-linux-musl
|
||||
//@[riscv32gc] needs-llvm-components: riscv
|
||||
// riscv32gc: !{i32 1, !"target-abi", !"ilp32d"}
|
||||
|
||||
//@[riscv32imac] compile-flags: --target=riscv32imac-unknown-none-elf
|
||||
//@[riscv32imac] needs-llvm-components: riscv
|
||||
// riscv32imac-NOT: !"target-abi"
|
||||
|
||||
#![feature(no_core, lang_items)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
5
tests/run-make/cross-lang-lto-riscv-abi/cstart.c
Normal file
5
tests/run-make/cross-lang-lto-riscv-abi/cstart.c
Normal file
@ -0,0 +1,5 @@
|
||||
extern void hello();
|
||||
|
||||
void _start() {
|
||||
hello();
|
||||
}
|
9
tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs
Normal file
9
tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn hello() {}
|
74
tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
Normal file
74
tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
Normal file
@ -0,0 +1,74 @@
|
||||
//! Make sure that cross-language LTO works on riscv targets,
|
||||
//! which requires extra abi metadata to be emitted.
|
||||
//@ needs-matching-clang
|
||||
//@ needs-llvm-components riscv
|
||||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::{bin_name, rustc, tmp_dir};
|
||||
use std::{
|
||||
env,
|
||||
path::PathBuf,
|
||||
process::{Command, Output},
|
||||
str,
|
||||
};
|
||||
|
||||
fn handle_failed_output(output: Output) {
|
||||
eprintln!("output status: `{}`", output.status);
|
||||
eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
|
||||
eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
|
||||
std::process::exit(1)
|
||||
}
|
||||
|
||||
fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: bool) {
|
||||
eprintln!("Checking target {target}");
|
||||
// Rust part
|
||||
rustc()
|
||||
.input("riscv-xlto.rs")
|
||||
.crate_type("rlib")
|
||||
.target(target)
|
||||
.panic("abort")
|
||||
.linker_plugin_lto("on")
|
||||
.run();
|
||||
// C part
|
||||
let clang = env::var("CLANG").unwrap();
|
||||
let mut cmd = Command::new(clang);
|
||||
let executable = tmp_dir().join("riscv-xlto");
|
||||
cmd.arg("-target")
|
||||
.arg(clang_target)
|
||||
.arg(format!("-march={carch}"))
|
||||
.arg(format!("-flto=thin"))
|
||||
.arg(format!("-fuse-ld=lld"))
|
||||
.arg("-nostdlib")
|
||||
.arg("-o")
|
||||
.arg(&executable)
|
||||
.arg("cstart.c")
|
||||
.arg(tmp_dir().join("libriscv_xlto.rlib"));
|
||||
eprintln!("{cmd:?}");
|
||||
let output = cmd.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(output);
|
||||
}
|
||||
// Check that the built binary has correct float abi
|
||||
let llvm_readobj =
|
||||
PathBuf::from(env::var("LLVM_BIN_DIR").unwrap()).join(bin_name("llvm-readobj"));
|
||||
let mut cmd = Command::new(llvm_readobj);
|
||||
cmd.arg("--file-header").arg(executable);
|
||||
eprintln!("{cmd:?}");
|
||||
let output = cmd.output().unwrap();
|
||||
if output.status.success() {
|
||||
assert!(
|
||||
!(is_double_float
|
||||
^ dbg!(str::from_utf8(&output.stdout).unwrap())
|
||||
.contains("EF_RISCV_FLOAT_ABI_DOUBLE"))
|
||||
)
|
||||
} else {
|
||||
handle_failed_output(output);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
check_target("riscv64gc-unknown-linux-gnu", "riscv64-linux-gnu", "rv64gc", true);
|
||||
check_target("riscv64imac-unknown-none-elf", "riscv64-unknown-elf", "rv64imac", false);
|
||||
check_target("riscv32imac-unknown-none-elf", "riscv32-unknown-elf", "rv32imac", false);
|
||||
check_target("riscv32gc-unknown-linux-gnu", "riscv32-linux-gnu", "rv32gc", true);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) success.rs; [ $$? -eq 0 ]
|
||||
$(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||
$(RUSTC) compile-error.rs; [ $$? -eq 1 ]
|
||||
RUSTC_ICE=0 $(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ]
|
||||
$(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ]
|
||||
$(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||
$(RUSTDOC) compile-error.rs; [ $$? -eq 1 ]
|
||||
$(RUSTDOC) lint-failure.rs; [ $$? -eq 1 ]
|
43
tests/run-make/exit-code/rmake.rs
Normal file
43
tests/run-make/exit-code/rmake.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations
|
||||
|
||||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::{rustc, rustdoc, tmp_dir};
|
||||
|
||||
fn main() {
|
||||
rustc()
|
||||
.arg("success.rs")
|
||||
.run();
|
||||
|
||||
rustc()
|
||||
.arg("--invalid-arg-foo")
|
||||
.run_fail_assert_exit_code(1);
|
||||
|
||||
rustc()
|
||||
.arg("compile-error.rs")
|
||||
.run_fail_assert_exit_code(1);
|
||||
|
||||
rustc()
|
||||
.env("RUSTC_ICE", "0")
|
||||
.arg("-Ztreat-err-as-bug")
|
||||
.arg("compile-error.rs")
|
||||
.run_fail_assert_exit_code(101);
|
||||
|
||||
rustdoc()
|
||||
.arg("success.rs")
|
||||
.arg("-o")
|
||||
.arg(tmp_dir().join("exit-code"))
|
||||
.run();
|
||||
|
||||
rustdoc()
|
||||
.arg("--invalid-arg-foo")
|
||||
.run_fail_assert_exit_code(1);
|
||||
|
||||
rustdoc()
|
||||
.arg("compile-error.rs")
|
||||
.run_fail_assert_exit_code(1);
|
||||
|
||||
rustdoc()
|
||||
.arg("lint-failure.rs")
|
||||
.run_fail_assert_exit_code(1);
|
||||
}
|
@ -12,6 +12,8 @@ error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md
|
||||
|
||||
note: please make sure that you have updated to the latest nightly
|
||||
|
||||
note: rustc {version} running on {platform}
|
||||
|
||||
query stack during panic:
|
||||
|
@ -4,6 +4,8 @@ error: internal compiler error[E0080]: evaluation of constant value failed
|
||||
LL | const X: i32 = 1 / 0;
|
||||
| ^^^^^ attempt to divide `1_i32` by zero
|
||||
|
||||
note: please make sure that you have updated to the latest nightly
|
||||
|
||||
query stack during panic:
|
||||
#0 [eval_to_allocation_raw] const-evaluating + checking `X`
|
||||
#1 [eval_to_const_value_raw] simplifying constant for the type system `X`
|
||||
|
@ -1,2 +0,0 @@
|
||||
fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
|
||||
//~^ ERROR cannot find value `this_does_nothing_what_the` in this scope
|
@ -1,9 +0,0 @@
|
||||
error[E0425]: cannot find value `this_does_nothing_what_the` in this scope
|
||||
--> $DIR/does-nothing.rs:1:32
|
||||
|
|
||||
LL | fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
@ -20,6 +20,8 @@ error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
query stack during panic:
|
||||
#0 [resolver_for_lowering_raw] getting the resolver for lowering
|
||||
end of query stack
|
||||
|
@ -30,6 +30,8 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
||||
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
|
||||
|
||||
note: please make sure that you have updated to the latest nightly
|
||||
|
||||
note: rustc $VERSION running on $TARGET
|
||||
|
||||
note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics
|
||||
|
11
tests/ui/typeck/remove-semi-but-confused-char.rs
Normal file
11
tests/ui/typeck/remove-semi-but-confused-char.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Ensures our "remove semicolon" suggestion isn't hardcoded with a character width,
|
||||
// in case it was accidentally mixed up with a greek question mark.
|
||||
// issue: rust-lang/rust#123607
|
||||
|
||||
pub fn square(num: i32) -> i32 {
|
||||
//~^ ERROR mismatched types
|
||||
num * num;
|
||||
//~^ ERROR unknown start of token
|
||||
}
|
||||
|
||||
fn main() {}
|
25
tests/ui/typeck/remove-semi-but-confused-char.stderr
Normal file
25
tests/ui/typeck/remove-semi-but-confused-char.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error: unknown start of token: \u{37e}
|
||||
--> $DIR/remove-semi-but-confused-char.rs:7:14
|
||||
|
|
||||
LL | num * num;
|
||||
| ^
|
||||
|
|
||||
help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
|
||||
|
|
||||
LL | num * num;
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/remove-semi-but-confused-char.rs:5:28
|
||||
|
|
||||
LL | pub fn square(num: i32) -> i32 {
|
||||
| ------ ^^^ expected `i32`, found `()`
|
||||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
LL |
|
||||
LL | num * num;
|
||||
| - help: remove this semicolon to return this value
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
x
Reference in New Issue
Block a user