diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 2a7dc8ba10162..11b8890346dfb 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -35,18 +35,18 @@ pub(crate) struct LoweredConstraints<'tcx> { pub(crate) placeholder_indices: PlaceholderIndices<'tcx>, } -impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { - pub(crate) fn init(definitions: &'d IndexVec>) -> Self { - Self { scc_to_annotation: IndexVec::new(), definitions } - } -} - /// A Visitor for SCC annotation construction. pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> { pub(crate) scc_to_annotation: IndexVec, definitions: &'d IndexVec>, } +impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { + pub(crate) fn init(definitions: &'d IndexVec>) -> Self { + Self { scc_to_annotation: IndexVec::new(), definitions } + } +} + impl scc::Annotations for SccAnnotations<'_, '_, RegionTracker> { fn new(&self, element: RegionVid) -> RegionTracker { RegionTracker::new(element, &self.definitions[element]) @@ -118,7 +118,7 @@ impl RegionTracker { } /// The largest universe this SCC can name. It's the smallest - /// largest nameable universe of any reachable region, or + /// max-nameable-universe of any reachable region, or /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)` pub(crate) fn max_nameable_universe(self) -> UniverseIndex { self.max_nameable_universe.0 @@ -208,7 +208,7 @@ pub(super) fn region_definitions<'tcx>( /// graph such that there is a series of constraints /// A: B: C: ... : X where /// A contains a placeholder whose universe cannot be named by X, -/// add a constraint that A: 'static. This is a safe upper bound +/// add a constraint that X: 'static. This is a safe upper bound /// in the face of borrow checker/trait solver limitations that will /// eventually go away. /// @@ -327,8 +327,6 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>( for scc in sccs.all_sccs() { // No point in adding 'static: 'static! - // This micro-optimisation makes somewhat sense - // because static outlives *everything*. if scc == sccs.scc(fr_static) { continue; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5cdda777723b3..2a759387788a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -501,43 +501,48 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut errors_buffer = RegionErrors::new(infcx.tcx); - // If this is a closure, we can propagate unsatisfied - // `outlives_requirements` to our creator, so create a vector - // to store those. Otherwise, we'll pass in `None` to the - // functions below, which will trigger them to report errors - // eagerly. - let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); - debug!(?outlives_requirements); + debug!(?propagated_outlives_requirements); // In Polonius mode, the errors about missing universal region relations are in the output // and need to be emitted or propagated. Otherwise, we need to check whether the // constraints were too strong, and if so, emit or propagate those errors. if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { self.check_polonius_subset_errors( - outlives_requirements.as_mut(), + propagated_outlives_requirements.as_mut(), &mut errors_buffer, polonius_output .as_ref() .expect("Polonius output is unavailable despite `-Z polonius`"), ); } else { - self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer); + self.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); } debug!(?errors_buffer); - let outlives_requirements = outlives_requirements.unwrap_or_default(); + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); - if outlives_requirements.is_empty() { + if propagated_outlives_requirements.is_empty() { (None, errors_buffer) } else { let num_external_vids = self.universal_regions().num_global_and_external_regions(); ( - Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }), + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), errors_buffer, ) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3e373c42eca34..9ecf5afcbcb35 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2350,6 +2350,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; + pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 180559d28d848..e9983d11c127f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -480,6 +480,10 @@ pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { match req.kind { PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out), PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out), + PrintKind::BackendHasMnemonic => { + let mnemonic = req.arg.as_deref().expect("BackendHasMnemonic requires arg"); + print_target_has_mnemonic(tm.raw(), mnemonic, out) + } _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } @@ -738,3 +742,10 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } + +fn print_target_has_mnemonic(tm: &llvm::TargetMachine, mnemonic: &str, out: &mut String) { + use std::fmt::Write; + let cstr = SmallCStr::new(mnemonic); + let has_mnemonic = unsafe { llvm::LLVMRustTargetHasMnemonic(tm, cstr.as_ptr()) }; + writeln!(out, "{}", has_mnemonic).unwrap(); +} diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 3f12e857391b2..9b9fa737d6d8d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -217,12 +217,10 @@ fn create_mingw_dll_import_lib( // able to control the *exact* spelling of each of the symbols that are being imported: // hence we don't want `dlltool` adding leading underscores automatically. let dlltool = find_binutils_dlltool(sess); - let temp_prefix = { - let mut path = PathBuf::from(&output_path); - path.pop(); - path.push(lib_name); - path - }; + // temp_prefix doesn't handle paths with spaces so + // use a relative path and set the current working directory + let cwd = output_path.parent().unwrap_or(output_path); + let temp_prefix = lib_name; // dlltool target architecture args from: // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch { @@ -246,7 +244,8 @@ fn create_mingw_dll_import_lib( .arg(dlltool_target_bitness) .arg("--no-leading-underscore") .arg("--temp-prefix") - .arg(temp_prefix); + .arg(temp_prefix) + .current_dir(cwd); match dlltool_cmd.output() { Err(e) => { diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 10abfd7a55ced..c04688e0a49fa 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -27,7 +27,7 @@ mod tests; /// the max/min element of the SCC, or all of the above. /// /// Concretely, the both merge operations must commute, e.g. where `merge` -/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)` +/// is `update_scc` and `update_reachable`: `a.merge(b) == b.merge(a)` /// /// In general, what you want is probably always min/max according /// to some ordering, potentially with side constraints (min x such diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c15c3c229398c..b05f5bc4a8e20 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -804,6 +804,9 @@ fn print_crate_info( let calling_conventions = rustc_abi::all_names(); println_info!("{}", calling_conventions.join("\n")); } + BackendHasMnemonic => { + codegen_backend.print(req, &mut crate_info, sess); + } BackendHasZstd => { let has_zstd: bool = codegen_backend.has_zstd(); println_info!("{has_zstd}"); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 726f05e36ac9f..c7e8f99465e18 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/LTO/LTO.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" @@ -94,6 +95,25 @@ extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, return MCInfo->checkFeatures(std::string("+") + Feature); } +/// Check whether the target has a specific assembly mnemonic like `ret` or +/// `nop`. +/// This should be fast enough but if its not we have to look into another +/// method of checking. +extern "C" bool LLVMRustTargetHasMnemonic(LLVMTargetMachineRef TM, + const char *Mnemonic) { + TargetMachine *Target = unwrap(TM); + const MCInstrInfo *MII = Target->getMCInstrInfo(); + StringRef MnemonicRef(Mnemonic); + + for (unsigned i = 0; i < MII->getNumOpcodes(); i++) { + StringRef Name = MII->getName(i); + if (Name.equals_insensitive(MnemonicRef)) { + return true; + } + } + return false; +} + enum class LLVMRustCodeModel { Tiny, Small, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 60237c98fed2c..e1ef06ca7c713 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1416,12 +1416,12 @@ impl<'tcx> TyCtxt<'tcx> { self, stable_crate_id: StableCrateId, ) -> Result, CrateNum> { - if let Some(&existing) = self.untracked().stable_crate_ids.read().get(&stable_crate_id) { + let mut lock = self.untracked().stable_crate_ids.write(); + if let Some(&existing) = lock.get(&stable_crate_id) { return Err(existing); } - - let num = CrateNum::new(self.untracked().stable_crate_ids.read().len()); - self.untracked().stable_crate_ids.write().insert(stable_crate_id, num); + let num = CrateNum::new(lock.len()); + lock.insert(stable_crate_id, num); Ok(TyCtxtFeed { key: num, tcx: self }) } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 857a4056bae87..6199e3766604d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -924,22 +924,24 @@ pub(crate) struct IrrefutableLetPatternsIfLetGuard { } #[derive(Diagnostic)] -#[diag( - "irrefutable `let...else` {$count -> - [one] pattern - *[other] patterns -}" -)] -#[note( - "{$count -> - [one] this pattern always matches, so the else clause is unreachable - *[other] these patterns always match, so the else clause is unreachable -}" -)] +#[diag("unreachable `else` clause")] +#[note("this pattern always matches, so the else clause is unreachable")] pub(crate) struct IrrefutableLetPatternsLetElse { - pub(crate) count: usize, - #[help("remove this `else` block")] - pub(crate) else_span: Option, + #[subdiagnostic] + pub(crate) be_replaced: Option, +} + +#[derive(Subdiagnostic, Debug)] +#[suggestion( + "consider using `let {$lhs} = {$rhs}` to match on a specific variant", + code = "let {lhs} = {rhs}", + applicability = "machine-applicable" +)] +pub(crate) struct LetElseReplacementSuggestion { + #[primary_span] + pub(crate) span: Span, + pub(crate) lhs: String, + pub(crate) rhs: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8a34320990e19..4dc3e02ace71a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -168,7 +168,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return }; // Lint only single irrefutable let binding. if let [Some((_, Irrefutable))] = chain_refutabilities[..] { - self.lint_single_let(ex.span, None); + self.lint_single_let(ex.span, None, None); } return; } @@ -438,7 +438,45 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { if let LetSource::PlainLet = self.let_source { self.check_binding_is_irrefutable(pat, "local binding", scrut, Some(span)); } else if let Ok(Irrefutable) = self.is_let_irrefutable(pat, scrut) { - self.lint_single_let(span, else_span); + if span.from_expansion() { + self.lint_single_let(span, None, None); + return; + } + let let_else_span = self.check_irrefutable_option_some(pat, scrut, span); + + let sm = self.tcx.sess.source_map(); + let next_token_start = sm.span_extend_while_whitespace(span.clone()).hi(); + let line_span = sm.span_extend_to_line(span.clone()).with_lo(next_token_start); + let else_keyword_span = sm.span_until_whitespace(line_span); + self.lint_single_let(span, Some(else_keyword_span), let_else_span); + } + } + + /// Check case `let x = Some(y);`, user likely intended to destructure `Option` + fn check_irrefutable_option_some( + &self, + pat: &'p Pat<'tcx>, + initializer: Option<&Expr<'tcx>>, + span: Span, + ) -> Option { + if let sm = self.tcx.sess.source_map() + && let Some(initializer) = initializer + && let Some(s_ty) = initializer.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, s_ty.did()) + && let ExprKind::Scope { value, .. } = initializer.kind + && let initializer_expr = &self.thir[value] + && let ExprKind::Adt(box AdtExpr { fields, .. }) = &initializer_expr.kind + && let Some(field) = fields.first() + && let inner = &self.thir[field.expr] + && let Some(inner_ty) = inner.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, inner_ty.did()) + && let Ok(rhs) = sm.span_to_snippet(inner.span) + && let Ok(lhs) = sm.span_to_snippet(pat.span) + { + let lhs = format!("Some({})", lhs); + Some(LetElseReplacementSuggestion { span, lhs, rhs }) + } else { + None } } @@ -559,14 +597,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn lint_single_let(&mut self, let_span: Span, else_span: Option) { + fn lint_single_let( + &mut self, + let_span: Span, + else_keyword_span: Option, + let_else_span: Option, + ) { report_irrefutable_let_patterns( self.tcx, self.hir_source, self.let_source, 1, let_span, - else_span, + else_keyword_span, + let_else_span, ); } @@ -862,7 +906,8 @@ fn report_irrefutable_let_patterns( source: LetSource, count: usize, span: Span, - else_span: Option, + else_keyword_span: Option, + let_else_span: Option, ) { macro_rules! emit_diag { ($lint:tt) => {{ @@ -875,11 +920,23 @@ fn report_irrefutable_let_patterns( LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => { + let spans = match else_keyword_span { + Some(else_keyword_span) => { + let mut spans = MultiSpan::from_span(else_keyword_span); + spans.push_span_label( + span, + msg!("assigning to binding pattern will always succeed"), + ); + spans + } + None => span.into(), + }; + tcx.emit_node_span_lint( IRREFUTABLE_LET_PATTERNS, id, - span, - IrrefutableLetPatternsLetElse { count, else_span }, + spans, + IrrefutableLetPatternsLetElse { be_replaced: let_else_span }, ); } LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index cd9d573957f45..63806cbc701e6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1487,11 +1487,7 @@ impl Options { } pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.cg.symbol_mangling_version.unwrap_or(if self.unstable_features.is_nightly_build() { - SymbolManglingVersion::V0 - } else { - SymbolManglingVersion::Legacy - }) + self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::V0) } #[inline] diff --git a/compiler/rustc_session/src/config/print_request.rs b/compiler/rustc_session/src/config/print_request.rs index b87236cef7646..65e25ab5e6006 100644 --- a/compiler/rustc_session/src/config/print_request.rs +++ b/compiler/rustc_session/src/config/print_request.rs @@ -15,6 +15,7 @@ use crate::macros::AllVariants; pub struct PrintRequest { pub kind: PrintKind, pub out: OutFileName, + pub arg: Option, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -22,6 +23,7 @@ pub struct PrintRequest { pub enum PrintKind { // tidy-alphabetical-start AllTargetSpecsJson, + BackendHasMnemonic, BackendHasZstd, CallingConventions, Cfg, @@ -55,6 +57,7 @@ impl PrintKind { match self { // tidy-alphabetical-start AllTargetSpecsJson => "all-target-specs-json", + BackendHasMnemonic => "backend-has-mnemonic", BackendHasZstd => "backend-has-zstd", CallingConventions => "calling-conventions", Cfg => "cfg", @@ -108,7 +111,8 @@ impl PrintKind { // Unstable values: AllTargetSpecsJson => false, - BackendHasZstd => false, // (perma-unstable, for use by compiletest) + BackendHasMnemonic => false, // (perma-unstable, for use by compiletest) + BackendHasZstd => false, // (perma-unstable, for use by compiletest) CheckCfg => false, CrateRootLintLevels => false, SupportedCrateTypes => false, @@ -145,11 +149,19 @@ pub(crate) fn collect_print_requests( ) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_deref() == Some("help") { - prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetCPUs, + out: OutFileName::Stdout, + arg: None, + }); cg.target_cpu = None; }; if cg.target_feature == "help" { - prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetFeatures, + out: OutFileName::Stdout, + arg: None, + }); cg.target_feature = String::new(); } @@ -162,9 +174,22 @@ pub(crate) fn collect_print_requests( prints.extend(matches.opt_strs("print").into_iter().map(|req| { let (req, out) = split_out_file_name(&req); - let kind = if let Some(print_kind) = PrintKind::from_str(req) { + let (kind, arg) = if let Some(mnemonic) = req.strip_prefix("backend-has-mnemonic") { + check_print_request_stability(early_dcx, unstable_opts, PrintKind::BackendHasMnemonic); + // BackendHasMnemonic requires a mnemonic argument + if let Some(mnemonic) = mnemonic.strip_prefix(':') + && !mnemonic.is_empty() + { + (PrintKind::BackendHasMnemonic, Some(mnemonic.to_string())) + } else { + early_dcx.early_fatal( + "expected mnemonic name after `--print=backend-has-mnemonic:`, \ + for example: `--print=backend-has-mnemonic:RET`", + ); + } + } else if let Some(print_kind) = PrintKind::from_str(req) { check_print_request_stability(early_dcx, unstable_opts, print_kind); - print_kind + (print_kind, None) } else { let is_nightly = nightly_options::match_is_nightly_build(matches); emit_unknown_print_request_help(early_dcx, req, is_nightly) @@ -180,7 +205,7 @@ pub(crate) fn collect_print_requests( } } - PrintRequest { kind, out } + PrintRequest { kind, out, arg } })); prints diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2a2d46615e2e7..a4e9a89a78c7a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2166,7 +2166,7 @@ options! { "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"), + "which mangling version to use for symbol names ('legacy', 'v0' (default), or 'hashed')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index f0587b8e4e23e..0f36edcdd830e 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -554,11 +554,7 @@ fn evaluate_host_effect_for_fn_goal<'tcx>( // but they don't really need to right now. ty::CoroutineClosure(_, _) => return Err(EvaluationFailure::NoSolution), - ty::Closure(def, args) => { - // For now we limit ourselves to closures without binders. The next solver can handle them. - args.as_closure().sig().no_bound_vars().ok_or(EvaluationFailure::NoSolution)?; - (def, args) - } + ty::Closure(def, args) => (def, args), // Everything else needs explicit impls or cannot have an impl _ => return Err(EvaluationFailure::NoSolution), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d4dd33b948193..02cd88a6a4340 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -40,9 +40,6 @@ //! } //! ``` //! -// -// FIXME: Show how `Option` is used in practice, with lots of methods -// //! # Options and pointers ("nullable" pointers) //! //! Rust's pointer types must always point to a valid location; there are diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 3a4e1e657a3da..48bf57356b575 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1794,6 +1794,7 @@ mod prim_ref {} /// have different sizes. /// /// ### ABI compatibility +/// [ABI compatibility]: #abi-compatibility /// /// Generally, when a function is declared with one signature and called via a function pointer with /// a different signature, the two signatures must be *ABI-compatible* or else calling the function @@ -1831,7 +1832,7 @@ mod prim_ref {} /// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box` (specifically, only `Box`), and /// `NonNull` are all ABI-compatible with each other for all `T`. They are also ABI-compatible /// with each other for _different_ `T` if they have the same metadata type (`::Metadata`). +/// Pointee>::Metadata`). However, see the [Control Flow Integrity][cfi-docs] docs for caveats. /// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is /// ABI-compatible with the `iN` integer type of the same size. /// - `char` is ABI-compatible with `u32`. @@ -1890,6 +1891,8 @@ mod prim_ref {} /// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// +/// [cfi-docs]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity +/// /// ### Trait implementations /// /// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index e9659f0176fc5..473c5f3e0faab 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -687,16 +687,6 @@ impl Builder<'_> { rustflags.arg(sysroot_str); } - let use_new_symbol_mangling = self.config.rust_new_symbol_mangling.or_else(|| { - if mode != Mode::Std { - // The compiler and tools default to the new scheme - Some(true) - } else { - // std follows the flag's default, which per compiler-team#938 is v0 on nightly - None - } - }); - // By default, windows-rs depends on a native library that doesn't get copied into the // sysroot. Passing this cfg enables raw-dylib support instead, which makes the native // library unnecessary. This can be removed when windows-rs enables raw-dylib @@ -706,7 +696,8 @@ impl Builder<'_> { rustflags.arg("--cfg=windows_raw_dylib"); } - if let Some(usm) = use_new_symbol_mangling { + // When unset, follow the default of the compiler flag - the compiler, tools and std use v0 + if let Some(usm) = self.config.rust_new_symbol_mangling { rustflags.arg(if usm { "-Csymbol-mangling-version=v0" } else { diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 4c534e9ae0eda..53a6c0cb5737d 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -346,6 +346,17 @@ See also the [codegen tests](#codegen-tests) for a similar set of tests. If you need to work with `#![no_std]` cross-compiling tests, consult the [`minicore` test auxiliary](./minicore.md) chapter. +#### Conditional assembly tests based on instruction support + +Tests that depend on specific assembly instructions being available can use the +`//@ needs-asm-mnemonic: ` directive. This will skip the test if the +target backend does not support the specified instruction mnemonic. + +For example, a test that requires the `RET` instruction: +```rust,ignore +//@ needs-asm-mnemonic: RET +``` + [`tests/assembly-llvm`]: https://github.com/rust-lang/rust/tree/HEAD/tests/assembly-llvm diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 38450d991d05a..caa400b573135 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -163,6 +163,9 @@ The following directives will check rustc build settings and target settings: For tests that cross-compile to explicit targets via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. +- `needs-asm-mnemonic: ` — ignores if the target backend does not + support the specified assembly mnemonic (e.g., `RET`, `NOP`). + Only supported with the LLVM backend. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not enabled for the target (`build.profiler = true` in `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled diff --git a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md index 001159b0d3266..c87cc1d5f863d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md +++ b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md @@ -15,7 +15,7 @@ From the wider Wasm ecosystem perspective, implementing WALI within engines allo ## Requirements ### Compilation -This target is cross-compiled and requires an installation of the [WALI compiler/sysroot](https://github.com/arjunr2/WALI). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). +This target is cross-compiled and requires an installation of the [WALI sysroot](https://github.com/Wasm-Thin-Kernel-Interfaces/WALI.git). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). `wali` targets *minimally require* the following LLVM feature flags: @@ -31,7 +31,7 @@ This target is cross-compiled and requires an installation of the [WALI compiler > **Note**: Users can expect that new enabled-by-default Wasm features for LLVM are transitively incorporatable into this target -- see [wasm32-unknown-unknown](wasm32-unknown-unknown.md) for detailed information on WebAssembly features. -> **Note**: The WALI ABI is similar to default Clang wasm32 ABIs but *not identical*. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maintain minimum source code changes for 64-bit host platforms currently supported. This may change in the future as the spec evolves. +> **Note**: The WALI ABI is *not identical* to the `wasm32-wasip2` or `wasm32-unknown-unknown` ABI. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maximize portability with minimum source code changes for currently supported 64-bit host platforms. These ABIs may converge in the future as the spec evolves. ### Execution Running generated WALI binaries also requires a supported compliant engine implementation -- a working implementation in the [WebAssembly Micro-Runtime (WAMR)](https://github.com/arjunr2/WALI) is included in the repo. @@ -41,38 +41,28 @@ Running generated WALI binaries also requires a supported compliant engine imple ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `config.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): +list in `bootstrap.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `bootstrap.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): ```toml [build] target = ["wasm32-wali-linux-musl"] [target.wasm32-wali-linux-musl] -musl-root = "/wali-musl/sysroot" -llvm-config = "/llvm-project/build/bin/llvm-config" -cc = "/llvm-project/build/bin/clang-18" -cxx = "/llvm-project/build/bin/clang-18" -ar = "/llvm-project/build/bin/llvm-ar" -ranlib = "/llvm-project/build/bin/llvm-ranlib" +musl-root = "/build/sysroot" +cc = "/build/llvm/bin/clang" +cxx = "/build/llvm/bin/clang++" +ar = "/build/llvm/bin/llvm-ar" +ranlib = "/build/llvm/bin/llvm-ranlib" llvm-libunwind = "system" crt-static = true ``` -> The `llvm-config` settings are only temporary, and the changes will eventually be upstreamed into LLVM - ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using -`build-std` or similar. - -Rust program builds can use this target normally. Currently, linking WALI programs may require pointing the `linker` to the llvm build in the [Cargo config](https://doc.rust-lang.org/cargo/reference/config.html) (until LLVM is upstreamed). A `config.toml` for Cargo will look like the following: - -```toml -[target.wasm32-wali-linux-musl] -linker = "/llvm-project/build/bin/lld" -``` +`build-std` or similar (with the appropriate sysroot links). Note that the following `cfg` directives are set for `wasm32-wali-linux-*`: diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md index ad565da9746cb..3f7d55063ca6a 100644 --- a/src/doc/rustc/src/symbol-mangling/index.md +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -46,7 +46,6 @@ foo::example_function ## Mangling versions -`rustc` supports different mangling versions which encode the names in different ways. -The legacy version (which is currently the default on beta/stable) is not described here. -The "v0" mangling scheme addresses several limitations of the legacy format, -and is described in the [v0 Symbol Format](v0.md) chapter. +There is currently one stable mangling scheme version - `v0`. On nightly builds, rustc supports +switching back to the `legacy` mangling scheme using [`-C symbol-mangling-version`]. The `v0` +mangling scheme is described in the [v0 Symbol Format](v0.md) chapter. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index b0f6c97ff5a73..5bd518b14154b 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -246,6 +246,37 @@ Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI. See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. +## Divergence from the Rust ABI + +There are some caveats to [the ABI-compatibility rules for Rust-to-Rust +calls][rust-abi] due to how the CFI sanitizer is implemented. CFI is a tool +that can be used to validate that dynamic function calls respect the ABI, but +due to its C/C++ origins, it disagrees with the above documented guarantees in +a few ways, see below. As CFI is unstable, the details may change in the +future. + +When running the CFI sanitizer, pointer types are only ABI-compatible if the +target type and mutability is the same. This means that `*mut String` and `*mut +i32` are incompatible when using CFI. It also means that `*mut i32` is +incompatible with `*const i32`. The `NonNull<_>` and `Box<_>` pointer types are +currently considered immutable under CFI. For non-primitive target types, CFI +uses the name of the type for its compatibility check. + +When not using the `-Zsanitizer-cfi-normalize-integers` flag, the CFI sanitizer +further restricts the rules by considering `usize`/`isize` incompatible with +the `uN`/`iN` integer type of the same size. + +Unlike other cases where the function ABI is violated, function calls that +violate the CFI-specific ABI-compatibility rules are not undefined behavior. +They are guaranteed to either function correctly, or to crash the program. + +This section only covers cases where CFI disagrees with the ABI-compatibility +rules for Rust-to-Rust calls. It is not meant to be a complete explanation of +how CFI works, and details important for C-to-Rust or Rust-to-C calls are +omitted. + +[rust-abi]: https://doc.rust-lang.org/stable/std/primitive.fn.html#abi-compatibility + ## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination ```rust diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 0d06f6e75af7c..5ef0335b24e58 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -156,6 +156,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "minicore-compile-flags", + "needs-asm-mnemonic", "needs-asm-support", "needs-backends", "needs-crate-type", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index e9f3d6c28d6ef..88ca347edd0a5 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -290,6 +290,37 @@ pub(super) fn handle_needs( } } + if name == "needs-asm-mnemonic" { + let Some(rest) = ln.value_after_colon() else { + return IgnoreDecision::Error { + message: "expected `needs-asm-mnemonic` to have a mnemonic name after colon" + .to_string(), + }; + }; + + if !config.default_codegen_backend.is_llvm() { + return IgnoreDecision::Ignore { + reason: "skipping test as non-LLVM backend does not support mnemonic queries" + .to_string(), + }; + } + + let mnemonic = rest.trim(); + let has_mnemonic = match mnemonic { + "ret" => cache.has_ret_mnemonic, + "nop" => cache.has_nop_mnemonic, + _ => has_mnemonic(config, mnemonic), + }; + + if has_mnemonic { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!("skipping test as target does not have `{mnemonic}` mnemonic"), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -352,6 +383,10 @@ pub(super) struct CachedNeedsConditions { symlinks: bool, /// Whether LLVM built with zstd, for the `needs-llvm-zstd` directive. llvm_zstd: bool, + /// Might add particular other mnemonics heavily needed by tests here. + /// Otherwise call into llvm for every check + has_ret_mnemonic: bool, + has_nop_mnemonic: bool, } impl CachedNeedsConditions { @@ -399,6 +434,8 @@ impl CachedNeedsConditions { llvm_zstd: llvm_has_zstd(&config), dlltool: find_dlltool(&config), symlinks: has_symlinks(), + has_ret_mnemonic: has_mnemonic(config, "ret"), + has_nop_mnemonic: has_mnemonic(config, "nop"), } } } @@ -466,3 +503,26 @@ fn llvm_has_zstd(config: &Config) -> bool { _ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"), } } + +fn has_mnemonic(config: &Config, mnemonic: &str) -> bool { + if !config.default_codegen_backend.is_llvm() { + return false; + } + + let target_flag = format!("--target={}", config.target); + let output = query_rustc_output( + config, + &[ + &target_flag, + "-Zunstable-options", + &format!("--print=backend-has-mnemonic:{}", mnemonic), + ], + Default::default(), + ); + + match output.trim() { + "true" => true, + "false" => false, + _ => panic!("unexpected output from `--print=backend-has-mnemonic:{mnemonic}`: {output:?}"), + } +} diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 4cd75fcfa511a..56d52982a8211 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -1254,3 +1254,25 @@ fn test_edition_range_edition_to_test() { assert_edition_to_test(2018, range, Some(e2024)); assert_edition_to_test(2018, range, Some(efuture)); } + +#[test] +fn needs_asm_mnemonic() { + let config_x86_64 = cfg().target("x86_64-unknown-linux-gnu").build(); + let config_aarch64 = cfg().target("aarch64-unknown-linux-gnu").build(); + + // invalid mnemonic + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:GRUGGY")); + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:gruggy")); + + // valid x86 and aarch64 + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:RET")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:ret")); + + // this is aarch64 specific + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:ldrsbwui")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:LDRSBWui")); + + // this is x86 specific + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:CMPxCHG16B")); + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:CMPXchg16B")); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 568e307366641..ab268f944816f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -319,20 +319,6 @@ impl<'test> TestCx<'test> { TestMode::RustdocJs => true, TestMode::Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build), TestMode::Crashes => false, - TestMode::Incremental => { - let revision = - self.revision.expect("incremental tests require a list of revisions"); - if revision.starts_with("cpass") - || revision.starts_with("bpass") - || revision.starts_with("rpass") - { - true - } else if revision.starts_with("bfail") { - false - } else { - panic!("revision name must begin with `cpass`, `bfail`, `bpass`, or `rpass`"); - } - } mode => panic!("unimplemented for mode {:?}", mode), } } diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 85e0c89a8d018..6529882715a90 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,26 +1,43 @@ -use super::{Emit, FailMode, PassMode, ProcRes, TestCx, WillExecute}; +use std::sync::LazyLock; + +use crate::runtest::{Emit, TestCx, WillExecute}; +use crate::util::string_enum; + +string_enum!( + /// How far an incremental test revision should proceed through the compile/run + /// sequence, and whether the last step should succeed or fail, as determined + /// from the start of the revision name. + #[derive(Clone, Copy, PartialEq, Eq)] + enum IncrRevKind { + CheckPass => "cpass", + BuildFail => "bfail", + BuildPass => "bpass", + RunPass => "rpass", + } +); + +impl IncrRevKind { + fn for_revision_name(rev_name: &str) -> Result { + static MESSAGE: LazyLock = LazyLock::new(|| { + let values = IncrRevKind::STR_VARIANTS + .iter() + .map(|s| format!("`{s}`")) + .collect::>() + .join(", "); + format!("incremental revision name must begin with one of: {values}") + }); + + IncrRevKind::VARIANTS + .iter() + .copied() + .find(|kind| rev_name.starts_with(kind.to_str())) + .ok_or_else(|| MESSAGE.as_str()) + } +} impl TestCx<'_> { + /// Runs a single revision of an incremental test. pub(super) fn run_incremental_test(&self) { - // Basic plan for a test incremental/foo/bar.rs: - // - load list of revisions rpass1, bfail2, rpass3 - // - each should begin with `bfail`, `bpass`, or `rpass` - // - if `bfail`, expect compilation to fail - // - if `bpass`, expect compilation to succeed, don't execute - // - if `rpass`, expect compilation and execution to succeed - // - create a directory build/foo/bar.incremental - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 - // - because name of revision starts with "rpass", expect success - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C bfail2 - // - because name of revision starts with "bfail", expect an error - // - load expected errors as usual, but filter for those with `[bfail2]` - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3 - // - because name of revision starts with "rpass", expect success - // - execute build/foo/bar.exe and save output - // - // FIXME -- use non-incremental mode as an oracle? That doesn't apply - // to #[rustc_clean] tests I guess - let revision = self.revision.expect("incremental tests require a list of revisions"); // Incremental workproduct directory should have already been created. @@ -31,68 +48,63 @@ impl TestCx<'_> { write!(self.stdout, "revision={:?} props={:#?}", revision, self.props); } - if revision.starts_with("cpass") { - self.run_cpass_test(); - } else if revision.starts_with("bpass") { - self.run_bpass_test(); - } else if revision.starts_with("rpass") { - self.run_rpass_test(); - } else if revision.starts_with("bfail") { - self.run_bfail_test(); - } else { - self.fatal("revision name must begin with `bfail`, `bpass`, or `rpass`"); + // Determine the revision kind from the revision name. + // The revision kind should be matched exhaustively to ensure that no cases are missed. + let rev_kind = IncrRevKind::for_revision_name(revision).unwrap_or_else(|e| self.fatal(e)); + + // Compile the test for this revision. + let emit = match rev_kind { + IncrRevKind::CheckPass => Emit::Metadata, // Do a check build. + IncrRevKind::BuildFail | IncrRevKind::BuildPass | IncrRevKind::RunPass => Emit::None, + }; + let will_execute = match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => { + WillExecute::No + } + IncrRevKind::RunPass => { + // Yes, unless running test binaries is disabled. + self.run_if_enabled() + } + }; + let proc_res = &self.compile_test(will_execute, emit); + + // Check the compiler's exit status. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildPass | IncrRevKind::RunPass => { + // Compilation should have succeeded. + if !proc_res.status.success() { + self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); + } + } + + IncrRevKind::BuildFail => { + // Compilation should have failed, with the expected status code. + if proc_res.status.success() { + self.fatal_proc_rec("incremental test did not emit an error", proc_res); + } + if !self.props.dont_check_failure_status { + self.check_correct_failure_status(proc_res); + } + } } - } - - fn run_cpass_test(&self) { - let proc_res = self.compile_test(WillExecute::No, Emit::Metadata); - self.check_if_test_should_compile(None, Some(PassMode::Check), &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_bpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let proc_res = self.compile_test(WillExecute::No, emit_metadata); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_rpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, emit_metadata); - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - - if let WillExecute::Disabled = should_run { - return; - } - - let proc_res = self.exec_compiled_test(); - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } - - fn run_bfail_test(&self) { - let pm = self.pass_mode(); - let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); - self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn check_compiler_output_for_incr(&self, proc_res: &ProcRes) { + // Check compilation output. let output_to_check = self.get_output(proc_res); self.check_expected_errors(&proc_res); self.check_all_error_patterns(&output_to_check, proc_res); self.check_forbid_output(&output_to_check, proc_res); + + // Run the binary and check its exit status, if appropriate. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => {} + IncrRevKind::RunPass => { + if self.config.run_enabled() { + let run_proc_res = self.exec_compiled_test(); + if !run_proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &run_proc_res); + } + } + } + } } } diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs index 1be22de367c99..8e4c26fc34508 100644 --- a/tests/run-make/naked-dead-code-elimination/rmake.rs +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -1,5 +1,6 @@ //@ ignore-cross-compile //@ needs-asm-support +//@ needs-asm-mnemonic: RET use run_make_support::symbols::object_contains_any_symbol; use run_make_support::{bin_name, rustc}; diff --git a/tests/run-make/print-request-help-stable-unstable/help-diff.diff b/tests/run-make/print-request-help-stable-unstable/help-diff.diff index e382a24782711..828a98d96b563 100644 --- a/tests/run-make/print-request-help-stable-unstable/help-diff.diff +++ b/tests/run-make/print-request-help-stable-unstable/help-diff.diff @@ -2,6 +2,6 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models` -+ = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` ++ = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err index 70764ea13aa87..d0e4c81f1de9d 100644 --- a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err +++ b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err @@ -1,5 +1,5 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/raw-dylib-whitespace/main.rs b/tests/run-make/raw-dylib-whitespace/main.rs new file mode 100644 index 0000000000000..023c3570c3262 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/main.rs @@ -0,0 +1,18 @@ +type BOOL = i32; + +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} + +fn main() { + let mut num: u8 = 0; + unsafe { + ProcessPrng(&mut num, 1); + } + println!("{num}"); +} diff --git a/tests/run-make/raw-dylib-whitespace/rmake.rs b/tests/run-make/raw-dylib-whitespace/rmake.rs new file mode 100644 index 0000000000000..45a557aa37387 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/rmake.rs @@ -0,0 +1,15 @@ +// Ensure that raw-dylib still works if the output directory contains spaces. + +//@ only-windows-gnu +//@ ignore-cross-compile + +use run_make_support::{rfs, rustc}; + +fn main() { + let out_dir = "path with spaces"; + rfs::create_dir_all(out_dir); + unsafe { + std::env::set_var("TMP", out_dir); + } + rustc().crate_type("bin").input("main.rs").out_dir(out_dir).run(); +} diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index 0acbb766c1556..1531f61089e9a 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 4075dd0282999..f96feccf35980 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/ui/compile-flags/invalid/print-without-arg.stderr b/tests/ui/compile-flags/invalid/print-without-arg.stderr index ff9669614360a..98788b4b87228 100644 --- a/tests/ui/compile-flags/invalid/print-without-arg.stderr +++ b/tests/ui/compile-flags/invalid/print-without-arg.stderr @@ -3,5 +3,5 @@ error: Argument to option 'print' missing --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . diff --git a/tests/ui/compile-flags/invalid/print.stderr b/tests/ui/compile-flags/invalid/print.stderr index e2521ebf26a41..3eb7634d915db 100644 --- a/tests/ui/compile-flags/invalid/print.stderr +++ b/tests/ui/compile-flags/invalid/print.stderr @@ -1,5 +1,5 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/consts/const-closure-hkl.rs b/tests/ui/consts/const-closure-hkl.rs new file mode 100644 index 0000000000000..25927b3a61ecd --- /dev/null +++ b/tests/ui/consts/const-closure-hkl.rs @@ -0,0 +1,20 @@ +//! Regression test for hkl const closures not working in old solver + +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(const_trait_impl)] +#![feature(const_closures)] +const fn partial_compare() { + let len_chain = const move |_a: &_, _b: &_| {}; + + chaining_impl(len_chain); +} + +const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { + std::mem::forget(x); +} + +fn main() {} diff --git a/tests/ui/let-else/let-else-irrefutable-152938.rs b/tests/ui/let-else/let-else-irrefutable-152938.rs index 6e0ffe3fb8706..25e3e0f6e5708 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.rs +++ b/tests/ui/let-else/let-else-irrefutable-152938.rs @@ -6,7 +6,7 @@ pub fn say_hello(name: Option) { let name_str = Some(name) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause drop(name_str); } diff --git a/tests/ui/let-else/let-else-irrefutable-152938.stderr b/tests/ui/let-else/let-else-irrefutable-152938.stderr index 57632964be9b3..e32f4960a3350 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.stderr +++ b/tests/ui/let-else/let-else-irrefutable-152938.stderr @@ -1,16 +1,18 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable-152938.rs:8:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable-152938.rs:8:31 | LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable-152938.rs:8:36 - | -LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default +help: consider using `let Some(name_str) = name` to match on a specific variant + | +LL - let name_str = Some(name) else { return; }; +LL + let Some(name_str) = name else { return; }; + | warning: 1 warning emitted diff --git a/tests/ui/let-else/let-else-irrefutable.rs b/tests/ui/let-else/let-else-irrefutable.rs index f9675ff5938eb..59de726d38ddf 100644 --- a/tests/ui/let-else/let-else-irrefutable.rs +++ b/tests/ui/let-else/let-else-irrefutable.rs @@ -1,10 +1,18 @@ //@ check-pass fn main() { - let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern + let x = 1 else { return }; //~ WARN unreachable `else` clause // Multiline else blocks should not get printed - let x = 1 else { //~ WARN irrefutable `let...else` pattern + let x = 1 else { //~ WARN unreachable `else` clause + eprintln!("problem case encountered"); + return + }; + + let case = Some("a"); + let name = Some(case) else { + //~^ WARN unreachable `else` clause + //~| HELP consider using `let Some(name) = case` to match on a specific variant eprintln!("problem case encountered"); return }; diff --git a/tests/ui/let-else/let-else-irrefutable.stderr b/tests/ui/let-else/let-else-irrefutable.stderr index d36d227b4156a..12338789d2a03 100644 --- a/tests/ui/let-else/let-else-irrefutable.stderr +++ b/tests/ui/let-else/let-else-irrefutable.stderr @@ -1,33 +1,38 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:4:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:4:15 | LL | let x = 1 else { return }; - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:4:20 - | -LL | let x = 1 else { return }; - | ^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:7:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:7:15 | LL | let x = 1 else { - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed + | + = note: this pattern always matches, so the else clause is unreachable + +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:13:27 + | +LL | let name = Some(case) else { + | --------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:7:20 - | -LL | let x = 1 else { - | ____________________^ -LL | | eprintln!("problem case encountered"); -LL | | return -LL | | }; - | |_____^ +help: consider using `let Some(name) = case` to match on a specific variant + | +LL - let name = Some(case) else { +LL + let Some(name) = case else { + | -warning: 2 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 3ede26dbcd06c..a552fbcfc1fc3 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -93,10 +93,10 @@ fn i() { fn j() { let mut bar = 0; let foo = bar = { - //~^ WARN irrefutable `let...else` pattern 1 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } @@ -158,21 +158,21 @@ fn o() -> Result<(), ()> { fn q() { let foo = |x: i32| { - //~^ WARN irrefutable `let...else` pattern x } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn r() { let ok = format_args!("") else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed - //~| WARN irrefutable `let...else` pattern + //~| WARN unreachable `else` clause } fn s() { @@ -202,10 +202,10 @@ fn t() { } let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { - //~^ WARN irrefutable `let...else` pattern 8 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 8545d95f507f6..76fbbbb8c1e10 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -125,7 +125,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:98:5 + --> $DIR/bad-let-else-statement.rs:97:5 | LL | } else { | ^ @@ -133,7 +133,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ -LL | LL | 1 LL ~ }) else { | @@ -204,7 +203,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:163:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -212,7 +211,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ -LL | LL | x LL ~ }) else { | @@ -230,7 +228,7 @@ LL + let bad = format_args! ("") else { return; }; | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:207:5 + --> $DIR/bad-let-else-statement.rs:206:5 | LL | } else { | ^ @@ -238,7 +236,6 @@ LL | } else { help: use parentheses instead of braces for this macro | LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! ( -LL | LL | 8 LL ~ ) else { | @@ -259,92 +256,62 @@ LL - let 0 = a! {} else { return; }; LL + let 0 = a! () else { return; }; | -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:95:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:97:7 | LL | / let foo = bar = { -LL | | LL | | 1 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:98:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:160:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:162:7 | LL | / let foo = |x: i32| { -LL | | LL | | x LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:163:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:170:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:170:31 | LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:170:36 - | -LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:173:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:173:33 | LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:173:38 - | -LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:204:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:206:7 | LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { -LL | | LL | | 8 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:207:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ error: aborting due to 19 previous errors; 5 warnings emitted diff --git a/tests/ui/print-request/print-lints-help.stderr b/tests/ui/print-request/print-lints-help.stderr index d39c6326e318b..c6e74e7dce7b6 100644 --- a/tests/ui/print-request/print-lints-help.stderr +++ b/tests/ui/print-request/print-lints-help.stderr @@ -1,6 +1,6 @@ error: unknown print request: `lints` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: use `-Whelp` to print a list of lints = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/span/let-offset-of.rs b/tests/ui/span/let-offset-of.rs index 99b34a1928470..eeecf38e6b6a9 100644 --- a/tests/ui/span/let-offset-of.rs +++ b/tests/ui/span/let-offset-of.rs @@ -15,5 +15,5 @@ fn init_to_offset_of() { //~^ WARN irrefutable `if let` pattern let x = offset_of!(Foo, field) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause } diff --git a/tests/ui/span/let-offset-of.stderr b/tests/ui/span/let-offset-of.stderr index df9b1e695b1e4..afcf8a8103d9d 100644 --- a/tests/ui/span/let-offset-of.stderr +++ b/tests/ui/span/let-offset-of.stderr @@ -8,18 +8,15 @@ LL | if let x = offset_of!(Foo, field) {} = help: consider replacing the `if let` with a `let` = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-offset-of.rs:17:5 +warning: unreachable `else` clause + --> $DIR/let-offset-of.rs:17:36 | LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------ ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-offset-of.rs:17:41 - | -LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^ warning: 2 warnings emitted diff --git a/triagebot.toml b/triagebot.toml index 9c69061c7b8cf..33ef3d097e618 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -940,10 +940,6 @@ Issue #{number} "{title}" has been added. # Mentions # ------------------------------------------------------------------------------ -[mentions."triagebot.toml"] -message = "`triagebot.toml` has been modified, there may have been changes to the review queue." -cc = ["@davidtwco", "@wesleywiser"] - [mentions."compiler/rustc_codegen_cranelift"] message = "The Cranelift subtree was changed" cc = ["@bjorn3"]