From 3d90595054e1da5905024098aa15aceb193e5925 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 23 Apr 2024 13:17:57 +0300 Subject: [PATCH 01/63] DependencyList: remove outdated comment --- compiler/rustc_middle/src/middle/dependency_format.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index e7d0cffc85cfb..e4750147456d1 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -10,9 +10,6 @@ use rustc_session::config::CrateType; /// A list of dependencies for a certain crate type. /// /// The length of this vector is the same as the number of external crates used. -/// The value is None if the crate does not need to be linked (it was found -/// statically in another dylib), or Some(kind) if it needs to be linked as -/// `kind` (either static or dynamic). pub type DependencyList = Vec; /// A mapping of all required dependencies for a particular flavor of output. From 9e40b546eb6cd75aaca9bacf39f2463e5b5ffe86 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 23 Apr 2024 13:34:12 +0300 Subject: [PATCH 02/63] add fixme --- compiler/rustc_middle/src/middle/dependency_format.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index e4750147456d1..a3aff9a110130 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -4,6 +4,9 @@ //! For all the gory details, see the provider of the `dependency_formats` //! query. +// FIXME: move this file to rustc_metadata::dependency_format, but +// this will introduce circular dependency between rustc_metadata and rustc_middle + use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::config::CrateType; From 372847dd4447bcb5a8c3595f70fd88002a580cbd Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 26 Jun 2024 17:01:04 -0400 Subject: [PATCH 03/63] Implement TC's match ergonomics 2024 proposal Under gate `ref_pat_eat_one_layer_2024_structural`. Enabling `ref_pat_eat_one_layer_2024` at the same time allows the union of what the individual gates allow. --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_typeck/src/pat.rs | 84 ++++++--- compiler/rustc_span/src/symbol.rs | 1 + ...feature-gate-ref_pat_eat_one_layer_2024.rs | 1 + ...ure-gate-ref_pat_eat_one_layer_2024.stderr | 20 +-- .../ref_pat_eat_one_layer_2024.rs | 12 +- ...ef_pat_eat_one_layer_2024_fail.both.stderr | 156 ++++++++++++++++ ...at_eat_one_layer_2024_fail.classic.stderr} | 56 +++--- .../ref_pat_eat_one_layer_2024_fail.rs | 24 ++- ..._eat_one_layer_2024_fail.structural.stderr | 167 ++++++++++++++++++ 11 files changed, 451 insertions(+), 73 deletions(-) create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr rename tests/ui/match/ref_pat_eat_one_layer_2024/{ref_pat_eat_one_layer_2024_fail.stderr => ref_pat_eat_one_layer_2024_fail.classic.stderr} (76%) create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4a3ce0e0c3066..9fcc0b25a2634 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -711,6 +711,7 @@ pub enum ByRef { } impl ByRef { + #[must_use] pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self { if let ByRef::Yes(old_mutbl) = &mut self { *old_mutbl = cmp::min(*old_mutbl, mutbl); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f4e20328814d7..f100d3e4ca84e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -573,6 +573,8 @@ declare_features! ( (unstable, raw_ref_op, "1.41.0", Some(64490)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), + /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant + (incomplete, ref_pat_eat_one_layer_2024_structural, "1.79.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index aaf3d3ec34d01..8ce99e204e19f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -328,8 +328,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adjust_mode: AdjustMode, max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { - if let ByRef::Yes(Mutability::Mut) = def_br { - debug_assert!(max_ref_mutbl == MutblCap::Mut); + #[cfg(debug_assertions)] + if def_br == ByRef::Yes(Mutability::Mut) && max_ref_mutbl != MutblCap::Mut { + span_bug!(pat.span, "Pattern mutability cap violated!"); } match adjust_mode { AdjustMode::Pass => (expected, def_br, max_ref_mutbl), @@ -437,7 +438,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); } - if self.tcx.features().ref_pat_eat_one_layer_2024 { + let features = self.tcx.features(); + if features.ref_pat_eat_one_layer_2024 || features.ref_pat_eat_one_layer_2024_structural { def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl()); if def_br == ByRef::Yes(Mutability::Not) { max_ref_mutbl = MutblCap::Not; @@ -669,7 +671,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Determine the binding mode... let bm = match user_bind_annot { BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => { - if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 { + if pat.span.at_least_rust_2024() + && (self.tcx.features().ref_pat_eat_one_layer_2024 + || self.tcx.features().ref_pat_eat_one_layer_2024_structural) + { if !self.tcx.features().mut_ref { feature_err( &self.tcx.sess, @@ -2122,7 +2127,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut expected: Ty<'tcx>, mut pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - let no_ref_mut_behind_and = self.tcx.features().ref_pat_eat_one_layer_2024; + let tcx = self.tcx; + let features = tcx.features(); + let ref_pat_eat_one_layer_2024 = features.ref_pat_eat_one_layer_2024; + let ref_pat_eat_one_layer_2024_structural = features.ref_pat_eat_one_layer_2024_structural; + + let no_ref_mut_behind_and = + ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural; let new_match_ergonomics = pat.span.at_least_rust_2024() && no_ref_mut_behind_and; let pat_prefix_span = @@ -2137,32 +2148,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.max_ref_mutbl = MutblCap::Mut; } + expected = self.try_structurally_resolve_type(pat.span, expected); if new_match_ergonomics { if let ByRef::Yes(inh_mut) = pat_info.binding_mode { - // ref pattern consumes inherited reference - - if pat_mutbl > inh_mut { - // Tried to match inherited `ref` with `&mut`, which is an error - let err_msg = "cannot match inherited `&` with `&mut` pattern"; - let err = if let Some(span) = pat_prefix_span { - let mut err = self.dcx().struct_span_err(span, err_msg); - err.span_suggestion_verbose( - span, - "replace this `&mut` pattern with `&`", - "&", - Applicability::MachineApplicable, - ); - err + if !ref_pat_eat_one_layer_2024 && let ty::Ref(_, _, r_mutbl) = *expected.kind() { + // Don't attempt to consume inherited reference + pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl); + } else { + // ref pattern attempts to consume inherited reference + if pat_mutbl > inh_mut { + // Tried to match inherited `ref` with `&mut` + if !ref_pat_eat_one_layer_2024_structural { + let err_msg = "mismatched types"; + let err = if let Some(span) = pat_prefix_span { + let mut err = self.dcx().struct_span_err(span, err_msg); + err.code(E0308); + err.note("cannot match inherited `&` with `&mut` pattern"); + err.span_suggestion_verbose( + span, + "replace this `&mut` pattern with `&`", + "&", + Applicability::MachineApplicable, + ); + err + } else { + self.dcx().struct_span_err(pat.span, err_msg) + }; + err.emit(); + + pat_info.binding_mode = ByRef::No; + self.typeck_results + .borrow_mut() + .skipped_ref_pats_mut() + .insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; + } } else { - self.dcx().struct_span_err(pat.span, err_msg) - }; - err.emit(); + pat_info.binding_mode = ByRef::No; + self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; + } } - - pat_info.binding_mode = ByRef::No; - self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); - self.check_pat(inner, expected, pat_info); - return expected; } } else { // Reset binding mode on old editions @@ -2177,8 +2205,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let tcx = self.tcx; - expected = self.try_structurally_resolve_type(pat.span, expected); let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) { Ok(()) => { // `demand::subtype` would be good enough, but using `eqtype` turns diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6d4a8c29bc902..7cd5e4f7ce4c1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1502,6 +1502,7 @@ symbols! { recursion_limit, reexport_test_harness_main, ref_pat_eat_one_layer_2024, + ref_pat_eat_one_layer_2024_structural, ref_pat_everywhere, ref_unwind_safe_trait, reference, diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs index 83f1ee6a77e89..7cbe8e0943ae4 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs @@ -1,5 +1,6 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options +// gate-test-ref_pat_eat_one_layer_2024_structural pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr index 132fe421a18d8..b3ea60252ac47 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:5:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:6:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -14,7 +14,7 @@ LL | if let Some(Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:10:23 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:11:23 | LL | let _: &u32 = x; | ---- ^ expected `&u32`, found integer @@ -27,7 +27,7 @@ LL | let _: &u32 = &x; | + error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:13:23 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:14:23 | LL | if let Some(Some(&&x)) = &Some(Some(&0)) { | ^^ --------------- this expression has type `&Option>` @@ -43,7 +43,7 @@ LL + if let Some(Some(&x)) = &Some(Some(&0)) { | error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:17:17 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:18:17 | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ^^^^^^^^ -------------- this expression has type `&Option>` @@ -54,7 +54,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:22:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` @@ -64,7 +64,7 @@ LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { = note: expected type `{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:22:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ @@ -74,7 +74,7 @@ LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:25:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:26:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -89,7 +89,7 @@ LL | if let Some(Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:29:27 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:30:27 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` @@ -104,7 +104,7 @@ LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:34:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` @@ -114,7 +114,7 @@ LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { = note: expected type `{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:34:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs index 829b7f86e2621..0130189b874c6 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs @@ -1,8 +1,10 @@ //@ run-pass //@ edition: 2024 //@ compile-flags: -Zunstable-options +//@ revisions: classic structural both #![allow(incomplete_features)] -#![feature(ref_pat_eat_one_layer_2024)] +#![cfg_attr(any(classic, both), feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(any(structural, both), feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { @@ -53,4 +55,12 @@ pub fn main() { if let Some(&Some(x)) = &mut Some(Some(0)) { let _: u32 = x; } + #[cfg(any(classic, both))] + if let Some(&mut x) = &mut Some(&0) { + let _: &u32 = x; + } + #[cfg(any(structural, both))] + if let Some(&mut x) = &Some(&mut 0) { + let _: &u32 = x; + } } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr new file mode 100644 index 0000000000000..f8931403774a3 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr @@ -0,0 +1,156 @@ +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected reference `&Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:12:23 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 + | +LL | let _: &mut u32 = x; + | -------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut u32` + found reference `&{integer}` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 + | +LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { + | ^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 + | +LL | let &mut _ = &&0; + | ^^^^^^ --- this expression has type `&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; + | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 + | +LL | let &mut _ = &&mut 0; + | ^^^^^^ ------- this expression has type `&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 + | +LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&mut &&&mut &mut {integer}` + found mutable reference `&mut _` + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 + | +LL | let Foo(mut a) = &Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:65:13 + | +LL | let Foo(mut a) = &mut Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr similarity index 76% rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr rename to tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr index 26317e43d023e..0010a612c30f1 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr @@ -1,27 +1,29 @@ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:12:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 | LL | let _: &mut u32 = x; | -------- ^ types differ in mutability @@ -31,52 +33,56 @@ LL | let _: &mut u32 = x; = note: expected mutable reference `&mut u32` found reference `&{integer}` -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 | LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 | LL | let &mut _ = &&0; | ^^^^^^ --- this expression has type `&&{integer}` @@ -87,7 +93,7 @@ LL | let &mut _ = &&0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:33:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 | LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` @@ -97,30 +103,32 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` found mutable reference `&mut _` -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:38:17 | LL | if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:40:22 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:42:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:44:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 | LL | let &mut _ = &&mut 0; | ^^^^^^ ------- this expression has type `&&mut {integer}` @@ -131,7 +139,7 @@ LL | let &mut _ = &&mut 0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:47:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 | LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` @@ -142,7 +150,7 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:50:14 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 | LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` @@ -153,7 +161,7 @@ LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; found mutable reference `&mut _` error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:13 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -163,7 +171,7 @@ LL | let Foo(mut a) = &Foo(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:59:13 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:65:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs index 40e8293e24111..4a40060b2ea40 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs @@ -1,30 +1,32 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options +//@ revisions: classic structural both #![allow(incomplete_features)] -#![feature(ref_pat_eat_one_layer_2024)] +#![cfg_attr(any(classic, both), feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(any(structural, both), feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&mut Some(&_)) = &Some(&Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(x)) = &mut Some(&Some(0)) { let _: &mut u32 = x; //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } let &mut _ = &&0; @@ -34,11 +36,11 @@ pub fn main() { //~^ ERROR: mismatched types if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //[classic]~^ ERROR: mismatched types } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //[classic]~^ ERROR: mismatched types } let &mut _ = &&mut 0; @@ -50,6 +52,10 @@ pub fn main() { let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; //~^ ERROR: mismatched types + if let Some(&mut _) = &mut Some(&0) { + //[structural]~^ ERROR + } + struct Foo(u8); let Foo(mut a) = &Foo(0); diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr new file mode 100644 index 0000000000000..379bb6f4eaab3 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr @@ -0,0 +1,167 @@ +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected reference `&Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:12:23 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 + | +LL | let _: &mut u32 = x; + | -------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut u32` + found reference `&{integer}` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 + | +LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { + | ^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 + | +LL | let &mut _ = &&0; + | ^^^^^^ --- this expression has type `&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; + | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 + | +LL | let &mut _ = &&mut 0; + | ^^^^^^ ------- this expression has type `&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 + | +LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&mut &&&mut &mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:17 + | +LL | if let Some(&mut _) = &mut Some(&0) { + | ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 + | +LL | let Foo(mut a) = &Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:65:13 + | +LL | let Foo(mut a) = &mut Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. From 35f6b7b97a7dd5fa21834a35faaa7470a071424a Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 26 Jun 2024 17:29:16 -0400 Subject: [PATCH 04/63] Fix tidy --- src/tools/tidy/src/features.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 3e84bf3c34be5..e8dff2dc26163 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -112,7 +112,7 @@ pub fn check( let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); let filen_underscore = filename.replace('-', "_").replace(".rs", ""); - let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features); + let filename_gate = test_filen_gate(&filen_underscore, &mut features); for (i, line) in contents.lines().enumerate() { let mut err = |msg: &str| { @@ -128,7 +128,7 @@ pub fn check( }; match features.get_mut(feature_name) { Some(f) => { - if filename_is_gate_test { + if filename_gate == Some(feature_name) { err(&format!( "The file is already marked as gate test \ through its name, no need for a \ @@ -259,18 +259,18 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { r.captures(line).and_then(|c| c.get(1)).map(|m| m.as_str()) } -fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { +fn test_filen_gate<'f>(filen_underscore: &'f str, features: &mut Features) -> Option<&'f str> { let prefix = "feature_gate_"; - if filen_underscore.starts_with(prefix) { + if let Some(suffix) = filen_underscore.strip_prefix(prefix) { for (n, f) in features.iter_mut() { // Equivalent to filen_underscore == format!("feature_gate_{n}") - if &filen_underscore[prefix.len()..] == n { + if suffix == n { f.has_gate_test = true; - return true; + return Some(suffix); } } } - false + None } pub fn collect_lang_features(base_compiler_path: &Path, bad: &mut bool) -> Features { From e09815f0efdf6a91f96974284b9e5129029da45f Mon Sep 17 00:00:00 2001 From: Guillaume Boisseau Date: Sun, 30 Jun 2024 14:26:28 +0200 Subject: [PATCH 05/63] New features gates mustn't specify a version by hand --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f100d3e4ca84e..8c30006e292b9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -574,7 +574,7 @@ declare_features! ( /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant - (incomplete, ref_pat_eat_one_layer_2024_structural, "1.79.0", Some(123076)), + (incomplete, ref_pat_eat_one_layer_2024_structural, "CURRENT_RUSTC_VERSION", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. From 45b0f68e34c37e5e5f47a1474ad87ebdb099af4b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:02:40 +0000 Subject: [PATCH 06/63] Use the native unwind function in miri where possible --- library/panic_unwind/src/lib.rs | 34 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 4dc3612060848..77abb9125f651 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -36,18 +36,14 @@ use core::panic::PanicPayload; cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] - mod real_imp; + mod imp; } else if #[cfg(target_os = "hermit")] { #[path = "hermit.rs"] - mod real_imp; + mod imp; } else if #[cfg(target_os = "l4re")] { // L4Re is unix family but does not yet support unwinding. #[path = "dummy.rs"] - mod real_imp; - } else if #[cfg(all(target_env = "msvc", not(target_arch = "arm")))] { - // LLVM does not support unwinding on 32 bit ARM msvc (thumbv7a-pc-windows-msvc) - #[path = "seh.rs"] - mod real_imp; + mod imp; } else if #[cfg(any( all(target_family = "windows", target_env = "gnu"), target_os = "psp", @@ -58,7 +54,16 @@ cfg_if::cfg_if! { target_family = "wasm", ))] { #[path = "gcc.rs"] - mod real_imp; + mod imp; + } else if #[cfg(miri)] { + // Use the Miri runtime on Windows as miri doesn't support funclet based unwinding, + // only landingpad based unwinding. Also use the Miri runtime on unsupported platforms. + #[path = "miri.rs"] + mod imp; + } else if #[cfg(all(target_env = "msvc", not(target_arch = "arm")))] { + // LLVM does not support unwinding on 32 bit ARM msvc (thumbv7a-pc-windows-msvc) + #[path = "seh.rs"] + mod imp; } else { // Targets that don't support unwinding. // - os=none ("bare metal" targets) @@ -67,20 +72,7 @@ cfg_if::cfg_if! { // - nvptx64-nvidia-cuda // - arch=avr #[path = "dummy.rs"] - mod real_imp; - } -} - -cfg_if::cfg_if! { - if #[cfg(miri)] { - // Use the Miri runtime. - // We still need to also load the normal runtime above, as rustc expects certain lang - // items from there to be defined. - #[path = "miri.rs"] mod imp; - } else { - // Use the real runtime. - use real_imp as imp; } } From 9e12d919c3a247299e48d8b0fd71ca502288e443 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 1 Jul 2024 22:41:08 +0200 Subject: [PATCH 07/63] Improve well known value check-cfg diagnostic for the standard library --- .../src/context/diagnostics/check_cfg.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index c69e680cb64fa..da36f68fca970 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -261,10 +261,16 @@ pub(super) fn unexpected_cfg_value( lints::unexpected_cfg_value::CodeSuggestion::RemoveCondition { suggestion, name } }; - // We don't want to suggest adding values to well known names - // since those are defined by rustc it-self. Users can still - // do it if they want, but should not encourage them. - let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name); + // We don't want to encourage people to add values to a well-known names, as these are + // defined by rustc/Rust itself. Users can still do this if they wish, but should not be + // encouraged to do so. + let can_suggest_adding_value = !sess.psess.check_config.well_known_names.contains(&name) + // Except when working on rustc or the standard library itself, in which case we want to + // suggest adding these cfgs to the "normal" place because of bootstraping reasons. As a + // basic heuristic, we use the "cheat" unstable feature enable method and the + // non-ui-testing enabled option. + || (matches!(sess.psess.unstable_features, rustc_feature::UnstableFeatures::Cheat) + && !sess.opts.unstable_opts.ui_testing); let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes); @@ -275,14 +281,14 @@ pub(super) fn unexpected_cfg_value( } else { Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures) } - } else if !is_cfg_a_well_know_name { + } else if can_suggest_adding_value { Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst))) } else { None }; lints::unexpected_cfg_value::InvocationHelp::Cargo(help) } else { - let help = if !is_cfg_a_well_know_name { + let help = if can_suggest_adding_value { Some(lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No))) } else { None From e03c3b6f19df854fbc52dc57bf39dbe9ae4972e9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 1 Jul 2024 19:09:25 +0000 Subject: [PATCH 08/63] Allow _Unwind_RaiseException with MinGW --- .../miri/src/shims/windows/foreign_items.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index c9db798caad7f..71f6a2bc03333 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -758,6 +758,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } + "_Unwind_RaiseException" => { + // This is not formally part of POSIX, but it is very wide-spread on POSIX systems. + // It was originally specified as part of the Itanium C++ ABI: + // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw. + // MinGW implements _Unwind_RaiseException on top of SEH exceptions. + if this.tcx.sess.target.env != "gnu" { + throw_unsup_format!( + "`_Unwind_RaiseException` is not supported on non-MinGW Windows", + ); + } + // This function looks and behaves excatly like miri_start_unwind. + let [payload] = this.check_shim(abi, Abi::C { unwind: true }, link_name, args)?; + this.handle_miri_start_unwind(payload)?; + return Ok(EmulateItemResult::NeedsUnwind); + } + _ => return Ok(EmulateItemResult::NotSupported), } From 57e76d45960770e45e20a76019c96643b7ef0845 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 3 Jul 2024 22:12:55 -0700 Subject: [PATCH 09/63] impl PathBuf::add_extension and Path::with_added_extension Signed-off-by: tison --- library/std/src/path.rs | 97 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index caae8f924d2b1..a6f6042eaefaf 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1519,6 +1519,77 @@ impl PathBuf { true } + /// Append [`self.extension`] with `extension`. + /// + /// Returns `false` and does nothing if [`self.file_name`] is [`None`], + /// returns `true` and updates the extension otherwise. + /// + /// If [`self.extension`] is [`None`], the extension is added; otherwise + /// it is appended. + /// + /// # Caveats + /// + /// The appended `extension` may contain dots and will be used in its entirety, + /// but only the part after the final dot will be reflected in + /// [`self.extension`]. + /// + /// See the examples below. + /// + /// [`self.file_name`]: Path::file_name + /// [`self.extension`]: Path::extension + /// + /// # Examples + /// + /// ``` + /// #![feature(path_add_extension)] + /// + /// use std::path::{Path, PathBuf}; + /// + /// let mut p = PathBuf::from("/feel/the"); + /// + /// p.add_extension("formatted"); + /// assert_eq!(Path::new("/feel/the.formatted"), p.as_path()); + /// + /// p.add_extension("dark.side"); + /// assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path()); + /// + /// p.set_extension("cookie"); + /// assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path()); + /// + /// p.add_extension(""); + /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path()); + /// ``` + #[unstable(feature = "path_add_extension", issue = "127292")] + pub fn add_extension>(&mut self, extension: S) -> bool { + self._add_extension(extension.as_ref()) + } + + fn _add_extension(&mut self, extension: &OsStr) -> bool { + let file_name = match self.file_name() { + None => return false, + Some(f) => f.as_encoded_bytes(), + }; + + let new = extension; + if !new.is_empty() { + // truncate until right after the file name + // this is necessary for trimming the trailing slash + let end_file_name = file_name[file_name.len()..].as_ptr().addr(); + let start = self.inner.as_encoded_bytes().as_ptr().addr(); + self.inner.truncate(end_file_name.wrapping_sub(start)); + + // append the new extension + self.inner.reserve_exact(new.len() + 1); + self.inner.push(OsStr::new(".")); + self.inner.push(new); + } + + true + } + /// Yields a mutable reference to the underlying [`OsString`] instance. /// /// # Examples @@ -2656,6 +2727,32 @@ impl Path { new_path } + /// Creates an owned [`PathBuf`] like `self` but with an extra extension. + /// + /// See [`PathBuf::add_extension`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_add_extension)] + /// + /// use std::path::{Path, PathBuf}; + /// + /// let path = Path::new("foo.rs"); + /// assert_eq!(path.with_added_extension("txt"), PathBuf::from("foo.rs.txt")); + /// + /// let path = Path::new("foo.tar.gz"); + /// assert_eq!(path.with_added_extension(""), PathBuf::from("foo.tar.gz")); + /// assert_eq!(path.with_added_extension("xz"), PathBuf::from("foo.tar.gz.xz")); + /// assert_eq!(path.with_added_extension("").with_added_extension("txt"), PathBuf::from("foo.tar.gz.txt")); + /// ``` + #[unstable(feature = "path_add_extension", issue = "127292")] + pub fn with_added_extension>(&self, extension: S) -> PathBuf { + let mut new_path = self.to_path_buf(); + new_path.add_extension(extension); + new_path + } + /// Produces an iterator over the [`Component`]s of the path. /// /// When parsing the path, there is a small amount of normalization: From 410f760ed530954a3f3da66b41207833207efdf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 4 Jul 2024 12:34:07 +0200 Subject: [PATCH 10/63] Make CI more agnostic of the owning GitHub organization This should make it possible to switch running `auto` and `try` builds from `rust-lang-ci` to `rust-lang`. --- src/ci/docker/run.sh | 3 +-- src/ci/github-actions/calculate-job-matrix.py | 14 +++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index a4c59b3067ead..695b8b4c0d9e1 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -93,8 +93,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then docker --version REGISTRY=ghcr.io - # PR CI runs on rust-lang, but we want to use the cache from rust-lang-ci - REGISTRY_USERNAME=rust-lang-ci + REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER} # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum} # Tag used to cache the Docker build diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 4f9bc39a628ce..d03bbda100807 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -91,21 +91,17 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]: if ctx.event_name == "pull_request": return PRRunType() elif ctx.event_name == "push": - old_bors_try_build = ( - ctx.ref in ("refs/heads/try", "refs/heads/try-perf") and - ctx.repository == "rust-lang-ci/rust" + try_build = ctx.ref in ( + "refs/heads/try", + "refs/heads/try-perf", + "refs/heads/automation/bors/try" ) - new_bors_try_build = ( - ctx.ref == "refs/heads/automation/bors/try" and - ctx.repository == "rust-lang/rust" - ) - try_build = old_bors_try_build or new_bors_try_build if try_build: jobs = get_custom_jobs(ctx) return TryRunType(custom_jobs=jobs) - if ctx.ref == "refs/heads/auto" and ctx.repository == "rust-lang-ci/rust": + if ctx.ref == "refs/heads/auto": return AutoRunType() return None From 273d253ce6855381c9b7c36d3ea92581dd54becb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 3 Jul 2024 16:04:37 +0200 Subject: [PATCH 11/63] offset_from: "the difference must fit in an isize" is a corollary also, isize::MIN is an impossible distance --- .../src/interpret/intrinsics.rs | 4 +-- library/core/src/ptr/const_ptr.rs | 27 +++----------- library/core/src/ptr/mut_ptr.rs | 27 +++----------- library/core/src/ptr/non_null.rs | 35 +++++-------------- tests/ui/consts/offset_from_ub.rs | 8 +++++ tests/ui/consts/offset_from_ub.stderr | 16 ++++++--- 6 files changed, 40 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1d54da267eebf..d86f1a7a34f2a 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -301,9 +301,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // The signed form of the intrinsic allows this. If we interpret the // difference as isize, we'll get the proper signed difference. If that - // seems *positive*, they were more than isize::MAX apart. + // seems *positive* or equal to isize::MIN, they were more than isize::MAX apart. let dist = val.to_target_isize(self)?; - if dist >= 0 { + if dist >= 0 || i128::from(dist) == self.pointer_size().signed_int_min() { throw_ub_custom!( fluent::const_eval_offset_from_underflow, name = intrinsic_name, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 5537d26669a23..039dc6d7a4981 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -611,8 +611,7 @@ impl *const T { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: + /// If any of the following conditions are violated, the result is Undefined Behavior: /// /// * `self` and `origin` must either /// @@ -623,26 +622,10 @@ impl *const T { /// * The distance between the pointers, in bytes, must be an exact multiple /// of the size of `T`. /// - /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. - /// - /// * The distance being in bounds cannot rely on "wrapping around" the address space. - /// - /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the - /// address space, so two pointers within some value of any Rust type `T` will always satisfy - /// the last two conditions. The standard library also generally ensures that allocations - /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they - /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())` - /// always satisfies the last two conditions. - /// - /// Most platforms fundamentally can't even construct such a large allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. - /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on - /// such large allocations either.) + /// As a consequence, the absolute distance between the pointers, **in bytes**, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. /// /// The requirement for pointers to be derived from the same allocated object is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 30d5b2cfc5a8b..cbd3de1268a18 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -836,8 +836,7 @@ impl *mut T { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: + /// If any of the following conditions are violated, the result is Undefined Behavior: /// /// * `self` and `origin` must either /// @@ -848,26 +847,10 @@ impl *mut T { /// * The distance between the pointers, in bytes, must be an exact multiple /// of the size of `T`. /// - /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. - /// - /// * The distance being in bounds cannot rely on "wrapping around" the address space. - /// - /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the - /// address space, so two pointers within some value of any Rust type `T` will always satisfy - /// the last two conditions. The standard library also generally ensures that allocations - /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they - /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())` - /// always satisfies the last two conditions. - /// - /// Most platforms fundamentally can't even construct such a large allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. - /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on - /// such large allocations either.) + /// As a consequence, the absolute distance between the pointers, in bytes, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. /// /// The requirement for pointers to be derived from the same allocated object is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0504a0fc32f4f..0b1bd5aeebb9c 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -761,38 +761,21 @@ impl NonNull { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * Both `self` and `origin` must be either in bounds or one - /// byte past the end of the same [allocated object]. + /// * `self` and `origin` must either /// - /// * Both pointers must be *derived from* a pointer to the same object. - /// (See below for an example.) + /// * both be *derived from* a pointer to the same [allocated object], and the memory range between + /// the two pointers must be either empty or in bounds of that object. (See below for an example.) + /// * or both be derived from an integer literal/constant, and point to the same address. /// /// * The distance between the pointers, in bytes, must be an exact multiple /// of the size of `T`. /// - /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. - /// - /// * The distance being in bounds cannot rely on "wrapping around" the address space. - /// - /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the - /// address space, so two pointers within some value of any Rust type `T` will always satisfy - /// the last two conditions. The standard library also generally ensures that allocations - /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they - /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())` - /// always satisfies the last two conditions. - /// - /// Most platforms fundamentally can't even construct such a large allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. - /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on - /// such large allocations either.) + /// As a consequence, the absolute distance between the pointers, in bytes, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. /// /// The requirement for pointers to be derived from the same allocated object is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs index 57767e965962b..e71f88b8d5fab 100644 --- a/tests/ui/consts/offset_from_ub.rs +++ b/tests/ui/consts/offset_from_ub.rs @@ -92,6 +92,14 @@ pub const TOO_FAR_APART2: isize = { unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed //~| too far before }; +pub const TOO_FAR_APART3: isize = { + let ptr1 = &0u8 as *const u8; + let ptr2 = ptr1.wrapping_offset(isize::MIN); + // The result of this would be `isize::MIN`, which *does* fit in an `isize`, but its + // absolute value does not. (Also anyway there cannot be an allocation of that size.) + unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed + //~| too far before +}; const WRONG_ORDER_UNSIGNED: usize = { let a = ['a', 'b', 'c']; diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 65f75a6e05875..7caf6247b9e9e 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -60,13 +60,19 @@ LL | unsafe { ptr_offset_from(ptr1, ptr2) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:99:14 + --> $DIR/offset_from_ub.rs:100:14 + | +LL | unsafe { ptr_offset_from(ptr1, ptr2) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:107:14 | LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8 error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:106:14 + --> $DIR/offset_from_ub.rs:114:14 | LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second @@ -79,7 +85,7 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR1` - --> $DIR/offset_from_ub.rs:115:14 + --> $DIR/offset_from_ub.rs:123:14 | LL | unsafe { ptr2.offset_from(ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -92,11 +98,11 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR2` - --> $DIR/offset_from_ub.rs:121:14 + --> $DIR/offset_from_ub.rs:129:14 | LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0080`. From 9ba492f2797250b2fcaa38d483ca5c23bf0bd8dd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 3 Jul 2024 16:42:33 +0200 Subject: [PATCH 12/63] also remove redundant requirements from offset() --- library/core/src/ptr/const_ptr.rs | 101 ++++++++++-------------------- library/core/src/ptr/mut_ptr.rs | 99 ++++++++++------------------- library/core/src/ptr/non_null.rs | 96 ++++++++++------------------ 3 files changed, 100 insertions(+), 196 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 039dc6d7a4981..68cf820343344 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -390,37 +390,26 @@ impl *const T { if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } } - /// Calculates the offset from a pointer. + /// Adds an offset to a pointer. /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_offset`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it @@ -622,7 +611,7 @@ impl *const T { /// * The distance between the pointers, in bytes, must be an exact multiple /// of the size of `T`. /// - /// As a consequence, the absolute distance between the pointers, **in bytes**, computed on + /// As a consequence, the absolute distance between the pointers, in bytes, computed on /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is /// implied by the in-bounds requirement, and the fact that no allocated object can be larger /// than `isize::MAX` bytes. @@ -862,37 +851,26 @@ impl *const T { } } - /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). + /// Adds an offset to a pointer (convenience for `.offset(count as isize)`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a `usize`. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_add`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it @@ -946,7 +924,7 @@ impl *const T { unsafe { self.cast::().add(count).with_metadata_of(self) } } - /// Calculates the offset from a pointer (convenience for + /// Subtracts an offset from a pointer (convenience for /// `.offset((count as isize).wrapping_neg())`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer @@ -954,30 +932,19 @@ impl *const T { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset cannot exceed `isize::MAX` **bytes**. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_sub`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index cbd3de1268a18..0dc910db5b9bd 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -404,37 +404,26 @@ impl *mut T { if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } } - /// Calculates the offset from a pointer. + /// Adds an offset to a pointer. /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_offset`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it @@ -1003,37 +992,26 @@ impl *mut T { unsafe { (self as *const T).sub_ptr(origin) } } - /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). + /// Adds an offset to a pointer (convenience for `.offset(count as isize)`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a `usize`. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_add`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it @@ -1087,7 +1065,7 @@ impl *mut T { unsafe { self.cast::().add(count).with_metadata_of(self) } } - /// Calculates the offset from a pointer (convenience for + /// Subtracts an offset from a pointer (convenience for /// `.offset((count as isize).wrapping_neg())`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer @@ -1095,30 +1073,19 @@ impl *mut T { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting - /// pointer must be either in bounds or at the end of the same [allocated object]. - /// (If it is zero, then the function is always well-defined.) - /// - /// * The computed offset cannot exceed `isize::MAX` **bytes**. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// Consider using [`wrapping_sub`] instead if these constraints are /// difficult to satisfy. The only advantage of this method is that it diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0b1bd5aeebb9c..75a99e14fdadc 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -476,36 +476,26 @@ impl NonNull { unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } - /// Calculates the offset from a pointer. + /// Adds an offset to a pointer. /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same [allocated object]. - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// [allocated object]: crate::ptr#allocated-object /// @@ -562,36 +552,26 @@ impl NonNull { unsafe { NonNull { pointer: self.pointer.byte_offset(count) } } } - /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). + /// Adds an offset to a pointer (convenience for `.offset(count as isize)`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// offset of `3 * size_of::()` bytes. /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same [allocated object]. - /// - /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a `usize`. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// [allocated object]: crate::ptr#allocated-object /// @@ -649,7 +629,7 @@ impl NonNull { unsafe { NonNull { pointer: self.pointer.byte_add(count) } } } - /// Calculates the offset from a pointer (convenience for + /// Subtracts an offset from a pointer (convenience for /// `.offset((count as isize).wrapping_neg())`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer @@ -657,29 +637,19 @@ impl NonNull { /// /// # Safety /// - /// If any of the following conditions are violated, the result is Undefined - /// Behavior: - /// - /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same [allocated object]. - /// - /// * The computed offset cannot exceed `isize::MAX` **bytes**. + /// If any of the following conditions are violated, the result is Undefined Behavior: /// - /// * The offset being in bounds cannot rely on "wrapping around" the address - /// space. That is, the infinite-precision sum must fit in a usize. + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// - /// The compiler and standard library generally tries to ensure allocations - /// never reach a size where an offset is a concern. For instance, `Vec` - /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe. + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. /// - /// Most platforms fundamentally can't even construct such an allocation. - /// For instance, no known 64-bit platform can ever serve a request - /// for 263 bytes due to page-table limitations or splitting the address space. - /// However, some 32-bit and 16-bit platforms may successfully serve a request for - /// more than `isize::MAX` bytes with things like Physical Address - /// Extension. As such, memory acquired directly from allocators or memory - /// mapped files *may* be too large to handle with this function. + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. /// /// [allocated object]: crate::ptr#allocated-object /// From 34860a56f09baf9bc02cde287f4baff921b9a748 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 4 Jul 2024 12:09:25 +0000 Subject: [PATCH 13/63] Update windows-bindgen to 0.58.0 --- Cargo.lock | 8 +- library/std/src/sys/pal/windows/c.rs | 9 +- .../std/src/sys/pal/windows/c/bindings.txt | 2 +- .../std/src/sys/pal/windows/c/windows_sys.rs | 970 +++--------------- .../src/sys/pal/windows/c/windows_targets.rs | 15 + library/std/src/sys/pal/windows/stdio.rs | 8 +- src/tools/generate-windows-sys/Cargo.toml | 2 +- src/tools/generate-windows-sys/src/main.rs | 1 + 8 files changed, 159 insertions(+), 856 deletions(-) create mode 100644 library/std/src/sys/pal/windows/c/windows_targets.rs diff --git a/Cargo.lock b/Cargo.lock index 96cef9070842e..fbe1abf2a3317 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6356,9 +6356,9 @@ dependencies = [ [[package]] name = "windows-bindgen" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ccb96113d6277ba543c0f77e1c5494af8094bf9daf9b85acdc3f1b620e7c7b4" +checksum = "91cd28d93c692351f3a6e5615567c56756e330bee1c99c6bdd57bfc5ab15f589" dependencies = [ "proc-macro2", "rayon", @@ -6379,9 +6379,9 @@ dependencies = [ [[package]] name = "windows-metadata" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8308d076825b9d9e5abc64f8113e96d02b2aeeba869b20fdd65c7e70cda13dfc" +checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809" [[package]] name = "windows-sys" diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 6ec82693077dc..27aa35f69f1bf 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -13,6 +13,8 @@ use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort, c_vo use crate::os::windows::io::{AsRawHandle, BorrowedHandle}; use crate::ptr; +mod windows_targets; + mod windows_sys; pub use windows_sys::*; @@ -504,11 +506,8 @@ if #[cfg(not(target_vendor = "uwp"))] { #[cfg(target_arch = "arm")] pub enum CONTEXT {} }} - -#[link(name = "ws2_32")] -extern "system" { - pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32; -} +// WSAStartup is only redefined here so that we can override WSADATA for Arm32 +windows_targets::link!("ws2_32.dll" "system" fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32); #[cfg(target_arch = "arm")] #[repr(C)] pub struct WSADATA { diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 849e64ac59135..5ad4a3731d822 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -1,5 +1,5 @@ --out windows_sys.rs ---config flatten std +--config flatten sys --filter !Windows.Win32.Foundation.INVALID_HANDLE_VALUE Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 19f013d3347e4..fea00fec9ae59 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -1,843 +1,136 @@ -// Bindings generated by `windows-bindgen` 0.57.0 +// Bindings generated by `windows-bindgen` 0.58.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] -#[link(name = "advapi32")] -extern "system" { - pub fn OpenProcessToken( - processhandle: HANDLE, - desiredaccess: TOKEN_ACCESS_MASK, - tokenhandle: *mut HANDLE, - ) -> BOOL; -} -#[link(name = "advapi32")] -extern "system" { - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(randombuffer: *mut core::ffi::c_void, randombufferlength: u32) -> BOOLEAN; -} -#[link(name = "kernel32")] -extern "system" { - pub fn AcquireSRWLockExclusive(srwlock: *mut SRWLOCK); -} -#[link(name = "kernel32")] -extern "system" { - pub fn AcquireSRWLockShared(srwlock: *mut SRWLOCK); -} -#[link(name = "kernel32")] -extern "system" { - pub fn CancelIo(hfile: HANDLE) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CloseHandle(hobject: HANDLE) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CompareStringOrdinal( - lpstring1: PCWSTR, - cchcount1: i32, - lpstring2: PCWSTR, - cchcount2: i32, - bignorecase: BOOL, - ) -> COMPARESTRING_RESULT; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CopyFileExW( - lpexistingfilename: PCWSTR, - lpnewfilename: PCWSTR, - lpprogressroutine: LPPROGRESS_ROUTINE, - lpdata: *const core::ffi::c_void, - pbcancel: *mut BOOL, - dwcopyflags: u32, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateDirectoryW( - lppathname: PCWSTR, - lpsecurityattributes: *const SECURITY_ATTRIBUTES, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateEventW( - lpeventattributes: *const SECURITY_ATTRIBUTES, - bmanualreset: BOOL, - binitialstate: BOOL, - lpname: PCWSTR, - ) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateFileW( - lpfilename: PCWSTR, - dwdesiredaccess: u32, - dwsharemode: FILE_SHARE_MODE, - lpsecurityattributes: *const SECURITY_ATTRIBUTES, - dwcreationdisposition: FILE_CREATION_DISPOSITION, - dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES, - htemplatefile: HANDLE, - ) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateHardLinkW( - lpfilename: PCWSTR, - lpexistingfilename: PCWSTR, - lpsecurityattributes: *const SECURITY_ATTRIBUTES, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateNamedPipeW( - lpname: PCWSTR, - dwopenmode: FILE_FLAGS_AND_ATTRIBUTES, - dwpipemode: NAMED_PIPE_MODE, - nmaxinstances: u32, - noutbuffersize: u32, - ninbuffersize: u32, - ndefaulttimeout: u32, - lpsecurityattributes: *const SECURITY_ATTRIBUTES, - ) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateProcessW( - lpapplicationname: PCWSTR, - lpcommandline: PWSTR, - lpprocessattributes: *const SECURITY_ATTRIBUTES, - lpthreadattributes: *const SECURITY_ATTRIBUTES, - binherithandles: BOOL, - dwcreationflags: PROCESS_CREATION_FLAGS, - lpenvironment: *const core::ffi::c_void, - lpcurrentdirectory: PCWSTR, - lpstartupinfo: *const STARTUPINFOW, - lpprocessinformation: *mut PROCESS_INFORMATION, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateSymbolicLinkW( - lpsymlinkfilename: PCWSTR, - lptargetfilename: PCWSTR, - dwflags: SYMBOLIC_LINK_FLAGS, - ) -> BOOLEAN; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateThread( - lpthreadattributes: *const SECURITY_ATTRIBUTES, - dwstacksize: usize, - lpstartaddress: LPTHREAD_START_ROUTINE, - lpparameter: *const core::ffi::c_void, - dwcreationflags: THREAD_CREATION_FLAGS, - lpthreadid: *mut u32, - ) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn CreateWaitableTimerExW( - lptimerattributes: *const SECURITY_ATTRIBUTES, - lptimername: PCWSTR, - dwflags: u32, - dwdesiredaccess: u32, - ) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn DeleteFileW(lpfilename: PCWSTR) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn DeleteProcThreadAttributeList(lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST); -} -#[link(name = "kernel32")] -extern "system" { - pub fn DeviceIoControl( - hdevice: HANDLE, - dwiocontrolcode: u32, - lpinbuffer: *const core::ffi::c_void, - ninbuffersize: u32, - lpoutbuffer: *mut core::ffi::c_void, - noutbuffersize: u32, - lpbytesreturned: *mut u32, - lpoverlapped: *mut OVERLAPPED, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn DuplicateHandle( - hsourceprocesshandle: HANDLE, - hsourcehandle: HANDLE, - htargetprocesshandle: HANDLE, - lptargethandle: *mut HANDLE, - dwdesiredaccess: u32, - binherithandle: BOOL, - dwoptions: DUPLICATE_HANDLE_OPTIONS, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn ExitProcess(uexitcode: u32) -> !; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FindClose(hfindfile: HANDLE) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FindFirstFileW(lpfilename: PCWSTR, lpfindfiledata: *mut WIN32_FIND_DATAW) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FindNextFileW(hfindfile: HANDLE, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FlushFileBuffers(hfile: HANDLE) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FormatMessageW( - dwflags: FORMAT_MESSAGE_OPTIONS, - lpsource: *const core::ffi::c_void, - dwmessageid: u32, - dwlanguageid: u32, - lpbuffer: PWSTR, - nsize: u32, - arguments: *const *const i8, - ) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn FreeEnvironmentStringsW(penv: PCWSTR) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetActiveProcessorCount(groupnumber: u16) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetCommandLineW() -> PCWSTR; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetConsoleMode(hconsolehandle: HANDLE, lpmode: *mut CONSOLE_MODE) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetCurrentDirectoryW(nbufferlength: u32, lpbuffer: PWSTR) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetCurrentProcess() -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetCurrentProcessId() -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetCurrentThread() -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetEnvironmentStringsW() -> PWSTR; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetEnvironmentVariableW(lpname: PCWSTR, lpbuffer: PWSTR, nsize: u32) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetExitCodeProcess(hprocess: HANDLE, lpexitcode: *mut u32) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFileAttributesW(lpfilename: PCWSTR) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFileInformationByHandle( - hfile: HANDLE, - lpfileinformation: *mut BY_HANDLE_FILE_INFORMATION, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFileInformationByHandleEx( - hfile: HANDLE, - fileinformationclass: FILE_INFO_BY_HANDLE_CLASS, - lpfileinformation: *mut core::ffi::c_void, - dwbuffersize: u32, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFileType(hfile: HANDLE) -> FILE_TYPE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFinalPathNameByHandleW( - hfile: HANDLE, - lpszfilepath: PWSTR, - cchfilepath: u32, - dwflags: GETFINALPATHNAMEBYHANDLE_FLAGS, - ) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetFullPathNameW( - lpfilename: PCWSTR, - nbufferlength: u32, - lpbuffer: PWSTR, - lpfilepart: *mut PWSTR, - ) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetLastError() -> WIN32_ERROR; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetModuleFileNameW(hmodule: HMODULE, lpfilename: PWSTR, nsize: u32) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetModuleHandleA(lpmodulename: PCSTR) -> HMODULE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetModuleHandleW(lpmodulename: PCWSTR) -> HMODULE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetOverlappedResult( - hfile: HANDLE, - lpoverlapped: *const OVERLAPPED, - lpnumberofbytestransferred: *mut u32, - bwait: BOOL, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetProcAddress(hmodule: HMODULE, lpprocname: PCSTR) -> FARPROC; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetProcessId(process: HANDLE) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetStdHandle(nstdhandle: STD_HANDLE) -> HANDLE; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetSystemDirectoryW(lpbuffer: PWSTR, usize: u32) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetSystemInfo(lpsysteminfo: *mut SYSTEM_INFO); -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime: *mut FILETIME); -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME); -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn GetWindowsDirectoryW(lpbuffer: PWSTR, usize: u32) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn InitOnceBeginInitialize( - lpinitonce: *mut INIT_ONCE, - dwflags: u32, - fpending: *mut BOOL, - lpcontext: *mut *mut core::ffi::c_void, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn InitOnceComplete( - lpinitonce: *mut INIT_ONCE, - dwflags: u32, - lpcontext: *const core::ffi::c_void, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn InitializeProcThreadAttributeList( - lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST, - dwattributecount: u32, - dwflags: u32, - lpsize: *mut usize, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn LocalFree(hmem: HLOCAL) -> HLOCAL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn MoveFileExW( - lpexistingfilename: PCWSTR, - lpnewfilename: PCWSTR, - dwflags: MOVE_FILE_FLAGS, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn MultiByteToWideChar( - codepage: u32, - dwflags: MULTI_BYTE_TO_WIDE_CHAR_FLAGS, - lpmultibytestr: PCSTR, - cbmultibyte: i32, - lpwidecharstr: PWSTR, - cchwidechar: i32, - ) -> i32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn QueryPerformanceCounter(lpperformancecount: *mut i64) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn QueryPerformanceFrequency(lpfrequency: *mut i64) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn ReadConsoleW( - hconsoleinput: HANDLE, - lpbuffer: *mut core::ffi::c_void, - nnumberofcharstoread: u32, - lpnumberofcharsread: *mut u32, - pinputcontrol: *const CONSOLE_READCONSOLE_CONTROL, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn ReadFile( - hfile: HANDLE, - lpbuffer: *mut u8, - nnumberofbytestoread: u32, - lpnumberofbytesread: *mut u32, - lpoverlapped: *mut OVERLAPPED, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn ReadFileEx( - hfile: HANDLE, - lpbuffer: *mut u8, - nnumberofbytestoread: u32, - lpoverlapped: *mut OVERLAPPED, - lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn ReleaseSRWLockExclusive(srwlock: *mut SRWLOCK); -} -#[link(name = "kernel32")] -extern "system" { - pub fn ReleaseSRWLockShared(srwlock: *mut SRWLOCK); -} -#[link(name = "kernel32")] -extern "system" { - pub fn RemoveDirectoryW(lppathname: PCWSTR) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetCurrentDirectoryW(lppathname: PCWSTR) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetEnvironmentVariableW(lpname: PCWSTR, lpvalue: PCWSTR) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetFileAttributesW( - lpfilename: PCWSTR, - dwfileattributes: FILE_FLAGS_AND_ATTRIBUTES, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetFileInformationByHandle( - hfile: HANDLE, - fileinformationclass: FILE_INFO_BY_HANDLE_CLASS, - lpfileinformation: *const core::ffi::c_void, - dwbuffersize: u32, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetFilePointerEx( - hfile: HANDLE, - lidistancetomove: i64, - lpnewfilepointer: *mut i64, - dwmovemethod: SET_FILE_POINTER_MOVE_METHOD, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetFileTime( - hfile: HANDLE, - lpcreationtime: *const FILETIME, - lplastaccesstime: *const FILETIME, - lplastwritetime: *const FILETIME, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetHandleInformation(hobject: HANDLE, dwmask: u32, dwflags: HANDLE_FLAGS) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetLastError(dwerrcode: WIN32_ERROR); -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SetWaitableTimer( - htimer: HANDLE, - lpduetime: *const i64, - lperiod: i32, - pfncompletionroutine: PTIMERAPCROUTINE, - lpargtocompletionroutine: *const core::ffi::c_void, - fresume: BOOL, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn Sleep(dwmilliseconds: u32); -} -#[link(name = "kernel32")] -extern "system" { - pub fn SleepConditionVariableSRW( - conditionvariable: *mut CONDITION_VARIABLE, - srwlock: *mut SRWLOCK, - dwmilliseconds: u32, - flags: u32, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SleepEx(dwmilliseconds: u32, balertable: BOOL) -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn SwitchToThread() -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TerminateProcess(hprocess: HANDLE, uexitcode: u32) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TlsAlloc() -> u32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TlsFree(dwtlsindex: u32) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TlsGetValue(dwtlsindex: u32) -> *mut core::ffi::c_void; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TlsSetValue(dwtlsindex: u32, lptlsvalue: *const core::ffi::c_void) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TryAcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> BOOLEAN; -} -#[link(name = "kernel32")] -extern "system" { - pub fn TryAcquireSRWLockShared(srwlock: *mut SRWLOCK) -> BOOLEAN; -} -#[link(name = "kernel32")] -extern "system" { - pub fn UpdateProcThreadAttribute( - lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST, - dwflags: u32, - attribute: usize, - lpvalue: *const core::ffi::c_void, - cbsize: usize, - lppreviousvalue: *mut core::ffi::c_void, - lpreturnsize: *const usize, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn WaitForMultipleObjects( - ncount: u32, - lphandles: *const HANDLE, - bwaitall: BOOL, - dwmilliseconds: u32, - ) -> WAIT_EVENT; -} -#[link(name = "kernel32")] -extern "system" { - pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WAIT_EVENT; -} -#[link(name = "kernel32")] -extern "system" { - pub fn WakeAllConditionVariable(conditionvariable: *mut CONDITION_VARIABLE); -} -#[link(name = "kernel32")] -extern "system" { - pub fn WakeConditionVariable(conditionvariable: *mut CONDITION_VARIABLE); -} -#[link(name = "kernel32")] -extern "system" { - pub fn WideCharToMultiByte( - codepage: u32, - dwflags: u32, - lpwidecharstr: PCWSTR, - cchwidechar: i32, - lpmultibytestr: PSTR, - cbmultibyte: i32, - lpdefaultchar: PCSTR, - lpuseddefaultchar: *mut BOOL, - ) -> i32; -} -#[link(name = "kernel32")] -extern "system" { - pub fn WriteConsoleW( - hconsoleoutput: HANDLE, - lpbuffer: *const core::ffi::c_void, - nnumberofcharstowrite: u32, - lpnumberofcharswritten: *mut u32, - lpreserved: *const core::ffi::c_void, - ) -> BOOL; -} -#[link(name = "kernel32")] -extern "system" { - pub fn WriteFileEx( - hfile: HANDLE, - lpbuffer: *const u8, - nnumberofbytestowrite: u32, - lpoverlapped: *mut OVERLAPPED, - lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, - ) -> BOOL; -} -#[link(name = "ntdll")] -extern "system" { - pub fn NtCreateFile( - filehandle: *mut HANDLE, - desiredaccess: FILE_ACCESS_RIGHTS, - objectattributes: *const OBJECT_ATTRIBUTES, - iostatusblock: *mut IO_STATUS_BLOCK, - allocationsize: *const i64, - fileattributes: FILE_FLAGS_AND_ATTRIBUTES, - shareaccess: FILE_SHARE_MODE, - createdisposition: NTCREATEFILE_CREATE_DISPOSITION, - createoptions: NTCREATEFILE_CREATE_OPTIONS, - eabuffer: *const core::ffi::c_void, - ealength: u32, - ) -> NTSTATUS; -} -#[link(name = "ntdll")] -extern "system" { - pub fn NtReadFile( - filehandle: HANDLE, - event: HANDLE, - apcroutine: PIO_APC_ROUTINE, - apccontext: *const core::ffi::c_void, - iostatusblock: *mut IO_STATUS_BLOCK, - buffer: *mut core::ffi::c_void, - length: u32, - byteoffset: *const i64, - key: *const u32, - ) -> NTSTATUS; -} -#[link(name = "ntdll")] -extern "system" { - pub fn NtWriteFile( - filehandle: HANDLE, - event: HANDLE, - apcroutine: PIO_APC_ROUTINE, - apccontext: *const core::ffi::c_void, - iostatusblock: *mut IO_STATUS_BLOCK, - buffer: *const core::ffi::c_void, - length: u32, - byteoffset: *const i64, - key: *const u32, - ) -> NTSTATUS; -} -#[link(name = "ntdll")] -extern "system" { - pub fn RtlNtStatusToDosError(status: NTSTATUS) -> u32; -} -#[link(name = "userenv")] -extern "system" { - pub fn GetUserProfileDirectoryW( - htoken: HANDLE, - lpprofiledir: PWSTR, - lpcchsize: *mut u32, - ) -> BOOL; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSACleanup() -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSADuplicateSocketW( - s: SOCKET, - dwprocessid: u32, - lpprotocolinfo: *mut WSAPROTOCOL_INFOW, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSAGetLastError() -> WSA_ERROR; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSARecv( - s: SOCKET, - lpbuffers: *const WSABUF, - dwbuffercount: u32, - lpnumberofbytesrecvd: *mut u32, - lpflags: *mut u32, - lpoverlapped: *mut OVERLAPPED, - lpcompletionroutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSASend( - s: SOCKET, - lpbuffers: *const WSABUF, - dwbuffercount: u32, - lpnumberofbytessent: *mut u32, - dwflags: u32, - lpoverlapped: *mut OVERLAPPED, - lpcompletionroutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn WSASocketW( - af: i32, - r#type: i32, - protocol: i32, - lpprotocolinfo: *const WSAPROTOCOL_INFOW, - g: u32, - dwflags: u32, - ) -> SOCKET; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn accept(s: SOCKET, addr: *mut SOCKADDR, addrlen: *mut i32) -> SOCKET; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn bind(s: SOCKET, name: *const SOCKADDR, namelen: i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn closesocket(s: SOCKET) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn connect(s: SOCKET, name: *const SOCKADDR, namelen: i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA); -} -#[link(name = "ws2_32")] -extern "system" { - pub fn getaddrinfo( - pnodename: PCSTR, - pservicename: PCSTR, - phints: *const ADDRINFOA, - ppresult: *mut *mut ADDRINFOA, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn getpeername(s: SOCKET, name: *mut SOCKADDR, namelen: *mut i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn getsockname(s: SOCKET, name: *mut SOCKADDR, namelen: *mut i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn getsockopt(s: SOCKET, level: i32, optname: i32, optval: PSTR, optlen: *mut i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn ioctlsocket(s: SOCKET, cmd: i32, argp: *mut u32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn listen(s: SOCKET, backlog: i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn recv(s: SOCKET, buf: PSTR, len: i32, flags: SEND_RECV_FLAGS) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn recvfrom( - s: SOCKET, - buf: PSTR, - len: i32, - flags: i32, - from: *mut SOCKADDR, - fromlen: *mut i32, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn select( - nfds: i32, - readfds: *mut FD_SET, - writefds: *mut FD_SET, - exceptfds: *mut FD_SET, - timeout: *const TIMEVAL, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn send(s: SOCKET, buf: PCSTR, len: i32, flags: SEND_RECV_FLAGS) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn sendto( - s: SOCKET, - buf: PCSTR, - len: i32, - flags: i32, - to: *const SOCKADDR, - tolen: i32, - ) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn setsockopt(s: SOCKET, level: i32, optname: i32, optval: PCSTR, optlen: i32) -> i32; -} -#[link(name = "ws2_32")] -extern "system" { - pub fn shutdown(s: SOCKET, how: WINSOCK_SHUTDOWN_HOW) -> i32; -} +windows_targets::link!("advapi32.dll" "system" fn OpenProcessToken(processhandle : HANDLE, desiredaccess : TOKEN_ACCESS_MASK, tokenhandle : *mut HANDLE) -> BOOL); +windows_targets::link!("advapi32.dll" "system" "SystemFunction036" fn RtlGenRandom(randombuffer : *mut core::ffi::c_void, randombufferlength : u32) -> BOOLEAN); +windows_targets::link!("kernel32.dll" "system" fn AcquireSRWLockExclusive(srwlock : *mut SRWLOCK)); +windows_targets::link!("kernel32.dll" "system" fn AcquireSRWLockShared(srwlock : *mut SRWLOCK)); +windows_targets::link!("kernel32.dll" "system" fn CancelIo(hfile : HANDLE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CloseHandle(hobject : HANDLE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CompareStringOrdinal(lpstring1 : PCWSTR, cchcount1 : i32, lpstring2 : PCWSTR, cchcount2 : i32, bignorecase : BOOL) -> COMPARESTRING_RESULT); +windows_targets::link!("kernel32.dll" "system" fn CopyFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, lpprogressroutine : LPPROGRESS_ROUTINE, lpdata : *const core::ffi::c_void, pbcancel : *mut BOOL, dwcopyflags : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CreateDirectoryW(lppathname : PCWSTR, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CreateEventW(lpeventattributes : *const SECURITY_ATTRIBUTES, bmanualreset : BOOL, binitialstate : BOOL, lpname : PCWSTR) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn CreateFileW(lpfilename : PCWSTR, dwdesiredaccess : u32, dwsharemode : FILE_SHARE_MODE, lpsecurityattributes : *const SECURITY_ATTRIBUTES, dwcreationdisposition : FILE_CREATION_DISPOSITION, dwflagsandattributes : FILE_FLAGS_AND_ATTRIBUTES, htemplatefile : HANDLE) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn CreateHardLinkW(lpfilename : PCWSTR, lpexistingfilename : PCWSTR, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CreateNamedPipeW(lpname : PCWSTR, dwopenmode : FILE_FLAGS_AND_ATTRIBUTES, dwpipemode : NAMED_PIPE_MODE, nmaxinstances : u32, noutbuffersize : u32, ninbuffersize : u32, ndefaulttimeout : u32, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn CreateProcessW(lpapplicationname : PCWSTR, lpcommandline : PWSTR, lpprocessattributes : *const SECURITY_ATTRIBUTES, lpthreadattributes : *const SECURITY_ATTRIBUTES, binherithandles : BOOL, dwcreationflags : PROCESS_CREATION_FLAGS, lpenvironment : *const core::ffi::c_void, lpcurrentdirectory : PCWSTR, lpstartupinfo : *const STARTUPINFOW, lpprocessinformation : *mut PROCESS_INFORMATION) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn CreateSymbolicLinkW(lpsymlinkfilename : PCWSTR, lptargetfilename : PCWSTR, dwflags : SYMBOLIC_LINK_FLAGS) -> BOOLEAN); +windows_targets::link!("kernel32.dll" "system" fn CreateThread(lpthreadattributes : *const SECURITY_ATTRIBUTES, dwstacksize : usize, lpstartaddress : LPTHREAD_START_ROUTINE, lpparameter : *const core::ffi::c_void, dwcreationflags : THREAD_CREATION_FLAGS, lpthreadid : *mut u32) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn CreateWaitableTimerExW(lptimerattributes : *const SECURITY_ATTRIBUTES, lptimername : PCWSTR, dwflags : u32, dwdesiredaccess : u32) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn DeleteFileW(lpfilename : PCWSTR) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn DeleteProcThreadAttributeList(lpattributelist : LPPROC_THREAD_ATTRIBUTE_LIST)); +windows_targets::link!("kernel32.dll" "system" fn DeviceIoControl(hdevice : HANDLE, dwiocontrolcode : u32, lpinbuffer : *const core::ffi::c_void, ninbuffersize : u32, lpoutbuffer : *mut core::ffi::c_void, noutbuffersize : u32, lpbytesreturned : *mut u32, lpoverlapped : *mut OVERLAPPED) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn DuplicateHandle(hsourceprocesshandle : HANDLE, hsourcehandle : HANDLE, htargetprocesshandle : HANDLE, lptargethandle : *mut HANDLE, dwdesiredaccess : u32, binherithandle : BOOL, dwoptions : DUPLICATE_HANDLE_OPTIONS) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn ExitProcess(uexitcode : u32) -> !); +windows_targets::link!("kernel32.dll" "system" fn FindClose(hfindfile : HANDLE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn FindFirstFileW(lpfilename : PCWSTR, lpfindfiledata : *mut WIN32_FIND_DATAW) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn FindNextFileW(hfindfile : HANDLE, lpfindfiledata : *mut WIN32_FIND_DATAW) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn FlushFileBuffers(hfile : HANDLE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn FormatMessageW(dwflags : FORMAT_MESSAGE_OPTIONS, lpsource : *const core::ffi::c_void, dwmessageid : u32, dwlanguageid : u32, lpbuffer : PWSTR, nsize : u32, arguments : *const *const i8) -> u32); +windows_targets::link!("kernel32.dll" "system" fn FreeEnvironmentStringsW(penv : PCWSTR) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetActiveProcessorCount(groupnumber : u16) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetCommandLineW() -> PCWSTR); +windows_targets::link!("kernel32.dll" "system" fn GetConsoleMode(hconsolehandle : HANDLE, lpmode : *mut CONSOLE_MODE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetCurrentDirectoryW(nbufferlength : u32, lpbuffer : PWSTR) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcess() -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcessId() -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetCurrentThread() -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn GetEnvironmentStringsW() -> PWSTR); +windows_targets::link!("kernel32.dll" "system" fn GetEnvironmentVariableW(lpname : PCWSTR, lpbuffer : PWSTR, nsize : u32) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetExitCodeProcess(hprocess : HANDLE, lpexitcode : *mut u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetFileAttributesW(lpfilename : PCWSTR) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetFileInformationByHandle(hfile : HANDLE, lpfileinformation : *mut BY_HANDLE_FILE_INFORMATION) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetFileInformationByHandleEx(hfile : HANDLE, fileinformationclass : FILE_INFO_BY_HANDLE_CLASS, lpfileinformation : *mut core::ffi::c_void, dwbuffersize : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetFileType(hfile : HANDLE) -> FILE_TYPE); +windows_targets::link!("kernel32.dll" "system" fn GetFinalPathNameByHandleW(hfile : HANDLE, lpszfilepath : PWSTR, cchfilepath : u32, dwflags : GETFINALPATHNAMEBYHANDLE_FLAGS) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetFullPathNameW(lpfilename : PCWSTR, nbufferlength : u32, lpbuffer : PWSTR, lpfilepart : *mut PWSTR) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> WIN32_ERROR); +windows_targets::link!("kernel32.dll" "system" fn GetModuleFileNameW(hmodule : HMODULE, lpfilename : PWSTR, nsize : u32) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename : PCSTR) -> HMODULE); +windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleW(lpmodulename : PCWSTR) -> HMODULE); +windows_targets::link!("kernel32.dll" "system" fn GetOverlappedResult(hfile : HANDLE, lpoverlapped : *const OVERLAPPED, lpnumberofbytestransferred : *mut u32, bwait : BOOL) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC); +windows_targets::link!("kernel32.dll" "system" fn GetProcessId(process : HANDLE) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetStdHandle(nstdhandle : STD_HANDLE) -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn GetSystemDirectoryW(lpbuffer : PWSTR, usize : u32) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetSystemInfo(lpsysteminfo : *mut SYSTEM_INFO)); +windows_targets::link!("kernel32.dll" "system" fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime : *mut FILETIME)); +windows_targets::link!("kernel32.dll" "system" fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime : *mut FILETIME)); +windows_targets::link!("kernel32.dll" "system" fn GetTempPathW(nbufferlength : u32, lpbuffer : PWSTR) -> u32); +windows_targets::link!("kernel32.dll" "system" fn GetWindowsDirectoryW(lpbuffer : PWSTR, usize : u32) -> u32); +windows_targets::link!("kernel32.dll" "system" fn InitOnceBeginInitialize(lpinitonce : *mut INIT_ONCE, dwflags : u32, fpending : *mut BOOL, lpcontext : *mut *mut core::ffi::c_void) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn InitOnceComplete(lpinitonce : *mut INIT_ONCE, dwflags : u32, lpcontext : *const core::ffi::c_void) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn InitializeProcThreadAttributeList(lpattributelist : LPPROC_THREAD_ATTRIBUTE_LIST, dwattributecount : u32, dwflags : u32, lpsize : *mut usize) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn LocalFree(hmem : HLOCAL) -> HLOCAL); +windows_targets::link!("kernel32.dll" "system" fn MoveFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, dwflags : MOVE_FILE_FLAGS) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn MultiByteToWideChar(codepage : u32, dwflags : MULTI_BYTE_TO_WIDE_CHAR_FLAGS, lpmultibytestr : PCSTR, cbmultibyte : i32, lpwidecharstr : PWSTR, cchwidechar : i32) -> i32); +windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceCounter(lpperformancecount : *mut i64) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceFrequency(lpfrequency : *mut i64) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn ReadConsoleW(hconsoleinput : HANDLE, lpbuffer : *mut core::ffi::c_void, nnumberofcharstoread : u32, lpnumberofcharsread : *mut u32, pinputcontrol : *const CONSOLE_READCONSOLE_CONTROL) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn ReadFile(hfile : HANDLE, lpbuffer : *mut u8, nnumberofbytestoread : u32, lpnumberofbytesread : *mut u32, lpoverlapped : *mut OVERLAPPED) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn ReadFileEx(hfile : HANDLE, lpbuffer : *mut u8, nnumberofbytestoread : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPOVERLAPPED_COMPLETION_ROUTINE) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn ReleaseSRWLockExclusive(srwlock : *mut SRWLOCK)); +windows_targets::link!("kernel32.dll" "system" fn ReleaseSRWLockShared(srwlock : *mut SRWLOCK)); +windows_targets::link!("kernel32.dll" "system" fn RemoveDirectoryW(lppathname : PCWSTR) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetCurrentDirectoryW(lppathname : PCWSTR) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetEnvironmentVariableW(lpname : PCWSTR, lpvalue : PCWSTR) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetFileAttributesW(lpfilename : PCWSTR, dwfileattributes : FILE_FLAGS_AND_ATTRIBUTES) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetFileInformationByHandle(hfile : HANDLE, fileinformationclass : FILE_INFO_BY_HANDLE_CLASS, lpfileinformation : *const core::ffi::c_void, dwbuffersize : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetFilePointerEx(hfile : HANDLE, lidistancetomove : i64, lpnewfilepointer : *mut i64, dwmovemethod : SET_FILE_POINTER_MOVE_METHOD) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetFileTime(hfile : HANDLE, lpcreationtime : *const FILETIME, lplastaccesstime : *const FILETIME, lplastwritetime : *const FILETIME) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetHandleInformation(hobject : HANDLE, dwmask : u32, dwflags : HANDLE_FLAGS) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetLastError(dwerrcode : WIN32_ERROR)); +windows_targets::link!("kernel32.dll" "system" fn SetThreadStackGuarantee(stacksizeinbytes : *mut u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SetWaitableTimer(htimer : HANDLE, lpduetime : *const i64, lperiod : i32, pfncompletionroutine : PTIMERAPCROUTINE, lpargtocompletionroutine : *const core::ffi::c_void, fresume : BOOL) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn Sleep(dwmilliseconds : u32)); +windows_targets::link!("kernel32.dll" "system" fn SleepConditionVariableSRW(conditionvariable : *mut CONDITION_VARIABLE, srwlock : *mut SRWLOCK, dwmilliseconds : u32, flags : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn SleepEx(dwmilliseconds : u32, balertable : BOOL) -> u32); +windows_targets::link!("kernel32.dll" "system" fn SwitchToThread() -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn TerminateProcess(hprocess : HANDLE, uexitcode : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn TlsAlloc() -> u32); +windows_targets::link!("kernel32.dll" "system" fn TlsFree(dwtlsindex : u32) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn TlsGetValue(dwtlsindex : u32) -> *mut core::ffi::c_void); +windows_targets::link!("kernel32.dll" "system" fn TlsSetValue(dwtlsindex : u32, lptlsvalue : *const core::ffi::c_void) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockExclusive(srwlock : *mut SRWLOCK) -> BOOLEAN); +windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockShared(srwlock : *mut SRWLOCK) -> BOOLEAN); +windows_targets::link!("kernel32.dll" "system" fn UpdateProcThreadAttribute(lpattributelist : LPPROC_THREAD_ATTRIBUTE_LIST, dwflags : u32, attribute : usize, lpvalue : *const core::ffi::c_void, cbsize : usize, lppreviousvalue : *mut core::ffi::c_void, lpreturnsize : *const usize) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn WaitForMultipleObjects(ncount : u32, lphandles : *const HANDLE, bwaitall : BOOL, dwmilliseconds : u32) -> WAIT_EVENT); +windows_targets::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT); +windows_targets::link!("kernel32.dll" "system" fn WakeAllConditionVariable(conditionvariable : *mut CONDITION_VARIABLE)); +windows_targets::link!("kernel32.dll" "system" fn WakeConditionVariable(conditionvariable : *mut CONDITION_VARIABLE)); +windows_targets::link!("kernel32.dll" "system" fn WideCharToMultiByte(codepage : u32, dwflags : u32, lpwidecharstr : PCWSTR, cchwidechar : i32, lpmultibytestr : PSTR, cbmultibyte : i32, lpdefaultchar : PCSTR, lpuseddefaultchar : *mut BOOL) -> i32); +windows_targets::link!("kernel32.dll" "system" fn WriteConsoleW(hconsoleoutput : HANDLE, lpbuffer : PCWSTR, nnumberofcharstowrite : u32, lpnumberofcharswritten : *mut u32, lpreserved : *const core::ffi::c_void) -> BOOL); +windows_targets::link!("kernel32.dll" "system" fn WriteFileEx(hfile : HANDLE, lpbuffer : *const u8, nnumberofbytestowrite : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPOVERLAPPED_COMPLETION_ROUTINE) -> BOOL); +windows_targets::link!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS); +windows_targets::link!("ntdll.dll" "system" fn NtReadFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *mut core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS); +windows_targets::link!("ntdll.dll" "system" fn NtWriteFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *const core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS); +windows_targets::link!("ntdll.dll" "system" fn RtlNtStatusToDosError(status : NTSTATUS) -> u32); +windows_targets::link!("userenv.dll" "system" fn GetUserProfileDirectoryW(htoken : HANDLE, lpprofiledir : PWSTR, lpcchsize : *mut u32) -> BOOL); +windows_targets::link!("ws2_32.dll" "system" fn WSACleanup() -> i32); +windows_targets::link!("ws2_32.dll" "system" fn WSADuplicateSocketW(s : SOCKET, dwprocessid : u32, lpprotocolinfo : *mut WSAPROTOCOL_INFOW) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn WSAGetLastError() -> WSA_ERROR); +windows_targets::link!("ws2_32.dll" "system" fn WSARecv(s : SOCKET, lpbuffers : *const WSABUF, dwbuffercount : u32, lpnumberofbytesrecvd : *mut u32, lpflags : *mut u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn WSASend(s : SOCKET, lpbuffers : *const WSABUF, dwbuffercount : u32, lpnumberofbytessent : *mut u32, dwflags : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn WSASocketW(af : i32, r#type : i32, protocol : i32, lpprotocolinfo : *const WSAPROTOCOL_INFOW, g : u32, dwflags : u32) -> SOCKET); +windows_targets::link!("ws2_32.dll" "system" fn accept(s : SOCKET, addr : *mut SOCKADDR, addrlen : *mut i32) -> SOCKET); +windows_targets::link!("ws2_32.dll" "system" fn bind(s : SOCKET, name : *const SOCKADDR, namelen : i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn closesocket(s : SOCKET) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn connect(s : SOCKET, name : *const SOCKADDR, namelen : i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn freeaddrinfo(paddrinfo : *const ADDRINFOA)); +windows_targets::link!("ws2_32.dll" "system" fn getaddrinfo(pnodename : PCSTR, pservicename : PCSTR, phints : *const ADDRINFOA, ppresult : *mut *mut ADDRINFOA) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn getpeername(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn getsockname(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn getsockopt(s : SOCKET, level : i32, optname : i32, optval : PSTR, optlen : *mut i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn ioctlsocket(s : SOCKET, cmd : i32, argp : *mut u32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn listen(s : SOCKET, backlog : i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn recv(s : SOCKET, buf : PSTR, len : i32, flags : SEND_RECV_FLAGS) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn recvfrom(s : SOCKET, buf : PSTR, len : i32, flags : i32, from : *mut SOCKADDR, fromlen : *mut i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn select(nfds : i32, readfds : *mut FD_SET, writefds : *mut FD_SET, exceptfds : *mut FD_SET, timeout : *const TIMEVAL) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn send(s : SOCKET, buf : PCSTR, len : i32, flags : SEND_RECV_FLAGS) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn sendto(s : SOCKET, buf : PCSTR, len : i32, flags : i32, to : *const SOCKADDR, tolen : i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn setsockopt(s : SOCKET, level : i32, optname : i32, optval : PCSTR, optlen : i32) -> i32); +windows_targets::link!("ws2_32.dll" "system" fn shutdown(s : SOCKET, how : WINSOCK_SHUTDOWN_HOW) -> i32); pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32; pub type ADDRESS_FAMILY = u16; #[repr(C)] @@ -3991,3 +3284,4 @@ pub struct XSAVE_FORMAT { pub Reserved4: [u8; 224], } // ignore-tidy-filelength +use super::windows_targets; diff --git a/library/std/src/sys/pal/windows/c/windows_targets.rs b/library/std/src/sys/pal/windows/c/windows_targets.rs new file mode 100644 index 0000000000000..cc3cc6e861194 --- /dev/null +++ b/library/std/src/sys/pal/windows/c/windows_targets.rs @@ -0,0 +1,15 @@ +pub macro link { + ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => ( + #[link(name = "kernel32")] + extern $abi { + $(#[link_name=$link_name])? + pub fn $($function)*; + } + ) +} + +#[link(name = "advapi32")] +#[link(name = "ntdll")] +#[link(name = "userenv")] +#[link(name = "ws2_32")] +extern "C" {} diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs index 690b60d1decca..10aeeac07ea2e 100644 --- a/library/std/src/sys/pal/windows/stdio.rs +++ b/library/std/src/sys/pal/windows/stdio.rs @@ -232,13 +232,7 @@ fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result { debug_assert!(data.len() < u32::MAX as usize); let mut written = 0; cvt(unsafe { - c::WriteConsoleW( - handle, - data.as_ptr() as c::LPCVOID, - data.len() as u32, - &mut written, - ptr::null_mut(), - ) + c::WriteConsoleW(handle, data.as_ptr(), data.len() as u32, &mut written, ptr::null_mut()) })?; Ok(written as usize) } diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index ebf3082fb4f24..882d3d6352526 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.57.0" +version = "0.58.0" diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index c8913910bd6e7..fd21e7a86b002 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -17,6 +17,7 @@ fn main() -> Result<(), Box> { let mut f = std::fs::File::options().append(true).open("windows_sys.rs")?; writeln!(&mut f, "// ignore-tidy-filelength")?; + writeln!(&mut f, "use super::windows_targets;")?; Ok(()) } From 14f4ed2ba3a86bbb2bca77690d036316c3d21fc8 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 4 Jul 2024 13:27:24 +0000 Subject: [PATCH 14/63] Add comments to windows_targets.rs --- library/std/src/sys/pal/windows/c/windows_targets.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/std/src/sys/pal/windows/c/windows_targets.rs b/library/std/src/sys/pal/windows/c/windows_targets.rs index cc3cc6e861194..56c563462d366 100644 --- a/library/std/src/sys/pal/windows/c/windows_targets.rs +++ b/library/std/src/sys/pal/windows/c/windows_targets.rs @@ -1,5 +1,14 @@ +//! Provides the `link!` macro used by the generated windows bindings. +//! +//! This is a simple wrapper around an `extern` block with a `#[link]` attribute. +//! It's very roughly equivalent to the windows-targets crate. + pub macro link { ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => ( + // Note: the windows-targets crate uses a pre-built Windows.lib import library which we don't + // have in this repo. So instead we always link kernel32.lib and add the rest of the import + // libraries below by using an empty extern block. This works because extern blocks are not + // connected to the library given in the #[link] attribute. #[link(name = "kernel32")] extern $abi { $(#[link_name=$link_name])? From 0adb82528fa00467a3f14a282f4581bb30f91aba Mon Sep 17 00:00:00 2001 From: mu001999 Date: Thu, 4 Jul 2024 22:05:00 +0800 Subject: [PATCH 15/63] Improve dead code analysis --- compiler/rustc_passes/src/dead.rs | 40 ++++++------------- library/core/src/default.rs | 1 - .../salsa-macros/src/database_storage.rs | 8 ---- tests/ui-fulldeps/deriving-global.rs | 3 ++ tests/ui-fulldeps/deriving-hygiene.rs | 1 + .../ui/const-generics/issues/issue-86535-2.rs | 1 + tests/ui/const-generics/issues/issue-86535.rs | 1 + .../impl-trait/extra-impl-in-trait-impl.fixed | 2 + .../ui/impl-trait/extra-impl-in-trait-impl.rs | 2 + .../extra-impl-in-trait-impl.stderr | 8 ++-- tests/ui/lint/dead-code/issue-59003.rs | 2 +- .../lint-unused-adt-appeared-in-pattern.rs | 37 +++++++++++++++++ ...lint-unused-adt-appeared-in-pattern.stderr | 20 ++++++++++ .../not-lint-used-adt-appeared-in-pattern.rs | 32 +++++++++++++++ ...sed-adt-impl-pub-trait-with-assoc-const.rs | 36 +++++++++++------ ...adt-impl-pub-trait-with-assoc-const.stderr | 24 +++++++++-- .../dead-code/unused-struct-derive-default.rs | 1 + .../unused-struct-derive-default.stderr | 1 - tests/ui/parser/issues/issue-105366.fixed | 1 + tests/ui/parser/issues/issue-105366.rs | 1 + tests/ui/parser/issues/issue-105366.stderr | 2 +- 21 files changed, 164 insertions(+), 60 deletions(-) create mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs create mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr create mode 100644 tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index bbd586386dd27..0d55a6777647d 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -277,7 +277,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { pats: &[hir::PatField<'_>], ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => adt.variant_of_res(res), + ty::Adt(adt, _) => { + self.check_def_id(adt.did()); + adt.variant_of_res(res) + } _ => span_bug!(lhs.span, "non-ADT in struct pattern"), }; for pat in pats { @@ -297,7 +300,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { dotdot: hir::DotDotPos, ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => adt.variant_of_res(res), + ty::Adt(adt, _) => { + self.check_def_id(adt.did()); + adt.variant_of_res(res) + } _ => { self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern"); return; @@ -402,31 +408,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return false; } - // don't ignore impls for Enums and pub Structs whose methods don't have self receiver, - // cause external crate may call such methods to construct values of these types - if let Some(local_impl_of) = impl_of.as_local() - && let Some(local_def_id) = def_id.as_local() - && let Some(fn_sig) = - self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) - && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) - && let TyKind::Path(hir::QPath::Resolved(_, path)) = - self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind - && let Res::Def(def_kind, did) = path.res - { - match def_kind { - // for example, #[derive(Default)] pub struct T(i32); - // external crate can call T::default() to construct T, - // so that don't ignore impl Default for pub Enum and Structs - DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => { - return false; - } - // don't ignore impl Default for Enums, - // cause we don't know which variant is constructed - DefKind::Enum => return false, - _ => (), - }; - } - if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { @@ -690,6 +671,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.handle_field_pattern_match(pat, res, fields); } PatKind::Path(ref qpath) => { + if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() { + self.check_def_id(adt.did()); + } let res = self.typeck_results().qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -845,7 +829,7 @@ fn check_item<'tcx>( // mark the method live if the self_ty is public, // or the method is public and may construct self if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + && (ty_and_all_fields_are_public || (ty_is_public && may_construct_self)) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 5cacedcb241a5..4524b352ec817 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -103,7 +103,6 @@ use crate::ascii::Char as AsciiChar; /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/database_storage.rs b/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/database_storage.rs index 14238e2fed55d..f16d814b9f038 100644 --- a/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/database_storage.rs +++ b/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/database_storage.rs @@ -241,11 +241,3 @@ impl Parse for QueryGroup { Ok(QueryGroup { group_path }) } } - -struct Nothing; - -impl Parse for Nothing { - fn parse(_input: ParseStream<'_>) -> syn::Result { - Ok(Nothing) - } -} diff --git a/tests/ui-fulldeps/deriving-global.rs b/tests/ui-fulldeps/deriving-global.rs index 7783010be441d..0ba149c9ad654 100644 --- a/tests/ui-fulldeps/deriving-global.rs +++ b/tests/ui-fulldeps/deriving-global.rs @@ -17,18 +17,21 @@ mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) // cause errors about unrecognised module `std` (or `extra`) + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] enum A { A1(usize), A2(isize), } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct B { x: usize, y: isize, } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct C(usize, isize); } diff --git a/tests/ui-fulldeps/deriving-hygiene.rs b/tests/ui-fulldeps/deriving-hygiene.rs index a3a6f9e022ebb..f948d6ac544e5 100644 --- a/tests/ui-fulldeps/deriving-hygiene.rs +++ b/tests/ui-fulldeps/deriving-hygiene.rs @@ -20,6 +20,7 @@ pub const s: u8 = 1; pub const state: u8 = 1; pub const cmp: u8 = 1; +#[allow(dead_code)] #[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)] struct Foo {} diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs index 1ba3b6d5347c0..bd9431dbc85b5 100644 --- a/tests/ui/const-generics/issues/issue-86535-2.rs +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -7,6 +7,7 @@ pub trait Foo { fn foo() where [(); Self::ASSOC_C]:; } +#[allow(dead_code)] struct Bar; impl Foo for Bar { const ASSOC_C: usize = 3; diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs index dd6bc88ad198f..cd9934a4a9971 100644 --- a/tests/ui/const-generics/issues/issue-86535.rs +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -2,6 +2,7 @@ #![feature(adt_const_params, generic_const_exprs)] #![allow(incomplete_features, unused_variables)] +#[allow(dead_code)] struct F; impl X for F<{ S }> { const W: usize = 3; diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed index 886fc1d005802..3c4499f017337 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed @@ -1,6 +1,8 @@ //@ run-rustfix +#[allow(dead_code)] struct S(T); +#[allow(dead_code)] struct S2; impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs index f3271993867cb..ac0783295242e 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs @@ -1,6 +1,8 @@ //@ run-rustfix +#[allow(dead_code)] struct S(T); +#[allow(dead_code)] struct S2; impl impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr index 5aafc8b64d4ff..91c7da5a04fb4 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr @@ -1,23 +1,23 @@ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:6:18 + --> $DIR/extra-impl-in-trait-impl.rs:8:18 | LL | impl impl Default for S { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:6:18 + --> $DIR/extra-impl-in-trait-impl.rs:8:18 | LL | impl impl Default for S { | ^^^^^^^^^^^^ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:12:6 + --> $DIR/extra-impl-in-trait-impl.rs:14:6 | LL | impl impl Default for S2 { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:12:6 + --> $DIR/extra-impl-in-trait-impl.rs:14:6 | LL | impl impl Default for S2 { | ^^^^^^^^^^^^ diff --git a/tests/ui/lint/dead-code/issue-59003.rs b/tests/ui/lint/dead-code/issue-59003.rs index e3dcaca577889..319cf2db1495f 100644 --- a/tests/ui/lint/dead-code/issue-59003.rs +++ b/tests/ui/lint/dead-code/issue-59003.rs @@ -4,8 +4,8 @@ #![deny(dead_code)] +#[allow(dead_code)] struct Foo { - #[allow(dead_code)] inner: u32, } diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs new file mode 100644 index 0000000000000..25777438456b6 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs @@ -0,0 +1,37 @@ +#![deny(dead_code)] + +struct Foo(u8); //~ ERROR struct `Foo` is never constructed + +enum Bar { //~ ERROR enum `Bar` is never used + Var1(u8), + Var2(u8), +} + +pub trait Tr1 { + fn f1() -> Self; +} + +impl Tr1 for Foo { + fn f1() -> Foo { + let f = Foo(0); + let Foo(tag) = f; + Foo(tag) + } +} + +impl Tr1 for Bar { + fn f1() -> Bar { + let b = Bar::Var1(0); + let b = if let Bar::Var1(_) = b { + Bar::Var1(0) + } else { + Bar::Var2(0) + }; + match b { + Bar::Var1(_) => Bar::Var2(0), + Bar::Var2(_) => Bar::Var1(0), + } + } +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr new file mode 100644 index 0000000000000..7c1a4b4597755 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr @@ -0,0 +1,20 @@ +error: struct `Foo` is never constructed + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8 + | +LL | struct Foo(u8); + | ^^^ + | +note: the lint level is defined here + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: enum `Bar` is never used + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6 + | +LL | enum Bar { + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs new file mode 100644 index 0000000000000..43a2e43190433 --- /dev/null +++ b/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs @@ -0,0 +1,32 @@ +//@ check-pass + +#![deny(dead_code)] + +#[repr(u8)] +#[derive(Copy, Clone, Debug)] +pub enum RecordField { + Target = 1, + Level, + Module, + File, + Line, + NumArgs, +} + +unsafe trait Pod {} + +#[repr(transparent)] +struct RecordFieldWrapper(RecordField); + +unsafe impl Pod for RecordFieldWrapper {} + +fn try_read(buf: &[u8]) -> T { + unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) } +} + +pub fn foo(buf: &[u8]) -> RecordField { + let RecordFieldWrapper(tag) = try_read(buf); + tag +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index bf2fc243e8194..658cc3d6c613a 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -1,8 +1,9 @@ #![deny(dead_code)] struct T1; //~ ERROR struct `T1` is never constructed -pub struct T2(i32); //~ ERROR struct `T2` is never constructed -struct T3; +struct T2; //~ ERROR struct `T2` is never constructed +pub struct T3(i32); //~ ERROR struct `T3` is never constructed +pub struct T4(i32); //~ ERROR field `0` is never read trait Trait1 { //~ ERROR trait `Trait1` is never used const UNUSED: i32; @@ -11,13 +12,13 @@ trait Trait1 { //~ ERROR trait `Trait1` is never used } pub trait Trait2 { - const USED: i32; - fn used(&self) {} + const MAY_USED: i32; + fn may_used(&self) {} } pub trait Trait3 { - const USED: i32; - fn construct_self() -> Self; + const MAY_USED: i32; + fn may_used() -> Self; } impl Trait1 for T1 { @@ -30,23 +31,34 @@ impl Trait1 for T1 { impl Trait1 for T2 { const UNUSED: i32 = 0; fn construct_self() -> Self { - T2(0) + Self } } impl Trait2 for T1 { - const USED: i32 = 0; + const MAY_USED: i32 = 0; } impl Trait2 for T2 { - const USED: i32 = 0; + const MAY_USED: i32 = 0; } -impl Trait3 for T3 { - const USED: i32 = 0; - fn construct_self() -> Self { +impl Trait2 for T3 { + const MAY_USED: i32 = 0; +} + +impl Trait3 for T2 { + const MAY_USED: i32 = 0; + fn may_used() -> Self { Self } } +impl Trait3 for T4 { + const MAY_USED: i32 = 0; + fn may_used() -> Self { + T4(0) + } +} + fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 174096d939883..08c7a5cb4b062 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -11,16 +11,32 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: struct `T2` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:8 | -LL | pub struct T2(i32); +LL | struct T2; + | ^^ + +error: struct `T3` is never constructed + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:12 + | +LL | pub struct T3(i32); | ^^ +error: field `0` is never read + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:6:15 + | +LL | pub struct T4(i32); + | -- ^^^ + | | + | field in this struct + | + = help: consider removing this field + error: trait `Trait1` is never used - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:8:7 | LL | trait Trait1 { | ^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs index 330ad32dd5709..f20b7cb66ee51 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.rs +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -22,4 +22,5 @@ pub struct T2 { fn main() { let _x: Used = Default::default(); + let _e: E = Default::default(); } diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr index bbb0bd7be7064..7422f9a39f312 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -4,7 +4,6 @@ error: struct `T` is never constructed LL | struct T; | ^ | - = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/unused-struct-derive-default.rs:1:9 | diff --git a/tests/ui/parser/issues/issue-105366.fixed b/tests/ui/parser/issues/issue-105366.fixed index 7157b647524dd..95419dc07f2cc 100644 --- a/tests/ui/parser/issues/issue-105366.fixed +++ b/tests/ui/parser/issues/issue-105366.fixed @@ -1,5 +1,6 @@ //@ run-rustfix +#[allow(dead_code)] struct Foo; impl From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.rs b/tests/ui/parser/issues/issue-105366.rs index dc3cb8b343d32..3278b73799125 100644 --- a/tests/ui/parser/issues/issue-105366.rs +++ b/tests/ui/parser/issues/issue-105366.rs @@ -1,5 +1,6 @@ //@ run-rustfix +#[allow(dead_code)] struct Foo; fn From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr index 18c04dfaf2088..195305a2ec889 100644 --- a/tests/ui/parser/issues/issue-105366.stderr +++ b/tests/ui/parser/issues/issue-105366.stderr @@ -1,5 +1,5 @@ error: you might have meant to write `impl` instead of `fn` - --> $DIR/issue-105366.rs:5:1 + --> $DIR/issue-105366.rs:6:1 | LL | fn From for Foo { | ^^ From 40cad01f2f9d830aeb798057a0aeb761316ebf28 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 19 Jun 2024 13:25:29 -0400 Subject: [PATCH 16/63] rewrite and rename include_bytes_deps to rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - .../input.bin | 0 .../input.md | 0 .../input.txt | 0 .../main.rs | 0 tests/run-make/include-bytes-deps/rmake.rs | 15 +++++++++++++++ tests/run-make/include_bytes_deps/Makefile | 7 ------- 7 files changed, 15 insertions(+), 8 deletions(-) rename tests/run-make/{include_bytes_deps => include-bytes-deps}/input.bin (100%) rename tests/run-make/{include_bytes_deps => include-bytes-deps}/input.md (100%) rename tests/run-make/{include_bytes_deps => include-bytes-deps}/input.txt (100%) rename tests/run-make/{include_bytes_deps => include-bytes-deps}/main.rs (100%) create mode 100644 tests/run-make/include-bytes-deps/rmake.rs delete mode 100644 tests/run-make/include_bytes_deps/Makefile diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2da4e476e9016..6d13559818669 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -46,7 +46,6 @@ run-make/fmt-write-bloat/Makefile run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/foreign-rust-exceptions/Makefile -run-make/include_bytes_deps/Makefile run-make/incr-add-rust-src-component/Makefile run-make/incr-foreign-head-span/Makefile run-make/interdependent-c-libraries/Makefile diff --git a/tests/run-make/include_bytes_deps/input.bin b/tests/run-make/include-bytes-deps/input.bin similarity index 100% rename from tests/run-make/include_bytes_deps/input.bin rename to tests/run-make/include-bytes-deps/input.bin diff --git a/tests/run-make/include_bytes_deps/input.md b/tests/run-make/include-bytes-deps/input.md similarity index 100% rename from tests/run-make/include_bytes_deps/input.md rename to tests/run-make/include-bytes-deps/input.md diff --git a/tests/run-make/include_bytes_deps/input.txt b/tests/run-make/include-bytes-deps/input.txt similarity index 100% rename from tests/run-make/include_bytes_deps/input.txt rename to tests/run-make/include-bytes-deps/input.txt diff --git a/tests/run-make/include_bytes_deps/main.rs b/tests/run-make/include-bytes-deps/main.rs similarity index 100% rename from tests/run-make/include_bytes_deps/main.rs rename to tests/run-make/include-bytes-deps/main.rs diff --git a/tests/run-make/include-bytes-deps/rmake.rs b/tests/run-make/include-bytes-deps/rmake.rs new file mode 100644 index 0000000000000..6ca29fa664c98 --- /dev/null +++ b/tests/run-make/include-bytes-deps/rmake.rs @@ -0,0 +1,15 @@ +// include_bytes! and include_str! in `main.rs` +// should register the included file as of #24423, +// and this test checks that this is still the case. +// See https://github.com/rust-lang/rust/pull/24423 + +//FIXME(Oneirical): check if works without ignore freebsd + +use run_make_support::{invalid_utf8_contains, rustc}; + +fn main() { + rustc().emit("dep-info").input("main.rs").run(); + invalid_utf8_contains("main.d", "input.txt"); + invalid_utf8_contains("main.d", "input.bin"); + invalid_utf8_contains("main.d", "input.md"); +} diff --git a/tests/run-make/include_bytes_deps/Makefile b/tests/run-make/include_bytes_deps/Makefile deleted file mode 100644 index 696dfd207bbff..0000000000000 --- a/tests/run-make/include_bytes_deps/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -# ignore-freebsd - -all: - $(RUSTC) --emit dep-info main.rs - $(CGREP) "input.txt" "input.bin" "input.md" < $(TMPDIR)/main.d From 73d7dc7f220c8e451defc1f3817b99ed70079a4e Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 19 Jun 2024 14:06:17 -0400 Subject: [PATCH 17/63] rewrite optimization-remarks-dir-pgo to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../optimization-remarks-dir-pgo/Makefile | 17 ----------------- .../optimization-remarks-dir-pgo/rmake.rs | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 18 deletions(-) delete mode 100644 tests/run-make/optimization-remarks-dir-pgo/Makefile create mode 100644 tests/run-make/optimization-remarks-dir-pgo/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 6d13559818669..e26a1326f443a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -101,7 +101,6 @@ run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile run-make/no-duplicate-libs/Makefile run-make/obey-crate-type-flag/Makefile -run-make/optimization-remarks-dir-pgo/Makefile run-make/optimization-remarks-dir/Makefile run-make/output-type-permutations/Makefile run-make/panic-abort-eh_frame/Makefile diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile deleted file mode 100644 index 57ffd6e70f00b..0000000000000 --- a/tests/run-make/optimization-remarks-dir-pgo/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# needs-profiler-support -# ignore-cross-compile - -include ../tools.mk - -PROFILE_DIR=$(TMPDIR)/profiles - -check_hotness: - $(RUSTC) -Cprofile-generate="$(TMPDIR)"/profdata -O foo.rs -o$(TMPDIR)/foo - $(TMPDIR)/foo - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/merged.profdata \ - "$(TMPDIR)"/profdata/*.profraw - $(RUSTC) -Cprofile-use=$(TMPDIR)/merged.profdata -O foo.rs -Cremark=all -Zremark-dir=$(PROFILE_DIR) - - # Check that PGO hotness is included in the remark files - cat $(PROFILE_DIR)/*.opt.yaml | $(CGREP) -e "Hotness" diff --git a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs new file mode 100644 index 0000000000000..678d9c2de8b40 --- /dev/null +++ b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs @@ -0,0 +1,19 @@ +// This test checks the -Zremark-dir flag, which writes LLVM +// optimization remarks to the YAML format. When using PGO (Profile +// Guided Optimization), the Hotness attribute should be included in +// the output remark files. +// See https://github.com/rust-lang/rust/pull/114439 + +//@ needs-profiler-support +//@ ignore-cross-compile + +use run_make_support::{run, llvm_profdata, rustc, invalid_utf8_contains}; + +fn main() { + rustc().profile_generate("profdata").opt().input("foo.rs").output("foo").run(); + run("foo"); + llvm_profdata().merge().output("merged.profdata").input("profdata/default_15907418011457399462_0.profraw").run(); + rustc().profile_use("merged.profdata").opt().input("foo.rs").arg("-Cremark=all").arg("-Zremark-dir=profiles").run(); + // Check that PGO hotness is included in the remark files + invalid_utf8_contains("profiles/foo.cba44757bc0621b9-cgu.0.opt.opt.yaml", "Hotness"); +} From 651f02363d96ce75ae297d70104153a8b3b0981f Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 19 Jun 2024 14:30:47 -0400 Subject: [PATCH 18/63] rewrite optimization-remarks-dir to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../optimization-remarks-dir-pgo/rmake.rs | 16 +++++++++--- .../optimization-remarks-dir/Makefile | 12 --------- .../optimization-remarks-dir/rmake.rs | 26 +++++++++++++++++++ 4 files changed, 39 insertions(+), 16 deletions(-) delete mode 100644 tests/run-make/optimization-remarks-dir/Makefile create mode 100644 tests/run-make/optimization-remarks-dir/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index e26a1326f443a..4516bf86e2b35 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -101,7 +101,6 @@ run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile run-make/no-duplicate-libs/Makefile run-make/obey-crate-type-flag/Makefile -run-make/optimization-remarks-dir/Makefile run-make/output-type-permutations/Makefile run-make/panic-abort-eh_frame/Makefile run-make/pass-linker-flags-flavor/Makefile diff --git a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs index 678d9c2de8b40..e527dcb0befa5 100644 --- a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs +++ b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs @@ -7,13 +7,23 @@ //@ needs-profiler-support //@ ignore-cross-compile -use run_make_support::{run, llvm_profdata, rustc, invalid_utf8_contains}; +use run_make_support::{invalid_utf8_contains, llvm_profdata, run, rustc}; fn main() { rustc().profile_generate("profdata").opt().input("foo.rs").output("foo").run(); run("foo"); - llvm_profdata().merge().output("merged.profdata").input("profdata/default_15907418011457399462_0.profraw").run(); - rustc().profile_use("merged.profdata").opt().input("foo.rs").arg("-Cremark=all").arg("-Zremark-dir=profiles").run(); + llvm_profdata() + .merge() + .output("merged.profdata") + .input("profdata/default_15907418011457399462_0.profraw") + .run(); + rustc() + .profile_use("merged.profdata") + .opt() + .input("foo.rs") + .arg("-Cremark=all") + .arg("-Zremark-dir=profiles") + .run(); // Check that PGO hotness is included in the remark files invalid_utf8_contains("profiles/foo.cba44757bc0621b9-cgu.0.opt.opt.yaml", "Hotness"); } diff --git a/tests/run-make/optimization-remarks-dir/Makefile b/tests/run-make/optimization-remarks-dir/Makefile deleted file mode 100644 index a8342c8ad14d5..0000000000000 --- a/tests/run-make/optimization-remarks-dir/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk - -PROFILE_DIR=$(TMPDIR)/profiles - -all: check_inline check_filter - -check_inline: - $(RUSTC) -O foo.rs --crate-type=lib -Cremark=all -Zremark-dir=$(PROFILE_DIR) - cat $(PROFILE_DIR)/*.opt.yaml | $(CGREP) -e "inline" -check_filter: - $(RUSTC) -O foo.rs --crate-type=lib -Cremark=foo -Zremark-dir=$(PROFILE_DIR) - cat $(PROFILE_DIR)/*.opt.yaml | $(CGREP) -e -v "inline" diff --git a/tests/run-make/optimization-remarks-dir/rmake.rs b/tests/run-make/optimization-remarks-dir/rmake.rs new file mode 100644 index 0000000000000..d0c4ccd72d13a --- /dev/null +++ b/tests/run-make/optimization-remarks-dir/rmake.rs @@ -0,0 +1,26 @@ +// In this test, the function `bar` has #[inline(never)] and the function `foo` +// does not. This test outputs LLVM optimization remarks twice - first for all +// functions (including `bar`, and the `inline` mention), and then for only `foo` +// (should not have the `inline` mention). +// See https://github.com/rust-lang/rust/pull/113040 + +use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rustc}; + +fn main() { + rustc() + .opt() + .input("foo.rs") + .crate_type("lib") + .arg("-Cremark=all") + .arg("-Zremark-dir=profiles_all") + .run(); + invalid_utf8_contains("profiles_all/foo.5be5606e1f6aa79b-cgu.0.opt.opt.yaml", "inline"); + rustc() + .opt() + .input("foo.rs") + .crate_type("lib") + .arg("-Cremark=foo") + .arg("-Zremark-dir=profiles_foo") + .run(); + invalid_utf8_not_contains("profiles_foo/foo.5be5606e1f6aa79b-cgu.0.opt.opt.yaml", "inline"); +} From 5e23dfea9dee65b8a5b7ed54354b4c46d38f12ca Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 19 Jun 2024 14:55:22 -0400 Subject: [PATCH 19/63] rewrite and rename issue-40535 to rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/issue-40535/Makefile | 13 ------------- .../bar.rs | 0 .../baz.rs | 0 .../foo.rs | 0 tests/run-make/metadata-only-crate-no-ice/rmake.rs | 14 ++++++++++++++ 6 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/issue-40535/Makefile rename tests/run-make/{issue-40535 => metadata-only-crate-no-ice}/bar.rs (100%) rename tests/run-make/{issue-40535 => metadata-only-crate-no-ice}/baz.rs (100%) rename tests/run-make/{issue-40535 => metadata-only-crate-no-ice}/foo.rs (100%) create mode 100644 tests/run-make/metadata-only-crate-no-ice/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 4516bf86e2b35..4fbfa442fcc54 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -63,7 +63,6 @@ run-make/issue-33329/Makefile run-make/issue-35164/Makefile run-make/issue-36710/Makefile run-make/issue-37839/Makefile -run-make/issue-40535/Makefile run-make/issue-47551/Makefile run-make/issue-69368/Makefile run-make/issue-83045/Makefile diff --git a/tests/run-make/issue-40535/Makefile b/tests/run-make/issue-40535/Makefile deleted file mode 100644 index 155c88252144d..0000000000000 --- a/tests/run-make/issue-40535/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -include ../tools.mk - -# The ICE occurred in the following situation: -# * `foo` declares `extern crate bar, baz`, depends only on `bar` (forgetting `baz` in `Cargo.toml`) -# * `bar` declares and depends on `extern crate baz` -# * All crates built in metadata-only mode (`cargo check`) -all: - # cc https://github.com/rust-lang/rust/issues/40623 - $(RUSTC) baz.rs --emit=metadata - $(RUSTC) bar.rs --emit=metadata --extern baz=$(TMPDIR)/libbaz.rmeta - $(RUSTC) foo.rs --emit=metadata --extern bar=$(TMPDIR)/libbar.rmeta 2>&1 | \ - $(CGREP) -v "unexpectedly panicked" - # ^ Succeeds if it doesn't find the ICE message diff --git a/tests/run-make/issue-40535/bar.rs b/tests/run-make/metadata-only-crate-no-ice/bar.rs similarity index 100% rename from tests/run-make/issue-40535/bar.rs rename to tests/run-make/metadata-only-crate-no-ice/bar.rs diff --git a/tests/run-make/issue-40535/baz.rs b/tests/run-make/metadata-only-crate-no-ice/baz.rs similarity index 100% rename from tests/run-make/issue-40535/baz.rs rename to tests/run-make/metadata-only-crate-no-ice/baz.rs diff --git a/tests/run-make/issue-40535/foo.rs b/tests/run-make/metadata-only-crate-no-ice/foo.rs similarity index 100% rename from tests/run-make/issue-40535/foo.rs rename to tests/run-make/metadata-only-crate-no-ice/foo.rs diff --git a/tests/run-make/metadata-only-crate-no-ice/rmake.rs b/tests/run-make/metadata-only-crate-no-ice/rmake.rs new file mode 100644 index 0000000000000..825da12cfd1bc --- /dev/null +++ b/tests/run-make/metadata-only-crate-no-ice/rmake.rs @@ -0,0 +1,14 @@ +// In a dependency hierarchy, metadata-only crates could cause an Internal +// Compiler Error (ICE) due to a compiler bug - not correctly fetching sources for +// metadata-only crates. This test is a minimal reproduction of a program that triggered +// this bug, and checks that no ICE occurs. +// See https://github.com/rust-lang/rust/issues/40535 + +use run_make_support::rustc; + +fn main() { + rustc().input("baz.rs").emit("metadata").run(); + rustc().input("bar.rs").emit("metadata").extern_("baz", "libbaz.rmeta").run(); + // There should be no internal compiler error message. + rustc().input("foo.rs").emit("metadata").extern_("bar", "libbaz.rmeta").run().assert_stderr_not_contains("unexpectedly panicked"); +} From b167a15d64c0777afa6b90d7883368c629049a16 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 19 Jun 2024 15:46:27 -0400 Subject: [PATCH 20/63] rewrite rmeta-preferred to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/include-bytes-deps/rmake.rs | 2 -- .../metadata-only-crate-no-ice/rmake.rs | 4 ++-- tests/run-make/rmeta-preferred/Makefile | 16 ---------------- tests/run-make/rmeta-preferred/rmake.rs | 18 ++++++++++++++++++ 5 files changed, 20 insertions(+), 21 deletions(-) delete mode 100644 tests/run-make/rmeta-preferred/Makefile create mode 100644 tests/run-make/rmeta-preferred/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 4fbfa442fcc54..70c1b055c6e40 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -132,7 +132,6 @@ run-make/return-non-c-like-enum-from-c/Makefile run-make/rlib-format-packed-bundled-libs-2/Makefile run-make/rlib-format-packed-bundled-libs-3/Makefile run-make/rlib-format-packed-bundled-libs/Makefile -run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile run-make/sanitizer-cdylib-link/Makefile run-make/sanitizer-dylib-link/Makefile diff --git a/tests/run-make/include-bytes-deps/rmake.rs b/tests/run-make/include-bytes-deps/rmake.rs index 6ca29fa664c98..ea371ddae5675 100644 --- a/tests/run-make/include-bytes-deps/rmake.rs +++ b/tests/run-make/include-bytes-deps/rmake.rs @@ -3,8 +3,6 @@ // and this test checks that this is still the case. // See https://github.com/rust-lang/rust/pull/24423 -//FIXME(Oneirical): check if works without ignore freebsd - use run_make_support::{invalid_utf8_contains, rustc}; fn main() { diff --git a/tests/run-make/metadata-only-crate-no-ice/rmake.rs b/tests/run-make/metadata-only-crate-no-ice/rmake.rs index 825da12cfd1bc..e6f852fca413a 100644 --- a/tests/run-make/metadata-only-crate-no-ice/rmake.rs +++ b/tests/run-make/metadata-only-crate-no-ice/rmake.rs @@ -9,6 +9,6 @@ use run_make_support::rustc; fn main() { rustc().input("baz.rs").emit("metadata").run(); rustc().input("bar.rs").emit("metadata").extern_("baz", "libbaz.rmeta").run(); - // There should be no internal compiler error message. - rustc().input("foo.rs").emit("metadata").extern_("bar", "libbaz.rmeta").run().assert_stderr_not_contains("unexpectedly panicked"); + // There should be no internal compiler error. + rustc().input("foo.rs").emit("metadata").extern_("bar", "libbaz.rmeta").run(); } diff --git a/tests/run-make/rmeta-preferred/Makefile b/tests/run-make/rmeta-preferred/Makefile deleted file mode 100644 index 3bf12cced29ab..0000000000000 --- a/tests/run-make/rmeta-preferred/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test that using rlibs and rmeta dep crates work together. Specifically, that -# there can be both an rmeta and an rlib file and rustc will prefer the rmeta -# file. -# -# This behavior is simply making sure this doesn't accidentally change; in this -# case we want to make sure that the rlib isn't being used as that would cause -# bugs in -Zbinary-dep-depinfo (see #68298). - -all: - $(RUSTC) rmeta_aux.rs --crate-type=rlib --emit link,metadata - $(RUSTC) lib.rs --crate-type=rlib --emit dep-info -Zbinary-dep-depinfo - $(CGREP) "librmeta_aux.rmeta" < $(TMPDIR)/lib.d - $(CGREP) -v "librmeta_aux.rlib" < $(TMPDIR)/lib.d diff --git a/tests/run-make/rmeta-preferred/rmake.rs b/tests/run-make/rmeta-preferred/rmake.rs new file mode 100644 index 0000000000000..09cba06e2f509 --- /dev/null +++ b/tests/run-make/rmeta-preferred/rmake.rs @@ -0,0 +1,18 @@ +// This test compiles `lib.rs`'s dependency, `rmeta_aux.rs`, as both an rlib +// and an rmeta crate. By default, rustc should give the metadata crate (rmeta) +// precedence over the rust-lib (rlib). This test inspects the contents of the binary +// and that the correct (rmeta) crate was used. +// rlibs being preferred could indicate a resurgence of the -Zbinary-dep-depinfo bug +// seen in #68298. +// See https://github.com/rust-lang/rust/pull/37681 + +//@ ignore-cross-compile + +use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rustc}; + +fn main() { + rustc().input("rmeta_aux.rs").crate_type("rlib").emit("link,metadata").run(); + rustc().input("lib.rs").crate_type("rlib").emit("dep-info").arg("-Zbinary-dep-depinfo").run(); + invalid_utf8_contains("lib.d", "librmeta_aux.rmeta"); + invalid_utf8_not_contains("lib.d", "librmeta_aux.rlib"); +} From 3ea36f5bb6845bc0c0737d174e49fd3ff9380708 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 20 Jun 2024 16:02:22 -0400 Subject: [PATCH 21/63] add shallow_find_files helper function to run-make-support --- src/tools/run-make-support/src/lib.rs | 34 +++++++++++++++++++ .../optimization-remarks-dir-pgo/rmake.rs | 26 ++++++++++---- .../optimization-remarks-dir/rmake.rs | 19 +++++++++-- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 9a180fe4ad19a..af5ae6a8e608c 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -261,6 +261,40 @@ pub fn test_while_readonly, F: FnOnce() + std::panic::UnwindSafe> success.unwrap(); } +/// Browse the directory `path` non-recursively and return all files which respect the parameters +/// outlined by `closure`. +#[track_caller] +pub fn shallow_find_files, F: Fn(&PathBuf) -> bool>( + path: P, + closure: F, +) -> Vec { + let mut matching_files = Vec::new(); + for entry in fs_wrapper::read_dir(path) { + let entry = entry.expect("failed to read directory entry."); + let path = entry.path(); + + if path.is_file() && closure(&path) { + matching_files.push(path); + } + } + matching_files +} + +/// Returns true if the filename at `path` starts with `prefix`. +pub fn has_prefix>(path: P, prefix: &str) -> bool { + path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().starts_with(prefix)) +} + +/// Returns true if the filename at `path` has the extension `extension`. +pub fn has_extension>(path: P, extension: &str) -> bool { + path.as_ref().extension().is_some_and(|ext| ext == extension) +} + +/// Returns true if the filename at `path` does not contain `expected`. +pub fn not_contains>(path: P, expected: &str) -> bool { + !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected)) +} + /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is /// available on the platform! #[track_caller] diff --git a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs index e527dcb0befa5..228c43cc5f18a 100644 --- a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs +++ b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs @@ -7,16 +7,20 @@ //@ needs-profiler-support //@ ignore-cross-compile -use run_make_support::{invalid_utf8_contains, llvm_profdata, run, rustc}; +use run_make_support::{ + has_extension, has_prefix, invalid_utf8_contains, llvm_profdata, run, rustc, shallow_find_files, +}; fn main() { rustc().profile_generate("profdata").opt().input("foo.rs").output("foo").run(); run("foo"); - llvm_profdata() - .merge() - .output("merged.profdata") - .input("profdata/default_15907418011457399462_0.profraw") - .run(); + // The profdata filename is a long sequence of numbers, fetch it by prefix and extension + // to keep the test working even if the filename changes. + let profdata_files = shallow_find_files("profdata", |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profdata_file = profdata_files.get(0).unwrap(); + llvm_profdata().merge().output("merged.profdata").input(profdata_file).run(); rustc() .profile_use("merged.profdata") .opt() @@ -25,5 +29,13 @@ fn main() { .arg("-Zremark-dir=profiles") .run(); // Check that PGO hotness is included in the remark files - invalid_utf8_contains("profiles/foo.cba44757bc0621b9-cgu.0.opt.opt.yaml", "Hotness"); + let remark_files = shallow_find_files("profiles", |path| { + has_prefix(path, "foo") && has_extension(path, "yaml") + }); + assert!(!remark_files.is_empty()); + for file in remark_files { + if !file.to_str().unwrap().contains("codegen") { + invalid_utf8_contains(file, "Hotness") + }; + } } diff --git a/tests/run-make/optimization-remarks-dir/rmake.rs b/tests/run-make/optimization-remarks-dir/rmake.rs index d0c4ccd72d13a..afcb8c3e3ebdb 100644 --- a/tests/run-make/optimization-remarks-dir/rmake.rs +++ b/tests/run-make/optimization-remarks-dir/rmake.rs @@ -4,7 +4,10 @@ // (should not have the `inline` mention). // See https://github.com/rust-lang/rust/pull/113040 -use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rustc}; +use run_make_support::{ + has_extension, has_prefix, invalid_utf8_contains, invalid_utf8_not_contains, not_contains, + rustc, shallow_find_files, +}; fn main() { rustc() @@ -14,7 +17,12 @@ fn main() { .arg("-Cremark=all") .arg("-Zremark-dir=profiles_all") .run(); - invalid_utf8_contains("profiles_all/foo.5be5606e1f6aa79b-cgu.0.opt.opt.yaml", "inline"); + let all_remark_files = shallow_find_files("profiles_all", |path| { + has_prefix(path, "foo") && has_extension(path, "yaml") && not_contains(path, "codegen") + }); + for file in all_remark_files { + invalid_utf8_contains(file, "inline") + } rustc() .opt() .input("foo.rs") @@ -22,5 +30,10 @@ fn main() { .arg("-Cremark=foo") .arg("-Zremark-dir=profiles_foo") .run(); - invalid_utf8_not_contains("profiles_foo/foo.5be5606e1f6aa79b-cgu.0.opt.opt.yaml", "inline"); + let foo_remark_files = shallow_find_files("profiles_foo", |path| { + has_prefix(path, "foo") && has_extension(path, "yaml") + }); + for file in foo_remark_files { + invalid_utf8_not_contains(file, "inline") + } } From eb19e8106b5828085a46aa0b86206459c293fa70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 4 Jul 2024 23:44:10 +0200 Subject: [PATCH 22/63] crashes: add latest --- tests/crashes/126896.rs | 17 +++++++++++++++++ tests/crashes/126939.rs | 21 +++++++++++++++++++++ tests/crashes/126942.rs | 11 +++++++++++ tests/crashes/126944.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/crashes/126966.rs | 29 +++++++++++++++++++++++++++++ tests/crashes/126969.rs | 9 +++++++++ tests/crashes/126982.rs | 18 ++++++++++++++++++ tests/crashes/127222.rs | 3 +++ tests/crashes/127266.rs | 17 +++++++++++++++++ tests/crashes/127299.rs | 12 ++++++++++++ tests/crashes/127304.rs | 20 ++++++++++++++++++++ tests/crashes/127332.rs | 9 +++++++++ 12 files changed, 204 insertions(+) create mode 100644 tests/crashes/126896.rs create mode 100644 tests/crashes/126939.rs create mode 100644 tests/crashes/126942.rs create mode 100644 tests/crashes/126944.rs create mode 100644 tests/crashes/126966.rs create mode 100644 tests/crashes/126969.rs create mode 100644 tests/crashes/126982.rs create mode 100644 tests/crashes/127222.rs create mode 100644 tests/crashes/127266.rs create mode 100644 tests/crashes/127299.rs create mode 100644 tests/crashes/127304.rs create mode 100644 tests/crashes/127332.rs diff --git a/tests/crashes/126896.rs b/tests/crashes/126896.rs new file mode 100644 index 0000000000000..35bf9d5207ac1 --- /dev/null +++ b/tests/crashes/126896.rs @@ -0,0 +1,17 @@ +//@ known-bug: rust-lang/rust#126896 +//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes + +#![feature(type_alias_impl_trait)] +type Two<'a, 'b> = impl std::fmt::Debug; + +fn set(x: &mut isize) -> isize { + *x +} + +fn d(x: Two) { + let c1 = || set(x); + c1; +} + +fn main() { +} diff --git a/tests/crashes/126939.rs b/tests/crashes/126939.rs new file mode 100644 index 0000000000000..1edf748460604 --- /dev/null +++ b/tests/crashes/126939.rs @@ -0,0 +1,21 @@ +//@ known-bug: rust-lang/rust#126939 + +struct MySlice(bool, T); +type MySliceBool = MySlice<[bool]>; + +use std::mem; + +struct P2 { + a: T, + b: MySliceBool, +} + +macro_rules! check { + ($t:ty, $align:expr) => ({ + assert_eq!(mem::align_of::<$t>(), $align); + }); +} + +pub fn main() { + check!(P2, 1); +} diff --git a/tests/crashes/126942.rs b/tests/crashes/126942.rs new file mode 100644 index 0000000000000..e4adc8fab287e --- /dev/null +++ b/tests/crashes/126942.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#126942 +struct Thing; + +pub trait Every { + type Assoc; +} +impl Every for Thing { + type Assoc = T; +} + +static I: ::Assoc = 3; diff --git a/tests/crashes/126944.rs b/tests/crashes/126944.rs new file mode 100644 index 0000000000000..c0c5622e26020 --- /dev/null +++ b/tests/crashes/126944.rs @@ -0,0 +1,38 @@ +//@ known-bug: rust-lang/rust#126944 +// Step 1: Create two names for a single type: `Thing` and `AlsoThing` + +struct Thing; +struct Dummy; +pub trait DummyTrait { + type DummyType; +} +impl DummyTrait for Dummy { + type DummyType = Thing; +} +type AlsoThing = ::DummyType; + +// Step 2: Create names for a single trait object type: `TraitObject` and `AlsoTraitObject` + +pub trait SomeTrait { + type Item; +} +type TraitObject = dyn SomeTrait; +type AlsoTraitObject = dyn SomeTrait; + +// Step 3: Force the compiler to check whether the two names are the same type + +pub trait Supertrait { + type Foo; +} +pub trait Subtrait: Supertrait {} + +pub trait HasOutput { + type Output; +} + +fn foo() -> F::Output +where + F: HasOutput>, +{ + todo!() +} diff --git a/tests/crashes/126966.rs b/tests/crashes/126966.rs new file mode 100644 index 0000000000000..edeedc68c40d7 --- /dev/null +++ b/tests/crashes/126966.rs @@ -0,0 +1,29 @@ +//@ known-bug: rust-lang/rust#126966 +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom, + { + } +} + +#[repr(u32)] +enum Ox00 { + V = 0x00, +} + +#[repr(C, packed(2))] +enum OxFF { + V = 0xFF, +} + +fn test() { + union Superset { + a: Ox00, + b: OxFF, + } + + assert::is_transmutable::(); +} diff --git a/tests/crashes/126969.rs b/tests/crashes/126969.rs new file mode 100644 index 0000000000000..676563d059caf --- /dev/null +++ b/tests/crashes/126969.rs @@ -0,0 +1,9 @@ +//@ known-bug: rust-lang/rust#126969 + +struct S { + _: union { t: T }, +} + +fn f(S::<&i8> { .. }: S<&i8>) {} + +fn main() {} diff --git a/tests/crashes/126982.rs b/tests/crashes/126982.rs new file mode 100644 index 0000000000000..8522d9415eb88 --- /dev/null +++ b/tests/crashes/126982.rs @@ -0,0 +1,18 @@ +//@ known-bug: rust-lang/rust#126982 + +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: T, +} + +impl CoerceUnsized for Foo {} + +union U { + a: usize, +} + +const C: U = Foo { a: 10 }; + +fn main() {} diff --git a/tests/crashes/127222.rs b/tests/crashes/127222.rs new file mode 100644 index 0000000000000..eda0ea3d9b729 --- /dev/null +++ b/tests/crashes/127222.rs @@ -0,0 +1,3 @@ +//@ known-bug: rust-lang/rust#127222 +#[marker] +trait Foo = PartialEq + Send; diff --git a/tests/crashes/127266.rs b/tests/crashes/127266.rs new file mode 100644 index 0000000000000..2bdbe03e373a9 --- /dev/null +++ b/tests/crashes/127266.rs @@ -0,0 +1,17 @@ +//@ known-bug: rust-lang/rust#127266 +#![feature(const_mut_refs)] +#![feature(const_refs_to_static)] + +struct Meh { + x: &'static dyn UnsafeCell, +} + +const MUH: Meh = Meh { + x: &mut *(READONLY as *mut _), +}; + +static READONLY: i32 = 0; + +trait UnsafeCell<'a> {} + +pub fn main() {} diff --git a/tests/crashes/127299.rs b/tests/crashes/127299.rs new file mode 100644 index 0000000000000..7eb78387997ab --- /dev/null +++ b/tests/crashes/127299.rs @@ -0,0 +1,12 @@ +//@ known-bug: rust-lang/rust#127299 +trait Qux { + fn bar() -> i32; +} + +pub struct Lint { + pub desc: &'static Qux, +} + +static FOO: &Lint = &Lint { desc: "desc" }; + +fn main() {} diff --git a/tests/crashes/127304.rs b/tests/crashes/127304.rs new file mode 100644 index 0000000000000..2975fc27f6766 --- /dev/null +++ b/tests/crashes/127304.rs @@ -0,0 +1,20 @@ +//@ known-bug: rust-lang/rust #127304 +#![feature(adt_const_params)] + +trait Trait {} +impl Trait for () {} + +struct MyStr(str); +impl std::marker::ConstParamTy for MyStr {} + +fn function_with_my_str() -> &'static MyStr { + S +} + +impl MyStr { + const fn new(s: &Trait str) -> &'static MyStr {} +} + +pub fn main() { + let f = function_with_my_str::<{ MyStr::new("hello") }>(); +} diff --git a/tests/crashes/127332.rs b/tests/crashes/127332.rs new file mode 100644 index 0000000000000..5c14af01cece8 --- /dev/null +++ b/tests/crashes/127332.rs @@ -0,0 +1,9 @@ +//@ known-bug: rust-lang/rust #127332 + +async fn fun() { + enum Foo { + A { x: u32 }, + } + let orig = Foo::A { x: 5 }; + Foo::A { x: 6, ..orig }; +} From 86a19467c1da6eb9353ad878979a8f74a8b5b230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 5 Jul 2024 00:52:01 +0000 Subject: [PATCH 23/63] Tweak `-1 as usize` suggestion When writing a negative unsigned integer literal, use a verbose suggestion and account for `as` casting. --- compiler/rustc_hir_typeck/src/op.rs | 13 +++++++-- .../feature-gate-negate-unsigned.stderr | 9 ++++--- tests/ui/unsigned-literal-negation.stderr | 27 ++++++++++--------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 5a11cb7096f33..7264bc5a78d82 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -838,8 +838,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ) = ex.kind { - err.span_suggestion( - ex.span, + let span = if let hir::Node::Expr(parent) = + self.tcx.parent_hir_node(ex.hir_id) + && let hir::ExprKind::Cast(..) = parent.kind + { + // `-1 as usize` -> `usize::MAX` + parent.span + } else { + ex.span + }; + err.span_suggestion_verbose( + span, format!( "you may have meant the maximum value of `{actual}`", ), diff --git a/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr b/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr index d1f4ed5cb04b8..696326157ce29 100644 --- a/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr +++ b/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr @@ -2,12 +2,13 @@ error[E0600]: cannot apply unary operator `-` to type `usize` --> $DIR/feature-gate-negate-unsigned.rs:10:23 | LL | let _max: usize = -1; - | ^^ - | | - | cannot apply unary operator `-` - | help: you may have meant the maximum value of `usize`: `usize::MAX` + | ^^ cannot apply unary operator `-` | = note: unsigned values cannot be negated +help: you may have meant the maximum value of `usize` + | +LL | let _max: usize = usize::MAX; + | ~~~~~~~~~~ error[E0600]: cannot apply unary operator `-` to type `u8` --> $DIR/feature-gate-negate-unsigned.rs:14:14 diff --git a/tests/ui/unsigned-literal-negation.stderr b/tests/ui/unsigned-literal-negation.stderr index 0aaa8c3b72f9d..b0a730477a1b0 100644 --- a/tests/ui/unsigned-literal-negation.stderr +++ b/tests/ui/unsigned-literal-negation.stderr @@ -2,34 +2,37 @@ error[E0600]: cannot apply unary operator `-` to type `usize` --> $DIR/unsigned-literal-negation.rs:2:13 | LL | let x = -1 as usize; - | ^^ - | | - | cannot apply unary operator `-` - | help: you may have meant the maximum value of `usize`: `usize::MAX` + | ^^ cannot apply unary operator `-` | = note: unsigned values cannot be negated +help: you may have meant the maximum value of `usize` + | +LL | let x = usize::MAX; + | ~~~~~~~~~~ error[E0600]: cannot apply unary operator `-` to type `usize` --> $DIR/unsigned-literal-negation.rs:3:13 | LL | let x = (-1) as usize; - | ^^^^ - | | - | cannot apply unary operator `-` - | help: you may have meant the maximum value of `usize`: `usize::MAX` + | ^^^^ cannot apply unary operator `-` | = note: unsigned values cannot be negated +help: you may have meant the maximum value of `usize` + | +LL | let x = usize::MAX; + | ~~~~~~~~~~ error[E0600]: cannot apply unary operator `-` to type `u32` --> $DIR/unsigned-literal-negation.rs:4:18 | LL | let x: u32 = -1; - | ^^ - | | - | cannot apply unary operator `-` - | help: you may have meant the maximum value of `u32`: `u32::MAX` + | ^^ cannot apply unary operator `-` | = note: unsigned values cannot be negated +help: you may have meant the maximum value of `u32` + | +LL | let x: u32 = u32::MAX; + | ~~~~~~~~ error: aborting due to 3 previous errors From f095de4bf105e92b035a7cd64c34bcce56b7cb78 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 4 Jul 2024 23:52:49 +1000 Subject: [PATCH 24/63] coverage: Rename `mir::coverage::BranchInfo` to `CoverageInfoHi` This opens the door to collecting and storing coverage information that is unrelated to branch coverage or MC/DC. --- compiler/rustc_middle/src/mir/coverage.rs | 11 +- compiler/rustc_middle/src/mir/mod.rs | 13 ++- compiler/rustc_middle/src/mir/pretty.rs | 16 ++- .../rustc_mir_build/src/build/coverageinfo.rs | 107 ++++++++++-------- .../src/build/coverageinfo/mcdc.rs | 12 +- .../rustc_mir_build/src/build/custom/mod.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 4 +- compiler/rustc_mir_build/src/build/mod.rs | 8 +- .../src/coverage/mappings.rs | 22 ++-- 9 files changed, 110 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index da25fbb0a82b3..beaaadd497d3a 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -103,7 +103,7 @@ pub enum CoverageKind { SpanMarker, /// Marks its enclosing basic block with an ID that can be referred to by - /// side data in [`BranchInfo`]. + /// side data in [`CoverageInfoHi`]. /// /// Should be erased before codegen (at some point after `InstrumentCoverage`). BlockMarker { id: BlockMarkerId }, @@ -274,10 +274,15 @@ pub struct FunctionCoverageInfo { pub mcdc_num_condition_bitmaps: usize, } -/// Branch information recorded during THIR-to-MIR lowering, and stored in MIR. +/// Coverage information for a function, recorded during MIR building and +/// attached to the corresponding `mir::Body`. Used by the `InstrumentCoverage` +/// MIR pass. +/// +/// ("Hi" indicates that this is "high-level" information collected at the +/// THIR/MIR boundary, before the MIR-based coverage instrumentation pass.) #[derive(Clone, Debug)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct BranchInfo { +pub struct CoverageInfoHi { /// 1 more than the highest-numbered [`CoverageKind::BlockMarker`] that was /// injected into the MIR body. This makes it possible to allocate per-ID /// data structures without having to scan the entire body first. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ef88b253864bd..83e3898cebfa4 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -430,11 +430,12 @@ pub struct Body<'tcx> { pub tainted_by_errors: Option, - /// Branch coverage information collected during MIR building, to be used by - /// the `InstrumentCoverage` pass. + /// Coverage information collected from THIR/MIR during MIR building, + /// to be used by the `InstrumentCoverage` pass. /// - /// Only present if branch coverage is enabled and this function is eligible. - pub coverage_branch_info: Option>, + /// Only present if coverage is enabled and this function is eligible. + /// Boxed to limit space overhead in non-coverage builds. + pub coverage_info_hi: Option>, /// Per-function coverage information added by the `InstrumentCoverage` /// pass, to be used in conjunction with the coverage statements injected @@ -484,7 +485,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors, - coverage_branch_info: None, + coverage_info_hi: None, function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); @@ -515,7 +516,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors: None, - coverage_branch_info: None, + coverage_info_hi: None, function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 4453ce44b0371..5b2c603ce25ac 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -473,8 +473,8 @@ pub fn write_mir_intro<'tcx>( // Add an empty line before the first block is printed. writeln!(w)?; - if let Some(branch_info) = &body.coverage_branch_info { - write_coverage_branch_info(branch_info, w)?; + if let Some(coverage_info_hi) = &body.coverage_info_hi { + write_coverage_info_hi(coverage_info_hi, w)?; } if let Some(function_coverage_info) = &body.function_coverage_info { write_function_coverage_info(function_coverage_info, w)?; @@ -483,12 +483,16 @@ pub fn write_mir_intro<'tcx>( Ok(()) } -fn write_coverage_branch_info( - branch_info: &coverage::BranchInfo, +fn write_coverage_info_hi( + coverage_info_hi: &coverage::CoverageInfoHi, w: &mut dyn io::Write, ) -> io::Result<()> { - let coverage::BranchInfo { branch_spans, mcdc_branch_spans, mcdc_decision_spans, .. } = - branch_info; + let coverage::CoverageInfoHi { + num_block_markers: _, + branch_spans, + mcdc_branch_spans, + mcdc_decision_spans, + } = coverage_info_hi; for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans { writeln!( diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 876faca5172ac..204ee45bfa2d7 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -2,7 +2,7 @@ use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageInfoHi, CoverageKind}; use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp}; use rustc_middle::thir::{ExprId, ExprKind, Pat, Thir}; use rustc_middle::ty::TyCtxt; @@ -13,16 +13,25 @@ use crate::build::{Builder, CFG}; mod mcdc; -pub(crate) struct BranchInfoBuilder { +/// Collects coverage-related information during MIR building, to eventually be +/// turned into a function's [`CoverageInfoHi`] when MIR building is complete. +pub(crate) struct CoverageInfoBuilder { /// Maps condition expressions to their enclosing `!`, for better instrumentation. nots: FxHashMap, markers: BlockMarkerGen, - branch_spans: Vec, + /// Present if branch coverage is enabled. + branch_info: Option, + /// Present if MC/DC coverage is enabled. mcdc_info: Option, } +#[derive(Default)] +struct BranchInfo { + branch_spans: Vec, +} + #[derive(Clone, Copy)] struct NotInfo { /// When visiting the associated expression as a branch condition, treat this @@ -62,20 +71,20 @@ impl BlockMarkerGen { } } -impl BranchInfoBuilder { - /// Creates a new branch info builder, but only if branch coverage instrumentation +impl CoverageInfoBuilder { + /// Creates a new coverage info builder, but only if coverage instrumentation /// is enabled and `def_id` represents a function that is eligible for coverage. pub(crate) fn new_if_enabled(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - if tcx.sess.instrument_coverage_branch() && tcx.is_eligible_for_coverage(def_id) { - Some(Self { - nots: FxHashMap::default(), - markers: BlockMarkerGen::default(), - branch_spans: vec![], - mcdc_info: tcx.sess.instrument_coverage_mcdc().then(MCDCInfoBuilder::new), - }) - } else { - None + if !tcx.sess.instrument_coverage() || !tcx.is_eligible_for_coverage(def_id) { + return None; } + + Some(Self { + nots: FxHashMap::default(), + markers: BlockMarkerGen::default(), + branch_info: tcx.sess.instrument_coverage_branch().then(BranchInfo::default), + mcdc_info: tcx.sess.instrument_coverage_mcdc().then(MCDCInfoBuilder::new), + }) } /// Unary `!` expressions inside an `if` condition are lowered by lowering @@ -88,6 +97,12 @@ impl BranchInfoBuilder { pub(crate) fn visit_unary_not(&mut self, thir: &Thir<'_>, unary_not: ExprId) { assert_matches!(thir[unary_not].kind, ExprKind::Unary { op: UnOp::Not, .. }); + // The information collected by this visitor is only needed when branch + // coverage or higher is enabled. + if self.branch_info.is_none() { + return; + } + self.visit_with_not_info( thir, unary_not, @@ -137,40 +152,40 @@ impl BranchInfoBuilder { false_block, inject_block_marker, ); - } else { - let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); - let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); - - self.branch_spans.push(BranchSpan { - span: source_info.span, - true_marker, - false_marker, - }); + return; } + + // Bail out if branch coverage is not enabled. + let Some(branch_info) = self.branch_info.as_mut() else { return }; + + let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); + let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); + + branch_info.branch_spans.push(BranchSpan { + span: source_info.span, + true_marker, + false_marker, + }); } - pub(crate) fn into_done(self) -> Option> { - let Self { - nots: _, - markers: BlockMarkerGen { num_block_markers }, - branch_spans, - mcdc_info, - } = self; + pub(crate) fn into_done(self) -> Box { + let Self { nots: _, markers: BlockMarkerGen { num_block_markers }, branch_info, mcdc_info } = + self; - if num_block_markers == 0 { - assert!(branch_spans.is_empty()); - return None; - } + let branch_spans = + branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default(); let (mcdc_decision_spans, mcdc_branch_spans) = mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default(); - Some(Box::new(mir::coverage::BranchInfo { + // For simplicity, always return an info struct (without Option), even + // if there's nothing interesting in it. + Box::new(CoverageInfoHi { num_block_markers, branch_spans, mcdc_branch_spans, mcdc_decision_spans, - })) + }) } } @@ -184,7 +199,7 @@ impl<'tcx> Builder<'_, 'tcx> { block: &mut BasicBlock, ) { // Bail out if condition coverage is not enabled for this function. - let Some(branch_info) = self.coverage_branch_info.as_mut() else { return }; + let Some(coverage_info) = self.coverage_info.as_mut() else { return }; if !self.tcx.sess.instrument_coverage_condition() { return; }; @@ -224,7 +239,7 @@ impl<'tcx> Builder<'_, 'tcx> { ); // Separate path for handling branches when MC/DC is enabled. - branch_info.register_two_way_branch( + coverage_info.register_two_way_branch( self.tcx, &mut self.cfg, source_info, @@ -247,12 +262,12 @@ impl<'tcx> Builder<'_, 'tcx> { mut then_block: BasicBlock, mut else_block: BasicBlock, ) { - // Bail out if branch coverage is not enabled for this function. - let Some(branch_info) = self.coverage_branch_info.as_mut() else { return }; + // Bail out if coverage is not enabled for this function. + let Some(coverage_info) = self.coverage_info.as_mut() else { return }; // If this condition expression is nested within one or more `!` expressions, // replace it with the enclosing `!` collected by `visit_unary_not`. - if let Some(&NotInfo { enclosing_not, is_flipped }) = branch_info.nots.get(&expr_id) { + if let Some(&NotInfo { enclosing_not, is_flipped }) = coverage_info.nots.get(&expr_id) { expr_id = enclosing_not; if is_flipped { std::mem::swap(&mut then_block, &mut else_block); @@ -261,7 +276,7 @@ impl<'tcx> Builder<'_, 'tcx> { let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; - branch_info.register_two_way_branch( + coverage_info.register_two_way_branch( self.tcx, &mut self.cfg, source_info, @@ -280,13 +295,11 @@ impl<'tcx> Builder<'_, 'tcx> { true_block: BasicBlock, false_block: BasicBlock, ) { - // Bail out if branch coverage is not enabled for this function. - let Some(branch_info) = self.coverage_branch_info.as_mut() else { return }; - - // FIXME(#124144) This may need special handling when MC/DC is enabled. + // Bail out if coverage is not enabled for this function. + let Some(coverage_info) = self.coverage_info.as_mut() else { return }; let source_info = SourceInfo { span: pattern.span, scope: self.source_scope }; - branch_info.register_two_way_branch( + coverage_info.register_two_way_branch( self.tcx, &mut self.cfg, source_info, diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index f97e9ef60a297..3aa6e708476d5 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -250,24 +250,24 @@ impl MCDCInfoBuilder { impl Builder<'_, '_> { pub(crate) fn visit_coverage_branch_operation(&mut self, logical_op: LogicalOp, span: Span) { - if let Some(branch_info) = self.coverage_branch_info.as_mut() - && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + if let Some(coverage_info) = self.coverage_info.as_mut() + && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut() { mcdc_info.state.record_conditions(logical_op, span); } } pub(crate) fn mcdc_increment_depth_if_enabled(&mut self) { - if let Some(branch_info) = self.coverage_branch_info.as_mut() - && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + if let Some(coverage_info) = self.coverage_info.as_mut() + && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut() { mcdc_info.state.decision_ctx_stack.push(MCDCDecisionCtx::default()); }; } pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) { - if let Some(branch_info) = self.coverage_branch_info.as_mut() - && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + if let Some(coverage_info) = self.coverage_info.as_mut() + && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut() { if mcdc_info.state.decision_ctx_stack.pop().is_none() { bug!("Unexpected empty decision stack"); diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index a0a512a2effcf..f6ebcbcbdc949 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -62,7 +62,7 @@ pub(super) fn build_custom_mir<'tcx>( tainted_by_errors: None, injection_phase: None, pass_count: 0, - coverage_branch_info: None, + coverage_info_hi: None, function_coverage_info: None, }; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index efed52231e3fa..e435e2f92883c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -160,8 +160,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Improve branch coverage instrumentation by noting conditions // nested within one or more `!` expressions. // (Skipped if branch coverage is not enabled.) - if let Some(branch_info) = this.coverage_branch_info.as_mut() { - branch_info.visit_unary_not(this.thir, expr_id); + if let Some(coverage_info) = this.coverage_info.as_mut() { + coverage_info.visit_unary_not(this.thir, expr_id); } let local_scope = this.local_scope(); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 601e5d4d3dc79..0f9746cb719ca 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -218,8 +218,8 @@ struct Builder<'a, 'tcx> { lint_level_roots_cache: GrowableBitSet, /// Collects additional coverage information during MIR building. - /// Only present if branch coverage is enabled and this function is eligible. - coverage_branch_info: Option, + /// Only present if coverage is enabled and this function is eligible. + coverage_info: Option, } type CaptureMap<'tcx> = SortedIndexMultiMap>; @@ -773,7 +773,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unit_temp: None, var_debug_info: vec![], lint_level_roots_cache: GrowableBitSet::new_empty(), - coverage_branch_info: coverageinfo::BranchInfoBuilder::new_if_enabled(tcx, def), + coverage_info: coverageinfo::CoverageInfoBuilder::new_if_enabled(tcx, def), }; assert_eq!(builder.cfg.start_new_block(), START_BLOCK); @@ -802,7 +802,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.coroutine, None, ); - body.coverage_branch_info = self.coverage_branch_info.and_then(|b| b.into_done()); + body.coverage_info_hi = self.coverage_info.map(|b| b.into_done()); body } diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 235992ac5470d..25297245172ac 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -3,7 +3,9 @@ use std::collections::BTreeSet; use rustc_data_structures::graph::DirectedGraph; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; -use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind}; +use rustc_middle::mir::coverage::{ + BlockMarkerId, BranchSpan, ConditionInfo, CoverageInfoHi, CoverageKind, +}; use rustc_middle::mir::{self, BasicBlock, StatementKind}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -157,12 +159,12 @@ impl ExtractedMappings { } fn resolve_block_markers( - branch_info: &mir::coverage::BranchInfo, + coverage_info_hi: &CoverageInfoHi, mir_body: &mir::Body<'_>, ) -> IndexVec> { let mut block_markers = IndexVec::>::from_elem_n( None, - branch_info.num_block_markers, + coverage_info_hi.num_block_markers, ); // Fill out the mapping from block marker IDs to their enclosing blocks. @@ -188,11 +190,11 @@ pub(super) fn extract_branch_pairs( hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Vec { - let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] }; + let Some(coverage_info_hi) = mir_body.coverage_info_hi.as_deref() else { return vec![] }; - let block_markers = resolve_block_markers(branch_info, mir_body); + let block_markers = resolve_block_markers(coverage_info_hi, mir_body); - branch_info + coverage_info_hi .branch_spans .iter() .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| { @@ -222,9 +224,9 @@ pub(super) fn extract_mcdc_mappings( mcdc_branches: &mut impl Extend, mcdc_decisions: &mut impl Extend, ) { - let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return }; + let Some(coverage_info_hi) = mir_body.coverage_info_hi.as_deref() else { return }; - let block_markers = resolve_block_markers(branch_info, mir_body); + let block_markers = resolve_block_markers(coverage_info_hi, mir_body); let bcb_from_marker = |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); @@ -243,7 +245,7 @@ pub(super) fn extract_mcdc_mappings( Some((span, true_bcb, false_bcb)) }; - mcdc_branches.extend(branch_info.mcdc_branch_spans.iter().filter_map( + mcdc_branches.extend(coverage_info_hi.mcdc_branch_spans.iter().filter_map( |&mir::coverage::MCDCBranchSpan { span: raw_span, condition_info, @@ -257,7 +259,7 @@ pub(super) fn extract_mcdc_mappings( }, )); - mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map( + mcdc_decisions.extend(coverage_info_hi.mcdc_decision_spans.iter().filter_map( |decision: &mir::coverage::MCDCDecisionSpan| { let span = unexpand_into_body_span(decision.span, body_span)?; From f96f4436310d889da0ace73659f73500cc6c93c3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 5 Jul 2024 13:07:30 +1000 Subject: [PATCH 25/63] Tweak how the extra newline is printed after coverage info --- compiler/rustc_middle/src/mir/pretty.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5b2c603ce25ac..af19ed95193a7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -494,11 +494,15 @@ fn write_coverage_info_hi( mcdc_decision_spans, } = coverage_info_hi; + // Only add an extra trailing newline if we printed at least one thing. + let mut did_print = false; + for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans { writeln!( w, "{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", )?; + did_print = true; } for coverage::MCDCBranchSpan { @@ -514,6 +518,7 @@ fn write_coverage_info_hi( "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}", condition_info.map(|info| info.condition_id) )?; + did_print = true; } for coverage::MCDCDecisionSpan { span, num_conditions, end_markers, decision_depth } in @@ -523,10 +528,10 @@ fn write_coverage_info_hi( w, "{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}" )?; + did_print = true; } - if !branch_spans.is_empty() || !mcdc_branch_spans.is_empty() || !mcdc_decision_spans.is_empty() - { + if did_print { writeln!(w)?; } From 3e4368053ffa72183f32c2c7c790cd6b29713f95 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Jul 2024 12:04:32 +0200 Subject: [PATCH 26/63] Improve `Command::args` API in `run-make-support` --- src/tools/run-make-support/src/command.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index ee651704c6fd0..c506c3d6b61a2 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -75,11 +75,12 @@ impl Command { /// Generic command arguments provider. Prefer specific helper methods if possible. /// Note that for some executables, arguments might be platform specific. For C/C++ /// compilers, arguments might be platform *and* compiler specific. - pub fn args(&mut self, args: &[S]) -> &mut Self + pub fn args(&mut self, args: V) -> &mut Self where S: AsRef, + V: AsRef<[S]>, { - self.cmd.args(args); + self.cmd.args(args.as_ref()); self } From 415e202c48d349dae9ad138c3adb78dc51d5ad9c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 5 Jul 2024 11:19:52 +0200 Subject: [PATCH 27/63] Improve code of `run-make/llvm-ident` test --- tests/run-make/llvm-ident/rmake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs index f460829288e8c..6934a4b36d013 100644 --- a/tests/run-make/llvm-ident/rmake.rs +++ b/tests/run-make/llvm-ident/rmake.rs @@ -28,7 +28,7 @@ fn main() { files.push(path.to_path_buf()); } }); - cmd(llvm_bin_dir().join("llvm-dis")).args(&files).run(); + cmd(llvm_bin_dir().join("llvm-dis")).args(files).run(); // Check LLVM IR files (including temporary outputs) have `!llvm.ident` // named metadata, reusing the related codegen test. From 4abc51a2196657adb20f1a83fb7c04063c7c7586 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 5 Jul 2024 14:05:29 +0200 Subject: [PATCH 28/63] Improve readability of some fmt code examples --- library/core/src/fmt/mod.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index d0e188dfcd1d8..25ab5b2db9641 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -517,7 +517,10 @@ impl Display for Arguments<'_> { /// /// let origin = Point { x: 0, y: 0 }; /// -/// assert_eq!(format!("The origin is: {origin:?}"), "The origin is: Point { x: 0, y: 0 }"); +/// assert_eq!( +/// format!("The origin is: {origin:?}"), +/// "The origin is: Point { x: 0, y: 0 }", +/// ); /// ``` /// /// Manually implementing: @@ -541,7 +544,10 @@ impl Display for Arguments<'_> { /// /// let origin = Point { x: 0, y: 0 }; /// -/// assert_eq!(format!("The origin is: {origin:?}"), "The origin is: Point { x: 0, y: 0 }"); +/// assert_eq!( +/// format!("The origin is: {origin:?}"), +/// "The origin is: Point { x: 0, y: 0 }", +/// ); /// ``` /// /// There are a number of helper methods on the [`Formatter`] struct to help you with manual @@ -582,11 +588,11 @@ impl Display for Arguments<'_> { /// /// let origin = Point { x: 0, y: 0 }; /// -/// assert_eq!(format!("The origin is: {origin:#?}"), -/// "The origin is: Point { +/// let expected = "The origin is: Point { /// x: 0, /// y: 0, -/// }"); +/// }"; +/// assert_eq!(format!("The origin is: {origin:#?}"), expected); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -738,8 +744,10 @@ pub trait Display { /// } /// } /// - /// assert_eq!("(1.987, 2.983)", - /// format!("{}", Position { longitude: 1.987, latitude: 2.983, })); + /// assert_eq!( + /// "(1.987, 2.983)", + /// format!("{}", Position { longitude: 1.987, latitude: 2.983, }), + /// ); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, f: &mut Formatter<'_>) -> Result; From 3d699a4fa1eee76a8d8951e449d5df37061af658 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 5 Jul 2024 22:06:57 +0800 Subject: [PATCH 29/63] Update LLVM submodule --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index e6a6470d1eb4c..c54cff0e6e4d1 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit e6a6470d1eb4c88fee4b1ea98cd8e0ac4a181c16 +Subproject commit c54cff0e6e4d1a0d0a2df7c1ce3d96cdd554763e From f763d621494d2f6358c3e774596468275e6ad046 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 5 Jul 2024 14:14:35 +0000 Subject: [PATCH 30/63] Fix a few doc comment for compiler-interal API docs. They only used `//` instead of `///` so weren't picked up by rustdoc. --- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 2 +- .../src/elaborate_drops.rs | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index b6e9000ef9506..c99e8a7fe8ecf 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -18,7 +18,7 @@ use rustc_trait_selection::traits::{ use std::cell::RefCell; use std::ops::Deref; -// Data shared between a "typeck root" and its nested bodies, +/// Data shared between a "typeck root" and its nested bodies, /// e.g. closures defined within the function. For example: /// ```ignore (illustrative) /// fn foo() { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index fbbb8c5e47245..25bebb0539a4f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -33,16 +33,16 @@ use std::fmt; /// as it would allow running a destructor on a place behind a reference: /// /// ```text -// fn drop_term(t: &mut T) { -// mir! { -// { -// Drop(*t, exit) -// } -// exit = { -// Return() -// } -// } -// } +/// fn drop_term(t: &mut T) { +/// mir! { +/// { +/// Drop(*t, exit) +/// } +/// exit = { +/// Return() +/// } +/// } +/// } /// ``` pub struct ElaborateDrops; From 1e4d821136033fb08ac5140127f37f35ff687273 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 13:22:02 -0400 Subject: [PATCH 31/63] rewrite pgo-gen to rmake --- src/tools/run-make-support/src/lib.rs | 1 - .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/pgo-gen/Makefile | 11 ----------- tests/run-make/pgo-gen/rmake.rs | 18 ++++++++++++++++++ 4 files changed, 18 insertions(+), 13 deletions(-) delete mode 100644 tests/run-make/pgo-gen/Makefile create mode 100644 tests/run-make/pgo-gen/rmake.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index af5ae6a8e608c..6c1bcc6d7cd90 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -272,7 +272,6 @@ pub fn shallow_find_files, F: Fn(&PathBuf) -> bool>( for entry in fs_wrapper::read_dir(path) { let entry = entry.expect("failed to read directory entry."); let path = entry.path(); - if path.is_file() && closure(&path) { matching_files.push(path); } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 70c1b055c6e40..97990e5923561 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -109,7 +109,6 @@ run-make/pass-non-c-like-enum-to-c/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-gen-no-imp-symbols/Makefile -run-make/pgo-gen/Makefile run-make/pgo-indirect-call-promotion/Makefile run-make/pgo-use/Makefile run-make/pointer-auth-link-with-c/Makefile diff --git a/tests/run-make/pgo-gen/Makefile b/tests/run-make/pgo-gen/Makefile deleted file mode 100644 index c1d456986fb28..0000000000000 --- a/tests/run-make/pgo-gen/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# needs-profiler-support -# ignore-cross-compile - -include ../tools.mk - -COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)" - -all: - $(RUSTC) $(COMPILE_FLAGS) test.rs - $(call RUN,test) || exit 1 - [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) diff --git a/tests/run-make/pgo-gen/rmake.rs b/tests/run-make/pgo-gen/rmake.rs new file mode 100644 index 0000000000000..d35b29302648e --- /dev/null +++ b/tests/run-make/pgo-gen/rmake.rs @@ -0,0 +1,18 @@ +// -C profile-generate, when used with rustc, is supposed to output +// profile files (.profraw) after running a binary to analyze how the compiler +// optimizes code. This test checks that these files are generated. +// See https://github.com/rust-lang/rust/pull/48346 + +//@ needs-profiler-support +//@ ignore-cross-compile + +use run_make_support::{cwd, find_files_by_prefix_and_extension, run, rustc}; + +fn main() { + rustc().arg("-g").profile_generate(cwd()).run(); + run("test"); + assert!( + find_files_by_prefix_and_extension(cwd(), "default", "profraw").len() > 0, + "no .profraw file generated" + ); +} From a1555eb0d618eb1abae39d07e6428e2688788b7b Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 13:46:20 -0400 Subject: [PATCH 32/63] rewrite pgo-use to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/pgo-use/Makefile | 43 --------------- tests/run-make/pgo-use/rmake.rs | 54 +++++++++++++++++++ 3 files changed, 54 insertions(+), 44 deletions(-) delete mode 100644 tests/run-make/pgo-use/Makefile create mode 100644 tests/run-make/pgo-use/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 97990e5923561..2050189cead96 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -110,7 +110,6 @@ run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-gen-no-imp-symbols/Makefile run-make/pgo-indirect-call-promotion/Makefile -run-make/pgo-use/Makefile run-make/pointer-auth-link-with-c/Makefile run-make/print-calling-conventions/Makefile run-make/print-target-list/Makefile diff --git a/tests/run-make/pgo-use/Makefile b/tests/run-make/pgo-use/Makefile deleted file mode 100644 index 92098a4019c47..0000000000000 --- a/tests/run-make/pgo-use/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# needs-profiler-support -# ignore-cross-compile - -include ../tools.mk - -# This test makes sure that PGO profiling data leads to cold functions being -# marked as `cold` and hot functions with `inlinehint`. -# The test program contains an `if` were actual execution only ever takes the -# `else` branch. Accordingly, we expect the function that is never called to -# be marked as cold. -# -# Disable the pre-inlining pass (i.e. a pass that does some inlining before -# it adds the profiling instrumentation). Disabling this pass leads to -# rather predictable IR which we need for this test to be stable. - -COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline - -ifeq ($(UNAME),Darwin) -# macOS does not have the `tac` command, but `tail -r` does the same thing -TAC := tail -r -else -# some other platforms don't support the `-r` flag for `tail`, so use `tac` -TAC := tac -endif - -all: - # Compile the test program with instrumentation - $(RUSTC) $(COMMON_FLAGS) -Cprofile-generate="$(TMPDIR)" main.rs - # Run it in order to generate some profiling data - $(call RUN,main some-argument) || exit 1 - # Postprocess the profiling data so it can be used by the compiler - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/merged.profdata \ - "$(TMPDIR)"/default_*.profraw - # Compile the test program again, making use of the profiling data - $(RUSTC) $(COMMON_FLAGS) -Cprofile-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs - # Check that the generate IR contains some things that we expect - # - # We feed the file into LLVM FileCheck tool *in reverse* so that we see the - # line with the function name before the line with the function attributes. - # FileCheck only supports checking that something matches on the next line, - # but not if something matches on the previous line. - $(TAC) "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs new file mode 100644 index 0000000000000..04777821b51b0 --- /dev/null +++ b/tests/run-make/pgo-use/rmake.rs @@ -0,0 +1,54 @@ +// This test makes sure that PGO profiling data leads to cold functions being +// marked as `cold` and hot functions with `inlinehint`. +// The test program contains an `if` where actual execution only ever takes the +// `else` branch. Accordingly, we expect the function that is never called to +// be marked as cold. +// See https://github.com/rust-lang/rust/pull/60262 + +//@ needs-profiler-support +//@ ignore-cross-compile + +use run_make_support::{ + cwd, find_files_by_prefix_and_extension, fs_wrapper, llvm_filecheck, llvm_profdata, + run_with_args, rustc, +}; + +fn main() { + // Compile the test program with instrumentation + // Disable the pre-inlining pass (i.e. a pass that does some inlining before + // it adds the profiling instrumentation). Disabling this pass leads to + // rather predictable IR which we need for this test to be stable. + rustc() + .opt_level("2") + .codegen_units(1) + .arg("-Cllvm-args=-disable-preinline") + .profile_generate(cwd()) + .input("main.rs") + .run(); + // Run it in order to generate some profiling data + run_with_args("main", &["some-argument"]); + // Postprocess the profiling data so it can be used by the compiler + llvm_profdata() + .merge() + .output("merged.profdata") + .input(find_files_by_prefix_and_extension(cwd(), "default", "profraw").get(0).unwrap()) + .run(); + // Compile the test program again, making use of the profiling data + rustc() + .opt_level("2") + .codegen_units(1) + .arg("-Cllvm-args=-disable-preinline") + .profile_use("merged.profdata") + .emit("llvm-ir") + .input("main.rs") + .run(); + // Check that the generate IR contains some things that we expect + // + // We feed the file into LLVM FileCheck tool *in reverse* so that we see the + // line with the function name before the line with the function attributes. + // FileCheck only supports checking that something matches on the next line, + // but not if something matches on the previous line. + let mut bytes = fs_wrapper::read("interesting.ll"); + bytes.reverse(); + llvm_filecheck().patterns("filecheck-patterns.txt").stdin(bytes).run(); +} From b15e72a9ed8f34b98d32eba2eb5d3a3d9befea77 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 13:58:48 -0400 Subject: [PATCH 33/63] rewrite profile to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/profile/Makefile | 13 ----------- tests/run-make/profile/rmake.rs | 22 +++++++++++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/profile/Makefile create mode 100644 tests/run-make/profile/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2050189cead96..0cb3275d7e934 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -113,7 +113,6 @@ run-make/pgo-indirect-call-promotion/Makefile run-make/pointer-auth-link-with-c/Makefile run-make/print-calling-conventions/Makefile run-make/print-target-list/Makefile -run-make/profile/Makefile run-make/prune-link-args/Makefile run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile diff --git a/tests/run-make/profile/Makefile b/tests/run-make/profile/Makefile deleted file mode 100644 index 7919b18ba74a5..0000000000000 --- a/tests/run-make/profile/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# needs-profiler-support -# ignore-cross-compile - -include ../tools.mk - -all: - $(RUSTC) -g -Z profile test.rs - $(call RUN,test) || exit 1 - [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) - [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) - $(RUSTC) -g -Z profile -Z profile-emit=$(TMPDIR)/abc/abc.gcda test.rs - $(call RUN,test) || exit 1 - [ -e "$(TMPDIR)/abc/abc.gcda" ] || (echo "gcda file not emitted to defined path"; exit 1) diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs new file mode 100644 index 0000000000000..8d41978baecdd --- /dev/null +++ b/tests/run-make/profile/rmake.rs @@ -0,0 +1,22 @@ +// This test revolves around the rustc flag -Z profile, which should +// generate a .gcno file (initial profiling information) as well +// as a .gcda file (branch counters). The path where these are emitted +// should also be configurable with -Z profile-emit. This test checks +// that the files are produced, and then that the latter flag is respected. +// See https://github.com/rust-lang/rust/pull/42433 + +//@ ignore-cross-compile +//@ needs-profiler-support + +use run_make_support::{run, rustc}; +use std::path::Path; + +fn main() { + rustc().arg("-g").arg("-Zprofile").input("test.rs").run(); + run("test"); + assert!(Path::new("test.gcno").exists(), "no .gcno file"); + assert!(Path::new("test.gcda").exists(), "no .gcda file"); + rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run(); + run("test"); + assert!(Path::new("abc/abc.gcda").exists(), "gcda file not emitted to defined path"); +} From 3cdce7ee1050930b696683906430c0641e55b3fc Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 28 Jun 2024 16:25:12 -0400 Subject: [PATCH 34/63] rewrite output-type-permutations to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../output-type-permutations/Makefile | 147 --------------- .../output-type-permutations/rmake.rs | 178 ++++++++++++++++++ 3 files changed, 178 insertions(+), 148 deletions(-) delete mode 100644 tests/run-make/output-type-permutations/Makefile create mode 100644 tests/run-make/output-type-permutations/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 70c1b055c6e40..3a9755e5658c0 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -100,7 +100,6 @@ run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile run-make/no-duplicate-libs/Makefile run-make/obey-crate-type-flag/Makefile -run-make/output-type-permutations/Makefile run-make/panic-abort-eh_frame/Makefile run-make/pass-linker-flags-flavor/Makefile run-make/pass-linker-flags-from-dep/Makefile diff --git a/tests/run-make/output-type-permutations/Makefile b/tests/run-make/output-type-permutations/Makefile deleted file mode 100644 index 035033b9fddd3..0000000000000 --- a/tests/run-make/output-type-permutations/Makefile +++ /dev/null @@ -1,147 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib - $(call REMOVE_RLIBS,bar) - $(call REMOVE_DYLIBS,bar) - rm $(call STATICLIB,bar) - rm -f $(TMPDIR)/{lib,}bar.{dll.exp,dll.lib,pdb,dll.a} - # Check that $(TMPDIR) is empty. - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --crate-type=bin - rm $(TMPDIR)/$(call BIN,bar) - rm -f $(TMPDIR)/bar.pdb - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link - rm $(TMPDIR)/bar.ll - rm $(TMPDIR)/bar.bc - rm $(TMPDIR)/bar.s - rm $(TMPDIR)/bar.o - rm $(TMPDIR)/$(call BIN,bar) - rm -f $(TMPDIR)/bar.pdb - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit asm -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit asm=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit=asm=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit llvm-bc -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit llvm-bc=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit=llvm-bc=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit llvm-ir -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit=llvm-ir=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit obj -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit obj=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --emit=obj=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit link -o $(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --emit link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --emit=link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - rm -f $(TMPDIR)/foo.pdb - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --crate-type=rlib --emit link=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --crate-type=rlib --emit=link=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --crate-type=dylib --emit link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --crate-type=dylib --emit=link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - rm -f $(TMPDIR)/{lib,}foo.{dll.exp,dll.lib,pdb,dll.a,exe.a} - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] || (ls -1 $(TMPDIR) && exit 1) - - $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --crate-type=staticlib --emit link=$(TMPDIR)/foo - rm $(TMPDIR)/foo - $(RUSTC) foo.rs --crate-type=staticlib --emit=link=$(TMPDIR)/foo - rm $(TMPDIR)/foo - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --crate-type=bin --emit link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo.rs --crate-type=bin --emit=link=$(TMPDIR)/$(call BIN,foo) - rm $(TMPDIR)/$(call BIN,foo) - rm -f $(TMPDIR)/foo.pdb - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/ir \ - --emit link \ - --crate-type=rlib - rm $(TMPDIR)/ir - rm $(TMPDIR)/libbar.rlib - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit asm=$(TMPDIR)/asm \ - --emit llvm-ir=$(TMPDIR)/ir \ - --emit llvm-bc=$(TMPDIR)/bc \ - --emit obj=$(TMPDIR)/obj \ - --emit link=$(TMPDIR)/link \ - --crate-type=staticlib - rm $(TMPDIR)/asm - rm $(TMPDIR)/ir - rm $(TMPDIR)/bc - rm $(TMPDIR)/obj - rm $(TMPDIR)/link - $(RUSTC) foo.rs --emit=asm=$(TMPDIR)/asm \ - --emit llvm-ir=$(TMPDIR)/ir \ - --emit=llvm-bc=$(TMPDIR)/bc \ - --emit obj=$(TMPDIR)/obj \ - --emit=link=$(TMPDIR)/link \ - --crate-type=staticlib - rm $(TMPDIR)/asm - rm $(TMPDIR)/ir - rm $(TMPDIR)/bc - rm $(TMPDIR)/obj - rm $(TMPDIR)/link - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - - $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib - rm $(TMPDIR)/bar.ll - rm $(TMPDIR)/bar.s - rm $(TMPDIR)/bar.o - rm $(call STATICLIB,bar) - mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc - # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later - # comparison. - - $(RUSTC) foo.rs --emit=llvm-bc,link --crate-type=rlib - cmp $(TMPDIR)/foo.bc $(TMPDIR)/bar.bc - rm $(TMPDIR)/bar.bc - rm $(TMPDIR)/foo.bc - $(call REMOVE_RLIBS,bar) - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs new file mode 100644 index 0000000000000..69af1274c68a1 --- /dev/null +++ b/tests/run-make/output-type-permutations/rmake.rs @@ -0,0 +1,178 @@ +// In 2014, rustc's output flags were reworked to be a lot more modular. +// This test uses these output flags in an expansive variety of combinations +// and syntax styles, checking that compilation is successful and that no unexpected +// files are created. +// The assert_eq! checks that "1 file remains" at the end of each part of the test, +// because foo.rs counts as a file, and should be the only remaining one. +// See https://github.com/rust-lang/rust/pull/12020 + +use run_make_support::{ + bin_name, cwd, dynamic_lib_name, fs_wrapper, rust_lib_name, rustc, static_lib_name, +}; + +fn remove_artifacts() { + std::fs::remove_file("libbar.ddl.exp").unwrap_or_default(); + std::fs::remove_file("libbar.dll.lib").unwrap_or_default(); + std::fs::remove_file("libbar.pdb").unwrap_or_default(); + std::fs::remove_file("libbar.dll.a").unwrap_or_default(); + std::fs::remove_file("libbar.exe.a").unwrap_or_default(); + std::fs::remove_file("bar.ddl.exp").unwrap_or_default(); + std::fs::remove_file("bar.dll.lib").unwrap_or_default(); + std::fs::remove_file("bar.pdb").unwrap_or_default(); + std::fs::remove_file("bar.dll.a").unwrap_or_default(); + std::fs::remove_file("bar.exe.a").unwrap_or_default(); +} + +fn main() { + rustc().input("foo.rs").crate_type("rlib,dylib,staticlib").run(); + fs_wrapper::remove_file(rust_lib_name("bar")); + fs_wrapper::remove_file(dynamic_lib_name("bar")); + fs_wrapper::remove_file(static_lib_name("bar")); + remove_artifacts(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").crate_type("bin").run(); + fs_wrapper::remove_file(bin_name("bar")); + std::fs::remove_file("bar.pdb").unwrap_or_default(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").run(); + fs_wrapper::remove_file("bar.ll"); + fs_wrapper::remove_file("bar.bc"); + fs_wrapper::remove_file("bar.s"); + fs_wrapper::remove_file("bar.o"); + fs_wrapper::remove_file(bin_name("bar")); + std::fs::remove_file("bar.pdb").unwrap_or_default(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("asm").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").emit("asm=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").arg("--emit=asm=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("llvm-bc").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").emit("llvm-bc=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").arg("--emit=llvm-bc=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("llvm-ir").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").emit("llvm-ir=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").arg("--emit=llvm-ir=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("obj").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").emit("obj=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").arg("--emit=obj=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + let bin_foo = bin_name("foo"); + rustc().input("foo.rs").emit("link").output(&bin_foo).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").emit(&format!("link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").arg(&format!("--emit=link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + std::fs::remove_file("foo.pdb").unwrap_or_default(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").crate_type("rlib").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").crate_type("rlib").emit("link=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").crate_type("rlib").arg("--emit=link=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").crate_type("dylib").output(&bin_foo).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").crate_type("dylib").emit(&format!("link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").crate_type("dylib").arg(&format!("--emit=link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + remove_artifacts(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").crate_type("staticlib").emit("link").output("foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").crate_type("staticlib").emit("link=foo").run(); + fs_wrapper::remove_file("foo"); + rustc().input("foo.rs").crate_type("staticlib").arg("--emit=link=foo").run(); + fs_wrapper::remove_file("foo"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").crate_type("bin").output(&bin_foo).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").crate_type("bin").emit(&format!("link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + rustc().input("foo.rs").crate_type("bin").arg(&format!("--emit=link={bin_foo}")).run(); + fs_wrapper::remove_file(&bin_foo); + std::fs::remove_file("foo.pdb").unwrap_or_default(); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("llvm-ir=ir").emit("link").crate_type("rlib").run(); + fs_wrapper::remove_file("ir"); + fs_wrapper::remove_file(rust_lib_name("bar")); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc() + .input("foo.rs") + .emit("asm=asm") + .emit("llvm-ir=ir") + .emit("llvm-bc=bc") + .emit("obj=obj") + .emit("link=link") + .crate_type("staticlib") + .run(); + fs_wrapper::remove_file("asm"); + fs_wrapper::remove_file("ir"); + fs_wrapper::remove_file("bc"); + fs_wrapper::remove_file("obj"); + fs_wrapper::remove_file("link"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc() + .input("foo.rs") + .arg("--emit=asm=asm") + .arg("--emit") + .arg("llvm-ir=ir") + .arg("--emit=llvm-bc=bc") + .arg("--emit") + .arg("obj=obj") + .arg("--emit=link=link") + .crate_type("staticlib") + .run(); + fs_wrapper::remove_file("asm"); + fs_wrapper::remove_file("ir"); + fs_wrapper::remove_file("bc"); + fs_wrapper::remove_file("obj"); + fs_wrapper::remove_file("link"); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + + rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").crate_type("staticlib").run(); + fs_wrapper::remove_file("bar.ll"); + fs_wrapper::remove_file("bar.s"); + fs_wrapper::remove_file("bar.o"); + fs_wrapper::remove_file(static_lib_name("bar")); + fs_wrapper::rename("bar.bc", "foo.bc"); + // Don't check that no files except foo.rs remain - we left `foo.bc` for later + // comparison. + + rustc().input("foo.rs").emit("llvm-bc,link").crate_type("rlib").run(); + assert_eq!(fs_wrapper::read("foo.bc"), fs_wrapper::read("bar.bc")); + fs_wrapper::remove_file("bar.bc"); + fs_wrapper::remove_file("foo.bc"); + fs_wrapper::remove_file(rust_lib_name("bar")); + assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); +} From 73994719b466350c1faf88d0bfbf20b44c29a8aa Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 2 Jul 2024 15:25:26 -0400 Subject: [PATCH 35/63] add shallow_find_files helper to run_make_support --- src/tools/run-make-support/src/lib.rs | 5 + .../output-type-permutations/rmake.rs | 447 +++++++++++------- 2 files changed, 285 insertions(+), 167 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index af5ae6a8e608c..20ceb03defef9 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -295,6 +295,11 @@ pub fn not_contains>(path: P, expected: &str) -> bool { !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected)) } +/// Returns true if the filename at `path` is not in `expected`. +pub fn name_not_among>(path: P, expected: &[&'static str]) -> bool { + path.as_ref().file_name().is_some_and(|name| !expected.contains(&name.to_str().unwrap())) +} + /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is /// available on the platform! #[track_caller] diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs index 69af1274c68a1..eb166307f6800 100644 --- a/tests/run-make/output-type-permutations/rmake.rs +++ b/tests/run-make/output-type-permutations/rmake.rs @@ -1,178 +1,291 @@ // In 2014, rustc's output flags were reworked to be a lot more modular. // This test uses these output flags in an expansive variety of combinations -// and syntax styles, checking that compilation is successful and that no unexpected -// files are created. -// The assert_eq! checks that "1 file remains" at the end of each part of the test, -// because foo.rs counts as a file, and should be the only remaining one. +// and syntax styles, checking that compilation is successful and that output +// files are exactly what is expected, no more, no less. // See https://github.com/rust-lang/rust/pull/12020 use run_make_support::{ - bin_name, cwd, dynamic_lib_name, fs_wrapper, rust_lib_name, rustc, static_lib_name, + bin_name, cwd, dynamic_lib_name, fs_wrapper, name_not_among, rust_lib_name, rustc, + shallow_find_files, static_lib_name, }; -fn remove_artifacts() { - std::fs::remove_file("libbar.ddl.exp").unwrap_or_default(); - std::fs::remove_file("libbar.dll.lib").unwrap_or_default(); - std::fs::remove_file("libbar.pdb").unwrap_or_default(); - std::fs::remove_file("libbar.dll.a").unwrap_or_default(); - std::fs::remove_file("libbar.exe.a").unwrap_or_default(); - std::fs::remove_file("bar.ddl.exp").unwrap_or_default(); - std::fs::remove_file("bar.dll.lib").unwrap_or_default(); - std::fs::remove_file("bar.pdb").unwrap_or_default(); - std::fs::remove_file("bar.dll.a").unwrap_or_default(); - std::fs::remove_file("bar.exe.a").unwrap_or_default(); +// Each test takes 4 arguments: +// `must_exist`: output files which must be found - if any are absent, the test fails +// `can_exist`: optional output files which will not trigger a failure +// `dir`: the name of the directory where the test happens +// `rustc_invocation`: the rustc command being tested +// Any unexpected output files not listed in `must_exist` or `can_exist` will cause a failure. +fn assert_expected_output_files( + must_exist: &[&'static str], + can_exist: &[&'static str], + dir: &str, + rustc_invocation: impl Fn(), +) { + fs_wrapper::create_dir(dir); + rustc_invocation(); + for file in must_exist { + fs_wrapper::remove_file(dir.to_owned() + "/" + file); + } + let actual_output_files = shallow_find_files(dir, |path| name_not_among(path, can_exist)); + if !&actual_output_files.is_empty() { + dbg!(&actual_output_files); + panic!("unexpected output artifacts detected"); + } } fn main() { - rustc().input("foo.rs").crate_type("rlib,dylib,staticlib").run(); - fs_wrapper::remove_file(rust_lib_name("bar")); - fs_wrapper::remove_file(dynamic_lib_name("bar")); - fs_wrapper::remove_file(static_lib_name("bar")); - remove_artifacts(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").crate_type("bin").run(); - fs_wrapper::remove_file(bin_name("bar")); - std::fs::remove_file("bar.pdb").unwrap_or_default(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").run(); - fs_wrapper::remove_file("bar.ll"); - fs_wrapper::remove_file("bar.bc"); - fs_wrapper::remove_file("bar.s"); - fs_wrapper::remove_file("bar.o"); - fs_wrapper::remove_file(bin_name("bar")); - std::fs::remove_file("bar.pdb").unwrap_or_default(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("asm").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").emit("asm=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").arg("--emit=asm=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("llvm-bc").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").emit("llvm-bc=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").arg("--emit=llvm-bc=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("llvm-ir").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").emit("llvm-ir=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").arg("--emit=llvm-ir=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("obj").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").emit("obj=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").arg("--emit=obj=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - let bin_foo = bin_name("foo"); - rustc().input("foo.rs").emit("link").output(&bin_foo).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").emit(&format!("link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").arg(&format!("--emit=link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - std::fs::remove_file("foo.pdb").unwrap_or_default(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").crate_type("rlib").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").crate_type("rlib").emit("link=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").crate_type("rlib").arg("--emit=link=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").crate_type("dylib").output(&bin_foo).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").crate_type("dylib").emit(&format!("link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").crate_type("dylib").arg(&format!("--emit=link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - remove_artifacts(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").crate_type("staticlib").emit("link").output("foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").crate_type("staticlib").emit("link=foo").run(); - fs_wrapper::remove_file("foo"); - rustc().input("foo.rs").crate_type("staticlib").arg("--emit=link=foo").run(); - fs_wrapper::remove_file("foo"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").crate_type("bin").output(&bin_foo).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").crate_type("bin").emit(&format!("link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - rustc().input("foo.rs").crate_type("bin").arg(&format!("--emit=link={bin_foo}")).run(); - fs_wrapper::remove_file(&bin_foo); - std::fs::remove_file("foo.pdb").unwrap_or_default(); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("llvm-ir=ir").emit("link").crate_type("rlib").run(); - fs_wrapper::remove_file("ir"); - fs_wrapper::remove_file(rust_lib_name("bar")); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc() - .input("foo.rs") - .emit("asm=asm") - .emit("llvm-ir=ir") - .emit("llvm-bc=bc") - .emit("obj=obj") - .emit("link=link") - .crate_type("staticlib") - .run(); - fs_wrapper::remove_file("asm"); - fs_wrapper::remove_file("ir"); - fs_wrapper::remove_file("bc"); - fs_wrapper::remove_file("obj"); - fs_wrapper::remove_file("link"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc() - .input("foo.rs") - .arg("--emit=asm=asm") - .arg("--emit") - .arg("llvm-ir=ir") - .arg("--emit=llvm-bc=bc") - .arg("--emit") - .arg("obj=obj") - .arg("--emit=link=link") - .crate_type("staticlib") - .run(); - fs_wrapper::remove_file("asm"); - fs_wrapper::remove_file("ir"); - fs_wrapper::remove_file("bc"); - fs_wrapper::remove_file("obj"); - fs_wrapper::remove_file("link"); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); - - rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").crate_type("staticlib").run(); - fs_wrapper::remove_file("bar.ll"); - fs_wrapper::remove_file("bar.s"); - fs_wrapper::remove_file("bar.o"); - fs_wrapper::remove_file(static_lib_name("bar")); - fs_wrapper::rename("bar.bc", "foo.bc"); - // Don't check that no files except foo.rs remain - we left `foo.bc` for later - // comparison. - - rustc().input("foo.rs").emit("llvm-bc,link").crate_type("rlib").run(); - assert_eq!(fs_wrapper::read("foo.bc"), fs_wrapper::read("bar.bc")); - fs_wrapper::remove_file("bar.bc"); - fs_wrapper::remove_file("foo.bc"); - fs_wrapper::remove_file(rust_lib_name("bar")); - assert_eq!(fs_wrapper::read_dir(cwd()).count(), 1); + let bin_foo = Box::leak(Box::new(bin_name("foo"))); + let bin_bar = Box::leak(Box::new(bin_name("bar"))); + let static_bar = Box::leak(Box::new(static_lib_name("bar"))); + let dynamic_bar = Box::leak(Box::new(dynamic_lib_name("bar"))); + let rust_bar = Box::leak(Box::new(rust_lib_name("bar"))); + + assert_expected_output_files( + &[static_bar, dynamic_bar, rust_bar], + &[ + "libbar.ddl.exp", + "libbar.dll.lib", + "libbar.pdb", + "libbar.dll.a", + "libbar.exe.a", + "bar.ddl.exp", + "bar.dll.lib", + "bar.pdb", + "bar.dll.a", + "bar.exe.a", + ], + "three-crates", + || { + rustc() + .input("foo.rs") + .out_dir("three-crates") + .crate_type("rlib,dylib,staticlib") + .run(); + }, + ); + + assert_expected_output_files(&[bin_bar], &["bar.pdb"], "bin-crate", || { + rustc().input("foo.rs").crate_type("bin").out_dir("bin-crate").run(); + }); + + assert_expected_output_files( + &["bar.ll", "bar.bc", "bar.s", "bar.o", bin_bar], + &["bar.pdb"], + "all-emit", + || { + rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").out_dir("all-emit").run(); + }, + ); + + assert_expected_output_files(&["foo"], &[], "asm-emit", || { + rustc().input("foo.rs").emit("asm").output("asm-emit/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "asm-emit2", || { + rustc().input("foo.rs").emit("asm=asm-emit2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "asm-emit3", || { + rustc().input("foo.rs").arg("--emit=asm=asm-emit3/foo").run(); + }); + + assert_expected_output_files(&["foo"], &[], "llvm-ir-emit", || { + rustc().input("foo.rs").emit("llvm-ir").output("llvm-ir-emit/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "llvm-ir-emit2", || { + rustc().input("foo.rs").emit("llvm-ir=llvm-ir-emit2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "llvm-ir-emit3", || { + rustc().input("foo.rs").arg("--emit=llvm-ir=llvm-ir-emit3/foo").run(); + }); + + assert_expected_output_files(&["foo"], &[], "llvm-bc-emit", || { + rustc().input("foo.rs").emit("llvm-bc").output("llvm-bc-emit/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "llvm-bc-emit2", || { + rustc().input("foo.rs").emit("llvm-bc=llvm-bc-emit2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "llvm-bc-emit3", || { + rustc().input("foo.rs").arg("--emit=llvm-bc=llvm-bc-emit3/foo").run(); + }); + + assert_expected_output_files(&["foo"], &[], "obj-emit", || { + rustc().input("foo.rs").emit("obj").output("obj-emit/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "obj-emit2", || { + rustc().input("foo.rs").emit("obj=obj-emit2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "obj-emit3", || { + rustc().input("foo.rs").arg("--emit=obj=obj-emit3/foo").run(); + }); + + assert_expected_output_files(&[bin_foo], &[], "link-emit", || { + rustc().input("foo.rs").emit("link").output("link-emit/".to_owned() + bin_foo).run(); + }); + assert_expected_output_files(&[bin_foo], &[], "link-emit2", || { + rustc().input("foo.rs").emit(&format!("link=link-emit2/{bin_foo}")).run(); + }); + assert_expected_output_files(&[bin_foo], &[], "link-emit3", || { + rustc().input("foo.rs").arg(&format!("--emit=link=link-emit3/{bin_foo}")).run(); + }); + + assert_expected_output_files(&["foo"], &[], "rlib", || { + rustc().crate_type("rlib").input("foo.rs").output("rlib/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "rlib2", || { + rustc().crate_type("rlib").input("foo.rs").emit("link=rlib2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "rlib3", || { + rustc().crate_type("rlib").input("foo.rs").arg("--emit=link=rlib3/foo").run(); + }); + + assert_expected_output_files( + &[bin_foo], + &[ + "libbar.ddl.exp", + "libbar.dll.lib", + "libbar.pdb", + "libbar.dll.a", + "libbar.exe.a", + "bar.ddl.exp", + "bar.dll.lib", + "bar.pdb", + "bar.dll.a", + "bar.exe.a", + ], + "dylib", + || { + rustc().crate_type("dylib").input("foo.rs").output("dylib/".to_owned() + bin_foo).run(); + }, + ); + assert_expected_output_files( + &[bin_foo], + &[ + "libbar.ddl.exp", + "libbar.dll.lib", + "libbar.pdb", + "libbar.dll.a", + "libbar.exe.a", + "bar.ddl.exp", + "bar.dll.lib", + "bar.pdb", + "bar.dll.a", + "bar.exe.a", + ], + "dylib2", + || { + rustc() + .crate_type("dylib") + .input("foo.rs") + .emit(&format!("link=dylib2/{bin_foo}")) + .run(); + }, + ); + assert_expected_output_files( + &[bin_foo], + &[ + "libbar.ddl.exp", + "libbar.dll.lib", + "libbar.pdb", + "libbar.dll.a", + "libbar.exe.a", + "bar.ddl.exp", + "bar.dll.lib", + "bar.pdb", + "bar.dll.a", + "bar.exe.a", + ], + "dylib3", + || { + rustc() + .crate_type("dylib") + .input("foo.rs") + .arg(&format!("--emit=link=dylib3/{bin_foo}")) + .run(); + }, + ); + + assert_expected_output_files(&["foo"], &[], "staticlib", || { + rustc().crate_type("staticlib").input("foo.rs").output("staticlib/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "staticlib2", || { + rustc().crate_type("staticlib").input("foo.rs").emit("link=staticlib2/foo").run(); + }); + assert_expected_output_files(&["foo"], &[], "staticlib3", || { + rustc().crate_type("staticlib").input("foo.rs").arg("--emit=link=staticlib3/foo").run(); + }); + + assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate", || { + rustc().crate_type("bin").input("foo.rs").output("bincrate/".to_owned() + bin_foo).run(); + }); + assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate2", || { + rustc().crate_type("bin").input("foo.rs").emit(&format!("link=bincrate2/{bin_foo}")).run(); + }); + assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate3", || { + rustc() + .crate_type("bin") + .input("foo.rs") + .arg(&format!("--emit=link=bincrate3/{bin_foo}")) + .run(); + }); + + assert_expected_output_files(&["ir", rust_bar], &[], "rlib-ir", || { + rustc() + .input("foo.rs") + .emit("llvm-ir=rlib-ir/ir") + .emit("link") + .crate_type("rlib") + .out_dir("rlib-ir") + .run(); + }); + + assert_expected_output_files(&["ir", "asm", "bc", "obj", "link"], &[], "staticlib-all", || { + rustc() + .input("foo.rs") + .emit("asm=staticlib-all/asm") + .emit("llvm-ir=staticlib-all/ir") + .emit("llvm-bc=staticlib-all/bc") + .emit("obj=staticlib-all/obj") + .emit("link=staticlib-all/link") + .crate_type("staticlib") + .run(); + }); + assert_expected_output_files( + &["ir", "asm", "bc", "obj", "link"], + &[], + "staticlib-all2", + || { + rustc() + .input("foo.rs") + .arg("--emit=asm=staticlib-all2/asm") + .arg("--emit") + .arg("llvm-ir=staticlib-all2/ir") + .arg("--emit=llvm-bc=staticlib-all2/bc") + .arg("--emit") + .arg("obj=staticlib-all2/obj") + .arg("--emit=link=staticlib-all2/link") + .crate_type("staticlib") + .run(); + }, + ); + + assert_expected_output_files( + &["bar.ll", "bar.s", "bar.o", static_bar], + &["bar.bc"], // keep this one for the next test + "staticlib-all3", + || { + rustc() + .input("foo.rs") + .emit("asm,llvm-ir,llvm-bc,obj,link") + .crate_type("staticlib") + .out_dir("staticlib-all3") + .run(); + }, + ); + + // the .bc file from the previous test should be equivalent to this one, despite the difference + // in crate type + assert_expected_output_files(&["bar.bc", rust_bar, "foo.bc"], &[], "rlib-emits", || { + fs_wrapper::rename("staticlib-all3/bar.bc", "rlib-emits/foo.bc"); + rustc().input("foo.rs").emit("llvm-bc,link").crate_type("rlib").out_dir("rlib-emits").run(); + assert_eq!(fs_wrapper::read("rlib-emits/foo.bc"), fs_wrapper::read("rlib-emits/bar.bc")); + }); } From 811532be6e999c42f8101c6cba62a300da2855cc Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 3 Jul 2024 11:48:19 -0400 Subject: [PATCH 36/63] Expectations struct for output-type-permutations --- src/tools/run-make-support/src/lib.rs | 10 +- .../output-type-permutations/rmake.rs | 632 ++++++++++++------ 2 files changed, 448 insertions(+), 194 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 20ceb03defef9..7bb89106de1b9 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -266,14 +266,14 @@ pub fn test_while_readonly, F: FnOnce() + std::panic::UnwindSafe> #[track_caller] pub fn shallow_find_files, F: Fn(&PathBuf) -> bool>( path: P, - closure: F, + filter: F, ) -> Vec { let mut matching_files = Vec::new(); for entry in fs_wrapper::read_dir(path) { let entry = entry.expect("failed to read directory entry."); let path = entry.path(); - if path.is_file() && closure(&path) { + if path.is_file() && filter(&path) { matching_files.push(path); } } @@ -296,8 +296,10 @@ pub fn not_contains>(path: P, expected: &str) -> bool { } /// Returns true if the filename at `path` is not in `expected`. -pub fn name_not_among>(path: P, expected: &[&'static str]) -> bool { - path.as_ref().file_name().is_some_and(|name| !expected.contains(&name.to_str().unwrap())) +pub fn filename_not_in_denylist>(path: P, expected: &[String]) -> bool { + path.as_ref() + .file_name() + .is_some_and(|name| !expected.contains(&name.to_str().unwrap().to_owned())) } /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs index eb166307f6800..30036dc7eeacd 100644 --- a/tests/run-make/output-type-permutations/rmake.rs +++ b/tests/run-make/output-type-permutations/rmake.rs @@ -5,9 +5,10 @@ // See https://github.com/rust-lang/rust/pull/12020 use run_make_support::{ - bin_name, cwd, dynamic_lib_name, fs_wrapper, name_not_among, rust_lib_name, rustc, + bin_name, dynamic_lib_name, filename_not_in_denylist, fs_wrapper, rust_lib_name, rustc, shallow_find_files, static_lib_name, }; +use std::path::PathBuf; // Each test takes 4 arguments: // `must_exist`: output files which must be found - if any are absent, the test fails @@ -15,46 +16,69 @@ use run_make_support::{ // `dir`: the name of the directory where the test happens // `rustc_invocation`: the rustc command being tested // Any unexpected output files not listed in `must_exist` or `can_exist` will cause a failure. -fn assert_expected_output_files( - must_exist: &[&'static str], - can_exist: &[&'static str], - dir: &str, - rustc_invocation: impl Fn(), -) { - fs_wrapper::create_dir(dir); +fn assert_expected_output_files(expectations: Expectations, rustc_invocation: impl Fn()) { + let must_exist = expectations.expected_files; + let can_exist = expectations.allowed_files; + let dir = expectations.test_dir; + + fs_wrapper::create_dir(&dir); rustc_invocation(); for file in must_exist { - fs_wrapper::remove_file(dir.to_owned() + "/" + file); + fs_wrapper::remove_file(PathBuf::from(&dir).join(&file)); } - let actual_output_files = shallow_find_files(dir, |path| name_not_among(path, can_exist)); + let actual_output_files = + shallow_find_files(dir, |path| filename_not_in_denylist(path, &can_exist)); if !&actual_output_files.is_empty() { dbg!(&actual_output_files); panic!("unexpected output artifacts detected"); } } +struct Expectations { + /// Output files which must be found. The test fails if any are absent. + expected_files: Vec, + /// Allowed output files which will not trigger a failure. + allowed_files: Vec, + /// Name of the directory where the test happens. + test_dir: String, +} + +macro_rules! s { + ( $( $x:expr ),* ) => { + { + let mut temp_vec = Vec::new(); + $( + temp_vec.push($x.to_string()); + )* + temp_vec + } + }; +} + fn main() { - let bin_foo = Box::leak(Box::new(bin_name("foo"))); - let bin_bar = Box::leak(Box::new(bin_name("bar"))); - let static_bar = Box::leak(Box::new(static_lib_name("bar"))); - let dynamic_bar = Box::leak(Box::new(dynamic_lib_name("bar"))); - let rust_bar = Box::leak(Box::new(rust_lib_name("bar"))); + let bin_foo = bin_name("foo"); assert_expected_output_files( - &[static_bar, dynamic_bar, rust_bar], - &[ - "libbar.ddl.exp", - "libbar.dll.lib", - "libbar.pdb", - "libbar.dll.a", - "libbar.exe.a", - "bar.ddl.exp", - "bar.dll.lib", - "bar.pdb", - "bar.dll.a", - "bar.exe.a", - ], - "three-crates", + Expectations { + expected_files: s![ + static_lib_name("bar"), + dynamic_lib_name("bar"), + rust_lib_name("bar") + ], + allowed_files: s![ + "libbar.dll.exp", + "libbar.dll.lib", + "libbar.pdb", + "libbar.dll.a", + "libbar.exe.a", + "bar.dll.exp", + "bar.dll.lib", + "bar.pdb", + "bar.dll.a", + "bar.exe.a" + ], + test_dir: "three-crates".to_string(), + }, || { rustc() .input("foo.rs") @@ -64,113 +88,256 @@ fn main() { }, ); - assert_expected_output_files(&[bin_bar], &["bar.pdb"], "bin-crate", || { - rustc().input("foo.rs").crate_type("bin").out_dir("bin-crate").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s![bin_name("bar")], + allowed_files: s!["bar.pdb"], + test_dir: "bin-crate".to_string(), + }, + || { + rustc().input("foo.rs").crate_type("bin").out_dir("bin-crate").run(); + }, + ); assert_expected_output_files( - &["bar.ll", "bar.bc", "bar.s", "bar.o", bin_bar], - &["bar.pdb"], - "all-emit", + Expectations { + expected_files: s!["bar.ll", "bar.bc", "bar.s", "bar.o", bin_name("bar")], + allowed_files: s!["bar.pdb"], + test_dir: "all-emit".to_string(), + }, || { rustc().input("foo.rs").emit("asm,llvm-ir,llvm-bc,obj,link").out_dir("all-emit").run(); }, ); - assert_expected_output_files(&["foo"], &[], "asm-emit", || { - rustc().input("foo.rs").emit("asm").output("asm-emit/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "asm-emit2", || { - rustc().input("foo.rs").emit("asm=asm-emit2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "asm-emit3", || { - rustc().input("foo.rs").arg("--emit=asm=asm-emit3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "asm-emit".to_string(), + }, + || { + rustc().input("foo.rs").emit("asm").output("asm-emit/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "asm-emit2".to_string(), + }, + || { + rustc().input("foo.rs").emit("asm=asm-emit2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "asm-emit3".to_string(), + }, + || { + rustc().input("foo.rs").arg("--emit=asm=asm-emit3/foo").run(); + }, + ); - assert_expected_output_files(&["foo"], &[], "llvm-ir-emit", || { - rustc().input("foo.rs").emit("llvm-ir").output("llvm-ir-emit/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "llvm-ir-emit2", || { - rustc().input("foo.rs").emit("llvm-ir=llvm-ir-emit2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "llvm-ir-emit3", || { - rustc().input("foo.rs").arg("--emit=llvm-ir=llvm-ir-emit3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-ir-emit".to_string(), + }, + || { + rustc().input("foo.rs").emit("llvm-ir").output("llvm-ir-emit/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-ir-emit2".to_string(), + }, + || { + rustc().input("foo.rs").emit("llvm-ir=llvm-ir-emit2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-ir-emit3".to_string(), + }, + || { + rustc().input("foo.rs").arg("--emit=llvm-ir=llvm-ir-emit3/foo").run(); + }, + ); - assert_expected_output_files(&["foo"], &[], "llvm-bc-emit", || { - rustc().input("foo.rs").emit("llvm-bc").output("llvm-bc-emit/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "llvm-bc-emit2", || { - rustc().input("foo.rs").emit("llvm-bc=llvm-bc-emit2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "llvm-bc-emit3", || { - rustc().input("foo.rs").arg("--emit=llvm-bc=llvm-bc-emit3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-bc-emit".to_string(), + }, + || { + rustc().input("foo.rs").emit("llvm-bc").output("llvm-bc-emit/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-bc-emit2".to_string(), + }, + || { + rustc().input("foo.rs").emit("llvm-bc=llvm-bc-emit2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "llvm-bc-emit3".to_string(), + }, + || { + rustc().input("foo.rs").arg("--emit=llvm-bc=llvm-bc-emit3/foo").run(); + }, + ); - assert_expected_output_files(&["foo"], &[], "obj-emit", || { - rustc().input("foo.rs").emit("obj").output("obj-emit/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "obj-emit2", || { - rustc().input("foo.rs").emit("obj=obj-emit2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "obj-emit3", || { - rustc().input("foo.rs").arg("--emit=obj=obj-emit3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "obj-emit".to_string(), + }, + || { + rustc().input("foo.rs").emit("obj").output("obj-emit/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "obj-emit2".to_string(), + }, + || { + rustc().input("foo.rs").emit("obj=obj-emit2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "obj-emit3".to_string(), + }, + || { + rustc().input("foo.rs").arg("--emit=obj=obj-emit3/foo").run(); + }, + ); - assert_expected_output_files(&[bin_foo], &[], "link-emit", || { - rustc().input("foo.rs").emit("link").output("link-emit/".to_owned() + bin_foo).run(); - }); - assert_expected_output_files(&[bin_foo], &[], "link-emit2", || { - rustc().input("foo.rs").emit(&format!("link=link-emit2/{bin_foo}")).run(); - }); - assert_expected_output_files(&[bin_foo], &[], "link-emit3", || { - rustc().input("foo.rs").arg(&format!("--emit=link=link-emit3/{bin_foo}")).run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s![&bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "link-emit".to_string(), + }, + || { + rustc().input("foo.rs").emit("link").output("link-emit/".to_owned() + &bin_foo).run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s![&bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "link-emit2".to_string(), + }, + || { + rustc().input("foo.rs").emit(&format!("link=link-emit2/{bin_foo}")).run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s![&bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "link-emit3".to_string(), + }, + || { + rustc().input("foo.rs").arg(&format!("--emit=link=link-emit3/{bin_foo}")).run(); + }, + ); - assert_expected_output_files(&["foo"], &[], "rlib", || { - rustc().crate_type("rlib").input("foo.rs").output("rlib/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "rlib2", || { - rustc().crate_type("rlib").input("foo.rs").emit("link=rlib2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "rlib3", || { - rustc().crate_type("rlib").input("foo.rs").arg("--emit=link=rlib3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "rlib".to_string(), + }, + || { + rustc().crate_type("rlib").input("foo.rs").output("rlib/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "rlib2".to_string(), + }, + || { + rustc().crate_type("rlib").input("foo.rs").emit("link=rlib2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "rlib3".to_string(), + }, + || { + rustc().crate_type("rlib").input("foo.rs").arg("--emit=link=rlib3/foo").run(); + }, + ); assert_expected_output_files( - &[bin_foo], - &[ - "libbar.ddl.exp", - "libbar.dll.lib", - "libbar.pdb", - "libbar.dll.a", - "libbar.exe.a", - "bar.ddl.exp", - "bar.dll.lib", - "bar.pdb", - "bar.dll.a", - "bar.exe.a", - ], - "dylib", - || { - rustc().crate_type("dylib").input("foo.rs").output("dylib/".to_owned() + bin_foo).run(); - }, - ); - assert_expected_output_files( - &[bin_foo], - &[ - "libbar.ddl.exp", - "libbar.dll.lib", - "libbar.pdb", - "libbar.dll.a", - "libbar.exe.a", - "bar.ddl.exp", - "bar.dll.lib", - "bar.pdb", - "bar.dll.a", - "bar.exe.a", - ], - "dylib2", + Expectations { + expected_files: s![bin_foo], + allowed_files: s![ + "libfoo.dll.exp", + "libfoo.dll.lib", + "libfoo.pdb", + "libfoo.dll.a", + "libfoo.exe.a", + "foo.dll.exp", + "foo.dll.lib", + "foo.pdb", + "foo.dll.a", + "foo.exe.a" + ], + test_dir: "dylib".to_string(), + }, + || { + rustc() + .crate_type("dylib") + .input("foo.rs") + .output("dylib/".to_owned() + &bin_foo) + .run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s![bin_foo], + allowed_files: s![ + "libfoo.dll.exp", + "libfoo.dll.lib", + "libfoo.pdb", + "libfoo.dll.a", + "libfoo.exe.a", + "foo.dll.exp", + "foo.dll.lib", + "foo.pdb", + "foo.dll.a", + "foo.exe.a" + ], + test_dir: "dylib2".to_string(), + }, || { rustc() .crate_type("dylib") @@ -180,20 +347,22 @@ fn main() { }, ); assert_expected_output_files( - &[bin_foo], - &[ - "libbar.ddl.exp", - "libbar.dll.lib", - "libbar.pdb", - "libbar.dll.a", - "libbar.exe.a", - "bar.ddl.exp", - "bar.dll.lib", - "bar.pdb", - "bar.dll.a", - "bar.exe.a", - ], - "dylib3", + Expectations { + expected_files: s![bin_foo], + allowed_files: s![ + "libfoo.dll.exp", + "libfoo.dll.lib", + "libfoo.pdb", + "libfoo.dll.a", + "libfoo.exe.a", + "foo.dll.exp", + "foo.dll.lib", + "foo.pdb", + "foo.dll.a", + "foo.exe.a" + ], + test_dir: "dylib3".to_string(), + }, || { rustc() .crate_type("dylib") @@ -203,55 +372,121 @@ fn main() { }, ); - assert_expected_output_files(&["foo"], &[], "staticlib", || { - rustc().crate_type("staticlib").input("foo.rs").output("staticlib/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "staticlib2", || { - rustc().crate_type("staticlib").input("foo.rs").emit("link=staticlib2/foo").run(); - }); - assert_expected_output_files(&["foo"], &[], "staticlib3", || { - rustc().crate_type("staticlib").input("foo.rs").arg("--emit=link=staticlib3/foo").run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "staticlib".to_string(), + }, + || { + rustc().crate_type("staticlib").input("foo.rs").output("staticlib/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "staticlib2".to_string(), + }, + || { + rustc().crate_type("staticlib").input("foo.rs").emit("link=staticlib2/foo").run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["foo"], + allowed_files: s![], + test_dir: "staticlib3".to_string(), + }, + || { + rustc().crate_type("staticlib").input("foo.rs").arg("--emit=link=staticlib3/foo").run(); + }, + ); - assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate", || { - rustc().crate_type("bin").input("foo.rs").output("bincrate/".to_owned() + bin_foo).run(); - }); - assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate2", || { - rustc().crate_type("bin").input("foo.rs").emit(&format!("link=bincrate2/{bin_foo}")).run(); - }); - assert_expected_output_files(&["foo"], &["foo.pdb"], "bincrate3", || { - rustc() - .crate_type("bin") - .input("foo.rs") - .arg(&format!("--emit=link=bincrate3/{bin_foo}")) - .run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s![bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "bincrate".to_string(), + }, + || { + rustc() + .crate_type("bin") + .input("foo.rs") + .output("bincrate/".to_owned() + &bin_foo) + .run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s![bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "bincrate2".to_string(), + }, + || { + rustc() + .crate_type("bin") + .input("foo.rs") + .emit(&format!("link=bincrate2/{bin_foo}")) + .run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s![bin_foo], + allowed_files: s!["foo.pdb"], + test_dir: "bincrate3".to_string(), + }, + || { + rustc() + .crate_type("bin") + .input("foo.rs") + .arg(&format!("--emit=link=bincrate3/{bin_foo}")) + .run(); + }, + ); - assert_expected_output_files(&["ir", rust_bar], &[], "rlib-ir", || { - rustc() - .input("foo.rs") - .emit("llvm-ir=rlib-ir/ir") - .emit("link") - .crate_type("rlib") - .out_dir("rlib-ir") - .run(); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["ir", rust_lib_name("bar")], + allowed_files: s![], + test_dir: "rlib-ir".to_string(), + }, + || { + rustc() + .input("foo.rs") + .emit("llvm-ir=rlib-ir/ir") + .emit("link") + .crate_type("rlib") + .out_dir("rlib-ir") + .run(); + }, + ); - assert_expected_output_files(&["ir", "asm", "bc", "obj", "link"], &[], "staticlib-all", || { - rustc() - .input("foo.rs") - .emit("asm=staticlib-all/asm") - .emit("llvm-ir=staticlib-all/ir") - .emit("llvm-bc=staticlib-all/bc") - .emit("obj=staticlib-all/obj") - .emit("link=staticlib-all/link") - .crate_type("staticlib") - .run(); - }); - assert_expected_output_files( - &["ir", "asm", "bc", "obj", "link"], - &[], - "staticlib-all2", + assert_expected_output_files( + Expectations { + expected_files: s!["ir", "asm", "bc", "obj", "link"], + allowed_files: s![], + test_dir: "staticlib-all".to_string(), + }, + || { + rustc() + .input("foo.rs") + .emit("asm=staticlib-all/asm") + .emit("llvm-ir=staticlib-all/ir") + .emit("llvm-bc=staticlib-all/bc") + .emit("obj=staticlib-all/obj") + .emit("link=staticlib-all/link") + .crate_type("staticlib") + .run(); + }, + ); + assert_expected_output_files( + Expectations { + expected_files: s!["ir", "asm", "bc", "obj", "link"], + allowed_files: s![], + test_dir: "staticlib-all2".to_string(), + }, || { rustc() .input("foo.rs") @@ -268,9 +503,11 @@ fn main() { ); assert_expected_output_files( - &["bar.ll", "bar.s", "bar.o", static_bar], - &["bar.bc"], // keep this one for the next test - "staticlib-all3", + Expectations { + expected_files: s!["bar.ll", "bar.s", "bar.o", static_lib_name("bar")], + allowed_files: s!["bar.bc"], // keep this one for the next test + test_dir: "staticlib-all3".to_string(), + }, || { rustc() .input("foo.rs") @@ -283,9 +520,24 @@ fn main() { // the .bc file from the previous test should be equivalent to this one, despite the difference // in crate type - assert_expected_output_files(&["bar.bc", rust_bar, "foo.bc"], &[], "rlib-emits", || { - fs_wrapper::rename("staticlib-all3/bar.bc", "rlib-emits/foo.bc"); - rustc().input("foo.rs").emit("llvm-bc,link").crate_type("rlib").out_dir("rlib-emits").run(); - assert_eq!(fs_wrapper::read("rlib-emits/foo.bc"), fs_wrapper::read("rlib-emits/bar.bc")); - }); + assert_expected_output_files( + Expectations { + expected_files: s!["bar.bc", rust_lib_name("bar"), "foo.bc"], + allowed_files: s![], + test_dir: "rlib-emits".to_string(), + }, + || { + fs_wrapper::rename("staticlib-all3/bar.bc", "rlib-emits/foo.bc"); + rustc() + .input("foo.rs") + .emit("llvm-bc,link") + .crate_type("rlib") + .out_dir("rlib-emits") + .run(); + assert_eq!( + fs_wrapper::read("rlib-emits/foo.bc"), + fs_wrapper::read("rlib-emits/bar.bc") + ); + }, + ); } From c9be69fd0a6214902749338074c7617cb9f40366 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 27 Jun 2024 13:51:53 -0400 Subject: [PATCH 37/63] Add shallow_find_files helper function to run-make-support --- src/tools/run-make-support/src/lib.rs | 1 + tests/run-make/pgo-gen/rmake.rs | 12 ++++++------ tests/run-make/pgo-use/rmake.rs | 27 ++++++++++++++------------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 6c1bcc6d7cd90..af5ae6a8e608c 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -272,6 +272,7 @@ pub fn shallow_find_files, F: Fn(&PathBuf) -> bool>( for entry in fs_wrapper::read_dir(path) { let entry = entry.expect("failed to read directory entry."); let path = entry.path(); + if path.is_file() && closure(&path) { matching_files.push(path); } diff --git a/tests/run-make/pgo-gen/rmake.rs b/tests/run-make/pgo-gen/rmake.rs index d35b29302648e..ad2f6388e8fff 100644 --- a/tests/run-make/pgo-gen/rmake.rs +++ b/tests/run-make/pgo-gen/rmake.rs @@ -6,13 +6,13 @@ //@ needs-profiler-support //@ ignore-cross-compile -use run_make_support::{cwd, find_files_by_prefix_and_extension, run, rustc}; +use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files}; fn main() { - rustc().arg("-g").profile_generate(cwd()).run(); + rustc().arg("-g").profile_generate(cwd()).input("test.rs").run(); run("test"); - assert!( - find_files_by_prefix_and_extension(cwd(), "default", "profraw").len() > 0, - "no .profraw file generated" - ); + let profraw_files = shallow_find_files(cwd(), |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + assert!(!profraw_files.is_empty(), "no .profraw file generated"); } diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs index 04777821b51b0..0f76aff80d0ca 100644 --- a/tests/run-make/pgo-use/rmake.rs +++ b/tests/run-make/pgo-use/rmake.rs @@ -9,8 +9,8 @@ //@ ignore-cross-compile use run_make_support::{ - cwd, find_files_by_prefix_and_extension, fs_wrapper, llvm_filecheck, llvm_profdata, - run_with_args, rustc, + cwd, fs_wrapper, has_extension, has_prefix, llvm_filecheck, llvm_profdata, run_with_args, + rustc, shallow_find_files, }; fn main() { @@ -28,11 +28,11 @@ fn main() { // Run it in order to generate some profiling data run_with_args("main", &["some-argument"]); // Postprocess the profiling data so it can be used by the compiler - llvm_profdata() - .merge() - .output("merged.profdata") - .input(find_files_by_prefix_and_extension(cwd(), "default", "profraw").get(0).unwrap()) - .run(); + let profraw_files = shallow_find_files(cwd(), |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profraw_file = profraw_files.get(0).unwrap(); + llvm_profdata().merge().output("merged.profdata").input(profraw_file).run(); // Compile the test program again, making use of the profiling data rustc() .opt_level("2") @@ -42,13 +42,14 @@ fn main() { .emit("llvm-ir") .input("main.rs") .run(); - // Check that the generate IR contains some things that we expect - // - // We feed the file into LLVM FileCheck tool *in reverse* so that we see the + // Check that the generate IR contains some things that we expect. + // We feed the file into LLVM FileCheck tool *with its lines reversed* so that we see the // line with the function name before the line with the function attributes. // FileCheck only supports checking that something matches on the next line, // but not if something matches on the previous line. - let mut bytes = fs_wrapper::read("interesting.ll"); - bytes.reverse(); - llvm_filecheck().patterns("filecheck-patterns.txt").stdin(bytes).run(); + let ir = fs_wrapper::read_to_string("main.ll"); + let lines: Vec<_> = ir.lines().rev().collect(); + let mut reversed_ir = lines.join("\n"); + reversed_ir.push('\n'); + llvm_filecheck().patterns("filecheck-patterns.txt").stdin(reversed_ir.as_bytes()).run(); } From 7dca61b68b50b7e38bf3cec027eec2002755b2a4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 5 Jul 2024 15:00:40 +0000 Subject: [PATCH 38/63] Use `ControlFlow` results for visitors that are only looking for a single value --- .../src/diagnostics/conflict_errors.rs | 61 ++++++--------- .../src/deriving/default.rs | 2 +- .../src/collect/generics_of.rs | 74 ++++++++----------- .../src/fn_ctxt/inspect_obligations.rs | 2 - .../src/traits/object_safety.rs | 5 +- .../rustc_trait_selection/src/traits/wf.rs | 2 - 6 files changed, 59 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index e291ebd9bb832..c2c3f5bc79ed1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -39,6 +39,7 @@ use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::FindExprBySpan; use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; use std::iter; +use std::ops::ControlFlow; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; @@ -784,20 +785,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { /// binding declaration within every scope we inspect. struct Finder { hir_id: hir::HirId, - found: bool, } impl<'hir> Visitor<'hir> for Finder { - fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) { + type Result = ControlFlow<()>; + fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) -> Self::Result { if pat.hir_id == self.hir_id { - self.found = true; + return ControlFlow::Break(()); } - hir::intravisit::walk_pat(self, pat); + hir::intravisit::walk_pat(self, pat) } - fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { + fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) -> Self::Result { if ex.hir_id == self.hir_id { - self.found = true; + return ControlFlow::Break(()); } - hir::intravisit::walk_expr(self, ex); + hir::intravisit::walk_expr(self, ex) } } // The immediate HIR parent of the moved expression. We'll look for it to be a call. @@ -822,9 +823,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { _ => continue, }; if let Some(&hir_id) = local_hir_id { - let mut finder = Finder { hir_id, found: false }; - finder.visit_expr(e); - if finder.found { + if (Finder { hir_id }).visit_expr(e).is_break() { // The current scope includes the declaration of the binding we're accessing, we // can't look up any further for loops. break; @@ -839,9 +838,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If(cond, ..), .. }) => { - let mut finder = Finder { hir_id: expr.hir_id, found: false }; - finder.visit_expr(cond); - if finder.found { + if (Finder { hir_id: expr.hir_id }).visit_expr(cond).is_break() { // The expression where the move error happened is in a `while let` // condition Don't suggest clone as it will likely end in an // infinite loop. @@ -1837,7 +1834,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { pub struct Holds<'tcx> { ty: Ty<'tcx>, - holds: bool, } impl<'tcx> TypeVisitor> for Holds<'tcx> { @@ -1845,7 +1841,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t == self.ty { - self.holds = true; + return ControlFlow::Break(()); } t.super_visit_with(self) } @@ -1863,9 +1859,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { && rcvr_ty == ty && let ty::Ref(_, inner, _) = rcvr_ty.kind() && let inner = inner.peel_refs() - && let mut v = (Holds { ty: inner, holds: false }) - && let _ = v.visit_ty(local_ty) - && v.holds + && (Holds { ty: inner }).visit_ty(local_ty).is_break() && let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env) { err.span_label( @@ -4325,15 +4319,14 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { } /// Detect whether one of the provided spans is a statement nested within the top-most visited expr -struct ReferencedStatementsVisitor<'a>(&'a [Span], bool); +struct ReferencedStatementsVisitor<'a>(&'a [Span]); -impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> { - fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { +impl<'v> Visitor<'v> for ReferencedStatementsVisitor<'_> { + type Result = ControlFlow<()>; + fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result { match s.kind { - hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => { - self.1 = true; - } - _ => {} + hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => ControlFlow::Break(()), + _ => ControlFlow::Continue(()), } } } @@ -4375,9 +4368,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> { hir::ExprKind::If(cond, body, None) => { // `if` expressions with no `else` that initialize the binding might be missing an // `else` arm. - let mut v = ReferencedStatementsVisitor(self.spans, false); - v.visit_expr(body); - if v.1 { + if ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break() { self.errors.push(( cond.span, format!( @@ -4394,11 +4385,9 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> { hir::ExprKind::If(cond, body, Some(other)) => { // `if` expressions where the binding is only initialized in one of the two arms // might be missing a binding initialization. - let mut a = ReferencedStatementsVisitor(self.spans, false); - a.visit_expr(body); - let mut b = ReferencedStatementsVisitor(self.spans, false); - b.visit_expr(other); - match (a.1, b.1) { + let a = ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break(); + let b = ReferencedStatementsVisitor(self.spans).visit_expr(other).is_break(); + match (a, b) { (true, true) | (false, false) => {} (true, false) => { if other.span.is_desugaring(DesugaringKind::WhileLoop) { @@ -4437,11 +4426,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> { // arms might be missing an initialization. let results: Vec = arms .iter() - .map(|arm| { - let mut v = ReferencedStatementsVisitor(self.spans, false); - v.visit_arm(arm); - v.1 - }) + .map(|arm| ReferencedStatementsVisitor(self.spans).visit_arm(arm).is_break()) .collect(); if results.iter().any(|x| *x) && !results.iter().all(|x| *x) { for (arm, seen) in arms.iter().zip(results) { diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 577523a1d5a32..7a65ed97f00c2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -240,7 +240,7 @@ fn has_a_default_variant(item: &Annotatable) -> bool { if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) { ControlFlow::Break(()) } else { - // no need to subrecurse. + // no need to walk the variant, we are only looking for top level variants ControlFlow::Continue(()) } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9b02c1a61fa97..22d465c8e62be 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use crate::middle::resolve_bound_vars as rbv; use hir::{ intravisit::{self, Visitor}, @@ -87,14 +89,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamTyDetector { - in_param_ty: false, - found_anon_const_in_param_ty: false, - ct: hir_id, - }; + let mut visitor = AnonConstInParamTyDetector { in_param_ty: false, ct: hir_id }; - visitor.visit_generics(generics); - in_param_ty = visitor.found_anon_const_in_param_ty; + in_param_ty = visitor.visit_generics(generics).is_break(); break; } } @@ -460,50 +457,45 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option { tcx: TyCtxt<'tcx>, outer_index: ty::DebruijnIndex, - has_late_bound_regions: Option, } impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - if self.has_late_bound_regions.is_some() { - return; - } + type Result = ControlFlow; + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) -> ControlFlow { match ty.kind { hir::TyKind::BareFn(..) => { self.outer_index.shift_in(1); - intravisit::walk_ty(self, ty); + let res = intravisit::walk_ty(self, ty); self.outer_index.shift_out(1); + res } _ => intravisit::walk_ty(self, ty), } } - fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) { - if self.has_late_bound_regions.is_some() { - return; - } + fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) -> ControlFlow { self.outer_index.shift_in(1); - intravisit::walk_poly_trait_ref(self, tr); + let res = intravisit::walk_poly_trait_ref(self, tr); self.outer_index.shift_out(1); + res } - fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { - if self.has_late_bound_regions.is_some() { - return; - } - + fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) -> ControlFlow { match self.tcx.named_bound_var(lt.hir_id) { - Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {} + Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => { + ControlFlow::Continue(()) + } Some(rbv::ResolvedArg::LateBound(debruijn, _, _)) - if debruijn < self.outer_index => {} + if debruijn < self.outer_index => + { + ControlFlow::Continue(()) + } Some( rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..) | rbv::ResolvedArg::Error(_), ) - | None => { - self.has_late_bound_regions = Some(lt.ident.span); - } + | None => ControlFlow::Break(lt.ident.span), } } } @@ -513,11 +505,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option, decl: &'tcx hir::FnDecl<'tcx>, ) -> Option { - let mut visitor = LateBoundRegionsDetector { - tcx, - outer_index: ty::INNERMOST, - has_late_bound_regions: None, - }; + let mut visitor = LateBoundRegionsDetector { tcx, outer_index: ty::INNERMOST }; for param in generics.params { if let GenericParamKind::Lifetime { .. } = param.kind { if tcx.is_late_bound(param.hir_id) { @@ -525,8 +513,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamTyDetector { - fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { + type Result = ControlFlow<()>; + + fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result { if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; - self.visit_ty(ty); + let res = self.visit_ty(ty); self.in_param_ty = prev; + res + } else { + ControlFlow::Continue(()) } } - fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { + fn visit_anon_const(&mut self, c: &'v hir::AnonConst) -> Self::Result { if self.in_param_ty && self.ct == c.hir_id { - self.found_anon_const_in_param_ty = true; - } else { - intravisit::walk_anon_const(self, c) + return ControlFlow::Break(()); } + intravisit::walk_anon_const(self, c) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index fab7eb7495c5f..90dd5f73586b3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -104,8 +104,6 @@ struct NestedObligationsForSelfTy<'a, 'tcx> { } impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> { - type Result = (); - fn span(&self) -> Span { self.root_cause.span } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index f1611bd049de9..5b2c8fb1950d8 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -805,10 +805,11 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( .unwrap() .contains(&data.trait_ref(self.tcx).def_id); + // only walk contained types if it's not a super trait if is_supertrait_of_current_trait { - ControlFlow::Continue(()) // do not walk contained types, do not report error, do collect $200 + ControlFlow::Continue(()) } else { - t.super_visit_with(self) // DO walk contained types, POSSIBLY reporting an error + t.super_visit_with(self) // POSSIBLY reporting an error } } _ => t.super_visit_with(self), // walk contained types, if any diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e3952679f96b3..f071dc6c78486 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -640,8 +640,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { - type Result = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind()); From 5fd5b650935c27754dcf8cef06df37c3b91818eb Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 5 Jul 2024 11:06:18 -0400 Subject: [PATCH 39/63] Rename edition 2021 fail test --- ....rs => ref_pat_eat_one_layer_2021_fail.rs} | 0 ...=> ref_pat_eat_one_layer_2021_fail.stderr} | 20 +++++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) rename tests/ui/match/ref_pat_eat_one_layer_2024/{ref_pat_eat_one_layer_2021.rs => ref_pat_eat_one_layer_2021_fail.rs} (100%) rename tests/ui/match/ref_pat_eat_one_layer_2024/{ref_pat_eat_one_layer_2021.stderr => ref_pat_eat_one_layer_2021_fail.stderr} (88%) diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.rs similarity index 100% rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs rename to tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.rs diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.stderr similarity index 88% rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr rename to tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.stderr index 28706f89c066b..1a921234ea069 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:5:22 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:5:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -14,7 +14,7 @@ LL | if let Some(Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:10:23 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:10:23 | LL | let _: &u32 = x; | ---- ^ expected `&u32`, found integer @@ -27,7 +27,7 @@ LL | let _: &u32 = &x; | + error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:13:23 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:13:23 | LL | if let Some(Some(&&x)) = &Some(Some(&0)) { | ^^ --------------- this expression has type `&Option>` @@ -43,7 +43,7 @@ LL + if let Some(Some(&x)) = &Some(Some(&0)) { | error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:17:17 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:17:17 | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ^^^^^^^^ -------------- this expression has type `&Option>` @@ -54,7 +54,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:21:22 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` @@ -64,7 +64,7 @@ LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { = note: expected type `{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/ref_pat_eat_one_layer_2021.rs:21:22 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ @@ -74,7 +74,7 @@ LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:25:22 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:25:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -89,7 +89,7 @@ LL | if let Some(Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:29:27 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:29:27 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` @@ -104,7 +104,7 @@ LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2021.rs:33:23 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` @@ -114,7 +114,7 @@ LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { = note: expected type `{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/ref_pat_eat_one_layer_2021.rs:33:23 + --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ From 291ed596f71b4a9829cb1d93a177a52b677deabd Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Fri, 5 Jul 2024 18:10:05 +0300 Subject: [PATCH 40/63] Added dots at the sentence ends of rustc AST doc --- compiler/rustc_ast/src/ast.rs | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index dbbc4980050de..1e1339fe14457 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -176,7 +176,7 @@ pub enum GenericArgs { AngleBracketed(AngleBracketedArgs), /// The `(A, B)` and `C` in `Foo(A, B) -> C`. Parenthesized(ParenthesizedArgs), - /// `(..)` in return type notation + /// `(..)` in return type notation. ParenthesizedElided(Span), } @@ -197,11 +197,11 @@ impl GenericArgs { /// Concrete argument in the sequence of generic args. #[derive(Clone, Encodable, Decodable, Debug)] pub enum GenericArg { - /// `'a` in `Foo<'a>` + /// `'a` in `Foo<'a>`. Lifetime(Lifetime), - /// `Bar` in `Foo` + /// `Bar` in `Foo`. Type(P), - /// `1` in `Foo<1>` + /// `1` in `Foo<1>`. Const(AnonConst), } @@ -355,7 +355,7 @@ pub enum GenericParamKind { ty: P, /// Span of the `const` keyword. kw_span: Span, - /// Optional default value for the const generic param + /// Optional default value for the const generic param. default: Option, }, } @@ -832,7 +832,7 @@ pub enum PatKind { /// only one rest pattern may occur in the pattern sequences. Rest, - // A never pattern `!` + // A never pattern `!`. Never, /// Parentheses in patterns used for grouping (i.e., `(PAT)`). @@ -1121,9 +1121,9 @@ impl LocalKind { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Arm { pub attrs: AttrVec, - /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }` + /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`. pub pat: P, - /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }` + /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`. pub guard: Option>, /// Match arm body. Omitted if the pattern is a never pattern. pub body: Option>, @@ -1354,12 +1354,12 @@ pub struct Closure { pub fn_arg_span: Span, } -/// Limit types of a range (inclusive or exclusive) +/// Limit types of a range (inclusive or exclusive). #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)] pub enum RangeLimits { - /// Inclusive at the beginning, exclusive at the end + /// Inclusive at the beginning, exclusive at the end. HalfOpen, - /// Inclusive at the beginning and end + /// Inclusive at the beginning and end. Closed, } @@ -1400,9 +1400,9 @@ pub struct StructExpr { pub enum ExprKind { /// An array (e.g, `[a, b, c, d]`). Array(ThinVec>), - /// Allow anonymous constants from an inline `const` block + /// Allow anonymous constants from an inline `const` block. ConstBlock(AnonConst), - /// A function call + /// A function call. /// /// The first field resolves to the function itself, /// and the second field is the list of arguments. @@ -1456,7 +1456,7 @@ pub enum ExprKind { /// A block (`'label: { ... }`). Block(P, Option