From f429ab3c18fe47a5cc116f2c4daaa24a740f3511 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 3 May 2021 16:10:13 -0400 Subject: [PATCH 01/20] compiletest: "fix" FileCheck with --allow-unused-prefixes The default of --allow-unused-prefixes used to be false, but in LLVM change 87dbdd2e3b (https://reviews.llvm.org/D95849) the default became true. I'm not quite sure how we could do better here (specifically not providing the CHECK prefix when it's not needed), but this seems to work for now. --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ecbaccf744dcd..517ae9c4dff95 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2293,7 +2293,7 @@ impl<'test> TestCx<'test> { // For now, though… if let Some(rev) = self.revision { let prefixes = format!("CHECK,{}", rev); - filecheck.args(&["--check-prefixes", &prefixes]); + filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); } self.compose_and_run(filecheck, "", None, None) } From c34e7c60f5b0d3e860b5b26191535a86fb649dba Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 11 May 2021 16:20:52 -0700 Subject: [PATCH 02/20] Fix v0 symbol mangling bug --- compiler/rustc_symbol_mangling/src/v0.rs | 42 +++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 37a834043f624..c0690d93c967b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -485,27 +485,37 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { mut self, predicates: &'tcx ty::List>>, ) -> Result { - for predicate in predicates { - self = self.in_binder(&predicate, |mut cx, predicate| { - match predicate { - ty::ExistentialPredicate::Trait(trait_ref) => { + let mut predicate_iter = predicates.iter().peekable(); + while let Some(predicate) = predicate_iter.next() { + match predicate.as_ref().skip_binder() { + ty::ExistentialPredicate::Trait(trait_ref) => { + self = self.in_binder(&predicate, |mut cx, _predicate| { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0)); let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self); cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?; - } - ty::ExistentialPredicate::Projection(projection) => { - let name = cx.tcx.associated_item(projection.item_def_id).ident; - cx.push("p"); - cx.push_ident(&name.as_str()); - cx = projection.ty.print(cx)?; - } - ty::ExistentialPredicate::AutoTrait(def_id) => { - cx = cx.print_def_path(*def_id, &[])?; - } + while let Some(projection_pred) = predicate_iter.next_if(|p| { + matches!(p.skip_binder(), ty::ExistentialPredicate::Projection(_)) + }) { + let projection = match projection_pred.skip_binder() { + ty::ExistentialPredicate::Projection(projection) => projection, + _ => unreachable!(), + }; + let name = cx.tcx.associated_item(projection.item_def_id).ident; + cx.push("p"); + cx.push_ident(&name.as_str()); + cx = projection.ty.print(cx)?; + } + Ok(cx) + })?; } - Ok(cx) - })?; + ty::ExistentialPredicate::Projection(_) => { + unreachable!("handled in trait predicate arm") + } + ty::ExistentialPredicate::AutoTrait(def_id) => { + self = self.print_def_path(*def_id, &[])?; + } + } } self.push("E"); Ok(self) From 3fe1d7f78913231cdb7a8748149f7b2e67b814bd Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Thu, 13 May 2021 16:55:33 -0700 Subject: [PATCH 03/20] Only pass --[no-]gc-sections if linker is GNU ld. LinkerFlavor::Gcc does not always mean GNU ld specifically. And in the case of at least the solaris ld in illumos, that flag is unrecognized and will cause the linking step to fail. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 93059b2323da8..74629fcd118c3 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -469,7 +469,7 @@ impl<'a> Linker for GccLinker<'a> { // eliminate the metadata. If we're building an executable, however, // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. - } else if !keep_metadata { + } else if self.sess.target.linker_is_gnu && !keep_metadata { self.linker_arg("--gc-sections"); } } @@ -477,9 +477,7 @@ impl<'a> Linker for GccLinker<'a> { fn no_gc_sections(&mut self) { if self.sess.target.is_like_osx { self.linker_arg("-no_dead_strip"); - } else if self.sess.target.is_like_solaris { - self.linker_arg("-zrecord"); - } else { + } else if self.sess.target.linker_is_gnu { self.linker_arg("--no-gc-sections"); } } From 15aad5fcdb33a75e495a3d427228df62b6eadd5b Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Fri, 14 May 2021 19:22:41 +0100 Subject: [PATCH 04/20] bootstrap: build cargo only if requested in tools --- src/bootstrap/tool.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 4f2426648fd8a..6fc06896257b2 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -593,7 +593,14 @@ impl Step for Cargo { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/tools/cargo").default_condition(builder.config.extended) + run.path("src/tools/cargo").default_condition( + builder.config.extended + && builder.config.tools.as_ref().map_or( + true, + // If `tools` is set, search list for this tool. + |tools| tools.iter().any(|tool| tool == "cargo"), + ), + ) } fn make_run(run: RunConfig<'_>) { From 0daabbee2d255ec78811443cdc4def67b3e0de1d Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 15:19:01 -0400 Subject: [PATCH 05/20] Change to just use first binders and add test --- compiler/rustc_symbol_mangling/src/v0.rs | 73 ++++++++++++------- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- .../symbol-names/trait-objects.legacy.stderr | 56 ++++++++++++++ src/test/ui/symbol-names/trait-objects.rs | 56 ++++++++++++++ .../ui/symbol-names/trait-objects.v0.stderr | 56 ++++++++++++++ 5 files changed, 218 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/symbol-names/trait-objects.legacy.stderr create mode 100644 src/test/ui/symbol-names/trait-objects.rs create mode 100644 src/test/ui/symbol-names/trait-objects.v0.stderr diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c0690d93c967b..a70b374fc6d21 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -485,38 +485,59 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { mut self, predicates: &'tcx ty::List>>, ) -> Result { - let mut predicate_iter = predicates.iter().peekable(); - while let Some(predicate) = predicate_iter.next() { - match predicate.as_ref().skip_binder() { - ty::ExistentialPredicate::Trait(trait_ref) => { - self = self.in_binder(&predicate, |mut cx, _predicate| { + // Okay, so this is a bit tricky. Imagine we have a trait object like + // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the + // output looks really close to the syntax, where the `Bar = &'a ()` bit + // is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we + // actually desugar these into two separate `ExistentialPredicate`s. We + // can't enter/exit the "binder scope" twice though, because then we + // would mangle the binders twice. (Also, side note, we merging these + // two is kind of difficult, because of potential HRTBs in the Projection + // predicate.) + // + // Also worth mentioning: imagine that we instead had + // `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is + // under the same binders as `Foo`. Currently, this doesn't matter, + // because only *auto traits* are allowed other than the principal trait + // and all auto traits don't have any generics. Two things could + // make this not an "okay" mangling: + // 1) Instead of mangling only *used* + // bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a + // valid trait predicate); + // 2) We allow multiple "principal" traits in the future, or at least + // allow in any form another trait predicate that can take generics. + // + // Here we assume that predicates have the following structure: + // [ [{}]] [{}] + // Since any predicates after the first one shouldn't change the binders, + // just put them all in the binders of the first. + self = self.in_binder(&predicates[0], |mut cx, _| { + for predicate in predicates.iter() { + // It would be nice to be able to validate bound vars here, but + // projections can actually include bound vars from super traits + // because of HRTBs (only in the `Self` type). Also, auto traits + // could have different bound vars *anyways*. + match predicate.as_ref().skip_binder() { + ty::ExistentialPredicate::Trait(trait_ref) => { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0)); let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self); cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?; - while let Some(projection_pred) = predicate_iter.next_if(|p| { - matches!(p.skip_binder(), ty::ExistentialPredicate::Projection(_)) - }) { - let projection = match projection_pred.skip_binder() { - ty::ExistentialPredicate::Projection(projection) => projection, - _ => unreachable!(), - }; - let name = cx.tcx.associated_item(projection.item_def_id).ident; - cx.push("p"); - cx.push_ident(&name.as_str()); - cx = projection.ty.print(cx)?; - } - Ok(cx) - })?; - } - ty::ExistentialPredicate::Projection(_) => { - unreachable!("handled in trait predicate arm") - } - ty::ExistentialPredicate::AutoTrait(def_id) => { - self = self.print_def_path(*def_id, &[])?; + } + ty::ExistentialPredicate::Projection(projection) => { + let name = cx.tcx.associated_item(projection.item_def_id).ident; + cx.push("p"); + cx.push_ident(&name.as_str()); + cx = projection.ty.print(cx)?; + } + ty::ExistentialPredicate::AutoTrait(def_id) => { + cx = cx.print_def_path(*def_id, &[])?; + } } } - } + Ok(cx) + })?; + self.push("E"); Ok(self) } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2f2e90e4bd66f..c2e451670ed1c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1386,11 +1386,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) }); + // N.b. principal, projections, auto traits + // FIXME: This is actually wrong with multiple principals in regards to symbol mangling let mut v = regular_trait_predicates - .chain(auto_trait_predicates) .chain( existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), ) + .chain(auto_trait_predicates) .collect::>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); v.dedup(); diff --git a/src/test/ui/symbol-names/trait-objects.legacy.stderr b/src/test/ui/symbol-names/trait-objects.legacy.stderr new file mode 100644 index 0000000000000..200280c358f5b --- /dev/null +++ b/src/test/ui/symbol-names/trait-objects.legacy.stderr @@ -0,0 +1,56 @@ +error: symbol-name(_ZN136_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u20$as$u20$trait_objects..Bar$GT$6method17h1e14a5f2d365272fE) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method::h1e14a5f2d365272f) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Foo$GT$6method17he7a07961c9aaa367E) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method::he7a07961c9aaa367) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Baz$GT$6method17ha53e6f99bf033f0bE) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method::ha53e6f99bf033f0b) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/symbol-names/trait-objects.rs b/src/test/ui/symbol-names/trait-objects.rs new file mode 100644 index 0000000000000..ffbd3901b8e2a --- /dev/null +++ b/src/test/ui/symbol-names/trait-objects.rs @@ -0,0 +1,56 @@ +// Ensure that trait objects don't include more than one binder. See #83611 + +// build-fail +// revisions: legacy v0 +//[legacy]compile-flags: -Z symbol-mangling-version=legacy + //[v0]compile-flags: -Z symbol-mangling-version=v0 + +#![feature(rustc_attrs)] + +trait Bar { + fn method(&self) {} +} + +impl Bar for &dyn FnMut(&u8) { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name + //[legacy]~| ERROR demangling + //[legacy]~| ERROR demangling-alt + //[v0]~^^^^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +trait Foo { + fn method(&self) {} +} + +impl Foo for &(dyn FnMut(&u8) + for<'b> Send) { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name + //[legacy]~| ERROR demangling + //[legacy]~| ERROR demangling-alt + //[v0]~^^^^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +trait Baz { + fn method(&self) {} +} + +impl Baz for &(dyn for<'b> Send + FnMut(&u8)) { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name + //[legacy]~| ERROR demangling + //[legacy]~| ERROR demangling-alt + //[v0]~^^^^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +fn main() { +} diff --git a/src/test/ui/symbol-names/trait-objects.v0.stderr b/src/test/ui/symbol-names/trait-objects.v0.stderr new file mode 100644 index 0000000000000..7a29f44718af9 --- /dev/null +++ b/src/test/ui/symbol-names/trait-objects.v0.stderr @@ -0,0 +1,56 @@ +error: symbol-name(_RNvXCs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXs_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Foo>::method) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method) + --> $DIR/trait-objects.rs:30:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXs0_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Baz>::method) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method) + --> $DIR/trait-objects.rs:45:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + From 45225d24bff4bec2eec55f89695876454daa23e2 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 15 May 2021 22:09:34 -0700 Subject: [PATCH 06/20] Windows mingw targets use gcc as the linker so the target spec should also indicate linker_is_gnu. --- compiler/rustc_target/src/spec/windows_gnu_base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index 35a52896f6fa6..5808391ee065d 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -66,6 +66,7 @@ pub fn opts() -> TargetOptions { // FIXME(#13846) this should be enabled for windows function_sections: false, linker: Some("gcc".to_string()), + linker_is_gnu: true, dynamic_linking: true, executables: true, dll_prefix: String::new(), From fbc01e5332f0388a9a68e641a6adaaaa45ca2c64 Mon Sep 17 00:00:00 2001 From: Milan Landaverde Date: Tue, 11 May 2021 15:41:32 -0400 Subject: [PATCH 07/20] Add abstract namespace support for Unix domain sockets --- library/std/src/os/unix/net/addr.rs | 84 +++++++++++++++- library/std/src/os/unix/net/datagram.rs | 94 +++++++++++++++++- library/std/src/os/unix/net/listener.rs | 34 +++++++ library/std/src/os/unix/net/stream.rs | 31 ++++++ library/std/src/os/unix/net/tests.rs | 125 +++++++++++++++++++++++- 5 files changed, 363 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 459f3590e6470..bf1685d5a40bd 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, iter, mem}; +use crate::{ascii, fmt, io, iter, mem, ptr}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -92,8 +92,8 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { #[derive(Clone)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, + pub(super) addr: libc::sockaddr_un, + pub(super) len: libc::socklen_t, } impl SocketAddr { @@ -196,6 +196,30 @@ impl SocketAddr { if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } } + /// Returns the contents of this address if it is an abstract namespace + /// without the leading null byte. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let namespace = b"hidden"; + /// let namespace_addr = SocketAddr::from_abstract_namespace(&namespace[..])?; + /// let socket = UnixListener::bind_addr(&namespace_addr)?; + /// let local_addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(local_addr.as_abstract_namespace(), Some(&namespace[..])); + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn as_abstract_namespace(&self) -> Option<&[u8]> { + if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } + } + fn address(&self) -> AddressKind<'_> { let len = self.len as usize - sun_path_offset(&self.addr); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; @@ -212,6 +236,60 @@ impl SocketAddr { AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) } } + + /// Creates an abstract domain socket address from a namespace + /// + /// An abstract address does not create a file unlike traditional path-based + /// Unix sockets. The advantage of this is that the address will disappear when + /// the socket bound to it is closed, so no filesystem clean up is required. + /// + /// The leading null byte for the abstract namespace is automatically added. + /// + /// This is a Linux-specific extension. See more at [`unix(7)`]. + /// + /// [`unix(7)`]: https://man7.org/linux/man-pages/man7/unix.7.html + /// + /// # Errors + /// + /// This will return an error if the given namespace is too long + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; + /// let listener = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result { + unsafe { + let mut addr: libc::sockaddr_un = mem::zeroed(); + addr.sun_family = libc::AF_UNIX as libc::sa_family_t; + + if namespace.len() + 1 > addr.sun_path.len() { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"namespace must be shorter than SUN_LEN", + )); + } + + ptr::copy_nonoverlapping(namespace.as_ptr(), addr.sun_path.as_mut_ptr().offset(1) as *mut u8, namespace.len()); + let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t; + SocketAddr::from_parts(addr, len) + } + } } #[stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 9e39f70f68e69..f52c8b0768b3b 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -112,6 +112,35 @@ impl UnixDatagram { } } + /// Creates a Unix datagram socket bound to an address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; // Linux only + /// let sock = match UnixDatagram::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let socket = UnixDatagram::unbound()?; + cvt(libc::bind(*socket.0.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _))?; + Ok(socket) + } + } + /// Creates a Unix Datagram socket which is not bound to any address. /// /// # Examples @@ -156,7 +185,7 @@ impl UnixDatagram { Ok((UnixDatagram(i1), UnixDatagram(i2))) } - /// Connects the socket to the specified address. + /// Connects the socket to the specified path address. /// /// The [`send`] method may be used to send data to the specified address. /// [`recv`] and [`recv_from`] will only receive data from that address. @@ -192,6 +221,35 @@ impl UnixDatagram { Ok(()) } + /// Connects the socket to an address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; // Linux only + /// let sock = UnixDatagram::unbound()?; + /// match sock.connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { + unsafe { + cvt(libc::connect(*self.0.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len))?; + } + Ok(()) + } + /// Creates a new independently owned handle to the underlying socket. /// /// The returned `UnixDatagram` is a reference to the same socket that this @@ -473,6 +531,40 @@ impl UnixDatagram { } } + /// Sends data on the socket to the specified [SocketAddr]. + /// + /// On success, returns the number of bytes written. + /// + /// [SocketAddr]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; + /// let sock = UnixDatagram::unbound()?; + /// sock.send_to_addr(b"bacon egg and cheese", &addr).expect("send_to_addr function failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result { + unsafe { + let count = cvt(libc::sendto( + *self.0.as_inner(), + buf.as_ptr() as *const _, + buf.len(), + MSG_NOSIGNAL, + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; + Ok(count as usize) + } + } + /// Sends data on the socket to the socket's peer. /// /// The peer address may be set by the `connect` method, and this method diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index bdd08fe8380fa..598d792d98d38 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -81,6 +81,40 @@ impl UnixListener { } } + /// Creates a new `UnixListener` bound to the specified [`socket address`]. + /// + /// [`socket address`]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"namespace")?; // Linux only + /// let listener = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + cvt(libc::bind(*inner.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _))?; + cvt(libc::listen(*inner.as_inner(), 128))?; + + Ok(UnixListener(inner)) + } + } + + /// Accepts a new incoming connection to this listener. /// /// This function will block the calling thread until a new Unix connection diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index a6f6e091305d5..3f6e2e141057e 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -104,6 +104,37 @@ impl UnixStream { } } + /// Connects to the socket specified by [`address`]. + /// + /// [`address`]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixStream, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; // Linux only + /// match UnixStream::connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ```` + #[unstable(feature = "unix_socket_abstract", issue = "42048")] + pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + cvt(libc::connect(*inner.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len))?; + Ok(UnixStream(inner)) + } + } + /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index bd9b6dd727b96..b13ce0e252adb 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -388,10 +388,133 @@ fn test_unix_datagram_timeout_zero_duration() { } #[test] -fn abstract_namespace_not_allowed() { +fn abstract_namespace_not_allowed_connect() { assert!(UnixStream::connect("\0asdf").is_err()); } +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_stream_connect() { + let msg1 = b"hello"; + let msg2 = b"world"; + + let socket_addr = or_panic!(SocketAddr::from_abstract_namespace(b"namespace")); + let listener = or_panic!(UnixListener::bind_addr(&socket_addr)); + + let thread = thread::spawn(move || { + let mut stream = or_panic!(listener.accept()).0; + let mut buf = [0; 5]; + or_panic!(stream.read(&mut buf)); + assert_eq!(&msg1[..], &buf[..]); + or_panic!(stream.write_all(msg2)); + }); + + let mut stream = or_panic!(UnixStream::connect_addr(&socket_addr)); + + let peer = or_panic!(stream.peer_addr()); + assert_eq!(peer.as_abstract_namespace().unwrap(), b"namespace"); + + or_panic!(stream.write_all(msg1)); + let mut buf = vec![]; + or_panic!(stream.read_to_end(&mut buf)); + assert_eq!(&msg2[..], &buf[..]); + drop(stream); + + thread.join().unwrap(); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_stream_iter() { + let addr = or_panic!(SocketAddr::from_abstract_namespace(b"hidden")); + let listener = or_panic!(UnixListener::bind_addr(&addr)); + + let thread = thread::spawn(move || { + for stream in listener.incoming().take(2) { + let mut stream = or_panic!(stream); + let mut buf = [0]; + or_panic!(stream.read(&mut buf)); + } + }); + + for _ in 0..2 { + let mut stream = or_panic!(UnixStream::connect_addr(&addr)); + or_panic!(stream.write_all(&[0])); + } + + thread.join().unwrap(); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_datagram_bind_send_to_addr() { + let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns1")); + let sock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); + + let local = or_panic!(sock1.local_addr()); + assert_eq!(local.as_abstract_namespace().unwrap(), b"ns1"); + + let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns2")); + let sock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); + + let msg = b"hello world"; + or_panic!(sock1.send_to_addr(msg, &addr2)); + let mut buf = [0; 11]; + let (len, addr) = or_panic!(sock2.recv_from(&mut buf)); + assert_eq!(msg, &buf[..]); + assert_eq!(len, 11); + assert_eq!(addr.as_abstract_namespace().unwrap(), b"ns1"); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_datagram_connect_addr() { + let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns3")); + let bsock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); + + let sock = or_panic!(UnixDatagram::unbound()); + or_panic!(sock.connect_addr(&addr1)); + + let msg = b"hello world"; + or_panic!(sock.send(msg)); + let mut buf = [0; 11]; + let (len, addr) = or_panic!(bsock1.recv_from(&mut buf)); + assert_eq!(len, 11); + assert_eq!(addr.is_unnamed(), true); + assert_eq!(msg, &buf[..]); + + let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns4")); + let bsock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); + + or_panic!(sock.connect_addr(&addr2)); + or_panic!(sock.send(msg)); + or_panic!(bsock2.recv_from(&mut buf)); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_namespace_too_long() { + match SocketAddr::from_abstract_namespace( + b"abcdefghijklmnopqrstuvwxyzabcdefghijklmn\ + opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi\ + jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + ) { + Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} + Err(e) => panic!("unexpected error {}", e), + Ok(_) => panic!("unexpected success"), + } +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_namespace_no_pathname_and_not_unnamed() { + let namespace = b"local"; + let addr = or_panic!(SocketAddr::from_abstract_namespace(&namespace[..])); + assert_eq!(addr.as_pathname(), None); + assert_eq!(addr.as_abstract_namespace(), Some(&namespace[..])); + assert_eq!(addr.is_unnamed(), false); +} + #[test] fn test_unix_stream_peek() { let (txdone, rxdone) = crate::sync::mpsc::channel(); From 1c08ebbfd0b3515bece01de0832a758e7b71b3e8 Mon Sep 17 00:00:00 2001 From: Milan Landaverde Date: Sun, 16 May 2021 17:49:54 -0400 Subject: [PATCH 08/20] rustfmt --- library/std/src/os/unix/net/addr.rs | 6 +++++- library/std/src/os/unix/net/datagram.rs | 12 ++++++++++-- library/std/src/os/unix/net/listener.rs | 7 +++++-- library/std/src/os/unix/net/stream.rs | 6 +++++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index bf1685d5a40bd..4d70b510b82f9 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -285,7 +285,11 @@ impl SocketAddr { )); } - ptr::copy_nonoverlapping(namespace.as_ptr(), addr.sun_path.as_mut_ptr().offset(1) as *mut u8, namespace.len()); + ptr::copy_nonoverlapping( + namespace.as_ptr(), + addr.sun_path.as_mut_ptr().offset(1) as *mut u8, + namespace.len(), + ); let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t; SocketAddr::from_parts(addr, len) } diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index f52c8b0768b3b..0abcdca2c698f 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -136,7 +136,11 @@ impl UnixDatagram { pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let socket = UnixDatagram::unbound()?; - cvt(libc::bind(*socket.0.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _))?; + cvt(libc::bind( + *socket.0.as_inner(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len as _, + ))?; Ok(socket) } } @@ -245,7 +249,11 @@ impl UnixDatagram { #[unstable(feature = "unix_socket_abstract", issue = "42048")] pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { unsafe { - cvt(libc::connect(*self.0.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len))?; + cvt(libc::connect( + *self.0.as_inner(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; } Ok(()) } diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 598d792d98d38..658f54989075b 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -107,14 +107,17 @@ impl UnixListener { pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - cvt(libc::bind(*inner.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _))?; + cvt(libc::bind( + *inner.as_inner(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len as _, + ))?; cvt(libc::listen(*inner.as_inner(), 128))?; Ok(UnixListener(inner)) } } - /// Accepts a new incoming connection to this listener. /// /// This function will block the calling thread until a new Unix connection diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 3f6e2e141057e..640caf8d9925b 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -130,7 +130,11 @@ impl UnixStream { pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - cvt(libc::connect(*inner.as_inner(), &socket_addr.addr as *const _ as *const _, socket_addr.len))?; + cvt(libc::connect( + *inner.as_inner(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; Ok(UnixStream(inner)) } } From 253cbabc3974c4d4763b11061d7e2dc840a017e3 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sun, 16 May 2021 20:47:03 -0700 Subject: [PATCH 09/20] rustdoc: restore header sizes --- src/librustdoc/html/static/rustdoc.css | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index e2e1aefa4a842..cf91f18d73e35 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -427,9 +427,13 @@ nav.sub { border-bottom: 1px solid; } -#main > .docblock h1 { font-size: 1.3em; } -#main > .docblock h2 { font-size: 1.15em; } -#main > .docblock h3, #main > .docblock h4, #main > .docblock h5 { font-size: 1em; } +.top-doc .docblock h1 { font-size: 1.3em; } +.top-doc .docblock h2 { font-size: 1.15em; } +.top-doc .docblock h3, +.top-doc .docblock h4, +.top-doc .docblock h5 { + font-size: 1em; +} .docblock h1 { font-size: 1em; } .docblock h2 { font-size: 0.95em; } From a4d048931fb5e670aa16cafeb1fa0079b6f20f7d Mon Sep 17 00:00:00 2001 From: Milan Landaverde Date: Mon, 17 May 2021 08:29:49 -0400 Subject: [PATCH 10/20] Update tracking issue in stability refs --- library/std/src/os/unix/net/addr.rs | 4 ++-- library/std/src/os/unix/net/datagram.rs | 6 +++--- library/std/src/os/unix/net/listener.rs | 2 +- library/std/src/os/unix/net/stream.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 4d70b510b82f9..517e72eaf7e1c 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -215,7 +215,7 @@ impl SocketAddr { /// } /// ``` #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn as_abstract_namespace(&self) -> Option<&[u8]> { if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } } @@ -272,7 +272,7 @@ impl SocketAddr { /// } /// ``` #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result { unsafe { let mut addr: libc::sockaddr_un = mem::zeroed(); diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 0abcdca2c698f..2e750be5e7a35 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -132,7 +132,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let socket = UnixDatagram::unbound()?; @@ -246,7 +246,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { unsafe { cvt(libc::connect( @@ -558,7 +558,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result { unsafe { let count = cvt(libc::sendto( diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 658f54989075b..ecf121770c1ac 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -103,7 +103,7 @@ impl UnixListener { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 640caf8d9925b..1ae6acd7bbf09 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -126,7 +126,7 @@ impl UnixStream { /// Ok(()) /// } /// ```` - #[unstable(feature = "unix_socket_abstract", issue = "42048")] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; From 83459081bacfe30a593fc3cc95c029b11ed67468 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 23:18:59 -0400 Subject: [PATCH 11/20] Remove legacy for trait object mangling test and replace crate hash --- .../symbol-names/trait-objects.legacy.stderr | 56 ------------------- src/test/ui/symbol-names/trait-objects.rs | 22 +++----- .../ui/symbol-names/trait-objects.v0.stderr | 30 +++++----- 3 files changed, 22 insertions(+), 86 deletions(-) delete mode 100644 src/test/ui/symbol-names/trait-objects.legacy.stderr diff --git a/src/test/ui/symbol-names/trait-objects.legacy.stderr b/src/test/ui/symbol-names/trait-objects.legacy.stderr deleted file mode 100644 index 200280c358f5b..0000000000000 --- a/src/test/ui/symbol-names/trait-objects.legacy.stderr +++ /dev/null @@ -1,56 +0,0 @@ -error: symbol-name(_ZN136_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u20$as$u20$trait_objects..Bar$GT$6method17h1e14a5f2d365272fE) - --> $DIR/trait-objects.rs:15:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method::h1e14a5f2d365272f) - --> $DIR/trait-objects.rs:15:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method) - --> $DIR/trait-objects.rs:15:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Foo$GT$6method17he7a07961c9aaa367E) - --> $DIR/trait-objects.rs:30:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method::he7a07961c9aaa367) - --> $DIR/trait-objects.rs:30:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method) - --> $DIR/trait-objects.rs:30:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Baz$GT$6method17ha53e6f99bf033f0bE) - --> $DIR/trait-objects.rs:45:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method::ha53e6f99bf033f0b) - --> $DIR/trait-objects.rs:45:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method) - --> $DIR/trait-objects.rs:45:5 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/symbol-names/trait-objects.rs b/src/test/ui/symbol-names/trait-objects.rs index ffbd3901b8e2a..cea1a89d75746 100644 --- a/src/test/ui/symbol-names/trait-objects.rs +++ b/src/test/ui/symbol-names/trait-objects.rs @@ -1,9 +1,10 @@ // Ensure that trait objects don't include more than one binder. See #83611 // build-fail -// revisions: legacy v0 -//[legacy]compile-flags: -Z symbol-mangling-version=legacy - //[v0]compile-flags: -Z symbol-mangling-version=v0 +// revisions: v0 +//[v0]compile-flags: -Z symbol-mangling-version=v0 +//[v0]normalize-stderr-test: "Cs.*?_" -> "CRATE_HASH" +//[v0]normalize-stderr-test: "core\[.*?\]" -> "core[HASH]" #![feature(rustc_attrs)] @@ -13,10 +14,7 @@ trait Bar { impl Bar for &dyn FnMut(&u8) { #[rustc_symbol_name] - //[legacy]~^ ERROR symbol-name - //[legacy]~| ERROR demangling - //[legacy]~| ERROR demangling-alt - //[v0]~^^^^ ERROR symbol-name + //[v0]~^ ERROR symbol-name //[v0]~| ERROR demangling //[v0]~| ERROR demangling-alt fn method(&self) {} @@ -28,10 +26,7 @@ trait Foo { impl Foo for &(dyn FnMut(&u8) + for<'b> Send) { #[rustc_symbol_name] - //[legacy]~^ ERROR symbol-name - //[legacy]~| ERROR demangling - //[legacy]~| ERROR demangling-alt - //[v0]~^^^^ ERROR symbol-name + //[v0]~^ ERROR symbol-name //[v0]~| ERROR demangling //[v0]~| ERROR demangling-alt fn method(&self) {} @@ -43,10 +38,7 @@ trait Baz { impl Baz for &(dyn for<'b> Send + FnMut(&u8)) { #[rustc_symbol_name] - //[legacy]~^ ERROR symbol-name - //[legacy]~| ERROR demangling - //[legacy]~| ERROR demangling-alt - //[v0]~^^^^ ERROR symbol-name + //[v0]~^ ERROR symbol-name //[v0]~| ERROR demangling //[v0]~| ERROR demangling-alt fn method(&self) {} diff --git a/src/test/ui/symbol-names/trait-objects.v0.stderr b/src/test/ui/symbol-names/trait-objects.v0.stderr index 7a29f44718af9..2b09318f06c74 100644 --- a/src/test/ui/symbol-names/trait-objects.v0.stderr +++ b/src/test/ui/symbol-names/trait-objects.v0.stderr @@ -1,53 +1,53 @@ -error: symbol-name(_RNvXCs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method) - --> $DIR/trait-objects.rs:15:5 +error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method) + --> $DIR/trait-objects.rs:16:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method) - --> $DIR/trait-objects.rs:15:5 +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method) + --> $DIR/trait-objects.rs:16:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method) - --> $DIR/trait-objects.rs:15:5 + --> $DIR/trait-objects.rs:16:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXs_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method) - --> $DIR/trait-objects.rs:30:5 +error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method) + --> $DIR/trait-objects.rs:28:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Foo>::method) - --> $DIR/trait-objects.rs:30:5 +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method) + --> $DIR/trait-objects.rs:28:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method) - --> $DIR/trait-objects.rs:30:5 + --> $DIR/trait-objects.rs:28:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXs0_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method) - --> $DIR/trait-objects.rs:45:5 +error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method) + --> $DIR/trait-objects.rs:40:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Baz>::method) - --> $DIR/trait-objects.rs:45:5 +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method) + --> $DIR/trait-objects.rs:40:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method) - --> $DIR/trait-objects.rs:45:5 + --> $DIR/trait-objects.rs:40:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ From 3035816fc13c2ae30d46849bfcceec085a2f47e2 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 17 May 2021 13:08:42 -0400 Subject: [PATCH 12/20] runtest: correctly guard against LLVM version 13 --- src/tools/compiletest/src/runtest.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 517ae9c4dff95..80d905c730f49 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2293,7 +2293,11 @@ impl<'test> TestCx<'test> { // For now, though… if let Some(rev) = self.revision { let prefixes = format!("CHECK,{}", rev); - filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); + if self.config.llvm_version.unwrap_or(0) >= 130000 { + filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); + } else { + filecheck.args(&["--check-prefixes", &prefixes]); + } } self.compose_and_run(filecheck, "", None, None) } From a862b1f6cc904789f046dbef88c944f4c723970c Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Mon, 17 May 2021 16:14:13 -0700 Subject: [PATCH 13/20] Adjust linker_is_gnu branches for cases that don't work on windows. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 74629fcd118c3..dfcb3fe94f630 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -276,18 +276,27 @@ impl<'a> Linker for GccLinker<'a> { fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { match output_kind { LinkOutputKind::DynamicNoPicExe => { - if !self.is_ld && self.sess.target.linker_is_gnu { + if !self.is_ld + && self.sess.target.linker_is_gnu + && !self.sess.target.is_like_windows + { self.cmd.arg("-no-pie"); } } LinkOutputKind::DynamicPicExe => { - // `-pie` works for both gcc wrapper and ld. - self.cmd.arg("-pie"); + // noop on windows w/ gcc & ld, error w/ lld + if !self.sess.target.is_like_windows { + // `-pie` works for both gcc wrapper and ld + self.cmd.arg("-pie"); + } } LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. self.cmd.arg("-static"); - if !self.is_ld && self.sess.target.linker_is_gnu { + if !self.is_ld + && self.sess.target.linker_is_gnu + && !self.sess.target.is_like_windows + { self.cmd.arg("-no-pie"); } } @@ -347,7 +356,7 @@ impl<'a> Linker for GccLinker<'a> { // has -needed-l{} / -needed_library {} // but we have no way to detect that here. self.sess.warn("`as-needed` modifier not implemented yet for ld64"); - } else if self.sess.target.linker_is_gnu { + } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--no-as-needed"); } else { self.sess.warn("`as-needed` modifier not supported for current linker"); @@ -358,7 +367,7 @@ impl<'a> Linker for GccLinker<'a> { if !as_needed { if self.sess.target.is_like_osx { // See above FIXME comment - } else if self.sess.target.linker_is_gnu { + } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } } @@ -690,7 +699,7 @@ impl<'a> Linker for GccLinker<'a> { } fn add_as_needed(&mut self) { - if self.sess.target.linker_is_gnu { + if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } else if self.sess.target.is_like_solaris { // -z ignore is the Solaris equivalent to the GNU ld --as-needed option From 18b0e7bf2cc527aae98af62a9d66b26759d84db3 Mon Sep 17 00:00:00 2001 From: mbartlett21 <29034492+mbartlett21@users.noreply.github.com> Date: Tue, 18 May 2021 13:40:26 +1000 Subject: [PATCH 14/20] Fix must_use on `Option::is_none` This fixes the `#[must_use = ...]` on `Option::is_none` to have a working suggestion. --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 04551dded8c77..8e8b623c50bdd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -209,7 +209,7 @@ impl Option { /// assert_eq!(x.is_none(), true); /// ``` #[must_use = "if you intended to assert that this doesn't have a value, consider \ - `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"] + `.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"] #[inline] #[rustc_const_stable(feature = "const_option", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] From e48b6b459974245efcfc9edda468b4c587cbf37c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 22 Mar 2021 01:10:10 -0400 Subject: [PATCH 15/20] Stabilize extended_key_value_attributes # Stabilization report ## Summary This stabilizes using macro expansion in key-value attributes, like so: ```rust #[doc = include_str!("my_doc.md")] struct S; #[path = concat!(env!("OUT_DIR"), "/generated.rs")] mod m; ``` See the changes to the reference for details on what macros are allowed; see Petrochenkov's excellent blog post [on internals](https://internals.rust-lang.org/t/macro-expansion-points-in-attributes/11455) for alternatives that were considered and rejected ("why accept no more and no less?") This has been available on nightly since 1.50 with no major issues. ## Notes ### Accepted syntax The parser accepts arbitrary Rust expressions in this position, but any expression other than a macro invocation will ultimately lead to an error because it is not expected by the built-in expression forms (e.g., `#[doc]`). Note that decorators and the like may be able to observe other expression forms. ### Expansion ordering Expansion of macro expressions in "inert" attributes occurs after decorators have executed, analogously to macro expressions appearing in the function body or other parts of decorator input. There is currently no way for decorators to accept macros in key-value position if macro expansion must be performed before the decorator executes (if the macro can simply be copied into the output for later expansion, that can work). ## Test cases - https://github.com/rust-lang/rust/blob/master/src/test/ui/attributes/key-value-expansion-on-mac.rs - https://github.com/rust-lang/rust/blob/master/src/test/rustdoc/external-doc.rs The feature has also been dogfooded extensively in the compiler and standard library: - https://github.com/rust-lang/rust/pull/83329 - https://github.com/rust-lang/rust/pull/83230 - https://github.com/rust-lang/rust/pull/82641 - https://github.com/rust-lang/rust/pull/80534 ## Implementation history - Initial proposal: https://github.com/rust-lang/rust/issues/55414#issuecomment-554005412 - Experiment to see how much code it would break: https://github.com/rust-lang/rust/pull/67121 - Preliminary work to restrict expansion that would conflict with this feature: https://github.com/rust-lang/rust/pull/77271 - Initial implementation: https://github.com/rust-lang/rust/pull/78837 - Fix for an ICE: https://github.com/rust-lang/rust/pull/80563 ## Unresolved Questions ~~https://github.com/rust-lang/rust/pull/83366#issuecomment-805180738 listed some concerns, but they have been resolved as of this final report.~~ ## Additional Information There are two workarounds that have a similar effect for `#[doc]` attributes on nightly. One is to emulate this behavior by using a limited version of this feature that was stabilized for historical reasons: ```rust macro_rules! forward_inner_docs { ($e:expr => $i:item) => { #[doc = $e] $i }; } forward_inner_docs!(include_str!("lib.rs") => struct S {}); ``` This also works for other attributes (like `#[path = concat!(...)]`). The other is to use `doc(include)`: ```rust #![feature(external_doc)] #[doc(include = "lib.rs")] struct S {} ``` The first works, but is non-trivial for people to discover, and difficult to read and maintain. The second is a strange special-case for a particular use of the macro. This generalizes it to work for any use case, not just including files. I plan to remove `doc(include)` when this is stabilized. The `forward_inner_docs` workaround will still compile without warnings, but I expect it to be used less once it's no longer necessary. --- compiler/rustc_ast_passes/src/feature_gate.rs | 4 -- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 3 -- compiler/rustc_hir/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 13 ------- library/core/src/lib.rs | 2 +- library/std/src/lib.rs | 2 +- src/doc/rustdoc/README.md | 5 +++ src/doc/rustdoc/src/the-doc-attribute.md | 7 ++++ src/test/rustdoc/external-doc.rs | 1 - .../attributes/key-value-expansion-on-mac.rs | 1 - .../key-value-expansion-on-mac.stderr | 2 +- ...ture-gate-extended_key_value_attributes.rs | 8 ---- ...-gate-extended_key_value_attributes.stderr | 39 ------------------- src/test/ui/suffixed-literal-meta.rs | 2 +- 17 files changed, 21 insertions(+), 76 deletions(-) create mode 100644 src/doc/rustdoc/README.md delete mode 100644 src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 4215d5c55a049..4996c2195efdf 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -712,10 +712,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); - gate_all!( - extended_key_value_attributes, - "arbitrary expressions in key-value attributes are unstable" - ); gate_all!( const_generics_defaults, "default values for const generic parameters are experimental" diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 329458773ffaf..8eef06f018f3a 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,7 +8,7 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f53ce7ceace13..65352f0bc6e7b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(backtrace)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e8642a52749c4..eef71e096a52e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -281,6 +281,8 @@ declare_features! ( (accepted, or_patterns, "1.53.0", Some(54883), None), /// Allows defining identifiers beyond ASCII. (accepted, non_ascii_idents, "1.53.0", Some(55467), None), + /// Allows arbitrary expressions in key-value attributes at parse time. + (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 80fe5bafc6ee6..763264476b341 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -601,9 +601,6 @@ declare_features! ( /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (active, capture_disjoint_fields, "1.49.0", Some(53488), None), - /// Allows arbitrary expressions in key-value attributes at parse time. - (active, extended_key_value_attributes, "1.50.0", Some(78835), None), - /// Allows const generics to have default values (e.g. `struct Foo(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 65c99535c4e34..71e997994deff 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,7 @@ #![feature(crate_visibility_modifier)] #![feature(const_panic)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![cfg_attr(bootstrap, feature(or_patterns))] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 35cfaae13a4a0..4c2bc6ebf3143 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1065,24 +1065,11 @@ impl<'a> Parser<'a> { } else if !delimited_only { if self.eat(&token::Eq) { let eq_span = self.prev_token.span; - let mut is_interpolated_expr = false; - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtExpr(..) = **nt { - is_interpolated_expr = true; - } - } // Collect tokens because they are used during lowering to HIR. let expr = self.parse_expr_force_collect()?; let span = expr.span; - match &expr.kind { - // Not gated to support things like `doc = $expr` that work on stable. - _ if is_interpolated_expr => {} - ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {} - _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span), - } - let token_kind = token::Interpolated(Lrc::new(token::NtExpr(expr))); MacArgs::Eq(eq_span, Token::new(token_kind, span)) } else { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6a4f2d5a544c1..f652c52db5301 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -113,7 +113,7 @@ #![cfg_attr(bootstrap, feature(doc_spotlight))] #![cfg_attr(not(bootstrap), feature(doc_notable_trait))] #![feature(duration_consts_2)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(fundamental)] #![feature(intra_doc_pointers)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5f89ac059fd2d..6d11698d26822 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -268,7 +268,7 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] diff --git a/src/doc/rustdoc/README.md b/src/doc/rustdoc/README.md new file mode 100644 index 0000000000000..7d97d5e4ab52f --- /dev/null +++ b/src/doc/rustdoc/README.md @@ -0,0 +1,5 @@ +# Rustdoc + +This is documentation for rustdoc itself, written in mdbook format. +To build the book, use `x.py doc src/doc/rustdoc`. +To run doctests, use `x.py test src/doc/rustdoc`. diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index 52f2a3728fabb..d192f7d5ce9e5 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -35,6 +35,13 @@ Which can feel more flexible. Note that this would generate this: but given that docs are rendered via Markdown, it will remove these newlines. +Another use case is for including external files as documentation: + +```rust,no_run +#[doc = include_str!("../README.md")] +# fn f() {} +``` + The `doc` attribute has more options though! These don't involve the text of the output, but instead, various aspects of the presentation of the output. We've split them into two kinds below: attributes that are useful at the diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs index befd31a549290..0dadca551a9ff 100644 --- a/src/test/rustdoc/external-doc.rs +++ b/src/test/rustdoc/external-doc.rs @@ -1,5 +1,4 @@ #![feature(external_doc)] -#![feature(extended_key_value_attributes)] // @has external_doc/struct.CanHasDocs.html // @has - '//h1' 'External Docs' diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.rs b/src/test/ui/attributes/key-value-expansion-on-mac.rs index 1247ff2b23075..95bc1c04961b0 100644 --- a/src/test/ui/attributes/key-value-expansion-on-mac.rs +++ b/src/test/ui/attributes/key-value-expansion-on-mac.rs @@ -1,4 +1,3 @@ -#![feature(extended_key_value_attributes)] #![feature(rustc_attrs)] #[rustc_dummy = stringify!(a)] // OK diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.stderr b/src/test/ui/attributes/key-value-expansion-on-mac.stderr index b74f3518a7e97..fa9ea543765f7 100644 --- a/src/test/ui/attributes/key-value-expansion-on-mac.stderr +++ b/src/test/ui/attributes/key-value-expansion-on-mac.stderr @@ -1,5 +1,5 @@ error: unexpected token: `stringify!(b)` - --> $DIR/key-value-expansion-on-mac.rs:12:17 + --> $DIR/key-value-expansion-on-mac.rs:11:17 | LL | #[rustc_dummy = stringify!(b)] | ^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs deleted file mode 100644 index f19fdb45f1f1e..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(FALSE)] -#[attr = multi::segment::path] //~ ERROR arbitrary expressions in key-value attributes are unstable -#[attr = macro_call!()] //~ ERROR arbitrary expressions in key-value attributes are unstable -#[attr = 1 + 2] //~ ERROR arbitrary expressions in key-value attributes are unstable -#[attr = what?] //~ ERROR arbitrary expressions in key-value attributes are unstable -struct S; - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr deleted file mode 100644 index 9887814b90762..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0658]: arbitrary expressions in key-value attributes are unstable - --> $DIR/feature-gate-extended_key_value_attributes.rs:2:10 - | -LL | #[attr = multi::segment::path] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #78835 for more information - = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable - -error[E0658]: arbitrary expressions in key-value attributes are unstable - --> $DIR/feature-gate-extended_key_value_attributes.rs:3:10 - | -LL | #[attr = macro_call!()] - | ^^^^^^^^^^^^^ - | - = note: see issue #78835 for more information - = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable - -error[E0658]: arbitrary expressions in key-value attributes are unstable - --> $DIR/feature-gate-extended_key_value_attributes.rs:4:10 - | -LL | #[attr = 1 + 2] - | ^^^^^ - | - = note: see issue #78835 for more information - = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable - -error[E0658]: arbitrary expressions in key-value attributes are unstable - --> $DIR/feature-gate-extended_key_value_attributes.rs:5:10 - | -LL | #[attr = what?] - | ^^^^^ - | - = note: see issue #78835 for more information - = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs index 319264aec9cd6..a6531490c0159 100644 --- a/src/test/ui/suffixed-literal-meta.rs +++ b/src/test/ui/suffixed-literal-meta.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, extended_key_value_attributes)] +#![feature(rustc_attrs)] #[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes From e0d58725037b7a414d1ed60225207a9c708ac313 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Tue, 18 May 2021 02:42:29 -0700 Subject: [PATCH 16/20] Undo unnecessary changes. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index dfcb3fe94f630..2e909c29f557e 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -276,27 +276,18 @@ impl<'a> Linker for GccLinker<'a> { fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { match output_kind { LinkOutputKind::DynamicNoPicExe => { - if !self.is_ld - && self.sess.target.linker_is_gnu - && !self.sess.target.is_like_windows - { + if !self.is_ld && self.sess.target.linker_is_gnu { self.cmd.arg("-no-pie"); } } LinkOutputKind::DynamicPicExe => { - // noop on windows w/ gcc & ld, error w/ lld - if !self.sess.target.is_like_windows { - // `-pie` works for both gcc wrapper and ld - self.cmd.arg("-pie"); - } + // `-pie` works for both gcc wrapper and ld. + self.cmd.arg("-pie"); } LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. self.cmd.arg("-static"); - if !self.is_ld - && self.sess.target.linker_is_gnu - && !self.sess.target.is_like_windows - { + if !self.is_ld && self.sess.target.linker_is_gnu { self.cmd.arg("-no-pie"); } } From ac5fd90d822304a6b6e059d84a3c1e4103e24200 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Tue, 18 May 2021 03:57:53 -0700 Subject: [PATCH 17/20] Don't pass -pie to linker on windows targets. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 2e909c29f557e..bab38789a9f4c 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -281,8 +281,11 @@ impl<'a> Linker for GccLinker<'a> { } } LinkOutputKind::DynamicPicExe => { - // `-pie` works for both gcc wrapper and ld. - self.cmd.arg("-pie"); + // noop on windows w/ gcc & ld, error w/ lld + if !self.sess.target.is_like_windows { + // `-pie` works for both gcc wrapper and ld. + self.cmd.arg("-pie"); + } } LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. From 281dea47ceb2e0e56cc2e773c4c4bf0d901eff40 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 May 2021 14:32:20 +0200 Subject: [PATCH 18/20] Fix escape handling on search results --- src/librustdoc/html/static/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index be30871ea4c70..031438fb04588 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -428,9 +428,9 @@ function hideThemeButtonState() { function handleEscape(ev) { var help = getHelpElement(false); var search = searchState.outputElement(); - if (!hasClass(help, "hidden")) { + if (help && !hasClass(help, "hidden")) { displayHelp(false, ev, help); - } else if (!hasClass(search, "hidden")) { + } else if (search && !hasClass(search, "hidden")) { searchState.clearInputTimeout(); ev.preventDefault(); searchState.hideResults(search); From d314b065e71c0fa27c7f954d62537f932153f6cc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 May 2021 14:51:54 +0200 Subject: [PATCH 19/20] Add GUI tests for escape handling --- src/test/rustdoc-gui/escape-key.goml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/rustdoc-gui/escape-key.goml diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml new file mode 100644 index 0000000000000..303dd000ba391 --- /dev/null +++ b/src/test/rustdoc-gui/escape-key.goml @@ -0,0 +1,27 @@ +goto: file://|DOC_PATH|/test_docs/index.html +// First, we check that the search results are hidden when the Escape key is pressed. +write: (".search-input", "test") +wait-for: "#search > h1" // The search element is empty before the first search +assert: ("#search", "class", "content") +assert: ("#main", "class", "content hidden") +press-key: "Escape" +assert: ("#search", "class", "content hidden") +assert: ("#main", "class", "content") + +// Check that focusing the search input brings back the search results +focus: ".search-input" +assert: ("#search", "class", "content") +assert: ("#main", "class", "content hidden") + +// Now let's check that when the help popup is displayed and we press Escape, it doesn't +// hide the search results too. +click: "#help-button" +assert: ("#help", "class", "") +press-key: "Escape" +assert: ("#help", "class", "hidden") +assert: ("#search", "class", "content") +assert: ("#main", "class", "content hidden") + +// FIXME: Once https://github.com/rust-lang/rust/pull/84462 is merged, add check to ensure +// that Escape hides the search results when a result is focused. +// press-key: "ArrowDown" From b0b0267d5ce0a0dfc392bb828f7b76d517cca9f7 Mon Sep 17 00:00:00 2001 From: Milan Landaverde Date: Tue, 18 May 2021 09:27:53 -0400 Subject: [PATCH 20/20] moves use ptr within from_abstract_namespace fn --- library/std/src/os/unix/net/addr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 517e72eaf7e1c..c19078c509e19 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, iter, mem, ptr}; +use crate::{ascii, fmt, io, iter, mem}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -285,7 +285,7 @@ impl SocketAddr { )); } - ptr::copy_nonoverlapping( + crate::ptr::copy_nonoverlapping( namespace.as_ptr(), addr.sun_path.as_mut_ptr().offset(1) as *mut u8, namespace.len(),