From 49d2d5a1161720ccd5b76ac2afbdceb6ea7e2e6e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jan 2025 15:02:41 +0100 Subject: [PATCH 01/31] Extract `unescape` from `rustc_lexer` into its own crate --- Cargo.lock | 7 +++++++ compiler/rustc_ast/Cargo.toml | 1 + compiler/rustc_ast/src/util/literal.rs | 2 +- compiler/rustc_lexer/src/lib.rs | 1 - compiler/rustc_parse/Cargo.toml | 1 + compiler/rustc_parse/src/lexer/mod.rs | 6 +++--- .../rustc_parse/src/lexer/unescape_error_reporting.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse_format/Cargo.toml | 1 + compiler/rustc_parse_format/src/lib.rs | 11 ++++++----- library/literal-escaper/Cargo.toml | 10 ++++++++++ library/literal-escaper/README.md | 4 ++++ .../unescape.rs => library/literal-escaper/src/lib.rs | 0 .../unescape => library/literal-escaper/src}/tests.rs | 0 14 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 library/literal-escaper/Cargo.toml create mode 100644 library/literal-escaper/README.md rename compiler/rustc_lexer/src/unescape.rs => library/literal-escaper/src/lib.rs (100%) rename {compiler/rustc_lexer/src/unescape => library/literal-escaper/src}/tests.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index fc4c7c9888f..63441814d4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2151,6 +2151,10 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +[[package]] +name = "literal-escaper" +version = "0.0.1" + [[package]] name = "lld-wrapper" version = "0.1.0" @@ -3366,6 +3370,7 @@ name = "rustc_ast" version = "0.0.0" dependencies = [ "bitflags", + "literal-escaper", "memchr", "rustc_ast_ir", "rustc_data_structures", @@ -4325,6 +4330,7 @@ name = "rustc_parse" version = "0.0.0" dependencies = [ "bitflags", + "literal-escaper", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -4347,6 +4353,7 @@ dependencies = [ name = "rustc_parse_format" version = "0.0.0" dependencies = [ + "literal-escaper", "rustc_index", "rustc_lexer", ] diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 34c612dac69..176c2d6f8a7 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +literal-escaper = { path = "../../library/literal-escaper" } memchr = "2.7.4" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 6896ac723fa..121331ece6d 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -2,7 +2,7 @@ use std::{ascii, fmt, str}; -use rustc_lexer::unescape::{ +use literal_escaper::{ MixedUnit, Mode, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, }; use rustc_span::{Span, Symbol, kw, sym}; diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index c63ab77deca..334f451a39c 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -27,7 +27,6 @@ // tidy-alphabetical-end mod cursor; -pub mod unescape; #[cfg(test)] mod tests; diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 2360914a0ab..109e1f5c093 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +literal-escaper = { path = "../../library/literal-escaper" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 792e2cc26ef..cefaf13e31f 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,12 +1,12 @@ use std::ops::Range; +use literal_escaper::{self, EscapeError, Mode}; use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey}; -use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ @@ -970,7 +970,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_unicode(src, mode, &mut |span, result| { + literal_escaper::unescape_unicode(src, mode, &mut |span, result| { callback(span, result.map(drop)) }) }) @@ -986,7 +986,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_mixed(src, mode, &mut |span, result| { + literal_escaper::unescape_mixed(src, mode, &mut |span, result| { callback(span, result.map(drop)) }) }) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 2e066f0179c..e8aa400e73d 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,8 +3,8 @@ use std::iter::once; use std::ops::Range; +use literal_escaper::{EscapeError, Mode}; use rustc_errors::{Applicability, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; use tracing::debug; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0e6c2177da..0b745217bc8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -6,6 +6,7 @@ use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; +use literal_escaper::unescape_char; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; @@ -21,7 +22,6 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; -use rustc_lexer::unescape::unescape_char; use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 707c4e31847..51ea46f4c9b 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +literal-escaper = { path = "../../library/literal-escaper" } rustc_index = { path = "../rustc_index", default-features = false } rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 3b985621b57..7e89f9b079b 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -19,7 +19,6 @@ pub use Alignment::*; pub use Count::*; pub use Position::*; -use rustc_lexer::unescape; // Note: copied from rustc_span /// Range inside of a `Span` used for diagnostics when we only have access to relative positions. @@ -1095,12 +1094,14 @@ fn find_width_map_from_snippet( fn unescape_string(string: &str) -> Option { let mut buf = String::new(); let mut ok = true; - unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| { - match unescaped_char { + literal_escaper::unescape_unicode( + string, + literal_escaper::Mode::Str, + &mut |_, unescaped_char| match unescaped_char { Ok(c) => buf.push(c), Err(_) => ok = false, - } - }); + }, + ); ok.then_some(buf) } diff --git a/library/literal-escaper/Cargo.toml b/library/literal-escaper/Cargo.toml new file mode 100644 index 00000000000..708fcd3cacb --- /dev/null +++ b/library/literal-escaper/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "literal-escaper" +version = "0.0.0" +edition = "2021" + +[dependencies] +std = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-std' } + +[features] +rustc-dep-of-std = ["dep:std"] diff --git a/library/literal-escaper/README.md b/library/literal-escaper/README.md new file mode 100644 index 00000000000..5384ac4556a --- /dev/null +++ b/library/literal-escaper/README.md @@ -0,0 +1,4 @@ +# literal-escaper + +This crate provides code to unescape string literals. It is used by `rustc_lexer` +and `proc-macro`. diff --git a/compiler/rustc_lexer/src/unescape.rs b/library/literal-escaper/src/lib.rs similarity index 100% rename from compiler/rustc_lexer/src/unescape.rs rename to library/literal-escaper/src/lib.rs diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/library/literal-escaper/src/tests.rs similarity index 100% rename from compiler/rustc_lexer/src/unescape/tests.rs rename to library/literal-escaper/src/tests.rs From b993f9c835a3ed2119d45597f74e3eaedbf806e7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jan 2025 15:45:18 +0100 Subject: [PATCH 02/31] Add `_value` methods to proc_macro lib --- Cargo.lock | 11 +++- library/Cargo.lock | 8 +++ library/proc_macro/Cargo.toml | 1 + library/proc_macro/src/lib.rs | 114 ++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 63441814d4a..06c13942957 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2153,7 +2153,10 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "literal-escaper" -version = "0.0.1" +version = "0.0.0" +dependencies = [ + "rustc-std-workspace-std 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "lld-wrapper" @@ -3332,6 +3335,12 @@ version = "1.0.1" name = "rustc-std-workspace-std" version = "1.0.1" +[[package]] +name = "rustc-std-workspace-std" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba676a20abe46e5b0f1b0deae474aaaf31407e6c71147159890574599da04ef" + [[package]] name = "rustc_abi" version = "0.0.0" diff --git a/library/Cargo.lock b/library/Cargo.lock index 8b78908e6d7..f769fb2e1e1 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -158,6 +158,13 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "literal-escaper" +version = "0.0.0" +dependencies = [ + "rustc-std-workspace-std", +] + [[package]] name = "memchr" version = "2.7.4" @@ -220,6 +227,7 @@ name = "proc_macro" version = "0.0.0" dependencies = [ "core", + "literal-escaper", "std", ] diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml index e54a50aa15c..e5c90309f16 100644 --- a/library/proc_macro/Cargo.toml +++ b/library/proc_macro/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.0" edition = "2021" [dependencies] +literal-escaper = { path = "../literal-escaper", features = ["rustc-dep-of-std"] } std = { path = "../std" } # Workaround: when documenting this crate rustdoc will try to load crate named # `core` when resolving doc links. Without this line a different `core` will be diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 6611ce30a1b..57dd47f1060 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,6 +28,7 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(extend_one)] +#![feature(stmt_expr_attributes)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] @@ -50,11 +51,23 @@ use std::{error, fmt}; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +#[unstable(feature = "proc_macro_value", issue = "136652")] +pub use literal_escaper::EscapeError; +use literal_escaper::{MixedUnit, Mode, byte_from_char, unescape_mixed, unescape_unicode}; #[unstable(feature = "proc_macro_totokens", issue = "130977")] pub use to_tokens::ToTokens; use crate::escape::{EscapeOptions, escape_bytes}; +/// Errors returned when trying to retrieve a literal unescaped value. +#[unstable(feature = "proc_macro_value", issue = "136652")] +pub enum ConversionErrorKind { + /// The literal failed to be escaped, take a look at [`EscapeError`] for more information. + FailedToUnescape(EscapeError), + /// Trying to convert a literal with the wrong type. + InvalidLiteralKind, +} + /// Determines whether proc_macro has been made accessible to the currently /// running program. /// @@ -1450,6 +1463,107 @@ impl Literal { } }) } + + /// Returns the unescaped string value if the current literal is a string or a string literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn str_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Str => { + if symbol.contains('\\') { + let mut buf = String::with_capacity(symbol.len()); + let mut error = None; + // Force-inlining here is aggressive but the closure is + // called on every char in the string, so it can be hot in + // programs with many long strings containing escapes. + unescape_unicode( + symbol, + Mode::Str, + &mut #[inline(always)] + |_, c| match c { + Ok(c) => buf.push(c), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }, + ); + if let Some(error) = error { Err(error) } else { Ok(buf) } + } else { + Ok(symbol.to_string()) + } + } + bridge::LitKind::StrRaw(_) => Ok(symbol.to_string()), + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped string value if the current literal is a c-string or a c-string + /// literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn cstr_value(&self) -> Result, ConversionErrorKind> { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::CStr => { + let mut error = None; + let mut buf = Vec::with_capacity(symbol.len()); + + unescape_mixed(symbol, Mode::CStr, &mut |_span, c| match c { + Ok(MixedUnit::Char(c)) => { + buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) + } + Ok(MixedUnit::HighByte(b)) => buf.push(b), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + if let Some(error) = error { + Err(error) + } else { + buf.push(0); + Ok(buf) + } + } + bridge::LitKind::CStrRaw(_) => { + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc` after appending the terminating NUL + // char. + let mut buf = symbol.to_owned().into_bytes(); + buf.push(0); + Ok(buf) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped string value if the current literal is a byte string or a byte string + /// literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn byte_str_value(&self) -> Result, ConversionErrorKind> { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::ByteStr => { + let mut buf = Vec::with_capacity(symbol.len()); + let mut error = None; + + unescape_unicode(symbol, Mode::ByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Some(ConversionErrorKind::FailedToUnescape(err)); + } + } + }); + if let Some(error) = error { Err(error) } else { Ok(buf) } + } + bridge::LitKind::ByteStrRaw(_) => { + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc`. + Ok(symbol.to_owned().into_bytes()) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } } /// Parse a single literal from its stringified representation. From 615a9cd10a0d99f12c8b07a9e9fbff52b08e2139 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jan 2025 23:12:15 +0100 Subject: [PATCH 03/31] Ignore duplicated dep for `literal-escaper` --- src/bootstrap/src/core/metadata.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 983674d2c68..e6b01b2e2d9 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -63,6 +63,11 @@ pub fn build(build: &mut Build) { let relative_path = krate.local_path(build); build.crates.insert(name.clone(), krate); let existing_path = build.crate_paths.insert(relative_path, name); + // `literal-escaper` is both a dependency of `compiler/rustc_lexer` and of + // `library/proc-macro`, making it appear multiple times in the workspace. + if existing_path.as_deref() == Some("literal-escaper") { + continue; + } assert!( existing_path.is_none(), "multiple crates with the same path: {}", From 94f0f2b603bdd10fabc7e06e29d25f230d22a93f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jan 2025 23:42:09 +0100 Subject: [PATCH 04/31] Reexport `literal-escaper` from `rustc_lexer` to allow rust-analyzer to compile --- Cargo.lock | 1 + compiler/rustc_lexer/Cargo.toml | 1 + compiler/rustc_lexer/src/lib.rs | 3 +++ 3 files changed, 5 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 06c13942957..e0bf24f1eda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4074,6 +4074,7 @@ name = "rustc_lexer" version = "0.0.0" dependencies = [ "expect-test", + "literal-escaper", "memchr", "unicode-properties", "unicode-xid", diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 4b3492fdeda..5789cd01958 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -16,6 +16,7 @@ Rust lexer used by rustc. No stability guarantees are provided. [dependencies] memchr = "2.7.4" unicode-xid = "0.2.0" +literal-escaper = { path = "../../library/literal-escaper" } [dependencies.unicode-properties] version = "0.1.0" diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 334f451a39c..587ef89566a 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -31,6 +31,9 @@ mod cursor; #[cfg(test)] mod tests; +// FIXME: This is needed for rust-analyzer. Remove this dependency once rust-analyzer uses +// `literal-escaper`. +pub use literal_escaper as unescape; use unicode_properties::UnicodeEmoji; pub use unicode_xid::UNICODE_VERSION as UNICODE_XID_VERSION; From e256a21734dbd88bed0ec6934e5d6b2ab2754927 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 1 Feb 2025 00:07:21 +0100 Subject: [PATCH 05/31] Add `literal-escaper` and `rustc-std-workspace-std` to the allowed rustc deps list --- src/tools/tidy/src/deps.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index faa0db27b2b..5d871f0ab26 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -320,6 +320,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "libloading", "linux-raw-sys", "litemap", + "literal-escaper", "lock_api", "log", "matchers", @@ -366,6 +367,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "rustc-rayon", "rustc-rayon-core", "rustc-stable-hash", + "rustc-std-workspace-std", "rustc_apfloat", "rustc_version", "rustix", From d40ed632b6909f4ebf0b3cbda98615b9c2acd65b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Feb 2025 23:09:24 +0100 Subject: [PATCH 06/31] Fix bootstrap `build_all` test --- src/bootstrap/src/core/builder/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 74e1ed5c637..d72e185f51a 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -647,7 +647,7 @@ mod dist { let mut builder = Builder::new(&build); builder.run_step_descriptions( &Builder::get_step_descriptions(Kind::Build), - &["compiler/rustc".into(), "library".into()], + &["compiler/rustc".into(), "std".into()], ); assert_eq!( From 3c33cbe7789bf25611842b261f7fa07d592a672e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 6 Feb 2025 20:55:54 +0100 Subject: [PATCH 07/31] Add ui test for ensuring that users cannot use `literal-escaper` crate for the time being --- tests/ui/feature-gates/literal-escaper.rs | 3 +++ tests/ui/feature-gates/literal-escaper.stderr | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ui/feature-gates/literal-escaper.rs create mode 100644 tests/ui/feature-gates/literal-escaper.stderr diff --git a/tests/ui/feature-gates/literal-escaper.rs b/tests/ui/feature-gates/literal-escaper.rs new file mode 100644 index 00000000000..7c145fca7de --- /dev/null +++ b/tests/ui/feature-gates/literal-escaper.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +extern crate literal_escaper; //~ ERROR diff --git a/tests/ui/feature-gates/literal-escaper.stderr b/tests/ui/feature-gates/literal-escaper.stderr new file mode 100644 index 00000000000..edddb6504f5 --- /dev/null +++ b/tests/ui/feature-gates/literal-escaper.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/literal-escaper.rs:3:1 + | +LL | extern crate literal_escaper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27812 for more information + = help: add `#![feature(rustc_private)]` 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 1 previous error + +For more information about this error, try `rustc --explain E0658`. From c9ccec93fa5e87f1363f0ce6edc897340e8c3884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Thu, 26 Dec 2024 16:52:54 +0900 Subject: [PATCH 08/31] Initial STD support for Cygwin Signed-off-by: Ookiineko --- library/rtstartup/rsbegin.rs | 2 +- library/rtstartup/rsend.rs | 2 +- library/std/build.rs | 1 + library/std/src/os/cygwin/fs.rs | 122 ++++++++++++++++++ library/std/src/os/cygwin/mod.rs | 4 + library/std/src/os/cygwin/raw.rs | 70 ++++++++++ library/std/src/os/mod.rs | 2 + library/std/src/os/unix/mod.rs | 2 + library/std/src/os/unix/net/datagram.rs | 2 + library/std/src/os/unix/net/mod.rs | 1 + library/std/src/os/unix/net/stream.rs | 2 + library/std/src/os/unix/net/ucred.rs | 4 +- library/std/src/sys/fs/unix.rs | 6 +- library/std/src/sys/net/connection/socket.rs | 3 +- .../std/src/sys/net/connection/socket/unix.rs | 3 + library/std/src/sys/pal/unix/args.rs | 1 + library/std/src/sys/pal/unix/env.rs | 11 ++ library/std/src/sys/pal/unix/fd.rs | 3 + library/std/src/sys/pal/unix/mod.rs | 2 +- library/std/src/sys/pal/unix/os.rs | 2 + library/std/src/sys/pal/unix/pipe.rs | 1 + .../src/sys/pal/unix/process/process_unix.rs | 3 +- .../std/src/sys/pal/unix/stack_overflow.rs | 2 + library/std/src/sys/pal/unix/thread.rs | 5 +- 24 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 library/std/src/os/cygwin/fs.rs create mode 100644 library/std/src/os/cygwin/mod.rs create mode 100644 library/std/src/os/cygwin/raw.rs diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index 67b09599d9d..4ae218c2f9f 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -49,7 +49,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { // enumerating currently loaded modules via the dl_iterate_phdr() API and // finding their ".eh_frame" sections); Others, like Windows, require modules // to actively register their unwind info sections via unwinder API. -#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))] +#[cfg(all(any(target_os = "cygwin", all(target_os = "windows", target_env = "gnu")), target_arch = "x86"))] pub mod eh_frames { #[no_mangle] #[unsafe(link_section = ".eh_frame")] diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index a6f7d103356..9809f4b0878 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -27,7 +27,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { drop_in_place(to_drop); } -#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))] +#[cfg(all(any(target_os = "cygwin", all(target_os = "windows", target_env = "gnu")), target_arch = "x86"))] pub mod eh_frames { // Terminate the frame unwind info section with a 0 as a sentinel; // this would be the 'length' field in a real FDE. diff --git a/library/std/build.rs b/library/std/build.rs index cedfd7406a1..e4295eb2f68 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -61,6 +61,7 @@ fn main() { || target_os == "zkvm" || target_os == "rtems" || target_os == "nuttx" + || target_os == "cygwin" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/os/cygwin/fs.rs b/library/std/src/os/cygwin/fs.rs new file mode 100644 index 00000000000..a0667935ac1 --- /dev/null +++ b/library/std/src/os/cygwin/fs.rs @@ -0,0 +1,122 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] +use crate::fs::Metadata; +#[allow(deprecated)] +use crate::os::cygwin::raw; +use crate::sys_common::AsInner; +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Gain a reference to the underlying `stat` structure which contains + /// the raw information returned by the OS. + /// + /// The contents of the returned `stat` are **not** consistent across + /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the + /// cross-Unix abstractions contained within the raw stat. + #[stable(feature = "metadata_ext", since = "1.1.0")] + #[deprecated( + since = "1.8.0", + note = "deprecated in favor of the accessor \ + methods of this trait" + )] + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_birthtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_birthtime_nsec(&self) -> i64; +} +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat { + unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } + } + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } + fn st_birthtime(&self) -> i64 { + self.as_inner().as_inner().st_birthtime as i64 + } + fn st_birthtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_birthtime_nsec as i64 + } +} diff --git a/library/std/src/os/cygwin/mod.rs b/library/std/src/os/cygwin/mod.rs new file mode 100644 index 00000000000..638f738dac8 --- /dev/null +++ b/library/std/src/os/cygwin/mod.rs @@ -0,0 +1,4 @@ +//! Cygwin-specific definitions +#![stable(feature = "raw_ext", since = "1.1.0")] +pub mod fs; +pub mod raw; diff --git a/library/std/src/os/cygwin/raw.rs b/library/std/src/os/cygwin/raw.rs new file mode 100644 index 00000000000..7177b2f699c --- /dev/null +++ b/library/std/src/os/cygwin/raw.rs @@ -0,0 +1,70 @@ +//! Cygwin-specific raw type definitions +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] +use crate::os::raw::{c_long, c_void}; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = i64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = i32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = u16; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = i64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = i64; +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = *mut c_void; +#[repr(C)] +#[derive(Clone)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: ino_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: mode_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: nlink_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: off_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: blksize_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: blkcnt_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_birthtime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_birthtime_nsec: c_long, +} diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index e28a1c3e6d5..229c645b2d0 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -125,6 +125,8 @@ pub mod windows; pub mod aix; #[cfg(target_os = "android")] pub mod android; +#[cfg(target_os = "cygwin")] +pub mod cygwin; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 2f9dffe8c65..5802b653965 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -41,6 +41,8 @@ mod platform { pub use crate::os::aix::*; #[cfg(target_os = "android")] pub use crate::os::android::*; + #[cfg(target_os = "cygwin")] + pub use crate::os::cygwin::*; #[cfg(target_vendor = "apple")] pub use crate::os::darwin::*; #[cfg(target_os = "dragonfly")] diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 82446ea107f..7735637c840 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -9,6 +9,7 @@ target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "cygwin" ))] use libc::MSG_NOSIGNAL; @@ -37,6 +38,7 @@ use crate::{fmt, io}; target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "cygwin" )))] const MSG_NOSIGNAL: core::ffi::c_int = 0x0; diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index 3e45e3533ed..b07ba110c41 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -21,6 +21,7 @@ mod tests; target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] mod ucred; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index cb210b41eae..1cab04a454d 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -10,6 +10,7 @@ use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_wi target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] use super::{UCred, peer_cred}; use crate::fmt; @@ -231,6 +232,7 @@ impl UnixStream { target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] pub fn peer_cred(&self) -> io::Result { peer_cred(self) diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs index 2dd7d409e48..36fb9c46b4a 100644 --- a/library/std/src/os/unix/net/ucred.rs +++ b/library/std/src/os/unix/net/ucred.rs @@ -33,10 +33,10 @@ pub(super) use self::impl_apple::peer_cred; target_os = "nto" ))] pub(super) use self::impl_bsd::peer_cred; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(any(target_os = "android", target_os = "linux", target_os = "cygwin"))] pub(super) use self::impl_linux::peer_cred; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin"))] mod impl_linux { use libc::{SO_PEERCRED, SOL_SOCKET, c_void, getsockopt, socklen_t, ucred}; diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 914971934bf..e99d6a07731 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -543,7 +543,7 @@ impl FileAttr { SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } - #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_vendor = "apple"))] + #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_vendor = "apple", target_os = "cygwin"))] pub fn created(&self) -> io::Result { SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64) } @@ -553,6 +553,7 @@ impl FileAttr { target_os = "openbsd", target_os = "vita", target_vendor = "apple", + target_os = "cygwin", )))] pub fn created(&self) -> io::Result { cfg_has_statx! { @@ -960,6 +961,7 @@ impl DirEntry { #[cfg(any( target_os = "linux", + target_os = "cygwin", target_os = "emscripten", target_os = "android", target_os = "solaris", @@ -1220,6 +1222,7 @@ impl File { target_os = "freebsd", target_os = "fuchsia", target_os = "linux", + target_os = "cygwin", target_os = "android", target_os = "netbsd", target_os = "openbsd", @@ -1234,6 +1237,7 @@ impl File { target_os = "fuchsia", target_os = "freebsd", target_os = "linux", + target_os = "cygwin", target_os = "netbsd", target_os = "openbsd", target_os = "nto", diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket.rs index e154cf039ca..7301bde6881 100644 --- a/library/std/src/sys/net/connection/socket.rs +++ b/library/std/src/sys/net/connection/socket.rs @@ -59,7 +59,8 @@ cfg_if::cfg_if! { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "solaris", target_os = "illumos", - target_os = "haiku", target_os = "nto"))] { + target_os = "haiku", target_os = "nto", + target_os = "cygwin"))] { use libc::MSG_NOSIGNAL; } else { const MSG_NOSIGNAL: c_int = 0x0; diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index e633cf772c5..647058385a2 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -81,6 +81,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "nto", target_os = "solaris", ))] { @@ -128,6 +129,7 @@ impl Socket { target_os = "hurd", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "nto", ))] { // Like above, set cloexec atomically @@ -257,6 +259,7 @@ impl Socket { target_os = "hurd", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", ))] { unsafe { let fd = cvt_r(|| libc::accept4(self.as_raw_fd(), storage, len, libc::SOCK_CLOEXEC))?; diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 1c87a79803c..0bb7b64007a 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -100,6 +100,7 @@ impl DoubleEndedIterator for Args { target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "solaris", target_os = "illumos", target_os = "emscripten", diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/pal/unix/env.rs index 2aee0b5d460..c6609298f4b 100644 --- a/library/std/src/sys/pal/unix/env.rs +++ b/library/std/src/sys/pal/unix/env.rs @@ -108,6 +108,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "cygwin")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "cygwin"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const DLL_EXTENSION: &str = "dll"; + pub const EXE_SUFFIX: &str = ".exe"; + pub const EXE_EXTENSION: &str = "exe"; +} + #[cfg(target_os = "android")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index 2fc33bdfefb..8ec2a08966e 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -47,6 +47,7 @@ const READ_LIMIT: usize = if cfg!(target_vendor = "apple") { target_os = "netbsd", target_os = "openbsd", target_vendor = "apple", + target_os = "cygwin", ))] const fn max_iov() -> usize { libc::IOV_MAX as usize @@ -500,6 +501,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "l4re", target_os = "linux", + target_os = "cygwin", target_os = "haiku", target_os = "redox", target_os = "vxworks", @@ -522,6 +524,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "l4re", target_os = "linux", + target_os = "cygwin", target_os = "haiku", target_os = "redox", target_os = "vxworks", diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 419abe732ac..e2e537b7bd3 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -380,7 +380,7 @@ cfg_if::cfg_if! { #[link(name = "pthread")] #[link(name = "rt")] unsafe extern "C" {} - } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] { + } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd", target_os = "cygwin"))] { #[link(name = "pthread")] unsafe extern "C" {} } else if #[cfg(target_os = "solaris")] { diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 3a238d160cb..418211d24bb 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -46,6 +46,7 @@ unsafe extern "C" { any( target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "android", target_os = "redox", target_os = "nuttx", @@ -395,6 +396,7 @@ pub fn current_exe() -> io::Result { #[cfg(any( target_os = "linux", + target_os = "cygwin", target_os = "hurd", target_os = "android", target_os = "nuttx", diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 4a992e32a91..55510153dc8 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -27,6 +27,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "redox" ))] { unsafe { diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 25d9e935332..257732aaedc 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -1154,7 +1154,7 @@ fn signal_string(signal: i32) -> &'static str { ) ))] libc::SIGSTKFLT => " (SIGSTKFLT)", - #[cfg(any(target_os = "linux", target_os = "nto"))] + #[cfg(any(target_os = "linux", target_os = "nto", target_os = "cygwin"))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "freebsd", @@ -1163,6 +1163,7 @@ fn signal_string(signal: i32) -> &'static str { target_os = "dragonfly", target_os = "nto", target_vendor = "apple", + target_os = "cygwin", ))] libc::SIGEMT => " (SIGEMT)", #[cfg(any( diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0ecccdc8812..5a639d0545b 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -32,6 +32,7 @@ impl Drop for Handler { target_os = "macos", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "solaris", target_os = "illumos", ))] @@ -583,6 +584,7 @@ mod imp { target_os = "macos", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "solaris", target_os = "illumos", )))] diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 11f6998cac1..4397cb69a09 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -137,7 +137,8 @@ impl Thread { target_os = "linux", target_os = "freebsd", target_os = "dragonfly", - target_os = "nuttx" + target_os = "nuttx", + target_os = "cygwin" ))] pub fn set_name(name: &CStr) { unsafe { @@ -343,6 +344,7 @@ impl Drop for Thread { target_os = "illumos", target_os = "vxworks", target_vendor = "apple", + target_os = "cygwin", ))] fn truncate_cstr(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { let mut result = [0; MAX_WITH_NUL]; @@ -362,6 +364,7 @@ pub fn available_parallelism() -> io::Result> { target_os = "linux", target_os = "aix", target_vendor = "apple", + target_os = "cygwin", ))] { #[allow(unused_assignments)] #[allow(unused_mut)] From e3e98c84d3eb64181c25ff88f31aee432363ca12 Mon Sep 17 00:00:00 2001 From: Ookiineko Date: Mon, 4 Mar 2024 18:34:47 +0800 Subject: [PATCH 09/31] Fix `std::sys::unix::set_linger` for Cygwin Signed-off-by: Ookiineko --- library/std/src/sys/net/connection/socket/unix.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index 647058385a2..bbe1e038dcc 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -424,6 +424,7 @@ impl Socket { Ok(()) } + #[cfg(not(target_os = "cygwin"))] pub fn set_linger(&self, linger: Option) -> io::Result<()> { let linger = libc::linger { l_onoff: linger.is_some() as libc::c_int, @@ -433,6 +434,16 @@ impl Socket { setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger) } + #[cfg(target_os = "cygwin")] + pub fn set_linger(&self, linger: Option) -> io::Result<()> { + let linger = libc::linger { + l_onoff: linger.is_some() as libc::c_ushort, + l_linger: linger.unwrap_or_default().as_secs() as libc::c_ushort, + }; + + setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger) + } + pub fn linger(&self) -> io::Result> { let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?; From 1aad114afda473ccda8b0eb5e0d5a3dcfc35c40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Mon, 30 Dec 2024 05:00:20 +0900 Subject: [PATCH 10/31] Fix building for cygwin --- library/std/src/os/unix/net/mod.rs | 1 + library/std/src/sys/pal/unix/fd.rs | 1 + library/std/src/sys/pal/unix/stack_overflow.rs | 8 +++++--- library/std/src/sys/random/linux.rs | 6 +++++- library/std/src/sys/random/mod.rs | 3 ++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index b07ba110c41..6cd62303a53 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -45,6 +45,7 @@ pub use self::stream::*; target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin", ))] #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] pub use self::ucred::*; diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index 8ec2a08966e..eb873759ecb 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -75,6 +75,7 @@ const fn max_iov() -> usize { target_os = "horizon", target_os = "vita", target_vendor = "apple", + target_os = "cygwin", )))] const fn max_iov() -> usize { 16 // The minimum value required by POSIX. diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 5a639d0545b..463f18800a6 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -316,7 +316,8 @@ mod imp { target_os = "netbsd", target_os = "hurd", target_os = "linux", - target_os = "l4re" + target_os = "l4re", + target_os = "cygwin" ))] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { let mut ret = None; @@ -371,7 +372,7 @@ mod imp { // this way someone on any unix-y OS can check that all these compile if cfg!(all(target_os = "linux", not(target_env = "musl"))) { install_main_guard_linux(page_size) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { + } else if cfg!(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")) { install_main_guard_linux_musl(page_size) } else if cfg!(target_os = "freebsd") { install_main_guard_freebsd(page_size) @@ -511,7 +512,8 @@ mod imp { target_os = "hurd", target_os = "linux", target_os = "netbsd", - target_os = "l4re" + target_os = "l4re", + target_os = "cygwin" ))] // FIXME: I am probably not unsafe. unsafe fn current_guard() -> Option> { diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index e3cb79285cd..266c71abf3d 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -94,7 +94,10 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { let flags = if insecure { if GRND_INSECURE_AVAILABLE.load(Relaxed) { - libc::GRND_INSECURE + #[cfg(target_os = "cygwin")] + { libc::GRND_NONBLOCK } + #[cfg(not(target_os = "cygwin"))] + { libc::GRND_INSECURE } } else { libc::GRND_NONBLOCK } @@ -110,6 +113,7 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { libc::EINTR => continue, // `GRND_INSECURE` is not available, try // `GRND_NONBLOCK`. + #[cfg(not(target_os = "cygwin"))] libc::EINVAL if flags == libc::GRND_INSECURE => { GRND_INSECURE_AVAILABLE.store(false, Relaxed); continue; diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index f42351deb92..b6a357e5b07 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -1,6 +1,6 @@ cfg_if::cfg_if! { // Tier 1 - if #[cfg(any(target_os = "linux", target_os = "android"))] { + if #[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin"))] { mod linux; pub use linux::{fill_bytes, hashmap_random_keys}; } else if #[cfg(target_os = "windows")] { @@ -88,6 +88,7 @@ cfg_if::cfg_if! { target_os = "android", all(target_family = "wasm", target_os = "unknown"), target_os = "xous", + target_os = "cygwin", )))] pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; From 886fb15c0fb1125624a3d8e5f82f147431e8f708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Tue, 25 Feb 2025 23:33:53 +0800 Subject: [PATCH 11/31] Update metadata for cygwin target --- compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs | 2 +- src/doc/rustc/src/platform-support.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs index 8da4fe6b8b1..eac4caf41c8 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs @@ -18,7 +18,7 @@ pub(crate) fn target() -> Target { description: Some("64-bit x86 Cygwin".into()), tier: Some(3), host_tools: Some(false), - std: None, + std: Some(true), }, } } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f78ab151b9c..9048eb274b7 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -406,7 +406,7 @@ target | std | host | notes [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator -[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? | | 64-bit x86 Cygwin | +[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin | [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | [`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) | [`x86_64-pc-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 8.0 RTOS | From abcbd881754651af73f7454cbcbdab953d2e4e30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Wed, 26 Feb 2025 00:05:40 +0800 Subject: [PATCH 12/31] Revert changes for rtstartup --- library/rtstartup/rsbegin.rs | 2 +- library/rtstartup/rsend.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index 4ae218c2f9f..67b09599d9d 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -49,7 +49,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { // enumerating currently loaded modules via the dl_iterate_phdr() API and // finding their ".eh_frame" sections); Others, like Windows, require modules // to actively register their unwind info sections via unwinder API. -#[cfg(all(any(target_os = "cygwin", all(target_os = "windows", target_env = "gnu")), target_arch = "x86"))] +#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))] pub mod eh_frames { #[no_mangle] #[unsafe(link_section = ".eh_frame")] diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index 9809f4b0878..a6f7d103356 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -27,7 +27,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { drop_in_place(to_drop); } -#[cfg(all(any(target_os = "cygwin", all(target_os = "windows", target_env = "gnu")), target_arch = "x86"))] +#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))] pub mod eh_frames { // Terminate the frame unwind info section with a 0 as a sentinel; // this would be the 'length' field in a real FDE. From d24c6a29f5dca8c52ecf1ff88e4786e537078fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Wed, 26 Feb 2025 00:05:55 +0800 Subject: [PATCH 13/31] Fix code style --- library/std/src/sys/fs/unix.rs | 7 ++++++- library/std/src/sys/pal/unix/stack_overflow.rs | 3 ++- library/std/src/sys/random/linux.rs | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index e99d6a07731..7774461a493 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -543,7 +543,12 @@ impl FileAttr { SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } - #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_vendor = "apple", target_os = "cygwin"))] + #[cfg(any( + target_os = "freebsd", + target_os = "openbsd", + target_vendor = "apple", + target_os = "cygwin", + ))] pub fn created(&self) -> io::Result { SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64) } diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 463f18800a6..344f9c63257 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -372,7 +372,8 @@ mod imp { // this way someone on any unix-y OS can check that all these compile if cfg!(all(target_os = "linux", not(target_env = "musl"))) { install_main_guard_linux(page_size) - } else if cfg!(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")) { + } else if cfg!(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")) + { install_main_guard_linux_musl(page_size) } else if cfg!(target_os = "freebsd") { install_main_guard_freebsd(page_size) diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index 266c71abf3d..fb4274281d6 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -95,9 +95,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { let flags = if insecure { if GRND_INSECURE_AVAILABLE.load(Relaxed) { #[cfg(target_os = "cygwin")] - { libc::GRND_NONBLOCK } + { + libc::GRND_NONBLOCK + } #[cfg(not(target_os = "cygwin"))] - { libc::GRND_INSECURE } + { + libc::GRND_INSECURE + } } else { libc::GRND_NONBLOCK } From 7d80aaaca8f5828fe6ce265e1dc6cb2267e618a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 15:26:23 +0800 Subject: [PATCH 14/31] Remove std::os::cygwin::raw --- library/std/src/os/cygwin/fs.rs | 20 --------- library/std/src/os/cygwin/mod.rs | 1 - library/std/src/os/cygwin/raw.rs | 70 -------------------------------- 3 files changed, 91 deletions(-) delete mode 100644 library/std/src/os/cygwin/raw.rs diff --git a/library/std/src/os/cygwin/fs.rs b/library/std/src/os/cygwin/fs.rs index a0667935ac1..5533264fd51 100644 --- a/library/std/src/os/cygwin/fs.rs +++ b/library/std/src/os/cygwin/fs.rs @@ -1,27 +1,11 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] use crate::fs::Metadata; -#[allow(deprecated)] -use crate::os::cygwin::raw; use crate::sys_common::AsInner; /// OS-specific extensions to [`fs::Metadata`]. /// /// [`fs::Metadata`]: crate::fs::Metadata #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { - /// Gain a reference to the underlying `stat` structure which contains - /// the raw information returned by the OS. - /// - /// The contents of the returned `stat` are **not** consistent across - /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the - /// cross-Unix abstractions contained within the raw stat. - #[stable(feature = "metadata_ext", since = "1.1.0")] - #[deprecated( - since = "1.8.0", - note = "deprecated in favor of the accessor \ - methods of this trait" - )] - #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat; #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_dev(&self) -> u64; #[stable(feature = "metadata_ext2", since = "1.8.0")] @@ -61,10 +45,6 @@ pub trait MetadataExt { } #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for Metadata { - #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat { - unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } - } fn st_dev(&self) -> u64 { self.as_inner().as_inner().st_dev as u64 } diff --git a/library/std/src/os/cygwin/mod.rs b/library/std/src/os/cygwin/mod.rs index 638f738dac8..f6385653d77 100644 --- a/library/std/src/os/cygwin/mod.rs +++ b/library/std/src/os/cygwin/mod.rs @@ -1,4 +1,3 @@ //! Cygwin-specific definitions #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; -pub mod raw; diff --git a/library/std/src/os/cygwin/raw.rs b/library/std/src/os/cygwin/raw.rs deleted file mode 100644 index 7177b2f699c..00000000000 --- a/library/std/src/os/cygwin/raw.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Cygwin-specific raw type definitions -#![stable(feature = "raw_ext", since = "1.1.0")] -#![deprecated( - since = "1.8.0", - note = "these type aliases are no longer supported by \ - the standard library, the `libc` crate on \ - crates.io should be used instead for the correct \ - definitions" -)] -#![allow(deprecated)] -use crate::os::raw::{c_long, c_void}; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type blkcnt_t = i64; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type blksize_t = i32; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type dev_t = u32; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type ino_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type mode_t = u32; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type nlink_t = u16; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type off_t = i64; -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type time_t = i64; -#[stable(feature = "pthread_t", since = "1.8.0")] -pub type pthread_t = *mut c_void; -#[repr(C)] -#[derive(Clone)] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub struct stat { - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_dev: dev_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ino: ino_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mode: mode_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_nlink: nlink_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_uid: u32, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_gid: u32, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_rdev: dev_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_size: off_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_atime_nsec: c_long, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_mtime_nsec: c_long, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_ctime_nsec: c_long, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_blksize: blksize_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_blocks: blkcnt_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_birthtime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] - pub st_birthtime_nsec: c_long, -} From 268e73499652a27eeedd1d3e43430ebcdf1160f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 15:53:00 +0800 Subject: [PATCH 15/31] Impl cygwin rand with getrandom --- library/std/src/sys/random/cygwin.rs | 8 ++++++++ library/std/src/sys/random/linux.rs | 10 +--------- library/std/src/sys/random/mod.rs | 6 ++++-- 3 files changed, 13 insertions(+), 11 deletions(-) create mode 100644 library/std/src/sys/random/cygwin.rs diff --git a/library/std/src/sys/random/cygwin.rs b/library/std/src/sys/random/cygwin.rs new file mode 100644 index 00000000000..e6759c8a3ed --- /dev/null +++ b/library/std/src/sys/random/cygwin.rs @@ -0,0 +1,8 @@ +pub fn fill_bytes(mut bytes: &mut [u8]) { + while !bytes.is_empty() { + let ret = + unsafe { libc::getrandom(bytes.as_mut_ptr().cast(), bytes.len(), libc::GRND_NONBLOCK) }; + assert!(ret != -1, "failed to generate random data"); + bytes = &mut bytes[ret as usize..]; + } +} diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index fb4274281d6..e3cb79285cd 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -94,14 +94,7 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { let flags = if insecure { if GRND_INSECURE_AVAILABLE.load(Relaxed) { - #[cfg(target_os = "cygwin")] - { - libc::GRND_NONBLOCK - } - #[cfg(not(target_os = "cygwin"))] - { - libc::GRND_INSECURE - } + libc::GRND_INSECURE } else { libc::GRND_NONBLOCK } @@ -117,7 +110,6 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { libc::EINTR => continue, // `GRND_INSECURE` is not available, try // `GRND_NONBLOCK`. - #[cfg(not(target_os = "cygwin"))] libc::EINVAL if flags == libc::GRND_INSECURE => { GRND_INSECURE_AVAILABLE.store(false, Relaxed); continue; diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index b6a357e5b07..2e5765b8a42 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -1,11 +1,14 @@ cfg_if::cfg_if! { // Tier 1 - if #[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin"))] { + if #[cfg(any(target_os = "linux", target_os = "android"))] { mod linux; pub use linux::{fill_bytes, hashmap_random_keys}; } else if #[cfg(target_os = "windows")] { mod windows; pub use windows::fill_bytes; + } else if #[cfg(target_os = "cygwin")] { + mod cygwin; + pub use cygwin::fill_bytes; } else if #[cfg(target_vendor = "apple")] { mod apple; pub use apple::fill_bytes; @@ -88,7 +91,6 @@ cfg_if::cfg_if! { target_os = "android", all(target_family = "wasm", target_os = "unknown"), target_os = "xous", - target_os = "cygwin", )))] pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; From c3051b1f5a6fa308cab85f37be446e7946e1f22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 15:59:49 +0800 Subject: [PATCH 16/31] Unify cygwin & horizon random impl --- library/std/src/random.rs | 2 +- library/std/src/sys/random/cygwin.rs | 8 -------- .../std/src/sys/random/{horizon.rs => getrandom.rs} | 0 library/std/src/sys/random/mod.rs | 11 ++++------- 4 files changed, 5 insertions(+), 16 deletions(-) delete mode 100644 library/std/src/sys/random/cygwin.rs rename library/std/src/sys/random/{horizon.rs => getrandom.rs} (100%) diff --git a/library/std/src/random.rs b/library/std/src/random.rs index 45f51dd37b0..e7d4ab81df0 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -37,7 +37,7 @@ use crate::sys::random as sys; /// Solaris | [`arc4random_buf`](https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html) /// Vita | `arc4random_buf` /// Hermit | `read_entropy` -/// Horizon | `getrandom` shim +/// Horizon, Cygwin | `getrandom` /// AIX, Hurd, L4Re, QNX | `/dev/urandom` /// Redox | `/scheme/rand` /// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/master/bsp-howto/getentropy.html) diff --git a/library/std/src/sys/random/cygwin.rs b/library/std/src/sys/random/cygwin.rs deleted file mode 100644 index e6759c8a3ed..00000000000 --- a/library/std/src/sys/random/cygwin.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub fn fill_bytes(mut bytes: &mut [u8]) { - while !bytes.is_empty() { - let ret = - unsafe { libc::getrandom(bytes.as_mut_ptr().cast(), bytes.len(), libc::GRND_NONBLOCK) }; - assert!(ret != -1, "failed to generate random data"); - bytes = &mut bytes[ret as usize..]; - } -} diff --git a/library/std/src/sys/random/horizon.rs b/library/std/src/sys/random/getrandom.rs similarity index 100% rename from library/std/src/sys/random/horizon.rs rename to library/std/src/sys/random/getrandom.rs diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index 2e5765b8a42..7f598c9e5cc 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -6,9 +6,6 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "windows")] { mod windows; pub use windows::fill_bytes; - } else if #[cfg(target_os = "cygwin")] { - mod cygwin; - pub use cygwin::fill_bytes; } else if #[cfg(target_vendor = "apple")] { mod apple; pub use apple::fill_bytes; @@ -38,10 +35,10 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "hermit")] { mod hermit; pub use hermit::fill_bytes; - } else if #[cfg(target_os = "horizon")] { - // FIXME: add arc4random_buf to shim-3ds - mod horizon; - pub use horizon::fill_bytes; + } else if #[cfg(any(target_os = "horizon", target_os = "cygwin"))] { + // FIXME(horizon): add arc4random_buf to shim-3ds + mod getrandom; + pub use getrandom::fill_bytes; } else if #[cfg(any( target_os = "aix", target_os = "hurd", From b9fe8def52c996dcb7dd2d7ab3c362854caee8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 21:45:41 +0800 Subject: [PATCH 17/31] Readd os::cygwin::raw as pub(crate) --- library/std/src/os/cygwin/mod.rs | 1 + library/std/src/os/cygwin/raw.rs | 4 ++++ library/std/src/sys/pal/unix/thread.rs | 1 - 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 library/std/src/os/cygwin/raw.rs diff --git a/library/std/src/os/cygwin/mod.rs b/library/std/src/os/cygwin/mod.rs index f6385653d77..7f6d6a645c8 100644 --- a/library/std/src/os/cygwin/mod.rs +++ b/library/std/src/os/cygwin/mod.rs @@ -1,3 +1,4 @@ //! Cygwin-specific definitions #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub(crate) mod raw; diff --git a/library/std/src/os/cygwin/raw.rs b/library/std/src/os/cygwin/raw.rs new file mode 100644 index 00000000000..2bae1477fcf --- /dev/null +++ b/library/std/src/os/cygwin/raw.rs @@ -0,0 +1,4 @@ +//! Cygwin-specific raw type definitions. + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use libc::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, pthread_t, time_t}; diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 4397cb69a09..8aac58d65a2 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -344,7 +344,6 @@ impl Drop for Thread { target_os = "illumos", target_os = "vxworks", target_vendor = "apple", - target_os = "cygwin", ))] fn truncate_cstr(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { let mut result = [0; MAX_WITH_NUL]; From c3c02a517ca1ce8526abf0d1ed4201a888265b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 22:23:39 +0800 Subject: [PATCH 18/31] Use __xpg_strerror_r on cygwin --- library/std/src/sys/pal/unix/os.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 418211d24bb..b9a1e60b3dc 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -119,7 +119,12 @@ pub fn error_string(errno: i32) -> String { unsafe extern "C" { #[cfg_attr( all( - any(target_os = "linux", target_os = "hurd", target_env = "newlib"), + any( + target_os = "linux", + target_os = "hurd", + target_env = "newlib", + target_os = "cygwin" + ), not(target_env = "ohos") ), link_name = "__xpg_strerror_r" From 9cab8c25dc3c7c1cac7475568161b3b4fc34a88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 7 Mar 2025 22:30:35 +0800 Subject: [PATCH 19/31] Remove stack overflow handler for cygwin --- library/std/src/sys/pal/unix/stack_overflow.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 344f9c63257..0ecccdc8812 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -32,7 +32,6 @@ impl Drop for Handler { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "cygwin", target_os = "solaris", target_os = "illumos", ))] @@ -316,8 +315,7 @@ mod imp { target_os = "netbsd", target_os = "hurd", target_os = "linux", - target_os = "l4re", - target_os = "cygwin" + target_os = "l4re" ))] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { let mut ret = None; @@ -372,8 +370,7 @@ mod imp { // this way someone on any unix-y OS can check that all these compile if cfg!(all(target_os = "linux", not(target_env = "musl"))) { install_main_guard_linux(page_size) - } else if cfg!(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")) - { + } else if cfg!(all(target_os = "linux", target_env = "musl")) { install_main_guard_linux_musl(page_size) } else if cfg!(target_os = "freebsd") { install_main_guard_freebsd(page_size) @@ -513,8 +510,7 @@ mod imp { target_os = "hurd", target_os = "linux", target_os = "netbsd", - target_os = "l4re", - target_os = "cygwin" + target_os = "l4re" ))] // FIXME: I am probably not unsafe. unsafe fn current_guard() -> Option> { @@ -587,7 +583,6 @@ mod imp { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "cygwin", target_os = "solaris", target_os = "illumos", )))] From a9b536f8a41e731b64b98e6c3085f2a7e4614504 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 11 Mar 2025 14:43:21 +0800 Subject: [PATCH 20/31] std: Mention clone-on-write mutation in Arc Signed-off-by: xizheyin --- library/alloc/src/sync.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4999319f618..a521c53b690 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -84,9 +84,29 @@ macro_rules! acquire { /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something -/// inside an `Arc`. If you need to mutate through an `Arc`, use -/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] -/// types. +/// inside an `Arc`. If you do need to mutate through an `Arc`, you have several options: +/// +/// 1. Use interior mutability with synchronization primitives like [`Mutex`][mutex], +/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. +/// +/// 2. Use clone-on-write semantics with [`Arc::make_mut`] which provides efficient mutation +/// without requiring interior mutability. This approach clones the data only when +/// needed (when there are multiple references) and can be more efficient when mutations +/// are infrequent. +/// +/// 3. Use [`Arc::get_mut`] when you know your `Arc` is not shared (has a reference count of 1), +/// which provides direct mutable access to the inner value without any cloning. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let mut data = Arc::new(vec![1, 2, 3]); +/// +/// // This will clone the vector only if there are other references to it +/// Arc::make_mut(&mut data).push(4); +/// +/// assert_eq!(*data, vec![1, 2, 3, 4]); +/// ``` /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of pointers, which includes all platforms that support From bd385f3064f558d4bba19a0447f8b08208915dc9 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Wed, 12 Mar 2025 15:48:05 +0800 Subject: [PATCH 21/31] Fix panic handler for cygwin --- library/std/src/sys/personality/gcc.rs | 5 ++++- library/unwind/src/libunwind.rs | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index cd2c7899f4b..ad96774f39c 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -248,7 +248,10 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { + if #[cfg(any( + all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"), + target_os = "cygwin", + ))] { /// personality fn called by [Windows Structured Exception Handling][windows-eh] /// /// On x86_64 and AArch64 MinGW targets, the unwinding mechanism is SEH, diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 1a640bbde71..37668a64857 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -27,10 +27,10 @@ pub type _Unwind_Trace_Fn = #[cfg(target_arch = "x86")] pub const unwinder_private_data_size: usize = 5; -#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))] +#[cfg(all(target_arch = "x86_64", not(any(target_os = "windows", target_os = "cygwin"))))] pub const unwinder_private_data_size: usize = 2; -#[cfg(all(target_arch = "x86_64", target_os = "windows"))] +#[cfg(all(target_arch = "x86_64", any(target_os = "windows", target_os = "cygwin")))] pub const unwinder_private_data_size: usize = 6; #[cfg(all(target_arch = "arm", not(target_vendor = "apple")))] @@ -289,7 +289,10 @@ if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = } // cfg_if! cfg_if::cfg_if! { -if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { +if #[cfg(any( + all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"), + target_os = "cygwin", + ))] { // We declare these as opaque types. This is fine since you just need to // pass them to _GCC_specific_handler and forget about them. pub enum EXCEPTION_RECORD {} From 340a45282ac8a076b0b058ac066a8872d78302b3 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 2 Mar 2025 00:33:51 +1100 Subject: [PATCH 22/31] Stablize feature `anonymous_pipe` Signed-off-by: Jiahao XU --- library/std/src/io/mod.rs | 2 +- library/std/src/io/pipe.rs | 21 ++++++-------- library/std/src/sys/anonymous_pipe/unix.rs | 28 +++++++++---------- .../std/src/sys/anonymous_pipe/unsupported.rs | 4 +-- library/std/src/sys/anonymous_pipe/windows.rs | 28 +++++++++---------- library/std/tests/pipe_subprocess.rs | 2 -- src/tools/miri/tests/pass/shims/pipe.rs | 2 -- 7 files changed, 40 insertions(+), 47 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7f610bc88bf..679549093b3 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,7 +310,7 @@ pub use self::error::RawOsError; pub use self::error::SimpleMessage; #[unstable(feature = "io_const_error", issue = "133448")] pub use self::error::const_error; -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub use self::pipe::{PipeReader, PipeWriter, pipe}; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index 266c7bc9638..12ac62afb31 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -40,7 +40,6 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; /// # Examples /// /// ```no_run -/// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -67,19 +66,19 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; /// ``` /// [changes]: io#platform-specific-behavior /// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) } /// Read end of an anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug)] pub struct PipeReader(pub(crate) AnonPipe); /// Write end of an anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug)] pub struct PipeWriter(pub(crate) AnonPipe); @@ -89,7 +88,6 @@ impl PipeReader { /// # Examples /// /// ```no_run - /// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -137,7 +135,7 @@ impl PipeReader { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] + #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } @@ -149,7 +147,6 @@ impl PipeWriter { /// # Examples /// /// ```no_run - /// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -177,13 +174,13 @@ impl PipeWriter { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] + #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Read for &PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -203,7 +200,7 @@ impl io::Read for &PipeReader { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Read for PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -223,7 +220,7 @@ impl io::Read for PipeReader { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Write for &PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -241,7 +238,7 @@ impl io::Write for &PipeWriter { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Write for PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 9e398765634..f5e333d0b13 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -12,88 +12,88 @@ pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsFd for PipeReader { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsRawFd for PipeReader { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for OwnedFd { fn from(pipe: PipeReader) -> Self { FileDesc::into_inner(pipe.0) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl FromRawFd for PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl IntoRawFd for PipeReader { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeReader) -> Self { Self::from(OwnedFd::from(pipe)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsFd for PipeWriter { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsRawFd for PipeWriter { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for OwnedFd { fn from(pipe: PipeWriter) -> Self { FileDesc::into_inner(pipe.0) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl FromRawFd for PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl IntoRawFd for PipeWriter { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeWriter) -> Self { Self::from(OwnedFd::from(pipe)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for PipeReader { fn from(owned_fd: OwnedFd) -> Self { Self(FileDesc::from_inner(owned_fd)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for PipeWriter { fn from(owned_fd: OwnedFd) -> Self { Self(FileDesc::from_inner(owned_fd)) diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs index 4e79ac9c21a..ffd07bf2d86 100644 --- a/library/std/src/sys/anonymous_pipe/unsupported.rs +++ b/library/std/src/sys/anonymous_pipe/unsupported.rs @@ -7,14 +7,14 @@ pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { Err(io::Error::UNSUPPORTED_PLATFORM) } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeReader) -> Self { pipe.0.diverge() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeWriter) -> Self { pipe.0.diverge() diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index eb7fa8ec1c9..48a2f3994c3 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -23,92 +23,92 @@ pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsHandle for PipeReader { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsRawHandle for PipeReader { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl FromRawHandle for PipeReader { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self(Handle::from_raw_handle(raw_handle)) } } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl IntoRawHandle for PipeReader { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for OwnedHandle { fn from(pipe: PipeReader) -> Self { Handle::into_inner(pipe.0) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeReader) -> Self { Self::from(OwnedHandle::from(pipe)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsHandle for PipeWriter { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl AsRawHandle for PipeWriter { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl FromRawHandle for PipeWriter { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self(Handle::from_raw_handle(raw_handle)) } } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl IntoRawHandle for PipeWriter { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for OwnedHandle { fn from(pipe: PipeWriter) -> Self { Handle::into_inner(pipe.0) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for Stdio { fn from(pipe: PipeWriter) -> Self { Self::from(OwnedHandle::from(pipe)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for PipeReader { fn from(owned_handle: OwnedHandle) -> Self { Self(Handle::from_inner(owned_handle)) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl From for PipeWriter { fn from(owned_handle: OwnedHandle) -> Self { Self(Handle::from_inner(owned_handle)) diff --git a/library/std/tests/pipe_subprocess.rs b/library/std/tests/pipe_subprocess.rs index 00d99a578d5..c51a4459e71 100644 --- a/library/std/tests/pipe_subprocess.rs +++ b/library/std/tests/pipe_subprocess.rs @@ -1,5 +1,3 @@ -#![feature(anonymous_pipe)] - fn main() { #[cfg(all(not(miri), any(unix, windows), not(target_os = "emscripten")))] { diff --git a/src/tools/miri/tests/pass/shims/pipe.rs b/src/tools/miri/tests/pass/shims/pipe.rs index 1be29886d2d..c47feb8774a 100644 --- a/src/tools/miri/tests/pass/shims/pipe.rs +++ b/src/tools/miri/tests/pass/shims/pipe.rs @@ -1,7 +1,5 @@ //@ignore-target: windows -#![feature(anonymous_pipe)] - use std::io::{Read, Write, pipe}; fn main() { From 6863a99841f81ea18b9a26d053fd33a9700a8345 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sat, 8 Mar 2025 00:36:15 +1100 Subject: [PATCH 23/31] Mv os-specific trait impl of `Pipe*` into `std::os::*` Signed-off-by: Jiahao XU --- library/std/src/io/pipe.rs | 25 +++++ library/std/src/os/fd/owned.rs | 45 +++++++- library/std/src/os/fd/raw.rs | 43 ++++++++ library/std/src/os/windows/io/handle.rs | 42 ++++++++ library/std/src/os/windows/io/raw.rs | 42 ++++++++ library/std/src/process.rs | 14 +++ library/std/src/sys/anonymous_pipe/unix.rs | 94 +--------------- .../std/src/sys/anonymous_pipe/unsupported.rs | 17 +-- library/std/src/sys/anonymous_pipe/windows.rs | 101 +----------------- .../sys/pal/unix/process/process_common.rs | 6 ++ library/std/src/sys/pal/unsupported/pipe.rs | 51 +++++++++ library/std/src/sys/pal/windows/process.rs | 6 ++ 12 files changed, 278 insertions(+), 208 deletions(-) diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index 12ac62afb31..cfed9b05cc0 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -1,5 +1,6 @@ use crate::io; use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; +use crate::sys_common::{FromInner, IntoInner}; /// Create an anonymous pipe. /// @@ -82,6 +83,30 @@ pub struct PipeReader(pub(crate) AnonPipe); #[derive(Debug)] pub struct PipeWriter(pub(crate) AnonPipe); +impl FromInner for PipeReader { + fn from_inner(inner: AnonPipe) -> Self { + Self(inner) + } +} + +impl IntoInner for PipeReader { + fn into_inner(self) -> AnonPipe { + self.0 + } +} + +impl FromInner for PipeWriter { + fn from_inner(inner: AnonPipe) -> Self { + Self(inner) + } +} + +impl IntoInner for PipeWriter { + fn into_inner(self) -> AnonPipe { + self.0 + } +} + impl PipeReader { /// Create a new [`PipeReader`] instance that shares the same underlying file description. /// diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 701cf823357..2dcbfc96618 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -15,8 +15,9 @@ use crate::mem::ManuallyDrop; target_os = "trusty" )))] use crate::sys::cvt; +use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, IntoInner}; use crate::{fmt, io}; type ValidRawFd = core::num::niche_types::NotAllOnes; @@ -504,3 +505,45 @@ impl<'a> AsFd for io::StderrLock<'a> { unsafe { BorrowedFd::borrow_raw(2) } } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsFd for io::PipeReader { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for OwnedFd { + fn from(pipe: io::PipeReader) -> Self { + pipe.0.into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsFd for io::PipeWriter { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for OwnedFd { + fn from(pipe: io::PipeWriter) -> Self { + pipe.0.into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for io::PipeReader { + fn from(owned_fd: OwnedFd) -> Self { + Self(FromInner::from_inner(owned_fd)) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for io::PipeWriter { + fn from(owned_fd: OwnedFd) -> Self { + Self(FromInner::from_inner(owned_fd)) + } +} diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 083ac6e3fe6..596b21a5204 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -18,6 +18,7 @@ use crate::os::unix::io::AsFd; use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; +use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] use crate::sys_common::{AsInner, IntoInner}; @@ -284,3 +285,45 @@ impl AsRawFd for Box { (**self).as_raw_fd() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawFd for io::PipeReader { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawFd for io::PipeReader { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawFd for io::PipeReader { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawFd for io::PipeWriter { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawFd for io::PipeWriter { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawFd for io::PipeWriter { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 76f5f549dd2..7f21929b85f 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -660,3 +660,45 @@ impl From> for OwnedHandle { join_handle.into_inner().into_handle().into_inner() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsHandle for io::PipeReader { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.as_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for OwnedHandle { + fn from(pipe: io::PipeReader) -> Self { + pipe.into_inner().into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsHandle for io::PipeWriter { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.as_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for OwnedHandle { + fn from(pipe: io::PipeWriter) -> Self { + pipe.into_inner().into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for io::PipeReader { + fn from(owned_handle: OwnedHandle) -> Self { + Self::from_inner(FromInner::from_inner(owned_handle)) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for io::PipeWriter { + fn from(owned_handle: OwnedHandle) -> Self { + Self::from_inner(FromInner::from_inner(owned_handle)) + } +} diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index c0517fab950..bc3e55c8629 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -310,3 +310,45 @@ impl IntoRawSocket for net::UdpSocket { self.into_inner().into_socket().into_inner().into_raw_socket() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawHandle for io::PipeReader { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawHandle for io::PipeReader { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawHandle for io::PipeReader { + fn into_raw_handle(self) -> RawHandle { + self.0.into_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawHandle for io::PipeWriter { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawHandle for io::PipeWriter { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawHandle for io::PipeWriter { + fn into_raw_handle(self) -> RawHandle { + self.0.into_raw_handle() + } +} diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 37762c65f65..07a56010255 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1659,6 +1659,20 @@ impl From for Stdio { } } +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for Stdio { + fn from(pipe: io::PipeWriter) -> Self { + Stdio::from_inner(pipe.into_inner().into()) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From for Stdio { + fn from(pipe: io::PipeReader) -> Self { + Stdio::from_inner(pipe.into_inner().into()) + } +} + /// Describes the result of a process after it has terminated. /// /// This `struct` is used to represent the exit status or other termination of a child process. diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index f5e333d0b13..dfe10f7fafe 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -1,9 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::process::Stdio; +use crate::io; use crate::sys::fd::FileDesc; use crate::sys::pipe::anon_pipe; -use crate::sys_common::{FromInner, IntoInner}; +use crate::sys_common::IntoInner; pub type AnonPipe = FileDesc; @@ -11,91 +9,3 @@ pub type AnonPipe = FileDesc; pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) } - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsFd for PipeReader { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsRawFd for PipeReader { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for OwnedFd { - fn from(pipe: PipeReader) -> Self { - FileDesc::into_inner(pipe.0) - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl FromRawFd for PipeReader { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl IntoRawFd for PipeReader { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeReader) -> Self { - Self::from(OwnedFd::from(pipe)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsFd for PipeWriter { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsRawFd for PipeWriter { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for OwnedFd { - fn from(pipe: PipeWriter) -> Self { - FileDesc::into_inner(pipe.0) - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl FromRawFd for PipeWriter { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl IntoRawFd for PipeWriter { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeWriter) -> Self { - Self::from(OwnedFd::from(pipe)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for PipeReader { - fn from(owned_fd: OwnedFd) -> Self { - Self(FileDesc::from_inner(owned_fd)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for PipeWriter { - fn from(owned_fd: OwnedFd) -> Self { - Self(FileDesc::from_inner(owned_fd)) - } -} diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs index ffd07bf2d86..a0805ba9540 100644 --- a/library/std/src/sys/anonymous_pipe/unsupported.rs +++ b/library/std/src/sys/anonymous_pipe/unsupported.rs @@ -1,22 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::process::Stdio; +use crate::io; pub use crate::sys::pipe::AnonPipe; #[inline] pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { Err(io::Error::UNSUPPORTED_PLATFORM) } - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeReader) -> Self { - pipe.0.diverge() - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeWriter) -> Self { - pipe.0.diverge() - } -} diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index 48a2f3994c3..bdda7ffc5d2 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -1,12 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::os::windows::io::{ - AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, -}; -use crate::process::Stdio; -use crate::ptr; +use crate::os::windows::io::FromRawHandle; use crate::sys::c; use crate::sys::handle::Handle; -use crate::sys_common::{FromInner, IntoInner}; +use crate::{io, ptr}; pub type AnonPipe = Handle; @@ -22,95 +17,3 @@ pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { unsafe { Ok((Handle::from_raw_handle(read_pipe), Handle::from_raw_handle(write_pipe))) } } } - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsHandle for PipeReader { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.as_handle() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsRawHandle for PipeReader { - fn as_raw_handle(&self) -> RawHandle { - self.0.as_raw_handle() - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl FromRawHandle for PipeReader { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - unsafe { Self(Handle::from_raw_handle(raw_handle)) } - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl IntoRawHandle for PipeReader { - fn into_raw_handle(self) -> RawHandle { - self.0.into_raw_handle() - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for OwnedHandle { - fn from(pipe: PipeReader) -> Self { - Handle::into_inner(pipe.0) - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeReader) -> Self { - Self::from(OwnedHandle::from(pipe)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsHandle for PipeWriter { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.as_handle() - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl AsRawHandle for PipeWriter { - fn as_raw_handle(&self) -> RawHandle { - self.0.as_raw_handle() - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl FromRawHandle for PipeWriter { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - unsafe { Self(Handle::from_raw_handle(raw_handle)) } - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl IntoRawHandle for PipeWriter { - fn into_raw_handle(self) -> RawHandle { - self.0.into_raw_handle() - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for OwnedHandle { - fn from(pipe: PipeWriter) -> Self { - Handle::into_inner(pipe.0) - } -} -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for Stdio { - fn from(pipe: PipeWriter) -> Self { - Self::from(OwnedHandle::from(pipe)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for PipeReader { - fn from(owned_handle: OwnedHandle) -> Self { - Self(Handle::from_inner(owned_handle)) - } -} - -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] -impl From for PipeWriter { - fn from(owned_handle: OwnedHandle) -> Self { - Self(Handle::from_inner(owned_handle)) - } -} diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index 0ea9db211b3..bf037578fd1 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -491,6 +491,12 @@ impl From for Stdio { } } +impl From for Stdio { + fn from(fd: FileDesc) -> Stdio { + Stdio::Fd(fd) + } +} + impl From for Stdio { fn from(file: File) -> Stdio { Stdio::Fd(file.into_inner()) diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs index 6799d21a1ff..988e551de52 100644 --- a/library/std/src/sys/pal/unsupported/pipe.rs +++ b/library/std/src/sys/pal/unsupported/pipe.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::sys_common::{FromInner, IntoInner}; pub struct AnonPipe(!); @@ -54,3 +55,53 @@ impl AnonPipe { pub fn read2(p1: AnonPipe, _v1: &mut Vec, _p2: AnonPipe, _v2: &mut Vec) -> io::Result<()> { match p1.0 {} } + +impl FromInner for AnonPipe { + fn from_inner(inner: !) -> Self { + inner + } +} + +impl IntoInner for AnonPipe { + fn into_inner(self) -> ! { + self.0 + } +} + +#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] +mod unix_traits { + use super::AnonPipe; + use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; + use crate::sys_common::FromInner; + + impl AsRawFd for AnonPipe { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.0 + } + } + + impl AsFd for AnonPipe { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0 + } + } + + impl IntoRawFd for AnonPipe { + fn into_raw_fd(self) -> RawFd { + self.0 + } + } + + impl FromRawFd for AnonPipe { + unsafe fn from_raw_fd(_: RawFd) -> Self { + panic!("creating pipe on this platform is unsupported!") + } + } + + impl FromInner for AnonPipe { + fn from_inner(_: OwnedFd) -> Self { + panic!("creating pipe on this platform is unsupported!") + } + } +} diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index c57ff355d12..50e4baba607 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -621,6 +621,12 @@ impl From for Stdio { } } +impl From for Stdio { + fn from(pipe: Handle) -> Stdio { + Stdio::Handle(pipe) + } +} + impl From for Stdio { fn from(file: File) -> Stdio { Stdio::Handle(file.into_inner()) From ae4a4794e75a9317fa9f907dc38ecb177e46c663 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 14 Mar 2025 20:04:17 +0000 Subject: [PATCH 24/31] Improve upvar analysis for deref of child capture --- compiler/rustc_hir_typeck/src/upvar.rs | 25 +++++++--- .../async-closures/imm-deref-lending.rs | 46 +++++++++++++++++ .../async-closures/imm-deref-not-lending.rs | 49 +++++++++++++++++++ .../imm-deref-not-lending.stderr | 14 ++++++ 4 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 tests/ui/async-await/async-closures/imm-deref-lending.rs create mode 100644 tests/ui/async-await/async-closures/imm-deref-not-lending.rs create mode 100644 tests/ui/async-await/async-closures/imm-deref-not-lending.stderr diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 37f3786c00a..fc98a603dd8 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1862,8 +1862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// (1.) Are we borrowing data owned by the parent closure? We can determine if /// that is the case by checking if the parent capture is by move, EXCEPT if we -/// apply a deref projection, which means we're reborrowing a reference that we -/// captured by move. +/// apply a deref projection of an immutable reference, reborrows of immutable +/// references which aren't restricted to the LUB of the lifetimes of the deref +/// chain. This is why `&'short mut &'long T` can be reborrowed as `&'long T`. /// /// ```rust /// let x = &1i32; // Let's call this lifetime `'1`. @@ -1902,10 +1903,22 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>( ) -> bool { // (1.) (!parent_capture.is_by_ref() - && !matches!( - child_capture.place.projections.get(parent_capture.place.projections.len()), - Some(Projection { kind: ProjectionKind::Deref, .. }) - )) + // This is just inlined `place.deref_tys()` but truncated to just + // the child projections. Namely, look for a `&T` deref, since we + // can always extend `&'short mut &'long T` to `&'long T`. + && !child_capture + .place + .projections + .iter() + .enumerate() + .skip(parent_capture.place.projections.len()) + .any(|(idx, proj)| { + matches!(proj.kind, ProjectionKind::Deref) + && matches!( + child_capture.place.ty_before_projection(idx).kind(), + ty::Ref(.., ty::Mutability::Not) + ) + })) // (2.) || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::Mutable)) } diff --git a/tests/ui/async-await/async-closures/imm-deref-lending.rs b/tests/ui/async-await/async-closures/imm-deref-lending.rs new file mode 100644 index 00000000000..59f8d434d9c --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-lending.rs @@ -0,0 +1,46 @@ +//@ edition: 2021 +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +struct FooS { + precise: i32, +} + +fn ref_inside_mut(f: &mut &FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn mut_inside_ref(f: &&mut FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn mut_ref_inside_mut(f: &mut &mut FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn ref_inside_box(f: Box<&FooS>) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn box_inside_ref(f: &Box) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn box_inside_box(f: Box>) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/imm-deref-not-lending.rs b/tests/ui/async-await/async-closures/imm-deref-not-lending.rs new file mode 100644 index 00000000000..bd1197cc636 --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-not-lending.rs @@ -0,0 +1,49 @@ +//@ edition: 2021 + +#![feature(impl_trait_in_bindings)] + +struct FooS { + precise: i32, +} + +fn ref_inside_mut(f: &mut &FooS) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +fn mut_inside_ref(f: &&mut FooS) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +// Expected to fail, no immutable reference here. +fn mut_ref_inside_mut(f: &mut &mut FooS) { + let x: impl Fn() -> _ = async move || { + //~^ ERROR async closure does not implement `Fn` + let y = &f.precise; + }; +} + +fn ref_inside_box(f: Box<&FooS>) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +fn box_inside_ref(f: &Box) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +// Expected to fail, no immutable reference here. +fn box_inside_box(f: Box>) { + let x: impl Fn() -> _ = async move || { + //~^ ERROR async closure does not implement `Fn` + let y = &f.precise; + }; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr b/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr new file mode 100644 index 00000000000..cd3ff55e458 --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr @@ -0,0 +1,14 @@ +error: async closure does not implement `Fn` because it captures state from its environment + --> $DIR/imm-deref-not-lending.rs:23:29 + | +LL | let x: impl Fn() -> _ = async move || { + | ^^^^^^^^^^^^^ + +error: async closure does not implement `Fn` because it captures state from its environment + --> $DIR/imm-deref-not-lending.rs:43:29 + | +LL | let x: impl Fn() -> _ = async move || { + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From ec4b3c2779883a6b7ebb1ce5954904ef2c95d3a4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Mar 2025 14:28:10 +0100 Subject: [PATCH 25/31] Add test for new proc_macro literal methods --- library/literal-escaper/README.md | 2 +- library/proc_macro/src/lib.rs | 1 + tests/ui/proc-macro/auxiliary/api/literal.rs | 53 ++++++++++++++++++- .../auxiliary/api/proc_macro_api_tests.rs | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/library/literal-escaper/README.md b/library/literal-escaper/README.md index 5384ac4556a..9986d2451c7 100644 --- a/library/literal-escaper/README.md +++ b/library/literal-escaper/README.md @@ -1,4 +1,4 @@ # literal-escaper This crate provides code to unescape string literals. It is used by `rustc_lexer` -and `proc-macro`. +and `proc_macro`. diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 57dd47f1060..b1de87a4b08 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -61,6 +61,7 @@ use crate::escape::{EscapeOptions, escape_bytes}; /// Errors returned when trying to retrieve a literal unescaped value. #[unstable(feature = "proc_macro_value", issue = "136652")] +#[derive(Debug, PartialEq, Eq)] pub enum ConversionErrorKind { /// The literal failed to be escaped, take a look at [`EscapeError`] for more information. FailedToUnescape(EscapeError), diff --git a/tests/ui/proc-macro/auxiliary/api/literal.rs b/tests/ui/proc-macro/auxiliary/api/literal.rs index 7109340bb64..941de1521ad 100644 --- a/tests/ui/proc-macro/auxiliary/api/literal.rs +++ b/tests/ui/proc-macro/auxiliary/api/literal.rs @@ -1,10 +1,11 @@ // ignore-tidy-linelength -use proc_macro::Literal; +use proc_macro::{ConversionErrorKind, Literal}; pub fn test() { test_display_literal(); test_parse_literal(); + test_str_value_methods(); } fn test_display_literal() { @@ -81,3 +82,53 @@ fn test_parse_literal() { assert!("- 10".parse::().is_err()); assert!("-'x'".parse::().is_err()); } + +fn test_str_value_methods() { + // Testing `str_value` + let lit = "\"\n\"".parse::().unwrap(); + assert_eq!(lit.str_value(), Ok("\n".to_string())); + + let lit = "r#\"\n\"#".parse::().unwrap(); + assert_eq!(lit.str_value(), Ok("\n".to_string())); + + let lit = "1".parse::().unwrap(); + assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "b\"\n\"".parse::().unwrap(); + assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "c\"\n\"".parse::().unwrap(); + assert_eq!(lit.str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + // Testing `cstr_value` + let lit = "\"\n\"".parse::().unwrap(); + assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "r#\"\n\"#".parse::().unwrap(); + assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "1".parse::().unwrap(); + assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "b\"\n\"".parse::().unwrap(); + assert_eq!(lit.cstr_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "c\"\n\"".parse::().unwrap(); + assert_eq!(lit.cstr_value(), Ok(vec![b'\n', 0])); + + // Testing `byte_str_value` + let lit = "\"\n\"".parse::().unwrap(); + assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "r#\"\n\"#".parse::().unwrap(); + assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "1".parse::().unwrap(); + assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); + + let lit = "b\"\n\"".parse::().unwrap(); + assert_eq!(lit.byte_str_value(), Ok(vec![b'\n'])); + + let lit = "c\"\n\"".parse::().unwrap(); + assert_eq!(lit.byte_str_value(), Err(ConversionErrorKind::InvalidLiteralKind)); +} diff --git a/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs index abd667d8ce1..390d46852cd 100644 --- a/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs +++ b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs @@ -1,6 +1,7 @@ //@ edition: 2021 #![feature(proc_macro_span)] +#![feature(proc_macro_value)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; From 417bfe2125cfb371c3ce4b80437152e429b0e45c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Mar 2025 21:46:39 +0100 Subject: [PATCH 26/31] Exclude `literal-escaper` from `library` workspace --- library/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Cargo.toml b/library/Cargo.toml index 1205f7c9ed6..1e2d996278e 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -7,6 +7,7 @@ members = [ ] exclude = [ + "literal-escaper", # stdarch has its own Cargo workspace "stdarch", "windows_targets" From 04c9956c9a470ca6b809bb76620846641ac8c892 Mon Sep 17 00:00:00 2001 From: Alex Touchet <26315797+atouchet@users.noreply.github.com> Date: Sun, 16 Mar 2025 19:03:40 -0700 Subject: [PATCH 27/31] Update Rust Foundation links in Readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d84d96a0e91..611260470f1 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,11 @@ See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and trademarks and logos (the "Rust Trademarks"). If you want to use these names or brands, please read the -[media guide][media-guide]. +[Rust language trademark policy][trademark-policy]. Third-party logos may be subject to third-party copyrights and trademarks. See [Licenses][policies-licenses] for details. -[rust-foundation]: https://foundation.rust-lang.org/ -[media-guide]: https://foundation.rust-lang.org/policies/logo-policy-and-media-guide/ +[rust-foundation]: https://rustfoundation.org/ +[trademark-policy]: https://rustfoundation.org/policy/rust-trademark-policy/ [policies-licenses]: https://www.rust-lang.org/policies/licenses From 10bc5acf0d6736bc0a99d55beae739878f94de16 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 16 Mar 2025 22:27:09 -0400 Subject: [PATCH 28/31] Document `#![register_tool]` --- .../src/language-features/register-tool.md | 55 +++++++++++++++++++ tests/ui/tool-attributes/crate-attr.rs | 5 ++ .../ui/tool-attributes/multiple-registered.rs | 7 +++ tests/ui/tool-attributes/nested-disallowed.rs | 4 ++ .../tool-attributes/nested-disallowed.stderr | 8 +++ 5 files changed, 79 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/register-tool.md create mode 100644 tests/ui/tool-attributes/crate-attr.rs create mode 100644 tests/ui/tool-attributes/multiple-registered.rs create mode 100644 tests/ui/tool-attributes/nested-disallowed.rs create mode 100644 tests/ui/tool-attributes/nested-disallowed.stderr diff --git a/src/doc/unstable-book/src/language-features/register-tool.md b/src/doc/unstable-book/src/language-features/register-tool.md new file mode 100644 index 00000000000..58b923aab57 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/register-tool.md @@ -0,0 +1,55 @@ +# `register_tool` + +The tracking issue for this feature is: [#66079] + +[#66079]: https://github.com/rust-lang/rust/issues/66079 + +------------------------ + +The `register_tool` language feature informs the compiler that attributes in your code are meant to be used with tools other than the compiler itself. This can be useful if your code has semantic meaning without the external tool, but enables additional features when the tool is present. + +`register_tool` also allows configuring lint levels for external tools. + +Tool attributes are only meant for ignorable attributes. If your code *changes* meaning when the attribute is present, it should not use a tool attribute (because it cannot be compiled with anything other than the external tool, and in a sense is a fork of the language). + +------------------------ + +`#![register_tool(tool)]` is an attribute, and is only valid at the crate root. +Attributes using the registered tool are checked for valid syntax, and lint attributes are checked to be in a valid format. However, the compiler cannot validate the semantics of the attribute, nor can it tell whether the configured lint is present in the external tool. + +Semantically, `clippy::*`, `rustdoc::*`, and `rustfmt::*` lints and attributes all behave as if `#![register_tool(clippy, rustdoc, rustfmt)]` were injected into the crate root, except that the `rustdoc` namespace can only be used for lints, not for attributes. +When compiling with `-Z unstable-features`, `rustc::*` lints can also be used. Like `rustdoc`, the `rustc` namespace can only be used with lints, not attributes. + +The compiler will emit an error if it encounters a lint/attribute whose namespace isn't a registered tool. + +Tool namespaces cannot be nested; `register_tool(main_tool::subtool)` is an error. + +## Examples + +Tool attributes: + +```rust +#![feature(register_tool)] +#![register_tool(c2rust)] + +// Mark which C header file this module was generated from. +#[c2rust::header_src = "operations.h"] +pub mod operations_h { + use std::ffi::c_int; + + // Mark which source line this struct was generated from. + #[c2rust::src_loc = "11:0"] + pub struct Point { + pub x: c_int, + pub y: c_int, + } +} +``` + +Tool lints: + +``` +#![feature(register_tool)] +#![register_tool(bevy)] +#![deny(bevy::duplicate_bevy_dependencies)] +``` diff --git a/tests/ui/tool-attributes/crate-attr.rs b/tests/ui/tool-attributes/crate-attr.rs new file mode 100644 index 00000000000..c6d7974945f --- /dev/null +++ b/tests/ui/tool-attributes/crate-attr.rs @@ -0,0 +1,5 @@ +//@ check-pass +//@ compile-flags: -Z crate-attr=feature(register_tool) -Z crate-attr=register_tool(foo) + +#[allow(foo::bar)] +fn main() {} diff --git a/tests/ui/tool-attributes/multiple-registered.rs b/tests/ui/tool-attributes/multiple-registered.rs new file mode 100644 index 00000000000..4d54c2dcb08 --- /dev/null +++ b/tests/ui/tool-attributes/multiple-registered.rs @@ -0,0 +1,7 @@ +//@ check-pass + +#![feature(register_tool)] +#![register_tool(foo, bar, baz)] + +#[allow(foo::a, bar::b, baz::c)] +fn main() {} diff --git a/tests/ui/tool-attributes/nested-disallowed.rs b/tests/ui/tool-attributes/nested-disallowed.rs new file mode 100644 index 00000000000..8e780427761 --- /dev/null +++ b/tests/ui/tool-attributes/nested-disallowed.rs @@ -0,0 +1,4 @@ +#![feature(register_tool)] +#![register_tool(foo::bar)] //~ ERROR only accepts identifiers + +fn main() {} diff --git a/tests/ui/tool-attributes/nested-disallowed.stderr b/tests/ui/tool-attributes/nested-disallowed.stderr new file mode 100644 index 00000000000..1af73fc2f19 --- /dev/null +++ b/tests/ui/tool-attributes/nested-disallowed.stderr @@ -0,0 +1,8 @@ +error: `register_tool` only accepts identifiers + --> $DIR/nested-disallowed.rs:2:18 + | +LL | #![register_tool(foo::bar)] + | ^^^^^^^^ not an identifier + +error: aborting due to 1 previous error + From 0d100d34d51ceac4d0cf31d524f33fcbddad68c4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 17 Mar 2025 11:12:45 +0300 Subject: [PATCH 29/31] update change entry for #137147 Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index f8478725c4c..f2fae9862d3 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -383,6 +383,6 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ ChangeInfo { change_id: 137147, severity: ChangeSeverity::Info, - summary: "New option `build.exclude` that adds support for excluding test.", + summary: "Added new option `build.exclude` which works the same way as `--exclude` flag on `x`.", }, ]; From 51e8309f50ccd5046b0555f394376db59681a38e Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sun, 16 Mar 2025 22:23:48 +0000 Subject: [PATCH 30/31] Flatten and simplify some control flow --- compiler/rustc_borrowck/src/lib.rs | 16 +++---- compiler/rustc_hir_analysis/src/check/mod.rs | 12 ++--- .../src/fn_ctxt/suggestions.rs | 45 +++++++++---------- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +-- compiler/rustc_middle/src/ty/diagnostics.rs | 42 ++++++++--------- compiler/rustc_passes/src/dead.rs | 2 +- 6 files changed, 53 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 07b3f3477a8..ed95545dea4 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2479,19 +2479,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { let body = self.body; for local in body.mut_vars_and_args_iter().filter(|local| !self.used_mut.contains(local)) { let local_decl = &body.local_decls[local]; - let lint_root = match &body.source_scopes[local_decl.source_info.scope].local_data { - ClearCrossCrate::Set(data) => data.lint_root, - _ => continue, + let ClearCrossCrate::Set(SourceScopeLocalData { lint_root, .. }) = + body.source_scopes[local_decl.source_info.scope].local_data + else { + continue; }; // Skip over locals that begin with an underscore or have no name - match self.local_names[local] { - Some(name) => { - if name.as_str().starts_with('_') { - continue; - } - } - None => continue, + if self.local_names[local].is_none_or(|name| name.as_str().starts_with('_')) { + continue; } let span = local_decl.source_info.span; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index b4a16b2b805..d8ae4214527 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -153,10 +153,9 @@ pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDef } // If `#[link_section]` is missing, then nothing to verify - let attrs = tcx.codegen_fn_attrs(id); - if attrs.link_section.is_none() { + let Some(link_section) = tcx.codegen_fn_attrs(id).link_section else { return; - } + }; // For the wasm32 target statics with `#[link_section]` other than `.init_array` // are placed into custom sections of the final output file, but this isn't like @@ -182,11 +181,8 @@ pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDef // continue to work, but would no longer be necessary. if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) - && alloc.inner().provenance().ptrs().len() != 0 - && attrs - .link_section - .map(|link_section| !link_section.as_str().starts_with(".init_array")) - .unwrap() + && !alloc.inner().provenance().ptrs().is_empty() + && !link_section.as_str().starts_with(".init_array") { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index f19e36206a7..afbb1adf654 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1532,30 +1532,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.may_coerce(blk_ty, *elem_ty) && blk.stmts.is_empty() && blk.rules == hir::BlockCheckMode::DefaultBlock + && let source_map = self.tcx.sess.source_map() + && let Ok(snippet) = source_map.span_to_snippet(blk.span) + && snippet.starts_with('{') + && snippet.ends_with('}') { - let source_map = self.tcx.sess.source_map(); - if let Ok(snippet) = source_map.span_to_snippet(blk.span) { - if snippet.starts_with('{') && snippet.ends_with('}') { - diag.multipart_suggestion_verbose( - "to create an array, use square brackets instead of curly braces", - vec![ - ( - blk.span - .shrink_to_lo() - .with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)), - "[".to_string(), - ), - ( - blk.span - .shrink_to_hi() - .with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)), - "]".to_string(), - ), - ], - Applicability::MachineApplicable, - ); - } - } + diag.multipart_suggestion_verbose( + "to create an array, use square brackets instead of curly braces", + vec![ + ( + blk.span + .shrink_to_lo() + .with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)), + "[".to_string(), + ), + ( + blk.span + .shrink_to_hi() + .with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)), + "]".to_string(), + ), + ], + Applicability::MachineApplicable, + ); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2b9113242aa..212107edb4d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -843,9 +843,8 @@ fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> b } } } - } else if attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2 { - should_encode = - rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features); + } else if let &[sym::diagnostic, seg] = &*attr.path() { + should_encode = rustc_feature::is_stable_diagnostic_attribute(seg, state.features); } else { should_encode = true; } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 881381a5ee6..33b32be0de9 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -641,21 +641,19 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { } } - Alias(Projection, AliasTy { def_id, .. }) => { - if self.tcx.def_kind(def_id) != DefKind::AssocTy { - return ControlFlow::Break(()); - } + Alias(Projection, AliasTy { def_id, .. }) + if self.tcx.def_kind(def_id) != DefKind::AssocTy => + { + return ControlFlow::Break(()); } - Param(param) => { - // FIXME: It would be nice to make this not use string manipulation, - // but it's pretty hard to do this, since `ty::ParamTy` is missing - // sufficient info to determine if it is synthetic, and we don't - // always have a convenient way of getting `ty::Generics` at the call - // sites we invoke `IsSuggestable::is_suggestable`. - if param.name.as_str().starts_with("impl ") { - return ControlFlow::Break(()); - } + // FIXME: It would be nice to make this not use string manipulation, + // but it's pretty hard to do this, since `ty::ParamTy` is missing + // sufficient info to determine if it is synthetic, and we don't + // always have a convenient way of getting `ty::Generics` at the call + // sites we invoke `IsSuggestable::is_suggestable`. + Param(param) if param.name.as_str().starts_with("impl ") => { + return ControlFlow::Break(()); } _ => {} @@ -733,17 +731,13 @@ impl<'tcx> FallibleTypeFolder> for MakeSuggestableFolder<'tcx> { } } - Param(param) => { - // FIXME: It would be nice to make this not use string manipulation, - // but it's pretty hard to do this, since `ty::ParamTy` is missing - // sufficient info to determine if it is synthetic, and we don't - // always have a convenient way of getting `ty::Generics` at the call - // sites we invoke `IsSuggestable::is_suggestable`. - if param.name.as_str().starts_with("impl ") { - return Err(()); - } - - t + // FIXME: It would be nice to make this not use string manipulation, + // but it's pretty hard to do this, since `ty::ParamTy` is missing + // sufficient info to determine if it is synthetic, and we don't + // always have a convenient way of getting `ty::Generics` at the call + // sites we invoke `IsSuggestable::is_suggestable`. + Param(param) if param.name.as_str().starts_with("impl ") => { + return Err(()); } _ => t, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7029c60c343..d036cb74a56 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1132,7 +1132,7 @@ impl<'tcx> DeadVisitor<'tcx> { return; } dead_codes.sort_by_key(|v| v.level); - for group in dead_codes[..].chunk_by(|a, b| a.level == b.level) { + for group in dead_codes.chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } } From 4394f94023526f81b1c45f6e74a17360f31522e4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Mar 2025 10:43:28 +0100 Subject: [PATCH 31/31] Only add `rustc_randomized_layouts` if the crate has it --- src/bootstrap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index bc146eda1d5..8db2b4b5b3a 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -683,7 +683,7 @@ impl Build { features.push("llvm"); } // keep in sync with `bootstrap/compile.rs:rustc_cargo_env` - if self.config.rust_randomize_layout { + if self.config.rust_randomize_layout && check("rustc_randomized_layouts") { features.push("rustc_randomized_layouts"); }