diff options
118 files changed, 2058 insertions, 826 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index a95ef4c460f..9165b4f2df3 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -970,7 +970,7 @@ fn univariant< let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect(); - let optimize = !repr.inhibit_struct_field_reordering_opt(); + let optimize = !repr.inhibit_struct_field_reordering(); if optimize && fields.len() > 1 { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index.raw[..end]; @@ -1007,13 +1007,15 @@ fn univariant< // Calculates a sort key to group fields by their alignment or possibly some // size-derived pseudo-alignment. let alignment_group_key = |layout: &F| { + // The two branches here return values that cannot be meaningfully compared with + // each other. However, we know that consistently for all executions of + // `alignment_group_key`, one or the other branch will be taken, so this is okay. if let Some(pack) = pack { // Return the packed alignment in bytes. layout.align.abi.min(pack).bytes() } else { - // Returns `log2(effective-align)`. This is ok since `pack` applies to all - // fields equally. The calculation assumes that size is an integer multiple of - // align, except for ZSTs. + // Returns `log2(effective-align)`. The calculation assumes that size is an + // integer multiple of align, except for ZSTs. let align = layout.align.abi.bytes(); let size = layout.size.bytes(); let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 53aa8ad7cca..b1a17d5a24b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -137,23 +137,16 @@ impl ReprOptions { self.c() || self.int.is_some() } - /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`. - pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - if let Some(pack) = self.pack { - if pack.bytes() == 1 { - return true; - } - } - + /// Returns `true` if this `#[repr()]` guarantees a fixed field order, + /// e.g. `repr(C)` or `repr(<int>)`. + pub fn inhibit_struct_field_reordering(&self) -> bool { self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` /// was enabled for its declaration crate. pub fn can_randomize_type_layout(&self) -> bool { - !self.inhibit_struct_field_reordering_opt() - && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) + !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index d14fe0299e6..1c126e79762 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -18,6 +18,8 @@ codegen_llvm_error_creating_import_library = codegen_llvm_error_writing_def_file = Error writing .DEF file: {$error} +codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture + codegen_llvm_from_llvm_diag = {$message} codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index e15eda7c66c..9d83dc81163 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -254,3 +254,9 @@ pub struct MismatchedDataLayout<'a> { pub(crate) struct InvalidTargetFeaturePrefix<'a> { pub feature: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_fixed_x18_invalid_arch)] +pub(crate) struct FixedX18InvalidArch<'a> { + pub arch: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5552b381025..53b9b530e9b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,6 +1,6 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ - InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, + FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; @@ -615,6 +615,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str .flatten(); features.extend(feats); + // -Zfixed-x18 + if sess.opts.unstable_opts.fixed_x18 { + if sess.target.arch != "aarch64" { + sess.dcx().emit_fatal(FixedX18InvalidArch { arch: &sess.target.arch }); + } else { + features.push("+reserve-x18".into()); + } + } + if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { sess.dcx().emit_err(TargetFeatureDisableOrEnable { features: f, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c6cf7cf4f3f..6538995926a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -773,6 +773,7 @@ fn test_unstable_options_tracking_hash() { tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); + tracked!(fixed_x18, true); tracked!(flatten_format_args, false); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 0b164550096..fb71cb60140 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -232,11 +232,9 @@ lint_drop_trait_constraints = lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result lint_duplicate_macro_attribute = duplicated attribute @@ -271,10 +269,9 @@ lint_for_loops_over_fallibles = lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result + lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` - .note = use `let _ = ...` to ignore the expression or result lint_hidden_glob_reexport = private item shadows public glob re-export .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here @@ -893,6 +890,8 @@ lint_unused_op = unused {$op} that must be used lint_unused_result = unused result of type `{$ty}` +lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result + lint_variant_size_differences = enum variant is more than three times larger ({$largest} bytes) than the next largest diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 60b799f3c74..eea0898d83f 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,4 +1,4 @@ -use rustc_hir::{Arm, Expr, ExprKind, Node}; +use rustc_hir::{Arm, Expr, ExprKind, Node, StmtKind}; use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; @@ -6,7 +6,7 @@ use rustc_span::sym; use crate::{ lints::{ DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, - UndroppedManuallyDropsSuggestion, + UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -148,33 +148,59 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { let arg_ty = cx.typeck_results().expr_ty(arg); let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); + let let_underscore_ignore_sugg = || { + if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + UseLetUnderscoreIgnoreSuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + UseLetUnderscoreIgnoreSuggestion::Note + } + }; match fn_name { sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => { cx.emit_span_lint( DROPPING_REFERENCES, expr.span, - DropRefDiag { arg_ty, label: arg.span }, + DropRefDiag { arg_ty, label: arg.span, sugg: let_underscore_ignore_sugg() }, ); } sym::mem_forget if arg_ty.is_ref() => { cx.emit_span_lint( FORGETTING_REFERENCES, expr.span, - ForgetRefDiag { arg_ty, label: arg.span }, + ForgetRefDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { cx.emit_span_lint( DROPPING_COPY_TYPES, expr.span, - DropCopyDiag { arg_ty, label: arg.span }, + DropCopyDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_forget if is_copy => { cx.emit_span_lint( FORGETTING_COPY_TYPES, expr.span, - ForgetCopyDiag { arg_ty, label: arg.span }, + ForgetCopyDiag { + arg_ty, + label: arg.span, + sugg: let_underscore_ignore_sugg(), + }, ); } sym::mem_drop diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2edfb8d3df4..84d46ef3b65 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -656,41 +656,62 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { pub end_span: Span, } +#[derive(Subdiagnostic)] +pub enum UseLetUnderscoreIgnoreSuggestion { + #[note(lint_use_let_underscore_ignore_suggestion)] + Note, + #[multipart_suggestion( + lint_use_let_underscore_ignore_suggestion, + style = "verbose", + applicability = "maybe-incorrect" + )] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, +} + // drop_forget_useless.rs #[derive(LintDiagnostic)] #[diag(lint_dropping_references)] -#[note] pub struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -#[note] pub struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] #[diag(lint_forgetting_references)] -#[note] pub struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] #[diag(lint_forgetting_copy_types)] -#[note] pub struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 9cfb25e663d..728b63d5b21 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -217,12 +217,13 @@ impl MCDCInfoBuilder { } _ => { // Do not generate mcdc mappings and statements for decisions with too many conditions. - let rebase_idx = self.branch_spans.len() - decision.conditions_num + 1; + // Therefore, first erase the condition info of the (N-1) previous branch spans. + let rebase_idx = self.branch_spans.len() - (decision.conditions_num - 1); for branch in &mut self.branch_spans[rebase_idx..] { branch.condition_info = None; } - // ConditionInfo of this branch shall also be reset. + // Then, erase this last branch span's info too, for a total of N. condition_info = None; tcx.dcx().emit_warn(MCDCExceedsConditionNumLimit { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0655484ad85..bcdd6716cc3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4505,6 +4505,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.visit_expr(elem); self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes)); } + ExprKind::ConstBlock(ref expr) => { + self.resolve_anon_const_manual(false, AnonConstKind::InlineConst, |this| { + this.visit_expr(expr) + }); + } ExprKind::Index(ref elem, ref idx, _) => { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6309fcdd2db..cca9f1eb997 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1678,6 +1678,8 @@ options! { fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), + fixed_x18: bool = (false, parse_bool, [TRACKED], + "make the x18 register reserved on AArch64 (default: no)"), flatten_format_args: bool = (true, parse_bool, [TRACKED], "flatten nested format_args!() and literals into a simplified format_args!() call \ (default: yes)"), diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 6f513f24948..c5ea85c90dc 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -520,7 +520,8 @@ fn fn_abi_sanity_check<'tcx>( assert!( matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") || matches!(spec_abi, SpecAbi::PtxKernel | SpecAbi::Unadjusted), - r#"`PassMode::Direct` for aggregates only allowed for "unadjusted" and "ptx-kernel" functions and on wasm\nProblematic type: {:#?}"#, + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ + Problematic type: {:#?}", arg.layout, ); } diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 44f575b51da..601e4e55e09 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -9,6 +9,7 @@ use std::collections::VecDeque; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::mpsc::SyncSender; +use std::sync::Mutex; fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool { let mut cmd = Command::new(rustfmt); @@ -24,20 +25,23 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F cmd.args(paths); let cmd_debug = format!("{cmd:?}"); let mut cmd = cmd.spawn().expect("running rustfmt"); - // Poor man's async: return a closure that'll wait for rustfmt's completion. + // Poor man's async: return a closure that might wait for rustfmt's completion (depending on + // the value of the `block` argument). move |block: bool| -> bool { - if !block { + let status = if !block { match cmd.try_wait() { - Ok(Some(_)) => {} - _ => return false, + Ok(Some(status)) => Ok(status), + Ok(None) => return false, + Err(err) => Err(err), } - } - let status = cmd.wait().unwrap(); - if !status.success() { + } else { + cmd.wait() + }; + if !status.unwrap().success() { eprintln!( - "Running `{}` failed.\nIf you're running `tidy`, \ - try again with `--bless`. Or, if you just want to format \ - code, run `./x.py fmt` instead.", + "fmt error: Running `{}` failed.\nIf you're running `tidy`, \ + try again with `--bless`. Or, if you just want to format \ + code, run `./x.py fmt` instead.", cmd_debug, ); crate::exit!(1); @@ -97,35 +101,61 @@ struct RustfmtConfig { ignore: Vec<String>, } -pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { +// Prints output describing a collection of paths, with lines such as "formatted modified file +// foo/bar/baz" or "skipped 20 untracked files". +fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { + let len = paths.len(); + let adjective = + if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() }; + if len <= 10 { + for path in paths { + println!("fmt: {verb} {adjective}file {path}"); + } + } else { + println!("fmt: {verb} {len} {adjective}files"); + } +} + +pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { + if !paths.is_empty() { + eprintln!("fmt error: path arguments are not accepted"); + crate::exit!(1); + }; if build.config.dry_run() { return; } + + // By default, we only check modified files locally to speed up runtime. Exceptions are if + // `--all` is specified or we are in CI. We check all files in CI to avoid bugs in + // `get_modified_rs_files` letting regressions slip through; we also care about CI time less + // since this is still very fast compared to building the compiler. + let all = all || CiEnv::is_ci(); + let mut builder = ignore::types::TypesBuilder::new(); builder.add_defaults(); builder.select("rust"); let matcher = builder.build().unwrap(); let rustfmt_config = build.src.join("rustfmt.toml"); if !rustfmt_config.exists() { - eprintln!("Not running formatting checks; rustfmt.toml does not exist."); - eprintln!("This may happen in distributed tarballs."); + eprintln!("fmt error: Not running formatting checks; rustfmt.toml does not exist."); + eprintln!("fmt error: This may happen in distributed tarballs."); return; } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); - let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); + let mut override_builder = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { if ignore.starts_with('!') { - // A `!`-prefixed entry could be added as a whitelisted entry in `fmt_override`, i.e. - // strip the `!` prefix. But as soon as whitelisted entries are added, an + // A `!`-prefixed entry could be added as a whitelisted entry in `override_builder`, + // i.e. strip the `!` prefix. But as soon as whitelisted entries are added, an // `OverrideBuilder` will only traverse those whitelisted entries, and won't traverse // any files that aren't explicitly mentioned. No bueno! Maybe there's a way to combine // explicit whitelisted entries and traversal of unmentioned files, but for now just // forbid such entries. - eprintln!("`!`-prefixed entries are not supported in rustfmt.toml, sorry"); + eprintln!("fmt error: `!`-prefixed entries are not supported in rustfmt.toml, sorry"); crate::exit!(1); } else { - fmt_override.add(&format!("!{ignore}")).expect(&ignore); + override_builder.add(&format!("!{ignore}")).expect(&ignore); } } let git_available = match Command::new("git") @@ -138,6 +168,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { Err(_) => false, }; + let mut adjective = None; if git_available { let in_working_tree = match build .config @@ -161,127 +192,56 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { .arg("-z") .arg("--untracked-files=normal"), ); - let untracked_paths = untracked_paths_output.split_terminator('\0').filter_map( - |entry| entry.strip_prefix("?? "), // returns None if the prefix doesn't match - ); - let mut untracked_count = 0; + let untracked_paths: Vec<_> = untracked_paths_output + .split_terminator('\0') + .filter_map( + |entry| entry.strip_prefix("?? "), // returns None if the prefix doesn't match + ) + .map(|x| x.to_string()) + .collect(); + print_paths("skipped", Some("untracked"), &untracked_paths); + for untracked_path in untracked_paths { - println!("skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the // repository root, rather than a glob. Without that, if you // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. - untracked_count += 1; - fmt_override.add(&format!("!/{untracked_path}")).expect(untracked_path); + override_builder.add(&format!("!/{untracked_path}")).expect(&untracked_path); } - // Only check modified files locally to speed up runtime. We still check all files in - // CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; we - // also care about CI time less since this is still very fast compared to building the - // compiler. - if !CiEnv::is_ci() && paths.is_empty() { + if !all { + adjective = Some("modified"); match get_modified_rs_files(build) { Ok(Some(files)) => { - if files.len() <= 10 { - for file in &files { - println!("formatting modified file {file}"); - } - } else { - let pluralized = |count| if count > 1 { "files" } else { "file" }; - let untracked_msg = if untracked_count == 0 { - "".to_string() - } else { - format!( - ", skipped {} untracked {}", - untracked_count, - pluralized(untracked_count), - ) - }; - println!( - "formatting {} modified {}{}", - files.len(), - pluralized(files.len()), - untracked_msg - ); - } for file in files { - fmt_override.add(&format!("/{file}")).expect(&file); + override_builder.add(&format!("/{file}")).expect(&file); } } Ok(None) => {} Err(err) => { - println!( - "WARN: Something went wrong when running git commands:\n{err}\n\ - Falling back to formatting all files." - ); + eprintln!("fmt warning: Something went wrong running git commands:"); + eprintln!("fmt warning: {err}"); + eprintln!("fmt warning: Falling back to formatting all files."); } } } } else { - println!("Not in git tree. Skipping git-aware format checks"); + eprintln!("fmt: warning: Not in git tree. Skipping git-aware format checks"); } } else { - println!("Could not find usable git. Skipping git-aware format checks"); + eprintln!("fmt: warning: Could not find usable git. Skipping git-aware format checks"); } - let fmt_override = fmt_override.build().unwrap(); + let override_ = override_builder.build().unwrap(); // `override` is a reserved keyword let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { - eprintln!("./x.py fmt is not supported on this channel"); + eprintln!("fmt error: `x fmt` is not supported on this channel"); crate::exit!(1); }); assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); let (tx, rx): (SyncSender<PathBuf>, _) = std::sync::mpsc::sync_channel(128); - let walker = match paths.first() { - Some(first) => { - let find_shortcut_candidates = |p: &PathBuf| { - let mut candidates = Vec::new(); - for entry in - WalkBuilder::new(src.clone()).max_depth(Some(3)).build().map_while(Result::ok) - { - if let Some(dir_name) = p.file_name() { - if entry.path().is_dir() && entry.file_name() == dir_name { - candidates.push(entry.into_path()); - } - } - } - candidates - }; - - // Only try to look for shortcut candidates for single component paths like - // `std` and not for e.g. relative paths like `../library/std`. - let should_look_for_shortcut_dir = |p: &PathBuf| p.components().count() == 1; - - let mut walker = if should_look_for_shortcut_dir(first) { - if let [single_candidate] = &find_shortcut_candidates(first)[..] { - WalkBuilder::new(single_candidate) - } else { - WalkBuilder::new(first) - } - } else { - WalkBuilder::new(src.join(first)) - }; - - for path in &paths[1..] { - if should_look_for_shortcut_dir(path) { - if let [single_candidate] = &find_shortcut_candidates(path)[..] { - walker.add(single_candidate); - } else { - walker.add(path); - } - } else { - walker.add(src.join(path)); - } - } - - walker - } - None => WalkBuilder::new(src.clone()), - } - .types(matcher) - .overrides(fmt_override) - .build_parallel(); + let walker = WalkBuilder::new(src.clone()).types(matcher).overrides(override_).build_parallel(); // There is a lot of blocking involved in spawning a child process and reading files to format. // Spawn more processes than available concurrency to keep the CPU busy. @@ -319,16 +279,33 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } }); + let formatted_paths = Mutex::new(Vec::new()); + let formatted_paths_ref = &formatted_paths; walker.run(|| { let tx = tx.clone(); Box::new(move |entry| { + let cwd = std::env::current_dir(); let entry = t!(entry); if entry.file_type().map_or(false, |t| t.is_file()) { + formatted_paths_ref.lock().unwrap().push({ + // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter + // relative path. + let mut path = entry.clone().into_path(); + if let Ok(cwd) = cwd { + if let Ok(path2) = path.strip_prefix(cwd) { + path = path2.to_path_buf(); + } + } + path.display().to_string() + }); t!(tx.send(entry.into_path())); } ignore::WalkState::Continue }) }); + let mut paths = formatted_paths.into_inner().unwrap(); + paths.sort(); + print_paths(if check { "checked" } else { "formatted" }, adjective, &paths); drop(tx); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 360bd3840d4..21588686362 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1140,7 +1140,13 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to ); crate::exit!(1); } - crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), &[]); + let all = false; + crate::core::build_steps::format::format( + builder, + !builder.config.cmd.bless(), + all, + &[], + ); } builder.info("tidy check"); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index f4ed7e76fba..83def0c6df0 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -284,8 +284,8 @@ pub enum Subcommand { name = "fmt", long_about = "\n Arguments: - This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and - fails if it is not. For example: + This subcommand optionally accepts a `--check` flag which succeeds if + formatting is correct and fails if it is not. For example: ./x.py fmt ./x.py fmt --check" )] @@ -294,6 +294,10 @@ pub enum Subcommand { /// check formatting instead of applying #[arg(long)] check: bool, + + /// apply to all appropriate files, not just those that have been modified + #[arg(long)] + all: bool, }, #[command(aliases = ["d"], long_about = "\n Arguments: diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 52c94465cd3..8312885915c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -660,10 +660,11 @@ impl Build { // hardcoded subcommands match &self.config.cmd { - Subcommand::Format { check } => { + Subcommand::Format { check, all } => { return core::build_steps::format::format( &builder::Builder::new(self), *check, + *all, &self.config.paths, ); } diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 48b58f6f06a..e9cf2a0d1ae 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -247,7 +247,8 @@ approved by the appropriate team for that shared code before acceptance. target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. - Tier 3 targets must be able to produce assembly using at least one of - rustc's supported backends from any host target. + rustc's supported backends from any host target. (Having support in a fork + of the backend is not sufficient, it must be upstream.) If a tier 3 target stops meeting these requirements, or the target maintainers no longer have interest or time, or the target shows no signs of activity and diff --git a/src/doc/unstable-book/src/compiler-flags/fixed-x18.md b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md new file mode 100644 index 00000000000..8c8bff5fa29 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/fixed-x18.md @@ -0,0 +1,32 @@ +# `fixed-x18` + +This option prevents the compiler from using the x18 register. It is only +supported on aarch64. + +From the [ABI spec][arm-abi]: + +> X18 is the platform register and is reserved for the use of platform ABIs. +> This is an additional temporary register on platforms that don't assign a +> special meaning to it. + +This flag only has an effect when the x18 register would otherwise be considered +a temporary register. When the flag is applied, x18 is always a reserved +register. + +This flag is intended for use with the shadow call stack sanitizer. Generally, +when that sanitizer is enabled, the x18 register is used to store a pointer to +the shadow stack. Enabling this flag prevents the compiler from overwriting the +shadow stack pointer with temporary data, which is necessary for the sanitizer +to work correctly. + +Currently, the `-Zsanitizer=shadow-call-stack` flag is only supported on +platforms that always treat x18 as a reserved register, and the `-Zfixed-x18` +flag is not required to use the sanitizer on such platforms. However, the +sanitizer may be supported on targets where this is not the case in the future. + +It is undefined behavior for `-Zsanitizer=shadow-call-stack` code to call into +code where x18 is a temporary register. On the other hand, when you are *not* +using the shadow call stack sanitizer, compilation units compiled with and +without the `-Zfixed-x18` flag are compatible with each other. + +[arm-abi]: https://developer.arm.com/documentation/den0024/a/The-ABI-for-ARM-64-bit-Architecture/Register-use-in-the-AArch64-Procedure-Call-Standard/Parameters-in-general-purpose-registers diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 40a25f13fcb..7343f3147ee 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -216,6 +216,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'us complete -c x.py -n "__fish_seen_subcommand_from fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying' +complete -c x.py -n "__fish_seen_subcommand_from fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index f3d1d372c73..d9adb1778f2 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -275,6 +275,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') + [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 82cacb52ffe..6cb9e95c8c1 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -1077,7 +1077,7 @@ _x.py() { return 0 ;; x.py__fmt) - opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 12e96dbd40a..24ddd1c4b7c 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -271,6 +271,7 @@ _arguments "${_arguments_options[@]}" \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT: ' \ '*--set=[override options in config.toml]:section.option=value:( )' \ '--check[check formatting instead of applying]' \ +'--all[apply to all appropriate files, not just those that have been modified]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 9c8dd37d53d..3b32e4396b9 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -278,7 +278,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> ty = sized_ty; continue; } - if def.repr().inhibit_struct_field_reordering_opt() { + if def.repr().inhibit_struct_field_reordering() { ReducedTy::OrderedFields(Some(sized_ty)) } else { ReducedTy::UnorderedFields(ty) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e8ceff84722..910a829fbea 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -9,7 +9,7 @@ use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind}; -use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; +use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -41,6 +41,7 @@ use tracing::*; use crate::extract_gdb_version; use crate::is_android_gdb_target; +mod coverage; mod debugger; use debugger::DebuggerCommands; @@ -53,6 +54,7 @@ macro_rules! static_regex { RE.get_or_init(|| ::regex::Regex::new($re).unwrap()) }}; } +use static_regex; const FAKE_SRC_BASE: &str = "fake-test-src-base"; @@ -267,8 +269,8 @@ impl<'test> TestCx<'test> { MirOpt => self.run_mir_opt_test(), Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), - CoverageMap => self.run_coverage_map_test(), - CoverageRun => self.run_coverage_run_test(), + CoverageMap => self.run_coverage_map_test(), // see self::coverage + CoverageRun => self.run_coverage_run_test(), // see self::coverage Crashes => self.run_crash_test(), } } @@ -504,224 +506,6 @@ impl<'test> TestCx<'test> { } } - fn run_coverage_map_test(&self) { - let Some(coverage_dump_path) = &self.config.coverage_dump_path else { - self.fatal("missing --coverage-dump"); - }; - - let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - drop(proc_res); - - let mut dump_command = Command::new(coverage_dump_path); - dump_command.arg(llvm_ir_path); - let proc_res = self.run_command_to_procres(&mut dump_command); - if !proc_res.status.success() { - self.fatal_proc_rec("coverage-dump failed!", &proc_res); - } - - let kind = UI_COVERAGE_MAP; - - let expected_coverage_dump = self.load_expected_output(kind); - let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); - - let coverage_dump_errors = - self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); - - if coverage_dump_errors > 0 { - self.fatal_proc_rec( - &format!("{coverage_dump_errors} errors occurred comparing coverage output."), - &proc_res, - ); - } - } - - fn run_coverage_run_test(&self) { - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, Emit::None); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - drop(proc_res); - - if let WillExecute::Disabled = should_run { - return; - } - - let profraw_path = self.output_base_dir().join("default.profraw"); - let profdata_path = self.output_base_dir().join("default.profdata"); - - // Delete any existing profraw/profdata files to rule out unintended - // interference between repeated test runs. - if profraw_path.exists() { - std::fs::remove_file(&profraw_path).unwrap(); - } - if profdata_path.exists() { - std::fs::remove_file(&profdata_path).unwrap(); - } - - let proc_res = self.exec_compiled_test_general( - &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], - false, - ); - if self.props.failure_status.is_some() { - self.check_correct_failure_status(&proc_res); - } else if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - drop(proc_res); - - let mut profraw_paths = vec![profraw_path]; - let mut bin_paths = vec![self.make_exe_name()]; - - if self.config.suite == "coverage-run-rustdoc" { - self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); - } - - // Run `llvm-profdata merge` to index the raw coverage output. - let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { - cmd.args(["merge", "--sparse", "--output"]); - cmd.arg(&profdata_path); - cmd.args(&profraw_paths); - }); - if !proc_res.status.success() { - self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); - } - drop(proc_res); - - // Run `llvm-cov show` to produce a coverage report in text format. - let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { - cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); - - cmd.arg("--Xdemangler"); - cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); - - cmd.arg("--instr-profile"); - cmd.arg(&profdata_path); - - for bin in &bin_paths { - cmd.arg("--object"); - cmd.arg(bin); - } - - cmd.args(&self.props.llvm_cov_flags); - }); - if !proc_res.status.success() { - self.fatal_proc_rec("llvm-cov show failed!", &proc_res); - } - - let kind = UI_COVERAGE; - - let expected_coverage = self.load_expected_output(kind); - let normalized_actual_coverage = - self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| { - self.fatal_proc_rec(&err, &proc_res); - }); - - let coverage_errors = - self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); - - if coverage_errors > 0 { - self.fatal_proc_rec( - &format!("{} errors occurred comparing coverage output.", coverage_errors), - &proc_res, - ); - } - } - - /// Run any doctests embedded in this test file, and add any resulting - /// `.profraw` files and doctest executables to the given vectors. - fn run_doctests_for_coverage( - &self, - profraw_paths: &mut Vec<PathBuf>, - bin_paths: &mut Vec<PathBuf>, - ) { - // Put .profraw files and doctest executables in dedicated directories, - // to make it easier to glob them all later. - let profraws_dir = self.output_base_dir().join("doc_profraws"); - let bins_dir = self.output_base_dir().join("doc_bins"); - - // Remove existing directories to prevent cross-run interference. - if profraws_dir.try_exists().unwrap() { - std::fs::remove_dir_all(&profraws_dir).unwrap(); - } - if bins_dir.try_exists().unwrap() { - std::fs::remove_dir_all(&bins_dir).unwrap(); - } - - let mut rustdoc_cmd = - Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed")); - - // In general there will be multiple doctest binaries running, so we - // tell the profiler runtime to write their coverage data into separate - // profraw files. - rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw")); - - rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]); - - // Without this, the doctests complain about not being able to find - // their enclosing file's crate for some reason. - rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]); - - // Persist the doctest binaries so that `llvm-cov show` can read their - // embedded coverage mappings later. - rustdoc_cmd.arg("-Zunstable-options"); - rustdoc_cmd.arg("--persist-doctests"); - rustdoc_cmd.arg(&bins_dir); - - rustdoc_cmd.arg("-L"); - rustdoc_cmd.arg(self.aux_output_dir_name()); - - rustdoc_cmd.arg(&self.testpaths.file); - - let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); - if !proc_res.status.success() { - self.fatal_proc_rec("rustdoc --test failed!", &proc_res) - } - - fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> { - let path_str = path.as_ref().to_str().unwrap(); - let iter = glob(path_str).unwrap(); - iter.map(Result::unwrap) - } - - // Find all profraw files in the profraw directory. - for p in glob_iter(profraws_dir.join("*.profraw")) { - profraw_paths.push(p); - } - // Find all executables in the `--persist-doctests` directory, while - // avoiding other file types (e.g. `.pdb` on Windows). This doesn't - // need to be perfect, as long as it can handle the files actually - // produced by `rustdoc --test`. - for p in glob_iter(bins_dir.join("**/*")) { - let is_bin = p.is_file() - && match p.extension() { - None => true, - Some(ext) => ext == OsStr::new("exe"), - }; - if is_bin { - bin_paths.push(p); - } - } - } - - fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { - let tool_path = self - .config - .llvm_bin_dir - .as_ref() - .expect("this test expects the LLVM bin dir to be available") - .join(name); - - let mut cmd = Command::new(tool_path); - configure_cmd_fn(&mut cmd); - - self.run_command_to_procres(&mut cmd) - } - fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes { let output = cmd.output().unwrap_or_else(|e| panic!("failed to exec `{cmd:?}`: {e:?}")); @@ -737,143 +521,6 @@ impl<'test> TestCx<'test> { proc_res } - fn normalize_coverage_output(&self, coverage: &str) -> Result<String, String> { - let normalized = self.normalize_output(coverage, &[]); - let normalized = Self::anonymize_coverage_line_numbers(&normalized); - - let mut lines = normalized.lines().collect::<Vec<_>>(); - - Self::sort_coverage_file_sections(&mut lines)?; - Self::sort_coverage_subviews(&mut lines)?; - - let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::<String>(); - Ok(joined_lines) - } - - /// Replace line numbers in coverage reports with the placeholder `LL`, - /// so that the tests are less sensitive to lines being added/removed. - fn anonymize_coverage_line_numbers(coverage: &str) -> String { - // The coverage reporter prints line numbers at the start of a line. - // They are truncated or left-padded to occupy exactly 5 columns. - // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.) - // A pipe character `|` appears immediately after the final digit. - // - // Line numbers that appear inside expansion/instantiation subviews - // have an additional prefix of ` |` for each nesting level. - // - // Branch views also include the relevant line number, so we want to - // redact those too. (These line numbers don't have padding.) - // - // Note: The pattern `(?m:^)` matches the start of a line. - - // ` 1|` => ` LL|` - // ` 10|` => ` LL|` - // ` 100|` => ` LL|` - // ` | 1000|` => ` | LL|` - // ` | | 1000|` => ` | | LL|` - let coverage = static_regex!(r"(?m:^)(?<prefix>(?: \|)*) *[0-9]+\|") - .replace_all(&coverage, "${prefix} LL|"); - - // ` | Branch (1:` => ` | Branch (LL:` - // ` | | Branch (10:` => ` | | Branch (LL:` - let coverage = static_regex!(r"(?m:^)(?<prefix>(?: \|)+ Branch \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:"); - - // ` |---> MC/DC Decision Region (1:30) to (2:` => ` |---> MC/DC Decision Region (LL:30) to (LL:` - let coverage = - static_regex!(r"(?m:^)(?<prefix>(?: \|)+---> MC/DC Decision Region \()[0-9]+:(?<middle>[0-9]+\) to \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:${middle}LL:"); - - // ` | Condition C1 --> (1:` => ` | Condition C1 --> (LL:` - let coverage = - static_regex!(r"(?m:^)(?<prefix>(?: \|)+ Condition C[0-9]+ --> \()[0-9]+:") - .replace_all(&coverage, "${prefix}LL:"); - - coverage.into_owned() - } - - /// Coverage reports can describe multiple source files, separated by - /// blank lines. The order of these files is unpredictable (since it - /// depends on implementation details), so we need to sort the file - /// sections into a consistent order before comparing against a snapshot. - fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> { - // Group the lines into file sections, separated by blank lines. - let mut sections = coverage_lines.split(|line| line.is_empty()).collect::<Vec<_>>(); - - // The last section should be empty, representing an extra trailing blank line. - if !sections.last().is_some_and(|last| last.is_empty()) { - return Err("coverage report should end with an extra blank line".to_owned()); - } - - // Sort the file sections (not including the final empty "section"). - let except_last = sections.len() - 1; - (&mut sections[..except_last]).sort(); - - // Join the file sections back into a flat list of lines, with - // sections separated by blank lines. - let joined = sections.join(&[""] as &[_]); - assert_eq!(joined.len(), coverage_lines.len()); - *coverage_lines = joined; - - Ok(()) - } - - fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { - let mut output_lines = Vec::new(); - - // We accumulate a list of zero or more "subviews", where each - // subview is a list of one or more lines. - let mut subviews: Vec<Vec<&str>> = Vec::new(); - - fn flush<'a>(subviews: &mut Vec<Vec<&'a str>>, output_lines: &mut Vec<&'a str>) { - if subviews.is_empty() { - return; - } - - // Take and clear the list of accumulated subviews. - let mut subviews = std::mem::take(subviews); - - // The last "subview" should be just a boundary line on its own, - // so exclude it when sorting the other subviews. - let except_last = subviews.len() - 1; - (&mut subviews[..except_last]).sort(); - - for view in subviews { - for line in view { - output_lines.push(line); - } - } - } - - for (line, line_num) in coverage_lines.iter().zip(1..) { - if line.starts_with(" ------------------") { - // This is a subview boundary line, so start a new subview. - subviews.push(vec![line]); - } else if line.starts_with(" |") { - // Add this line to the current subview. - subviews - .last_mut() - .ok_or(format!( - "unexpected subview line outside of a subview on line {line_num}" - ))? - .push(line); - } else { - // This line is not part of a subview, so sort and print any - // accumulated subviews, and then print the line as-is. - flush(&mut subviews, &mut output_lines); - output_lines.push(line); - } - } - - flush(&mut subviews, &mut output_lines); - assert!(subviews.is_empty()); - - assert_eq!(output_lines.len(), coverage_lines.len()); - *coverage_lines = output_lines; - - Ok(()) - } - fn run_pretty_test(&self) { if self.props.pp_exact.is_some() { logv(self.config, "testing for exact pretty-printing".to_owned()); diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs new file mode 100644 index 00000000000..dad3fb30133 --- /dev/null +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -0,0 +1,367 @@ +//! Code specific to the coverage test suites. + +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use glob::glob; + +use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP}; +use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute}; + +impl<'test> TestCx<'test> { + pub(crate) fn run_coverage_map_test(&self) { + let Some(coverage_dump_path) = &self.config.coverage_dump_path else { + self.fatal("missing --coverage-dump"); + }; + + let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + let mut dump_command = Command::new(coverage_dump_path); + dump_command.arg(llvm_ir_path); + let proc_res = self.run_command_to_procres(&mut dump_command); + if !proc_res.status.success() { + self.fatal_proc_rec("coverage-dump failed!", &proc_res); + } + + let kind = UI_COVERAGE_MAP; + + let expected_coverage_dump = self.load_expected_output(kind); + let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); + + let coverage_dump_errors = + self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); + + if coverage_dump_errors > 0 { + self.fatal_proc_rec( + &format!("{coverage_dump_errors} errors occurred comparing coverage output."), + &proc_res, + ); + } + } + + pub(crate) fn run_coverage_run_test(&self) { + let should_run = self.run_if_enabled(); + let proc_res = self.compile_test(should_run, Emit::None); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + if let WillExecute::Disabled = should_run { + return; + } + + let profraw_path = self.output_base_dir().join("default.profraw"); + let profdata_path = self.output_base_dir().join("default.profdata"); + + // Delete any existing profraw/profdata files to rule out unintended + // interference between repeated test runs. + if profraw_path.exists() { + std::fs::remove_file(&profraw_path).unwrap(); + } + if profdata_path.exists() { + std::fs::remove_file(&profdata_path).unwrap(); + } + + let proc_res = self.exec_compiled_test_general( + &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], + false, + ); + if self.props.failure_status.is_some() { + self.check_correct_failure_status(&proc_res); + } else if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } + drop(proc_res); + + let mut profraw_paths = vec![profraw_path]; + let mut bin_paths = vec![self.make_exe_name()]; + + if self.config.suite == "coverage-run-rustdoc" { + self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); + } + + // Run `llvm-profdata merge` to index the raw coverage output. + let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { + cmd.args(["merge", "--sparse", "--output"]); + cmd.arg(&profdata_path); + cmd.args(&profraw_paths); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); + } + drop(proc_res); + + // Run `llvm-cov show` to produce a coverage report in text format. + let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { + cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); + + cmd.arg("--Xdemangler"); + cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); + + cmd.arg("--instr-profile"); + cmd.arg(&profdata_path); + + for bin in &bin_paths { + cmd.arg("--object"); + cmd.arg(bin); + } + + cmd.args(&self.props.llvm_cov_flags); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-cov show failed!", &proc_res); + } + + let kind = UI_COVERAGE; + + let expected_coverage = self.load_expected_output(kind); + let normalized_actual_coverage = + self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| { + self.fatal_proc_rec(&err, &proc_res); + }); + + let coverage_errors = + self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); + + if coverage_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occurred comparing coverage output.", coverage_errors), + &proc_res, + ); + } + } + + /// Run any doctests embedded in this test file, and add any resulting + /// `.profraw` files and doctest executables to the given vectors. + fn run_doctests_for_coverage( + &self, + profraw_paths: &mut Vec<PathBuf>, + bin_paths: &mut Vec<PathBuf>, + ) { + // Put .profraw files and doctest executables in dedicated directories, + // to make it easier to glob them all later. + let profraws_dir = self.output_base_dir().join("doc_profraws"); + let bins_dir = self.output_base_dir().join("doc_bins"); + + // Remove existing directories to prevent cross-run interference. + if profraws_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&profraws_dir).unwrap(); + } + if bins_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&bins_dir).unwrap(); + } + + let mut rustdoc_cmd = + Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed")); + + // In general there will be multiple doctest binaries running, so we + // tell the profiler runtime to write their coverage data into separate + // profraw files. + rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw")); + + rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]); + + // Without this, the doctests complain about not being able to find + // their enclosing file's crate for some reason. + rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]); + + // Persist the doctest binaries so that `llvm-cov show` can read their + // embedded coverage mappings later. + rustdoc_cmd.arg("-Zunstable-options"); + rustdoc_cmd.arg("--persist-doctests"); + rustdoc_cmd.arg(&bins_dir); + + rustdoc_cmd.arg("-L"); + rustdoc_cmd.arg(self.aux_output_dir_name()); + + rustdoc_cmd.arg(&self.testpaths.file); + + let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); + if !proc_res.status.success() { + self.fatal_proc_rec("rustdoc --test failed!", &proc_res) + } + + fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> { + let path_str = path.as_ref().to_str().unwrap(); + let iter = glob(path_str).unwrap(); + iter.map(Result::unwrap) + } + + // Find all profraw files in the profraw directory. + for p in glob_iter(profraws_dir.join("*.profraw")) { + profraw_paths.push(p); + } + // Find all executables in the `--persist-doctests` directory, while + // avoiding other file types (e.g. `.pdb` on Windows). This doesn't + // need to be perfect, as long as it can handle the files actually + // produced by `rustdoc --test`. + for p in glob_iter(bins_dir.join("**/*")) { + let is_bin = p.is_file() + && match p.extension() { + None => true, + Some(ext) => ext == OsStr::new("exe"), + }; + if is_bin { + bin_paths.push(p); + } + } + } + + fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { + let tool_path = self + .config + .llvm_bin_dir + .as_ref() + .expect("this test expects the LLVM bin dir to be available") + .join(name); + + let mut cmd = Command::new(tool_path); + configure_cmd_fn(&mut cmd); + + self.run_command_to_procres(&mut cmd) + } + + fn normalize_coverage_output(&self, coverage: &str) -> Result<String, String> { + let normalized = self.normalize_output(coverage, &[]); + let normalized = Self::anonymize_coverage_line_numbers(&normalized); + + let mut lines = normalized.lines().collect::<Vec<_>>(); + + Self::sort_coverage_file_sections(&mut lines)?; + Self::sort_coverage_subviews(&mut lines)?; + + let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::<String>(); + Ok(joined_lines) + } + + /// Replace line numbers in coverage reports with the placeholder `LL`, + /// so that the tests are less sensitive to lines being added/removed. + fn anonymize_coverage_line_numbers(coverage: &str) -> String { + // The coverage reporter prints line numbers at the start of a line. + // They are truncated or left-padded to occupy exactly 5 columns. + // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.) + // A pipe character `|` appears immediately after the final digit. + // + // Line numbers that appear inside expansion/instantiation subviews + // have an additional prefix of ` |` for each nesting level. + // + // Branch views also include the relevant line number, so we want to + // redact those too. (These line numbers don't have padding.) + // + // Note: The pattern `(?m:^)` matches the start of a line. + + // ` 1|` => ` LL|` + // ` 10|` => ` LL|` + // ` 100|` => ` LL|` + // ` | 1000|` => ` | LL|` + // ` | | 1000|` => ` | | LL|` + let coverage = static_regex!(r"(?m:^)(?<prefix>(?: \|)*) *[0-9]+\|") + .replace_all(&coverage, "${prefix} LL|"); + + // ` | Branch (1:` => ` | Branch (LL:` + // ` | | Branch (10:` => ` | | Branch (LL:` + let coverage = static_regex!(r"(?m:^)(?<prefix>(?: \|)+ Branch \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:"); + + // ` |---> MC/DC Decision Region (1:30) to (2:` => ` |---> MC/DC Decision Region (LL:30) to (LL:` + let coverage = + static_regex!(r"(?m:^)(?<prefix>(?: \|)+---> MC/DC Decision Region \()[0-9]+:(?<middle>[0-9]+\) to \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:${middle}LL:"); + + // ` | Condition C1 --> (1:` => ` | Condition C1 --> (LL:` + let coverage = + static_regex!(r"(?m:^)(?<prefix>(?: \|)+ Condition C[0-9]+ --> \()[0-9]+:") + .replace_all(&coverage, "${prefix}LL:"); + + coverage.into_owned() + } + + /// Coverage reports can describe multiple source files, separated by + /// blank lines. The order of these files is unpredictable (since it + /// depends on implementation details), so we need to sort the file + /// sections into a consistent order before comparing against a snapshot. + fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + // Group the lines into file sections, separated by blank lines. + let mut sections = coverage_lines.split(|line| line.is_empty()).collect::<Vec<_>>(); + + // The last section should be empty, representing an extra trailing blank line. + if !sections.last().is_some_and(|last| last.is_empty()) { + return Err("coverage report should end with an extra blank line".to_owned()); + } + + // Sort the file sections (not including the final empty "section"). + let except_last = sections.len() - 1; + (&mut sections[..except_last]).sort(); + + // Join the file sections back into a flat list of lines, with + // sections separated by blank lines. + let joined = sections.join(&[""] as &[_]); + assert_eq!(joined.len(), coverage_lines.len()); + *coverage_lines = joined; + + Ok(()) + } + + fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + let mut output_lines = Vec::new(); + + // We accumulate a list of zero or more "subviews", where each + // subview is a list of one or more lines. + let mut subviews: Vec<Vec<&str>> = Vec::new(); + + fn flush<'a>(subviews: &mut Vec<Vec<&'a str>>, output_lines: &mut Vec<&'a str>) { + if subviews.is_empty() { + return; + } + + // Take and clear the list of accumulated subviews. + let mut subviews = std::mem::take(subviews); + + // The last "subview" should be just a boundary line on its own, + // so exclude it when sorting the other subviews. + let except_last = subviews.len() - 1; + (&mut subviews[..except_last]).sort(); + + for view in subviews { + for line in view { + output_lines.push(line); + } + } + } + + for (line, line_num) in coverage_lines.iter().zip(1..) { + if line.starts_with(" ------------------") { + // This is a subview boundary line, so start a new subview. + subviews.push(vec![line]); + } else if line.starts_with(" |") { + // Add this line to the current subview. + subviews + .last_mut() + .ok_or(format!( + "unexpected subview line outside of a subview on line {line_num}" + ))? + .push(line); + } else { + // This line is not part of a subview, so sort and print any + // accumulated subviews, and then print the line as-is. + flush(&mut subviews, &mut output_lines); + output_lines.push(line); + } + } + + flush(&mut subviews, &mut output_lines); + assert!(subviews.is_empty()); + + assert_eq!(output_lines.len(), coverage_lines.len()); + *coverage_lines = output_lines; + + Ok(()) + } +} diff --git a/src/tools/compiletest/src/runtest/tests.rs b/src/tools/compiletest/src/runtest/tests.rs index 817b56109a5..fb3dd326a4c 100644 --- a/src/tools/compiletest/src/runtest/tests.rs +++ b/src/tools/compiletest/src/runtest/tests.rs @@ -48,71 +48,3 @@ fn normalize_platform_differences() { r#"println!("test\ntest")"#, ); } - -/// Test for anonymizing line numbers in coverage reports, especially for -/// MC/DC regions. -/// -/// FIXME(#123409): This test can be removed when we have examples of MC/DC -/// coverage in the actual coverage test suite. -#[test] -fn anonymize_coverage_line_numbers() { - let anon = |coverage| TestCx::anonymize_coverage_line_numbers(coverage); - - let input = r#" - 7| 2|fn mcdc_check_neither(a: bool, b: bool) { - 8| 2| if a && b { - ^0 - ------------------ - |---> MC/DC Decision Region (8:8) to (8:14) - | - | Number of Conditions: 2 - | Condition C1 --> (8:8) - | Condition C2 --> (8:13) - | - | Executed MC/DC Test Vectors: - | - | C1, C2 Result - | 1 { F, - = F } - | - | C1-Pair: not covered - | C2-Pair: not covered - | MC/DC Coverage for Decision: 0.00% - | - ------------------ - 9| 0| say("a and b"); - 10| 2| } else { - 11| 2| say("not both"); - 12| 2| } - 13| 2|} -"#; - - let expected = r#" - LL| 2|fn mcdc_check_neither(a: bool, b: bool) { - LL| 2| if a && b { - ^0 - ------------------ - |---> MC/DC Decision Region (LL:8) to (LL:14) - | - | Number of Conditions: 2 - | Condition C1 --> (LL:8) - | Condition C2 --> (LL:13) - | - | Executed MC/DC Test Vectors: - | - | C1, C2 Result - | 1 { F, - = F } - | - | C1-Pair: not covered - | C2-Pair: not covered - | MC/DC Coverage for Decision: 0.00% - | - ------------------ - LL| 0| say("a and b"); - LL| 2| } else { - LL| 2| say("not both"); - LL| 2| } - LL| 2|} -"#; - - assert_eq!(anon(input), expected); -} diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.rs b/src/tools/miri/tests/fail/reading_half_a_pointer.rs index 7dd98eab785..feac30b83c3 100644 --- a/src/tools/miri/tests/fail/reading_half_a_pointer.rs +++ b/src/tools/miri/tests/fail/reading_half_a_pointer.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] // We use packed structs to get around alignment restrictions -#[repr(packed)] +#[repr(C, packed)] struct Data { pad: u8, ptr: &'static i32, diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs index 8459c64ed2d..06dd97deeda 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.rs @@ -7,7 +7,7 @@ pub struct Aligned { _pad: [u8; 11], packed: Packed, } -#[repr(packed)] +#[repr(C, packed)] #[derive(Default, Copy, Clone)] pub struct Packed { _pad: [u8; 5], diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index b424ae3f421..5dde0f91fea 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -203,6 +203,12 @@ impl Rustc { self } + /// Specify the linker + pub fn linker(&mut self, linker: &str) -> &mut Self { + self.cmd.arg(format!("-Clinker={linker}")); + self + } + /// Get the [`Output`] of the finished process. #[track_caller] pub fn command_output(&mut self) -> ::std::process::Output { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 75cd2b4c773..ab8367b2247 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -21,7 +21,6 @@ run-make/compiler-lookup-paths-2/Makefile run-make/compiler-lookup-paths/Makefile run-make/compiler-rt-works-on-mingw/Makefile run-make/compressed-debuginfo/Makefile -run-make/const-prop-lint/Makefile run-make/const_fn_mir/Makefile run-make/crate-data-smoke/Makefile run-make/crate-hash-rustc-version/Makefile @@ -72,7 +71,6 @@ run-make/forced-unwind-terminate-pof/Makefile run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/foreign-rust-exceptions/Makefile -run-make/fpic/Makefile run-make/glibc-staticlib-args/Makefile run-make/inaccessible-temp-dir/Makefile run-make/include_bytes_deps/Makefile @@ -103,7 +101,6 @@ run-make/issue-33329/Makefile run-make/issue-35164/Makefile run-make/issue-36710/Makefile run-make/issue-37839/Makefile -run-make/issue-37893/Makefile run-make/issue-40535/Makefile run-make/issue-47384/Makefile run-make/issue-47551/Makefile @@ -116,7 +113,6 @@ run-make/issue-83112-incr-test-moved-file/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-85019-moved-src-dir/Makefile run-make/issue-85401-static-mir/Makefile -run-make/issue-85441/Makefile run-make/issue-88756-default-output/Makefile run-make/issue-97463-abi-param-passing/Makefile run-make/jobserver-error/Makefile @@ -235,7 +231,6 @@ run-make/share-generics-dylib/Makefile run-make/short-ice/Makefile run-make/silly-file-names/Makefile run-make/simd-ffi/Makefile -run-make/simple-dylib/Makefile run-make/split-debuginfo/Makefile run-make/stable-symbol-names/Makefile run-make/static-dylib-by-default/Makefile @@ -272,8 +267,4 @@ run-make/volatile-intrinsics/Makefile run-make/wasm-exceptions-nostd/Makefile run-make/wasm-override-linker/Makefile run-make/weird-output-filenames/Makefile -run-make/windows-binary-no-external-deps/Makefile -run-make/windows-safeseh/Makefile -run-make/windows-spawn/Makefile -run-make/windows-subsystem/Makefile run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile diff --git a/tests/codegen/fixed-x18.rs b/tests/codegen/fixed-x18.rs new file mode 100644 index 00000000000..4997a39a726 --- /dev/null +++ b/tests/codegen/fixed-x18.rs @@ -0,0 +1,22 @@ +// Test that the `reserve-x18` target feature is (not) emitted when +// the `-Zfixed-x18` flag is (not) set. + +//@ revisions: unset set +//@ needs-llvm-components: aarch64 +//@ compile-flags: --target aarch64-unknown-none +//@ [set] compile-flags: -Zfixed-x18 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // unset-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+reserve-x18{{.*}} } + // set: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+reserve-x18{{.*}} } +} diff --git a/tests/coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs index 72d479c74a6..c0556a5bb4c 100644 --- a/tests/coverage/auxiliary/used_crate.rs +++ b/tests/coverage/auxiliary/used_crate.rs @@ -17,23 +17,23 @@ pub fn used_function() { } pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); + println!("used_only_from_bin_crate_generic_function with {arg:?}"); } // Expect for above function: `Unexecuted instantiation` (see below) pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); } pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } pub fn unused_generic_function<T: Debug>(arg: T) { - println!("unused_generic_function with {:?}", arg); + println!("unused_generic_function with {arg:?}"); } pub fn unused_function() { diff --git a/tests/coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs index d5fe7478aa4..165d5c1e309 100644 --- a/tests/coverage/auxiliary/used_inline_crate.rs +++ b/tests/coverage/auxiliary/used_inline_crate.rs @@ -31,28 +31,28 @@ pub fn used_inline_function() { #[inline(always)] pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); + println!("used_only_from_bin_crate_generic_function with {arg:?}"); } // Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) #[inline(always)] pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); } #[inline(always)] pub fn unused_generic_function<T: Debug>(arg: T) { - println!("unused_generic_function with {:?}", arg); + println!("unused_generic_function with {arg:?}"); } #[inline(always)] diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 6ead788b82f..6ff5ed74a96 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -12,7 +12,7 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: coroutine::main -Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -26,7 +26,7 @@ Number of expressions: 8 - expression 7 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) -- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) = ((c1 + c2) + c3) @@ -41,11 +41,11 @@ Number of file 0 mappings: 9 = ((c4 - c5) - c6) Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 29, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 08, 01, 1f, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 21, 41) to (start + 1, 31) +- Code(Counter(0)) at (prev + 22, 8) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index 68b52d19831..611470c5773 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -10,15 +10,16 @@ LL| |// to handle this condition, and still report dead block coverage. LL| 1|fn get_u32(val: bool) -> Result<u32, String> { LL| 1| if val { - LL| 1| Ok(1) + LL| 1| Ok(1) // LL| | } else { - LL| 0| Err(String::from("some error")) + LL| 0| Err(String::from("some error")) // LL| | } LL| 1|} LL| | LL| 1|fn main() { LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield get_u32(is_true); LL| 1| return "foo"; LL| 1| }; diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 7f72e0d8bd4..bd149764b37 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -10,15 +10,16 @@ use std::pin::Pin; // to handle this condition, and still report dead block coverage. fn get_u32(val: bool) -> Result<u32, String> { if val { - Ok(1) + Ok(1) // } else { - Err(String::from("some error")) + Err(String::from("some error")) // } } fn main() { let is_true = std::env::args().len() == 1; - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield get_u32(is_true); return "foo"; }; diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index a2d24fd2f6a..c12668ce89a 100644 --- a/tests/coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage @@ -14,7 +14,7 @@ LL| |#[inline] LL| 1|fn live<const B: bool>() -> u32 { LL| 1| if B { - LL| 0| dead() + LL| 0| dead() // LL| | } else { LL| 1| 0 LL| | } diff --git a/tests/coverage/inline-dead.rs b/tests/coverage/inline-dead.rs index 327e68c60bb..4eb397a43fc 100644 --- a/tests/coverage/inline-dead.rs +++ b/tests/coverage/inline-dead.rs @@ -13,7 +13,7 @@ fn main() { #[inline] fn live<const B: bool>() -> u32 { if B { - dead() + dead() // } else { 0 } diff --git a/tests/coverage/inner_items.coverage b/tests/coverage/inner_items.coverage index 65493bcd9db..152f3da1a22 100644 --- a/tests/coverage/inner_items.coverage +++ b/tests/coverage/inner_items.coverage @@ -52,7 +52,7 @@ ^0 LL| | LL| 1| let mut val = InStruct { - LL| 1| in_struct_field: 101, + LL| 1| in_struct_field: 101, // LL| 1| }; LL| 1| LL| 1| val.default_trait_func(); diff --git a/tests/coverage/inner_items.rs b/tests/coverage/inner_items.rs index bcb62b3031c..4d513e612f0 100644 --- a/tests/coverage/inner_items.rs +++ b/tests/coverage/inner_items.rs @@ -50,7 +50,7 @@ fn main() { } let mut val = InStruct { - in_struct_field: 101, + in_struct_field: 101, // }; val.default_trait_func(); diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index b0cee300522..13d0d08adb1 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -1,12 +1,12 @@ Function name: let_else_loop::_if (unused) -Raw bytes (19): 0x[01, 01, 00, 03, 00, 16, 01, 01, 0c, 00, 02, 09, 00, 10, 00, 02, 09, 00, 10] +Raw bytes (19): 0x[01, 01, 00, 03, 00, 16, 01, 01, 0c, 00, 01, 0f, 00, 16, 00, 00, 20, 00, 27] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 - Code(Zero) at (prev + 22, 1) to (start + 1, 12) -- Code(Zero) at (prev + 2, 9) to (start + 0, 16) -- Code(Zero) at (prev + 2, 9) to (start + 0, 16) +- Code(Zero) at (prev + 1, 15) to (start + 0, 22) +- Code(Zero) at (prev + 0, 32) to (start + 0, 39) Function name: let_else_loop::_loop_either_way (unused) Raw bytes (19): 0x[01, 01, 00, 03, 00, 0f, 01, 01, 14, 00, 01, 1c, 00, 23, 00, 01, 05, 00, 0c] diff --git a/tests/coverage/let_else_loop.coverage b/tests/coverage/let_else_loop.coverage index d193c8ca1b5..bd13f6e5650 100644 --- a/tests/coverage/let_else_loop.coverage +++ b/tests/coverage/let_else_loop.coverage @@ -21,11 +21,7 @@ LL| |// Variant using regular `if` instead of let-else. LL| |// This doesn't trigger the original ICE, but might help detect regressions. LL| 0|fn _if(cond: bool) { - LL| 0| if cond { - LL| 0| loop {} - LL| | } else { - LL| 0| loop {} - LL| | } + LL| 0| if cond { loop {} } else { loop {} } LL| |} LL| | LL| |#[coverage(off)] diff --git a/tests/coverage/let_else_loop.rs b/tests/coverage/let_else_loop.rs index 12e0aeabcab..8217c0d072a 100644 --- a/tests/coverage/let_else_loop.rs +++ b/tests/coverage/let_else_loop.rs @@ -20,11 +20,7 @@ fn _loop_either_way(cond: bool) { // Variant using regular `if` instead of let-else. // This doesn't trigger the original ICE, but might help detect regressions. fn _if(cond: bool) { - if cond { - loop {} - } else { - loop {} - } + if cond { loop {} } else { loop {} } } #[coverage(off)] diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map new file mode 100644 index 00000000000..b4447a33691 --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -0,0 +1,162 @@ +Function name: condition_limit::bad +Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 44 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(7) +- expression 2 operands: lhs = Counter(1), rhs = Counter(7) +- expression 3 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 4 operands: lhs = Counter(1), rhs = Counter(7) +- expression 5 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 6 operands: lhs = Counter(1), rhs = Counter(7) +- expression 7 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 8 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 9 operands: lhs = Counter(1), rhs = Counter(7) +- expression 10 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 11 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 12 operands: lhs = Counter(1), rhs = Counter(7) +- expression 13 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 14 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 16 operands: lhs = Counter(1), rhs = Counter(7) +- expression 17 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 18 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 19 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 20 operands: lhs = Counter(1), rhs = Counter(7) +- expression 21 operands: lhs = Expression(27, Sub), rhs = Counter(3) +- expression 22 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 23 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 24 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 25 operands: lhs = Counter(1), rhs = Counter(7) +- expression 26 operands: lhs = Expression(27, Sub), rhs = Counter(3) +- expression 27 operands: lhs = Expression(28, Sub), rhs = Counter(4) +- expression 28 operands: lhs = Expression(29, Sub), rhs = Counter(5) +- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(6) +- expression 30 operands: lhs = Counter(1), rhs = Counter(7) +- expression 31 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub) +- expression 32 operands: lhs = Expression(40, Add), rhs = Counter(7) +- expression 33 operands: lhs = Expression(41, Add), rhs = Counter(6) +- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(5) +- expression 35 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 36 operands: lhs = Counter(2), rhs = Counter(3) +- expression 37 operands: lhs = Counter(8), rhs = Expression(38, Add) +- expression 38 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub) +- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(7) +- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(6) +- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5) +- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) +- expression 43 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Expression(30, Sub), false: Counter(7) } at (prev + 0, 13) to (start + 0, 14) + true = (c1 - c7) + false = c7 +- Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c1 - c7) +- Branch { true: Expression(29, Sub), false: Counter(6) } at (prev + 0, 18) to (start + 0, 19) + true = ((c1 - c7) - c6) + false = c6 +- Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c7) - c6) +- Branch { true: Expression(28, Sub), false: Counter(5) } at (prev + 0, 23) to (start + 0, 24) + true = (((c1 - c7) - c6) - c5) + false = c5 +- Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29) + = (((c1 - c7) - c6) - c5) +- Branch { true: Expression(27, Sub), false: Counter(4) } at (prev + 0, 28) to (start + 0, 29) + true = ((((c1 - c7) - c6) - c5) - c4) + false = c4 +- Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34) + = ((((c1 - c7) - c6) - c5) - c4) +- Branch { true: Expression(26, Sub), false: Counter(3) } at (prev + 0, 33) to (start + 0, 34) + true = (((((c1 - c7) - c6) - c5) - c4) - c3) + false = c3 +- Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39) + = (((((c1 - c7) - c6) - c5) - c4) - c3) +- Branch { true: Counter(8), false: Counter(2) } at (prev + 0, 38) to (start + 0, 39) + true = c8 + false = c2 +- Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6) +- Code(Expression(38, Add)) at (prev + 2, 6) to (start + 0, 7) + = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)) +- Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) + +Function name: condition_limit::good +Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 32 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(6) +- expression 2 operands: lhs = Counter(1), rhs = Counter(6) +- expression 3 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Counter(1), rhs = Counter(6) +- expression 5 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 6 operands: lhs = Counter(1), rhs = Counter(6) +- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 9 operands: lhs = Counter(1), rhs = Counter(6) +- expression 10 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(1), rhs = Counter(6) +- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(3) +- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 15 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 16 operands: lhs = Counter(1), rhs = Counter(6) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(3) +- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(4) +- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5) +- expression 20 operands: lhs = Counter(1), rhs = Counter(6) +- expression 21 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) +- expression 22 operands: lhs = Expression(29, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(30, Add), rhs = Counter(5) +- expression 24 operands: lhs = Expression(31, Add), rhs = Counter(4) +- expression 25 operands: lhs = Counter(2), rhs = Counter(3) +- expression 26 operands: lhs = Counter(7), rhs = Expression(27, Add) +- expression 27 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) +- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(6) +- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(5) +- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4) +- expression 31 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 16 +- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9) +- MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) +- MCDCBranch { true: Expression(20, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = (c1 - c6) + false = c6 +- Code(Expression(20, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c1 - c6) +- MCDCBranch { true: Expression(19, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = ((c1 - c6) - c5) + false = c5 +- Code(Expression(19, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c6) - c5) +- MCDCBranch { true: Expression(18, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) + true = (((c1 - c6) - c5) - c4) + false = c4 +- Code(Expression(18, Sub)) at (prev + 0, 28) to (start + 0, 29) + = (((c1 - c6) - c5) - c4) +- MCDCBranch { true: Expression(17, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) + true = ((((c1 - c6) - c5) - c4) - c3) + false = c3 +- Code(Expression(17, Sub)) at (prev + 0, 33) to (start + 0, 34) + = ((((c1 - c6) - c5) - c4) - c3) +- MCDCBranch { true: Counter(7), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34) + true = c7 + false = c2 +- Code(Counter(7)) at (prev + 0, 35) to (start + 2, 6) +- Code(Expression(27, Add)) at (prev + 2, 6) to (start + 0, 7) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +- Code(Expression(26, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c7 + (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))) + diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage new file mode 100644 index 00000000000..4eb87432fab --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -0,0 +1,76 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ min-llvm-version: 18 + LL| |//@ compile-flags: -Zcoverage-options=mcdc + LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc + LL| | + LL| |// Check that MC/DC instrumentation can gracefully handle conditions that + LL| |// exceed LLVM's limit of 6 conditions per decision. + LL| |// + LL| |// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + LL| | + LL| 1|fn good() { + LL| 1| // With only 6 conditions, perform full MC/DC instrumentation. + LL| 1| let [a, b, c, d, e, f] = <[bool; 6]>::default(); + LL| 1| if a && b && c && d && e && f { + ^0 ^0 ^0 ^0 ^0 + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:13): [True: 0, False: 0] + | Branch (LL:18): [True: 0, False: 0] + | Branch (LL:23): [True: 0, False: 0] + | Branch (LL:28): [True: 0, False: 0] + | Branch (LL:33): [True: 0, False: 0] + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:34) + | + | Number of Conditions: 6 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | Condition C3 --> (LL:18) + | Condition C4 --> (LL:23) + | Condition C5 --> (LL:28) + | Condition C6 --> (LL:33) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3, C4, C5, C6 Result + | 1 { F, -, -, -, -, - = F } + | + | C1-Pair: not covered + | C2-Pair: not covered + | C3-Pair: not covered + | C4-Pair: not covered + | C5-Pair: not covered + | C6-Pair: not covered + | MC/DC Coverage for Decision: 0.00% + | + ------------------ + LL| 0| core::hint::black_box("hello"); + LL| 1| } + LL| 1|} + LL| | + LL| 1|fn bad() { + LL| 1| // With 7 conditions, fall back to branch instrumentation only. + LL| 1| let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + LL| 1| if a && b && c && d && e && f && g { + ^0 ^0 ^0 ^0 ^0 ^0 + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:13): [True: 0, False: 0] + | Branch (LL:18): [True: 0, False: 0] + | Branch (LL:23): [True: 0, False: 0] + | Branch (LL:28): [True: 0, False: 0] + | Branch (LL:33): [True: 0, False: 0] + | Branch (LL:38): [True: 0, False: 0] + ------------------ + LL| 0| core::hint::black_box("hello"); + LL| 1| } + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | good(); + LL| | bad(); + LL| |} + diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs new file mode 100644 index 00000000000..571c600ebd0 --- /dev/null +++ b/tests/coverage/mcdc/condition-limit.rs @@ -0,0 +1,32 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-branches=count --show-mcdc + +// Check that MC/DC instrumentation can gracefully handle conditions that +// exceed LLVM's limit of 6 conditions per decision. +// +// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + +fn good() { + // With only 6 conditions, perform full MC/DC instrumentation. + let [a, b, c, d, e, f] = <[bool; 6]>::default(); + if a && b && c && d && e && f { + core::hint::black_box("hello"); + } +} + +fn bad() { + // With 7 conditions, fall back to branch instrumentation only. + let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + if a && b && c && d && e && f && g { + core::hint::black_box("hello"); + } +} + +#[coverage(off)] +fn main() { + good(); + bad(); +} diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 80670fbfa5a..6c39ac0e378 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -1,16 +1,16 @@ Function name: <partial_eq::Version>::new -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 06, 06] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 02, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 5) to (start + 6, 6) +- Code(Counter(0)) at (prev + 12, 5) to (start + 2, 6) Function name: partial_eq::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 0a, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 10, 2) +- Code(Counter(0)) at (prev + 17, 1) to (start + 10, 2) diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index 9de1c933570..dc5b82b3c5f 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -10,11 +10,7 @@ LL| | LL| |impl Version { LL| 2| pub fn new(major: usize, minor: usize, patch: usize) -> Self { - LL| 2| Self { - LL| 2| major, - LL| 2| minor, - LL| 2| patch, - LL| 2| } + LL| 2| Self { major, minor, patch } LL| 2| } LL| |} LL| | @@ -26,7 +22,7 @@ LL| 1| "{:?} < {:?} = {}", LL| 1| version_3_2_1, LL| 1| version_3_3_0, - LL| 1| version_3_2_1 < version_3_3_0 + LL| 1| version_3_2_1 < version_3_3_0, // LL| 1| ); LL| 1|} LL| | diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/partial_eq.rs index 825e266f111..081502d4a9d 100644 --- a/tests/coverage/partial_eq.rs +++ b/tests/coverage/partial_eq.rs @@ -10,11 +10,7 @@ pub struct Version { impl Version { pub fn new(major: usize, minor: usize, patch: usize) -> Self { - Self { - major, - minor, - patch, - } + Self { major, minor, patch } } } @@ -26,7 +22,7 @@ fn main() { "{:?} < {:?} = {}", version_3_2_1, version_3_3_0, - version_3_2_1 < version_3_3_0 + version_3_2_1 < version_3_3_0, // ); } diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 49e6c7ceefc..9c18827d8e6 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -25,26 +25,26 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Function name: try_error_result::call -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 20) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: try_error_result::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 73, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 115, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -81,7 +81,7 @@ Number of file 0 mappings: 11 = (((c4 + Zero) + Zero) + c3) Function name: try_error_result::test2 -Raw bytes (280): 0x[01, 01, 24, 01, 07, 00, 09, 03, 0d, 41, 00, 1e, 00, 41, 00, 1e, 00, 41, 00, 4a, 00, 4e, 00, 52, 41, 03, 0d, 52, 41, 03, 0d, 4e, 00, 52, 41, 03, 0d, 4a, 00, 4e, 00, 52, 41, 03, 0d, 66, 00, 45, 00, 45, 00, 66, 00, 45, 00, 7a, 00, 4d, 00, 4d, 00, 7a, 00, 4d, 00, 83, 01, 0d, 87, 01, 00, 00, 8b, 01, 8f, 01, 00, 19, 00, 28, 01, 3e, 01, 03, 17, 03, 08, 09, 00, 0e, 52, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 00, 00, 2f, 00, 30, 1e, 00, 31, 03, 35, 00, 04, 11, 00, 12, 1a, 02, 11, 04, 12, 00, 05, 11, 00, 14, 1a, 00, 17, 00, 41, 19, 00, 41, 00, 42, 00, 00, 43, 00, 5f, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 20, 00, 01, 11, 00, 14, 00, 00, 17, 00, 41, 00, 00, 41, 00, 42, 00, 00, 43, 00, 60, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 20, 46, 04, 11, 00, 14, 4e, 00, 17, 00, 42, 00, 00, 42, 00, 43, 4a, 00, 44, 00, 61, 00, 00, 61, 00, 62, 46, 01, 0d, 00, 20, 62, 01, 11, 00, 14, 45, 00, 17, 01, 36, 00, 01, 36, 00, 37, 66, 01, 12, 00, 2f, 00, 00, 2f, 00, 30, 62, 01, 0d, 00, 20, 76, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 00, 02, 11, 00, 12, 7a, 01, 12, 00, 2f, 00, 01, 11, 00, 12, 76, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, 7f, 01, 01, 00, 02] +Raw bytes (280): 0x[01, 01, 24, 01, 07, 00, 09, 03, 0d, 41, 00, 1e, 00, 41, 00, 1e, 00, 41, 00, 4a, 00, 4e, 00, 52, 41, 03, 0d, 52, 41, 03, 0d, 4e, 00, 52, 41, 03, 0d, 4a, 00, 4e, 00, 52, 41, 03, 0d, 66, 00, 45, 00, 45, 00, 66, 00, 45, 00, 7a, 00, 4d, 00, 4d, 00, 7a, 00, 4d, 00, 83, 01, 0d, 87, 01, 00, 00, 8b, 01, 8f, 01, 00, 19, 00, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 52, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 00, 00, 2f, 00, 30, 1e, 00, 31, 03, 35, 00, 04, 11, 00, 12, 1a, 02, 11, 04, 12, 00, 05, 11, 00, 14, 1a, 00, 17, 00, 41, 19, 00, 41, 00, 42, 00, 00, 43, 00, 5f, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 20, 00, 01, 11, 00, 14, 00, 00, 17, 00, 41, 00, 00, 41, 00, 42, 00, 00, 43, 00, 60, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 20, 46, 04, 11, 00, 14, 4e, 00, 17, 00, 42, 00, 00, 42, 00, 43, 4a, 00, 44, 00, 61, 00, 00, 61, 00, 62, 46, 01, 0d, 00, 20, 62, 01, 11, 00, 14, 45, 00, 17, 01, 36, 00, 01, 36, 00, 37, 66, 01, 12, 00, 2f, 00, 00, 2f, 00, 30, 62, 01, 0d, 00, 20, 76, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 00, 02, 11, 00, 12, 7a, 01, 12, 00, 2f, 00, 01, 11, 00, 12, 76, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, 7f, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 36 @@ -122,7 +122,7 @@ Number of expressions: 36 - expression 34 operands: lhs = Expression(35, Add), rhs = Zero - expression 35 operands: lhs = Counter(6), rhs = Zero Number of file 0 mappings: 40 -- Code(Counter(0)) at (prev + 62, 1) to (start + 3, 23) +- Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23) - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) = (c0 + (Zero + c2)) - Code(Expression(20, Sub)) at (prev + 2, 9) to (start + 4, 26) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 6fbe8b8db13..7100248f7df 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -1,4 +1,5 @@ LL| |#![allow(unused_assignments)] + LL| |#![cfg_attr(rustfmt, rustfmt::skip)] LL| |//@ failure-status: 1 LL| | LL| 6|fn call(return_error: bool) -> Result<(), ()> { @@ -9,7 +10,6 @@ LL| | } LL| 6|} LL| | - LL| |#[rustfmt::skip] LL| 1|fn test1() -> Result<(), ()> { LL| 1| let mut LL| 1| countdown = 10 @@ -59,7 +59,6 @@ LL| 17| } LL| |} LL| | - LL| |#[rustfmt::skip] LL| 1|fn test2() -> Result<(), ()> { LL| 1| let thing1 = Thing1{}; LL| 1| let mut @@ -117,7 +116,6 @@ LL| 0| Ok(()) LL| 1|} LL| | - LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), ()> { LL| 1| test1().expect_err("test1 should fail"); LL| 1| test2() diff --git a/tests/coverage/try_error_result.rs b/tests/coverage/try_error_result.rs index f36283c34c8..1fd176c353d 100644 --- a/tests/coverage/try_error_result.rs +++ b/tests/coverage/try_error_result.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +#![cfg_attr(rustfmt, rustfmt::skip)] //@ failure-status: 1 fn call(return_error: bool) -> Result<(), ()> { @@ -9,7 +10,6 @@ fn call(return_error: bool) -> Result<(), ()> { } } -#[rustfmt::skip] fn test1() -> Result<(), ()> { let mut countdown = 10 @@ -58,7 +58,6 @@ impl Thing2 { } } -#[rustfmt::skip] fn test2() -> Result<(), ()> { let thing1 = Thing1{}; let mut @@ -111,7 +110,6 @@ fn test2() -> Result<(), ()> { Ok(()) } -#[rustfmt::skip] fn main() -> Result<(), ()> { test1().expect_err("test1 should fail"); test2() diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index a6a570a0850..d001eeffd86 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -19,69 +19,69 @@ $DIR/auxiliary/used_crate.rs: LL| 1|} LL| | LL| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - LL| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_bin_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> ------------------ | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>: | LL| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_only_from_bin_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| |// Expect for above function: `Unexecuted instantiation` (see below) LL| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | LL| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| 0|pub fn unused_generic_function<T: Debug>(arg: T) { - LL| 0| println!("unused_generic_function with {:?}", arg); + LL| 0| println!("unused_generic_function with {arg:?}"); LL| 0|} LL| | LL| 0|pub fn unused_function() { diff --git a/tests/coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage index 0c9735990c7..832a5a6a62b 100644 --- a/tests/coverage/uses_inline_crate.coverage +++ b/tests/coverage/uses_inline_crate.coverage @@ -34,74 +34,74 @@ $DIR/auxiliary/used_inline_crate.rs: LL| | LL| |#[inline(always)] LL| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - LL| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + LL| 2| println!("used_only_from_bin_crate_generic_function with {arg:?}"); LL| 2|} ------------------ | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_> ------------------ | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>: | LL| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>: | LL| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_only_from_bin_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) LL| | LL| |#[inline(always)] LL| 4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + LL| 4| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); LL| 4|} ------------------ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | LL| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_only_from_this_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ LL| | LL| |#[inline(always)] LL| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 3|} ------------------ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | LL| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ LL| | LL| |#[inline(always)] LL| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - LL| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + LL| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); LL| 3|} ------------------ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 1|} ------------------ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: | LL| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - | LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | LL| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {arg:?}"); | LL| 2|} ------------------ LL| | LL| |#[inline(always)] LL| 0|pub fn unused_generic_function<T: Debug>(arg: T) { - LL| 0| println!("unused_generic_function with {:?}", arg); + LL| 0| println!("unused_generic_function with {arg:?}"); LL| 0|} LL| | LL| |#[inline(always)] diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index 0347aaaa367..a273c688e24 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -1,5 +1,5 @@ Function name: yield::main -Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02] +Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 08, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 11 @@ -16,7 +16,7 @@ Number of expressions: 11 - expression 10 operands: lhs = Counter(9), rhs = Counter(10) Number of file 0 mappings: 16 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) -- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 52) = (c1 + Zero) @@ -29,7 +29,7 @@ Number of file 0 mappings: 16 = (c4 + c5) - Code(Expression(7, Sub)) at (prev + 3, 9) to (start + 0, 22) = ((c3 - c4) - c5) -- Code(Expression(7, Sub)) at (prev + 7, 11) to (start + 0, 46) +- Code(Expression(7, Sub)) at (prev + 8, 11) to (start + 0, 46) = ((c3 - c4) - c5) - Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41) - Code(Expression(9, Add)) at (prev + 1, 14) to (start + 0, 52) @@ -41,21 +41,21 @@ Number of file 0 mappings: 16 - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) Function name: yield::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 29, 01, 10, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 09, 08, 01, 10, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 8, 41) to (start + 1, 16) +- Code(Counter(0)) at (prev + 9, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) Function name: yield::main::{closure#1} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 29, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 08, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 41) to (start + 1, 16) +- Code(Counter(0)) at (prev + 24, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) diff --git a/tests/coverage/yield.coverage b/tests/coverage/yield.coverage index e2fc9196d24..2c133cbec54 100644 --- a/tests/coverage/yield.coverage +++ b/tests/coverage/yield.coverage @@ -5,7 +5,8 @@ LL| |use std::pin::Pin; LL| | LL| 1|fn main() { - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield 1; LL| 1| return "foo"; LL| 1| }; @@ -19,7 +20,8 @@ LL| 0| _ => panic!("unexpected value from resume"), LL| | } LL| | - LL| 1| let mut coroutine = #[coroutine] || { + LL| 1| let mut coroutine = #[coroutine] + LL| 1| || { LL| 1| yield 1; LL| 1| yield 2; LL| 0| yield 3; diff --git a/tests/coverage/yield.rs b/tests/coverage/yield.rs index 64ea2706604..e02e3d35612 100644 --- a/tests/coverage/yield.rs +++ b/tests/coverage/yield.rs @@ -5,7 +5,8 @@ use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield 1; return "foo"; }; @@ -19,7 +20,8 @@ fn main() { _ => panic!("unexpected value from resume"), } - let mut coroutine = #[coroutine] || { + let mut coroutine = #[coroutine] + || { yield 1; yield 2; yield 3; diff --git a/tests/mir-opt/const_allocation3.rs b/tests/mir-opt/const_allocation3.rs index 46be3e1e36e..9d2006b6fe8 100644 --- a/tests/mir-opt/const_allocation3.rs +++ b/tests/mir-opt/const_allocation3.rs @@ -7,7 +7,7 @@ fn main() { FOO; } -#[repr(packed)] +#[repr(C, packed)] struct Packed { a: [u8; 28], b: &'static i32, diff --git a/tests/run-make/const-prop-lint/Makefile b/tests/run-make/const-prop-lint/Makefile deleted file mode 100644 index f29f282f787..00000000000 --- a/tests/run-make/const-prop-lint/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# Test that emitting an error because of arithmetic -# overflow lint does not leave .o files around -# because of interrupted codegen. - -all: - $(RUSTC) input.rs; test $$? -eq 1 - ls *.o; test $$? -ne 0 diff --git a/tests/run-make/const-prop-lint/rmake.rs b/tests/run-make/const-prop-lint/rmake.rs new file mode 100644 index 00000000000..fa27a18a591 --- /dev/null +++ b/tests/run-make/const-prop-lint/rmake.rs @@ -0,0 +1,18 @@ +// Tests that const prop lints interrupting codegen don't leave `.o` files around. + +use std::fs; + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().input("input.rs").run_fail_assert_exit_code(1); + + for entry in fs::read_dir(tmp_dir()).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if path.is_file() && path.extension().is_some_and(|ext| ext == "o") { + panic!("there should not be `.o` files!"); + } + } +} diff --git a/tests/run-make/fpic/Makefile b/tests/run-make/fpic/Makefile deleted file mode 100644 index d3754d17372..00000000000 --- a/tests/run-make/fpic/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows -# ignore-apple - -# Test for #39529. -# `-z text` causes ld to error if there are any non-PIC sections - -all: - $(RUSTC) hello.rs -C link-args=-Wl,-z,text diff --git a/tests/run-make/fpic/hello.rs b/tests/run-make/fpic/hello.rs deleted file mode 100644 index 45590d86ba6..00000000000 --- a/tests/run-make/fpic/hello.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() { } diff --git a/tests/run-make/issue-37893/Makefile b/tests/run-make/issue-37893/Makefile deleted file mode 100644 index 44e4a321a30..00000000000 --- a/tests/run-make/issue-37893/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs diff --git a/tests/run-make/issue-85441/Makefile b/tests/run-make/issue-85441/Makefile deleted file mode 100644 index 987d7f7d4a7..00000000000 --- a/tests/run-make/issue-85441/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# only-windows-msvc - -include ../tools.mk - -# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 - -all: - $(RUSTC) empty.rs - objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll" diff --git a/tests/run-make/issue-37893/a.rs b/tests/run-make/proc-macro-init-order/a.rs index b5dffac3ff6..b5dffac3ff6 100644 --- a/tests/run-make/issue-37893/a.rs +++ b/tests/run-make/proc-macro-init-order/a.rs diff --git a/tests/run-make/issue-37893/b.rs b/tests/run-make/proc-macro-init-order/b.rs index 355d2b16527..355d2b16527 100644 --- a/tests/run-make/issue-37893/b.rs +++ b/tests/run-make/proc-macro-init-order/b.rs diff --git a/tests/run-make/issue-37893/c.rs b/tests/run-make/proc-macro-init-order/c.rs index b9c2155728c..b9c2155728c 100644 --- a/tests/run-make/issue-37893/c.rs +++ b/tests/run-make/proc-macro-init-order/c.rs diff --git a/tests/run-make/proc-macro-init-order/rmake.rs b/tests/run-make/proc-macro-init-order/rmake.rs new file mode 100644 index 00000000000..3c3fc813381 --- /dev/null +++ b/tests/run-make/proc-macro-init-order/rmake.rs @@ -0,0 +1,15 @@ +// a.rs is a procedural macro crate, on which b.rs and c.rs depend. A now +// patched bug caused a compilation failure if the proc-macro crate was +// initialized with its dependents in this exact order. This test checks +// that compilation succeeds even when initialization is done in this order. +// See https://github.com/rust-lang/rust/issues/37893 + +//@ ignore-cross-compile + +use run_make_support::rustc; + +fn main() { + rustc().input("a.rs").run(); + rustc().input("b.rs").run(); + rustc().input("c.rs").run(); +} diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs index 876968727f3..6a8dae1043e 100644 --- a/tests/run-make/rust-lld-by-default/rmake.rs +++ b/tests/run-make/rust-lld-by-default/rmake.rs @@ -4,8 +4,6 @@ //@ needs-rust-lld //@ only-x86_64-unknown-linux-gnu -extern crate run_make_support; - use run_make_support::regex::Regex; use run_make_support::rustc; use std::process::Output; diff --git a/tests/run-make/simple-dylib/Makefile b/tests/run-make/simple-dylib/Makefile deleted file mode 100644 index f3e1c1da88c..00000000000 --- a/tests/run-make/simple-dylib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk -all: - $(RUSTC) bar.rs --crate-type=dylib -C prefer-dynamic - $(RUSTC) foo.rs - $(call RUN,foo) diff --git a/tests/run-make/simple-dylib/bar.rs b/tests/run-make/simple-dylib/bar.rs deleted file mode 100644 index c5c0bc606cd..00000000000 --- a/tests/run-make/simple-dylib/bar.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn bar() {} diff --git a/tests/run-make/simple-dylib/foo.rs b/tests/run-make/simple-dylib/foo.rs deleted file mode 100644 index 8d68535e3b6..00000000000 --- a/tests/run-make/simple-dylib/foo.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate bar; - -fn main() { - bar::bar(); -} diff --git a/tests/run-make/windows-binary-no-external-deps/Makefile b/tests/run-make/windows-binary-no-external-deps/Makefile deleted file mode 100644 index 8960020fed5..00000000000 --- a/tests/run-make/windows-binary-no-external-deps/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# only-windows - -PATH=$(SYSTEMROOT)/system32 - -all: - $(RUSTC) hello.rs - $(TMPDIR)/hello.exe diff --git a/tests/run-make/windows-binary-no-external-deps/rmake.rs b/tests/run-make/windows-binary-no-external-deps/rmake.rs new file mode 100644 index 00000000000..6704fe04148 --- /dev/null +++ b/tests/run-make/windows-binary-no-external-deps/rmake.rs @@ -0,0 +1,21 @@ +//! Ensure that we aren't relying on any non-system DLLs when running +//! a "hello world" application by setting `PATH` to `C:\Windows\System32`. +//@ only-windows + +use run_make_support::{rustc, tmp_dir}; +use std::env; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + rustc().input("hello.rs").run(); + + let windows_dir = env::var("SystemRoot").unwrap(); + let system32: PathBuf = [&windows_dir, "System32"].iter().collect(); + // Note: This does not use the support wrappers so that we can precisely control the PATH + let exe = tmp_dir().join("hello.exe"); + let status = Command::new(exe).env("PATH", &system32).spawn().unwrap().wait().unwrap(); + if !status.success() { + panic!("Command failed!\noutput status: `{status}`"); + } +} diff --git a/tests/run-make/windows-safeseh/Makefile b/tests/run-make/windows-safeseh/Makefile deleted file mode 100644 index d6a403961d7..00000000000 --- a/tests/run-make/windows-safeseh/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# only-windows -# needs-rust-lld - -include ../tools.mk - -all: foo bar - -# Ensure that LLD can link when an .rlib contains a synthetic object -# file referencing exported or used symbols. -foo: - $(RUSTC) -C linker=rust-lld foo.rs - -# Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib. -# Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware. -bar: baz - $(RUSTC) -C linker=rust-lld -C link-arg=/WHOLEARCHIVE:libbaz.rlib bar.rs - -baz: - $(RUSTC) baz.rs diff --git a/tests/run-make/windows-safeseh/rmake.rs b/tests/run-make/windows-safeseh/rmake.rs new file mode 100644 index 00000000000..10e6b38aa8d --- /dev/null +++ b/tests/run-make/windows-safeseh/rmake.rs @@ -0,0 +1,15 @@ +//@ only-windows +//@ needs-rust-lld + +use run_make_support::rustc; + +fn main() { + // Ensure that LLD can link when an .rlib contains a synthetic object + // file referencing exported or used symbols. + rustc().input("foo.rs").linker("rust-lld").run(); + + // Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib. + // Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware. + rustc().input("baz.rs").run(); + rustc().input("bar.rs").linker("rust-lld").link_arg("/WHOLEARCHIVE:libbaz.rlib").run(); +} diff --git a/tests/run-make/windows-spawn/Makefile b/tests/run-make/windows-spawn/Makefile deleted file mode 100644 index b6cdb169bab..00000000000 --- a/tests/run-make/windows-spawn/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -# only-windows - -all: - $(RUSTC) -o "$(TMPDIR)/hopefullydoesntexist bar.exe" hello.rs - $(RUSTC) spawn.rs - $(TMPDIR)/spawn.exe diff --git a/tests/run-make/windows-spawn/rmake.rs b/tests/run-make/windows-spawn/rmake.rs new file mode 100644 index 00000000000..fb9cf1e2149 --- /dev/null +++ b/tests/run-make/windows-spawn/rmake.rs @@ -0,0 +1,17 @@ +//@ only-windows + +use run_make_support::{run, rustc, tmp_dir}; + +// On Windows `Command` uses `CreateProcessW` to run a new process. +// However, in the past std used to not pass in the application name, leaving +// `CreateProcessW` to use heuristics to guess the intended name from the +// command line string. Sometimes this could go very wrong. +// E.g. in Rust 1.0 `Command::new("foo").arg("bar").spawn()` will try to launch +// `foo bar.exe` if foo.exe does not exist. Which is clearly not desired. + +fn main() { + let out_dir = tmp_dir(); + rustc().input("hello.rs").output(out_dir.join("hopefullydoesntexist bar.exe")).run(); + rustc().input("spawn.rs").run(); + run("spawn"); +} diff --git a/tests/run-make/windows-spawn/spawn.rs b/tests/run-make/windows-spawn/spawn.rs index c34da3d5fde..a9e86d1577e 100644 --- a/tests/run-make/windows-spawn/spawn.rs +++ b/tests/run-make/windows-spawn/spawn.rs @@ -3,10 +3,8 @@ use std::process::Command; fn main() { // Make sure it doesn't try to run "hopefullydoesntexist bar.exe". - assert_eq!(Command::new("hopefullydoesntexist") - .arg("bar") - .spawn() - .unwrap_err() - .kind(), - ErrorKind::NotFound); + assert_eq!( + Command::new("hopefullydoesntexist").arg("bar").spawn().unwrap_err().kind(), + ErrorKind::NotFound + ) } diff --git a/tests/run-make/windows-subsystem/Makefile b/tests/run-make/windows-subsystem/Makefile deleted file mode 100644 index e3cf9181de4..00000000000 --- a/tests/run-make/windows-subsystem/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) windows.rs - $(RUSTC) console.rs diff --git a/tests/run-make/issue-85441/empty.rs b/tests/run-make/windows-ws2_32/empty.rs index f328e4d9d04..f328e4d9d04 100644 --- a/tests/run-make/issue-85441/empty.rs +++ b/tests/run-make/windows-ws2_32/empty.rs diff --git a/tests/run-make/windows-ws2_32/rmake.rs b/tests/run-make/windows-ws2_32/rmake.rs new file mode 100644 index 00000000000..543f8594478 --- /dev/null +++ b/tests/run-make/windows-ws2_32/rmake.rs @@ -0,0 +1,27 @@ +//@ only-msvc + +// Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 + +use run_make_support::object::{self, read::Object}; +use run_make_support::{rustc, tmp_dir}; +use std::fs; + +fn main() { + rustc().input("empty.rs").run(); + rustc().input("tcp.rs").run(); + + assert!(!links_ws2_32("empty.exe")); + assert!(links_ws2_32("tcp.exe")); +} + +fn links_ws2_32(exe: &str) -> bool { + let path = tmp_dir().join(exe); + let binary_data = fs::read(path).unwrap(); + let file = object::File::parse(&*binary_data).unwrap(); + for import in file.imports().unwrap() { + if import.library().eq_ignore_ascii_case(b"WS2_32.dll") { + return true; + } + } + false +} diff --git a/tests/run-make/windows-ws2_32/tcp.rs b/tests/run-make/windows-ws2_32/tcp.rs new file mode 100644 index 00000000000..3d0248c76d7 --- /dev/null +++ b/tests/run-make/windows-ws2_32/tcp.rs @@ -0,0 +1,5 @@ +use std::net::TcpListener; + +fn main() { + TcpListener::bind("127.0.0.1:80").unwrap(); +} diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 373d1cce1d7..784c6d488ea 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -59,6 +59,7 @@ [nvptx64] needs-llvm-components: nvptx */ // FIXME: disabled since it fails on CI saying the csky component is missing +// see https://github.com/rust-lang/rust/issues/125697 /* revisions: csky [csky] compile-flags: --target csky-unknown-linux-gnuabiv2 [csky] needs-llvm-components: csky diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs new file mode 100644 index 00000000000..f1ff3e1d534 --- /dev/null +++ b/tests/ui/abi/fixed_x18.rs @@ -0,0 +1,25 @@ +// This tests that -Zfixed-x18 causes a compilation failure on targets other than aarch64. +// Behavior on aarch64 is tested by tests/codegen/fixed-x18.rs. +// +//@ revisions: x64 i686 arm riscv32 riscv64 +//@ error-pattern: the `-Zfixed-x18` flag is not supported +//@ dont-check-compiler-stderr +// +//@ compile-flags: -Zfixed-x18 +//@ [x64] needs-llvm-components: x86 +//@ [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +//@ [i686] needs-llvm-components: x86 +//@ [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib +//@ [arm] needs-llvm-components: arm +//@ [arm] compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib +//@ [riscv32] needs-llvm-components: riscv +//@ [riscv32] compile-flags: --target=riscv32i-unknown-none-elf --crate-type=rlib +//@ [riscv64] needs-llvm-components: riscv +//@ [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf --crate-type=rlib + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 834ae00a8d8..ffb02eccc77 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `<T as UncheckedCopy>::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 0f944a18ed5..e6ae8183e77 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `<T as UncheckedCopy>::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/errors/pic-linker.rs b/tests/ui/errors/pic-linker.rs new file mode 100644 index 00000000000..d9098990304 --- /dev/null +++ b/tests/ui/errors/pic-linker.rs @@ -0,0 +1,12 @@ +// `-z text` caused the linker to error if there were any non-position-independent +// code (PIC) sections. This test checks that this no longer happens. +// See https://github.com/rust-lang/rust/pull/39803 + +//@ ignore-windows +//@ ignore-macos +//@ ignore-cross-compile + +//@ compile-flags: -Clink-args=-Wl,-z,text +//@ run-pass + +fn main() {} diff --git a/tests/ui/imports/auxiliary/simple-dylib.rs b/tests/ui/imports/auxiliary/simple-dylib.rs new file mode 100644 index 00000000000..af64aa66f31 --- /dev/null +++ b/tests/ui/imports/auxiliary/simple-dylib.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Cprefer-dynamic + +#![crate_type = "dylib"] +pub fn bar() {} diff --git a/tests/ui/imports/simple-dylib-import.rs b/tests/ui/imports/simple-dylib-import.rs new file mode 100644 index 00000000000..d8ee3496b90 --- /dev/null +++ b/tests/ui/imports/simple-dylib-import.rs @@ -0,0 +1,12 @@ +// A simple test, where foo.rs has a dependency +// on the dynamic library simple-dylib.rs. If the test passes, +// dylibs can be built and linked into another file successfully.. + +//@ aux-crate:bar=simple-dylib.rs +//@ run-pass + +extern crate bar; + +fn main() { + bar::bar(); +} diff --git a/tests/ui/inline-const/referencing_local_variables.rs b/tests/ui/inline-const/referencing_local_variables.rs new file mode 100644 index 00000000000..f9f0fef07f0 --- /dev/null +++ b/tests/ui/inline-const/referencing_local_variables.rs @@ -0,0 +1,6 @@ +const fn test_me<T>(a: usize) -> usize { + const { a } + //~^ ERROR: attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/tests/ui/inline-const/referencing_local_variables.stderr b/tests/ui/inline-const/referencing_local_variables.stderr new file mode 100644 index 00000000000..4a0a5406602 --- /dev/null +++ b/tests/ui/inline-const/referencing_local_variables.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/referencing_local_variables.rs:2:13 + | +LL | const fn test_me<T>(a: usize) -> usize { + | - this would need to be a `const` +LL | const { a } + | ^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr new file mode 100644 index 00000000000..4d8d7e1560d --- /dev/null +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr @@ -0,0 +1,8 @@ +warning: Conditions number of the decision (7) exceeds limit (6). MCDC analysis will not count this expression. + --> $DIR/mcdc-condition-limit.rs:29:8 + | +LL | if a && b && c && d && e && f && g { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs new file mode 100644 index 00000000000..64c5f8e9b77 --- /dev/null +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -0,0 +1,32 @@ +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ revisions: good bad +//@ check-pass +//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime + +// Check that we emit some kind of diagnostic when MC/DC instrumentation sees +// code that exceeds the limit of 6 conditions per decision, and falls back +// to only instrumenting that code for branch coverage. +// +// See also `tests/coverage/mcdc/condition-limit.rs`, which tests the actual +// effect on instrumentation. +// +// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) + +#[cfg(good)] +fn main() { + // 6 conditions is OK, so no diagnostic. + let [a, b, c, d, e, f] = <[bool; 6]>::default(); + if a && b && c && d && e && f { + core::hint::black_box("hello"); + } +} + +#[cfg(bad)] +fn main() { + // 7 conditions is too many, so issue a diagnostic. + let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); + if a && b && c && d && e && f && g { //[bad]~ WARNING Conditions number of the decision + core::hint::black_box("hello"); + } +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs new file mode 100644 index 00000000000..12c984c932a --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs @@ -0,0 +1,14 @@ +//@ check-fail + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let z = 2; + match y { + 0 => drop(y), //~ ERROR calls to `std::mem::drop` + 1 => drop(z), //~ ERROR calls to `std::mem::drop` + 2 => drop(3), //~ ERROR calls to `std::mem::drop` + _ => {}, + } +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr new file mode 100644 index 00000000000..6c73e5ea90b --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr @@ -0,0 +1,37 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:9:14 + | +LL | 0 => drop(y), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:3:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:10:14 + | +LL | 1 => drop(z), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:11:14 + | +LL | 2 => drop(3), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.fixed b/tests/ui/lint/dropping_copy_types-issue-125189.fixed new file mode 100644 index 00000000000..2dfd68d4cc1 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.fixed @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let _ = 3.2; //~ ERROR calls to `std::mem::drop` + let _ = y; //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.rs b/tests/ui/lint/dropping_copy_types-issue-125189.rs new file mode 100644 index 00000000000..1f42efabba9 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + drop(3.2); //~ ERROR calls to `std::mem::drop` + drop(y); //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.stderr b/tests/ui/lint/dropping_copy_types-issue-125189.stderr new file mode 100644 index 00000000000..ba3e36f5b6e --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.stderr @@ -0,0 +1,35 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:8:5 + | +LL | drop(3.2); + | ^^^^^---^ + | | + | argument has type `f64` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(3.2); +LL + let _ = 3.2; + | + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:9:5 + | +LL | drop(y); + | ^^^^^-^ + | | + | argument has type `i32` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(y); +LL + let _ = y; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr index b6291aa5ed6..41aa66a4efc 100644 --- a/tests/ui/lint/dropping_copy_types.stderr +++ b/tests/ui/lint/dropping_copy_types.stderr @@ -6,12 +6,16 @@ LL | drop(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_copy_types.rs:3:9 | LL | #![warn(dropping_copy_types)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s1); +LL + let _ = s1; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | drop(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s2); +LL + let _ = s2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:36:5 @@ -31,8 +39,12 @@ LL | drop(s3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_references)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s3); +LL + let _ = s3; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:37:5 @@ -42,7 +54,11 @@ LL | drop(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s4); +LL + let _ = s4; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:38:5 @@ -52,7 +68,11 @@ LL | drop(s5); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s5); +LL + let _ = s5; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:50:5 @@ -62,7 +82,11 @@ LL | drop(a2); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(a2); +LL + let _ = a2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:52:5 @@ -72,7 +96,11 @@ LL | drop(a4); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(a4); +LL + let _ = a4; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:71:13 @@ -82,7 +110,11 @@ LL | drop(println_and(13)); | | | argument has type `i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(13)); +LL + let _ = println_and(13); + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:74:14 diff --git a/tests/ui/lint/dropping_references-can-fixed.fixed b/tests/ui/lint/dropping_references-can-fixed.fixed new file mode 100644 index 00000000000..f704d3c72df --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.fixed @@ -0,0 +1,31 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_references)] + +struct SomeStruct; + +fn main() { + let _ = &SomeStruct; //~ ERROR calls to `std::mem::drop` + + let mut owned1 = SomeStruct; + let _ = &owned1; //~ ERROR calls to `std::mem::drop` + let _ = &&owned1; //~ ERROR calls to `std::mem::drop` + let _ = &mut owned1; //~ ERROR calls to `std::mem::drop` + drop(owned1); + + let reference1 = &SomeStruct; + let _ = reference1; //~ ERROR calls to `std::mem::drop` + + let reference2 = &mut SomeStruct; + let _ = reference2; //~ ERROR calls to `std::mem::drop` + + let ref reference3 = SomeStruct; + let _ = reference3; //~ ERROR calls to `std::mem::drop` +} + +#[allow(dead_code)] +fn test_generic_fn_drop<T>(val: T) { + let _ = &val; //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.rs b/tests/ui/lint/dropping_references-can-fixed.rs new file mode 100644 index 00000000000..70d1c16d66b --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.rs @@ -0,0 +1,31 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_references)] + +struct SomeStruct; + +fn main() { + drop(&SomeStruct); //~ ERROR calls to `std::mem::drop` + + let mut owned1 = SomeStruct; + drop(&owned1); //~ ERROR calls to `std::mem::drop` + drop(&&owned1); //~ ERROR calls to `std::mem::drop` + drop(&mut owned1); //~ ERROR calls to `std::mem::drop` + drop(owned1); + + let reference1 = &SomeStruct; + drop(reference1); //~ ERROR calls to `std::mem::drop` + + let reference2 = &mut SomeStruct; + drop(reference2); //~ ERROR calls to `std::mem::drop` + + let ref reference3 = SomeStruct; + drop(reference3); //~ ERROR calls to `std::mem::drop` +} + +#[allow(dead_code)] +fn test_generic_fn_drop<T>(val: T) { + drop(&val); //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.stderr b/tests/ui/lint/dropping_references-can-fixed.stderr new file mode 100644 index 00000000000..42cdb81b524 --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.stderr @@ -0,0 +1,119 @@ +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:9:5 + | +LL | drop(&SomeStruct); + | ^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +note: the lint level is defined here + --> $DIR/dropping_references-can-fixed.rs:4:9 + | +LL | #![deny(dropping_references)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:12:5 + | +LL | drop(&owned1); + | ^^^^^-------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&owned1); +LL + let _ = &owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:13:5 + | +LL | drop(&&owned1); + | ^^^^^--------^ + | | + | argument has type `&&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&&owned1); +LL + let _ = &&owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:14:5 + | +LL | drop(&mut owned1); + | ^^^^^-----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&mut owned1); +LL + let _ = &mut owned1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:18:5 + | +LL | drop(reference1); + | ^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference1); +LL + let _ = reference1; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:21:5 + | +LL | drop(reference2); + | ^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference2); +LL + let _ = reference2; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:24:5 + | +LL | drop(reference3); + | ^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference3); +LL + let _ = reference3; + | + +error: calls to `std::mem::drop` with a reference instead of an owned value does nothing + --> $DIR/dropping_references-can-fixed.rs:29:5 + | +LL | drop(&val); + | ^^^^^----^ + | | + | argument has type `&T` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&val); +LL + let _ = &val; + | + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/dropping_references.stderr b/tests/ui/lint/dropping_references.stderr index 7e25a46216e..312334b82ad 100644 --- a/tests/ui/lint/dropping_references.stderr +++ b/tests/ui/lint/dropping_references.stderr @@ -6,12 +6,16 @@ LL | drop(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_references.rs:3:9 | LL | #![warn(dropping_references)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:11:5 @@ -21,7 +25,11 @@ LL | drop(&owned1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&owned1); +LL + let _ = &owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:12:5 @@ -31,7 +39,11 @@ LL | drop(&&owned1); | | | argument has type `&&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&&owned1); +LL + let _ = &&owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:13:5 @@ -41,7 +53,11 @@ LL | drop(&mut owned1); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&mut owned1); +LL + let _ = &mut owned1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:17:5 @@ -51,7 +67,11 @@ LL | drop(reference1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference1); +LL + let _ = reference1; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:20:5 @@ -61,7 +81,11 @@ LL | drop(reference2); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference2); +LL + let _ = reference2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:23:5 @@ -71,7 +95,11 @@ LL | drop(reference3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(reference3); +LL + let _ = reference3; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:28:5 @@ -81,7 +109,11 @@ LL | drop(&val); | | | argument has type `&T` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(&val); +LL + let _ = &val; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:36:5 @@ -91,7 +123,11 @@ LL | std::mem::drop(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::drop(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:91:13 @@ -101,7 +137,11 @@ LL | drop(println_and(&13)); | | | argument has type `&i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(&13)); +LL + let _ = println_and(&13); + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_references.rs:94:14 diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.fixed b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed new file mode 100644 index 00000000000..c5d65ecc1d4 --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed @@ -0,0 +1,22 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_copy_types)] +#![allow(unused_mut)] +#![allow(unused_imports)] + +use std::vec::Vec; +use std::mem::forget; + +#[derive(Copy, Clone)] +struct SomeStruct; + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let mut s3 = s1; + + let _ = s1; //~ ERROR calls to `std::mem::forget` + let _ = s2; //~ ERROR calls to `std::mem::forget` + let _ = s3; //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.rs b/tests/ui/lint/forgetting_copy_types-can-fixed.rs new file mode 100644 index 00000000000..c5572294280 --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.rs @@ -0,0 +1,22 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_copy_types)] +#![allow(unused_mut)] +#![allow(unused_imports)] + +use std::vec::Vec; +use std::mem::forget; + +#[derive(Copy, Clone)] +struct SomeStruct; + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let mut s3 = s1; + + forget(s1); //~ ERROR calls to `std::mem::forget` + forget(s2); //~ ERROR calls to `std::mem::forget` + forget(s3); //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.stderr b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr new file mode 100644 index 00000000000..cb7bbf02222 --- /dev/null +++ b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr @@ -0,0 +1,49 @@ +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:19:5 + | +LL | forget(s1); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +note: the lint level is defined here + --> $DIR/forgetting_copy_types-can-fixed.rs:4:9 + | +LL | #![deny(forgetting_copy_types)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s1); +LL + let _ = s1; + | + +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:20:5 + | +LL | forget(s2); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s2); +LL + let _ = s2; + | + +error: calls to `std::mem::forget` with a value that implements `Copy` does nothing + --> $DIR/forgetting_copy_types-can-fixed.rs:21:5 + | +LL | forget(s3); + | ^^^^^^^--^ + | | + | argument has type `SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s3); +LL + let _ = s3; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/forgetting_copy_types.stderr b/tests/ui/lint/forgetting_copy_types.stderr index 36d1ef5c53e..980ee6caba2 100644 --- a/tests/ui/lint/forgetting_copy_types.stderr +++ b/tests/ui/lint/forgetting_copy_types.stderr @@ -6,12 +6,16 @@ LL | forget(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/forgetting_copy_types.rs:3:9 | LL | #![warn(forgetting_copy_types)] | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s1); +LL + let _ = s1; + | warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing --> $DIR/forgetting_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | forget(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s2); +LL + let _ = s2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:36:5 @@ -31,8 +39,12 @@ LL | forget(s3); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(forgetting_references)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s3); +LL + let _ = s3; + | warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing --> $DIR/forgetting_copy_types.rs:37:5 @@ -42,7 +54,11 @@ LL | forget(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s4); +LL + let _ = s4; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:38:5 @@ -52,7 +68,11 @@ LL | forget(s5); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(s5); +LL + let _ = s5; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:50:5 @@ -62,7 +82,11 @@ LL | forget(a2); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a2); +LL + let _ = a2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:52:5 @@ -72,7 +96,11 @@ LL | forget(a3); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a3); +LL + let _ = a3; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_copy_types.rs:53:5 @@ -82,7 +110,11 @@ LL | forget(a4); | | | argument has type `&AnotherStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(a4); +LL + let _ = a4; + | warning: 8 warnings emitted diff --git a/tests/ui/lint/forgetting_references-can-fixed.fixed b/tests/ui/lint/forgetting_references-can-fixed.fixed new file mode 100644 index 00000000000..64475f04284 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.fixed @@ -0,0 +1,40 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_references)] + +use std::mem::forget; + +struct SomeStruct; + +fn main() { + let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget` + + let mut owned = SomeStruct; + let _ = &owned; //~ ERROR calls to `std::mem::forget` + let _ = &&owned; //~ ERROR calls to `std::mem::forget` + let _ = &mut owned; //~ ERROR calls to `std::mem::forget` + forget(owned); + + let reference1 = &SomeStruct; + let _ = &*reference1; //~ ERROR calls to `std::mem::forget` + + let reference2 = &mut SomeStruct; + let _ = reference2; //~ ERROR calls to `std::mem::forget` + + let ref reference3 = SomeStruct; + let _ = reference3; //~ ERROR calls to `std::mem::forget` +} + +#[allow(dead_code)] +fn test_generic_fn_forget<T>(val: T) { + let _ = &val; //~ ERROR calls to `std::mem::forget` + forget(val); +} + +#[allow(dead_code)] +fn test_similarly_named_function() { + fn forget<T>(_val: T) {} + forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name + let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_references-can-fixed.rs b/tests/ui/lint/forgetting_references-can-fixed.rs new file mode 100644 index 00000000000..4c9ef541d34 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.rs @@ -0,0 +1,40 @@ +//@ check-fail +//@ run-rustfix + +#![deny(forgetting_references)] + +use std::mem::forget; + +struct SomeStruct; + +fn main() { + forget(&SomeStruct); //~ ERROR calls to `std::mem::forget` + + let mut owned = SomeStruct; + forget(&owned); //~ ERROR calls to `std::mem::forget` + forget(&&owned); //~ ERROR calls to `std::mem::forget` + forget(&mut owned); //~ ERROR calls to `std::mem::forget` + forget(owned); + + let reference1 = &SomeStruct; + forget(&*reference1); //~ ERROR calls to `std::mem::forget` + + let reference2 = &mut SomeStruct; + forget(reference2); //~ ERROR calls to `std::mem::forget` + + let ref reference3 = SomeStruct; + forget(reference3); //~ ERROR calls to `std::mem::forget` +} + +#[allow(dead_code)] +fn test_generic_fn_forget<T>(val: T) { + forget(&val); //~ ERROR calls to `std::mem::forget` + forget(val); +} + +#[allow(dead_code)] +fn test_similarly_named_function() { + fn forget<T>(_val: T) {} + forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name + std::mem::forget(&SomeStruct); //~ ERROR calls to `std::mem::forget` +} diff --git a/tests/ui/lint/forgetting_references-can-fixed.stderr b/tests/ui/lint/forgetting_references-can-fixed.stderr new file mode 100644 index 00000000000..05eb636ab45 --- /dev/null +++ b/tests/ui/lint/forgetting_references-can-fixed.stderr @@ -0,0 +1,133 @@ +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:11:5 + | +LL | forget(&SomeStruct); + | ^^^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +note: the lint level is defined here + --> $DIR/forgetting_references-can-fixed.rs:4:9 + | +LL | #![deny(forgetting_references)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:14:5 + | +LL | forget(&owned); + | ^^^^^^^------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&owned); +LL + let _ = &owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:15:5 + | +LL | forget(&&owned); + | ^^^^^^^-------^ + | | + | argument has type `&&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&&owned); +LL + let _ = &&owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:16:5 + | +LL | forget(&mut owned); + | ^^^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&mut owned); +LL + let _ = &mut owned; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:20:5 + | +LL | forget(&*reference1); + | ^^^^^^^------------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&*reference1); +LL + let _ = &*reference1; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:23:5 + | +LL | forget(reference2); + | ^^^^^^^----------^ + | | + | argument has type `&mut SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference2); +LL + let _ = reference2; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:26:5 + | +LL | forget(reference3); + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference3); +LL + let _ = reference3; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:31:5 + | +LL | forget(&val); + | ^^^^^^^----^ + | | + | argument has type `&T` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&val); +LL + let _ = &val; + | + +error: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references-can-fixed.rs:39:5 + | +LL | std::mem::forget(&SomeStruct); + | ^^^^^^^^^^^^^^^^^-----------^ + | | + | argument has type `&SomeStruct` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::forget(&SomeStruct); +LL + let _ = &SomeStruct; + | + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/forgetting_references.rs b/tests/ui/lint/forgetting_references.rs index ecfa23ee497..d0ec2a77ab1 100644 --- a/tests/ui/lint/forgetting_references.rs +++ b/tests/ui/lint/forgetting_references.rs @@ -23,6 +23,16 @@ fn main() { let ref reference3 = SomeStruct; forget(reference3); //~ WARN calls to `std::mem::forget` + + let ref reference4 = SomeStruct; + + let a = 1; + match a { + 1 => forget(&*reference1), //~ WARN calls to `std::mem::forget` + 2 => forget(reference3), //~ WARN calls to `std::mem::forget` + 3 => forget(reference4), //~ WARN calls to `std::mem::forget` + _ => {} + } } #[allow(dead_code)] diff --git a/tests/ui/lint/forgetting_references.stderr b/tests/ui/lint/forgetting_references.stderr index 5624b690789..afd5030a680 100644 --- a/tests/ui/lint/forgetting_references.stderr +++ b/tests/ui/lint/forgetting_references.stderr @@ -6,12 +6,16 @@ LL | forget(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/forgetting_references.rs:3:9 | LL | #![warn(forgetting_references)] | ^^^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&SomeStruct); +LL + let _ = &SomeStruct; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:13:5 @@ -21,7 +25,11 @@ LL | forget(&owned); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&owned); +LL + let _ = &owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:14:5 @@ -31,7 +39,11 @@ LL | forget(&&owned); | | | argument has type `&&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&&owned); +LL + let _ = &&owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:15:5 @@ -41,7 +53,11 @@ LL | forget(&mut owned); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&mut owned); +LL + let _ = &mut owned; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:19:5 @@ -51,7 +67,11 @@ LL | forget(&*reference1); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&*reference1); +LL + let _ = &*reference1; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:22:5 @@ -61,7 +81,11 @@ LL | forget(reference2); | | | argument has type `&mut SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference2); +LL + let _ = reference2; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing --> $DIR/forgetting_references.rs:25:5 @@ -71,27 +95,69 @@ LL | forget(reference3); | | | argument has type `&SomeStruct` | +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(reference3); +LL + let _ = reference3; + | + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:31:14 + | +LL | 1 => forget(&*reference1), + | ^^^^^^^------------^ + | | + | argument has type `&SomeStruct` + | + = note: use `let _ = ...` to ignore the expression or result + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:32:14 + | +LL | 2 => forget(reference3), + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | + = note: use `let _ = ...` to ignore the expression or result + +warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing + --> $DIR/forgetting_references.rs:33:14 + | +LL | 3 => forget(reference4), + | ^^^^^^^----------^ + | | + | argument has type `&SomeStruct` + | = note: use `let _ = ...` to ignore the expression or result warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing - --> $DIR/forgetting_references.rs:30:5 + --> $DIR/forgetting_references.rs:40:5 | LL | forget(&val); | ^^^^^^^----^ | | | argument has type `&T` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - forget(&val); +LL + let _ = &val; + | warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing - --> $DIR/forgetting_references.rs:38:5 + --> $DIR/forgetting_references.rs:48:5 | LL | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^-----------^ | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - std::mem::forget(&SomeStruct); +LL + let _ = &SomeStruct; + | -warning: 9 warnings emitted +warning: 12 warnings emitted diff --git a/tests/run-make/windows-subsystem/console.rs b/tests/ui/windows-subsystem/console.rs index 61a92eb6a9d..8f0ca2de370 100644 --- a/tests/run-make/windows-subsystem/console.rs +++ b/tests/ui/windows-subsystem/console.rs @@ -1,3 +1,4 @@ +//@ run-pass #![windows_subsystem = "console"] fn main() {} diff --git a/tests/ui/windows-subsystem-invalid.rs b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs index c6a6dd00a92..c6a6dd00a92 100644 --- a/tests/ui/windows-subsystem-invalid.rs +++ b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs diff --git a/tests/ui/windows-subsystem-invalid.stderr b/tests/ui/windows-subsystem/windows-subsystem-invalid.stderr index 703f35c969c..703f35c969c 100644 --- a/tests/ui/windows-subsystem-invalid.stderr +++ b/tests/ui/windows-subsystem/windows-subsystem-invalid.stderr diff --git a/tests/run-make/windows-subsystem/windows.rs b/tests/ui/windows-subsystem/windows.rs index 1138248f07d..65db0fec7a8 100644 --- a/tests/run-make/windows-subsystem/windows.rs +++ b/tests/ui/windows-subsystem/windows.rs @@ -1,3 +1,4 @@ +//@ run-pass #![windows_subsystem = "windows"] fn main() {} |
