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 fc4c7c9888fa6..63441814d4a1f 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 34c612dac692b..176c2d6f8a791 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 6896ac723fa58..121331ece6d64 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 c63ab77decac9..334f451a39c71 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 2360914a0aba1..109e1f5c0931e 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 792e2cc26ef1c..cefaf13e31fbe 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 2e066f0179c3f..e8aa400e73d44 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 e0e6c2177da54..0b745217bc8be 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 707c4e318474a..51ea46f4c9b40 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 3b985621b5772..7e89f9b079b62 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 0000000000000..708fcd3cacb69 --- /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 0000000000000..5384ac4556a13 --- /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 63441814d4a1f..06c1394295769 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 8b78908e6d730..f769fb2e1e1d3 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 e54a50aa15c61..e5c90309f16d0 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 6611ce30a1b01..57dd47f106089 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 983674d2c6835..e6b01b2e2d95a 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 06c1394295769..e0bf24f1eda71 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 4b3492fdeda25..5789cd0195883 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 334f451a39c71..587ef89566a7e 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 faa0db27b2b05..5d871f0ab26f1 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 74e1ed5c63763..d72e185f51a74 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 0000000000000..7c145fca7dec2 --- /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 0000000000000..edddb6504f575 --- /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 67b09599d9d2b..4ae218c2f9f3f 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 a6f7d103356bf..9809f4b0878e1 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 cedfd7406a1aa..e4295eb2f682a 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 0000000000000..a0667935ac1f6 --- /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 0000000000000..638f738dac806 --- /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 0000000000000..7177b2f699c7e --- /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 e28a1c3e6d5f4..229c645b2d0c8 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 2f9dffe8c6561..5802b6539651c 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 82446ea107fe5..7735637c84059 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 3e45e3533ed28..b07ba110c41c2 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 cb210b41eae19..1cab04a454dc0 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 2dd7d409e48c2..36fb9c46b4aba 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 914971934bfb0..e99d6a07731e7 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 e154cf039cad1..7301bde6881a3 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 e633cf772c528..647058385a247 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 1c87a79803c0d..0bb7b64007aba 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 2aee0b5d46056..c6609298f4b23 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 2fc33bdfefbf5..8ec2a08966eee 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 419abe732ac3f..e2e537b7bd365 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 3a238d160cb57..418211d24bb3b 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 4a992e32a9184..55510153dc847 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 25d9e9353320f..257732aaedc06 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 0ecccdc8812dd..5a639d0545bfe 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 11f6998cac118..4397cb69a09e6 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 647058385a247..bbe1e038dccf5 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 b07ba110c41c2..6cd62303a5325 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 8ec2a08966eee..eb873759ecbb4 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 5a639d0545bfe..463f18800a6c8 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 e3cb79285cd15..266c71abf3d66 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 f42351deb92c0..b6a357e5b07f9 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 8da4fe6b8b152..eac4caf41c8bc 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 f78ab151b9c24..9048eb274b7f9 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 4ae218c2f9f3f..67b09599d9d2b 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 9809f4b0878e1..a6f7d103356bf 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 e99d6a07731e7..7774461a493bb 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 463f18800a6c8..344f9c63257e8 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 266c71abf3d66..fb4274281d63f 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 a0667935ac1f6..5533264fd515b 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 638f738dac806..f6385653d774d 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 7177b2f699c7e..0000000000000 --- 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 0000000000000..e6759c8a3ed99 --- /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 fb4274281d63f..e3cb79285cd15 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 b6a357e5b07f9..2e5765b8a429c 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 45f51dd37b041..e7d4ab81df0ac 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 e6759c8a3ed99..0000000000000 --- 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 2e5765b8a429c..7f598c9e5cc3b 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 f6385653d774d..7f6d6a645c855 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 0000000000000..2bae1477fcfe1 --- /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 4397cb69a09e6..8aac58d65a26f 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 418211d24bb3b..b9a1e60b3dc9b 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 344f9c63257e8..0ecccdc8812dd 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 4999319f618e4..a521c53b6906b 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 cd2c7899f4bf1..ad96774f39c37 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 1a640bbde71d7..37668a64857c3 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 7f610bc88bfd7..679549093b398 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 266c7bc96389b..12ac62afb3150 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 9e398765634b7..f5e333d0b1397 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 4e79ac9c21aad..ffd07bf2d863e 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 eb7fa8ec1c9a1..48a2f3994c338 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 00d99a578d580..c51a4459e718b 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 1be29886d2d32..c47feb8774ad1 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 12ac62afb3150..cfed9b05cc0c6 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 701cf82335757..2dcbfc966189d 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 083ac6e3fe6b1..596b21a52044b 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 76f5f549dd244..7f21929b85f99 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 c0517fab95068..bc3e55c862962 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 37762c65f6556..07a56010255de 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 f5e333d0b1397..dfe10f7fafe49 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 ffd07bf2d863e..a0805ba9540e0 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 48a2f3994c338..bdda7ffc5d251 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 0ea9db211b311..bf037578fd1b5 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 6799d21a1ff75..988e551de5223 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 c57ff355d124d..50e4baba60724 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 37f3786c00abc..fc98a603dd852 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 0000000000000..59f8d434d9cc0 --- /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 0000000000000..bd1197cc63654 --- /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 0000000000000..cd3ff55e458ab --- /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 5384ac4556a13..9986d2451c759 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 57dd47f106089..b1de87a4b0819 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 7109340bb645b..941de1521ade9 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 abd667d8ce1d0..390d46852cd54 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 1205f7c9ed6b5..1e2d996278e77 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 d84d96a0e9173..611260470f12b 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 0000000000000..58b923aab5775 --- /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 0000000000000..c6d7974945f4a --- /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 0000000000000..4d54c2dcb0820 --- /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 0000000000000..8e78042776106 --- /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 0000000000000..1af73fc2f1995 --- /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 f8478725c4cd0..f2fae9862d39e 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 07b3f3477a849..ed95545dea428 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 b4a16b2b8054c..d8ae421452759 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 f19e36206a7f5..afbb1adf6543d 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 2b9113242aa5d..212107edb4db9 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 881381a5ee61e..33b32be0de9f9 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 7029c60c3439b..d036cb74a565f 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 bc146eda1d5eb..8db2b4b5b3adc 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"); }