diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 093a985495c9f..01addc8127e8a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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, diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 06a681c24e697..e61af863dc079 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -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(), diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index df9f066e58a33..d32baa6dc02a6 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -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 diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d3a851b40c0a2..4fdaa59e0e559 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -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(), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 284bc74d5c434..5509baaa3e94c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -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<'_>; diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl index 62391daecd053..5b39248302e7a 100644 --- a/compiler/rustc_driver_impl/messages.ftl +++ b/compiler/rustc_driver_impl/messages.ftl @@ -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} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b4007aeb8d7c8..1f44621736cdb 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -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); } } diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 62d0da62d2a79..1a9683e840afd 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -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)] diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d3df3dd38853e..7a1a2c498aa7d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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); diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 9a05fb1c30f8e..7855031e705d7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -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 }) } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index e2010ab3830ac..16e3b8c11c133 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -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()) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index a6894a7e08988..37c2da4c23a1a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -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; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index d6ec7d64926c3..ccb229616e855 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -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() - { - loop { - let Some(&(parent_field_idx, parent_capture)) = parent_captures.peek() else { - bug!("we ran out of parent captures!") - }; + .peekable(); - 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"); - }; + // 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() + { + // 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; - 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, bool, &'tcx [Projection<'tcx>])>, diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 770624d331d1e..f721a04d6b968 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -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 { - 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 } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index af90372b97ce3..2067956d0f5f0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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 { diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/pal/unsupported/process.rs index 6a989dd3e76bb..2445d9073dbb9 100644 --- a/library/std/src/sys/pal/unsupported/process.rs +++ b/library/std/src/sys/pal/unsupported/process.rs @@ -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, env: CommandEnv, + + cwd: Option, + stdin: Option, + stdout: Option, + stderr: Option, } // passed back to std::process with the pipes connected to the child, if any @@ -27,39 +33,62 @@ pub struct StdioPipes { pub stderr: Option, } -// 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 for Stdio { impl From 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 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 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) { - (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() } } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index a60a40a2a4713..2bb63ec2b046b 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -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()) }, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 626841cb1bd12..ec944cb7fb47e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -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", diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 217da36ccc7d7..5a5b008a7cb8a 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -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); diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 9607ff02f9686..1fb4b589d76af 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -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>(&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 + } } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index dfd30d79abca9..3914feb3499dd 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -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 diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 0565254146193..78de8c0537dcc 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -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 diff --git a/tests/codegen/riscv-target-abi.rs b/tests/codegen/riscv-target-abi.rs new file mode 100644 index 0000000000000..5d545af9c7690 --- /dev/null +++ b/tests/codegen/riscv-target-abi.rs @@ -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 {} diff --git a/tests/run-make/cross-lang-lto-riscv-abi/cstart.c b/tests/run-make/cross-lang-lto-riscv-abi/cstart.c new file mode 100644 index 0000000000000..660469b75a821 --- /dev/null +++ b/tests/run-make/cross-lang-lto-riscv-abi/cstart.c @@ -0,0 +1,5 @@ +extern void hello(); + +void _start() { + hello(); +} diff --git a/tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs b/tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs new file mode 100644 index 0000000000000..c31cf27f9aef7 --- /dev/null +++ b/tests/run-make/cross-lang-lto-riscv-abi/riscv-xlto.rs @@ -0,0 +1,9 @@ +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn hello() {} diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs new file mode 100644 index 0000000000000..2f13cf17169fa --- /dev/null +++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs @@ -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); +} diff --git a/tests/run-make/exit-code/Makefile b/tests/run-make/exit-code/Makefile deleted file mode 100644 index 155e5cd112344..0000000000000 --- a/tests/run-make/exit-code/Makefile +++ /dev/null @@ -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 ] diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs new file mode 100644 index 0000000000000..f387626287e3f --- /dev/null +++ b/tests/run-make/exit-code/rmake.rs @@ -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); +} diff --git a/tests/rustdoc-ui/ice-bug-report-url.stderr b/tests/rustdoc-ui/ice-bug-report-url.stderr index 06a5269131083..66622a7654c9d 100644 --- a/tests/rustdoc-ui/ice-bug-report-url.stderr +++ b/tests/rustdoc-ui/ice-bug-report-url.stderr @@ -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: diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr index 96fd9ed5f043b..0a28c5b80bf77 100644 --- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr @@ -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` diff --git a/tests/ui/does-nothing.rs b/tests/ui/does-nothing.rs deleted file mode 100644 index e4992e2cfd3c9..0000000000000 --- a/tests/ui/does-nothing.rs +++ /dev/null @@ -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 diff --git a/tests/ui/does-nothing.stderr b/tests/ui/does-nothing.stderr deleted file mode 100644 index d5ea3626e81c8..0000000000000 --- a/tests/ui/does-nothing.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 82b61e43f4494..23b863568bc74 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -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 diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 54b1ea2764a5f..436f9ecf93dec 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -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 diff --git a/tests/ui/typeck/remove-semi-but-confused-char.rs b/tests/ui/typeck/remove-semi-but-confused-char.rs new file mode 100644 index 0000000000000..ccc6f59344c05 --- /dev/null +++ b/tests/ui/typeck/remove-semi-but-confused-char.rs @@ -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() {} diff --git a/tests/ui/typeck/remove-semi-but-confused-char.stderr b/tests/ui/typeck/remove-semi-but-confused-char.stderr new file mode 100644 index 0000000000000..2d0b53a60ce40 --- /dev/null +++ b/tests/ui/typeck/remove-semi-but-confused-char.stderr @@ -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`.