about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-28 19:12:21 +0000
committerbors <bors@rust-lang.org>2022-07-28 19:12:21 +0000
commit9067d5277d10f0f32a49ec9c125a33828e26a32b (patch)
tree20a468451b7c7a0fd07ad5ff352b6d04fff44c70
parent36f4f4aa38563d0c02bbdbbc03fb20145edef567 (diff)
parent55f041e1f6383fc7cafd6b4f9aa9b5d3c23b5c48 (diff)
downloadrust-9067d5277d10f0f32a49ec9c125a33828e26a32b.tar.gz
rust-9067d5277d10f0f32a49ec9c125a33828e26a32b.zip
Auto merge of #99863 - Dylan-DPC:rollup-lq9w047, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #99628 (add more docs regarding ideographic numbers)
 - #99689 (Revert `write!` and `writeln!` to late drop temporaries)
 - #99807 (Fix PermissionDenied UI tests on WSL)
 - #99817 (rustdoc: remove Clean trait impls for more items)
 - #99851 (Fix small typo in Cargo.toml comment)
 - #99856 (fix: remove fake no_dead_strip for osx)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.toml2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs4
-rw-r--r--library/core/src/char/methods.rs12
-rw-r--r--library/core/src/macros/mod.rs14
-rw-r--r--src/librustdoc/clean/mod.rs115
-rw-r--r--src/test/ui/linkage-attr/issue-10755.rs5
-rw-r--r--src/test/ui/macros/format-args-temporaries-async.rs37
-rw-r--r--src/test/ui/macros/format-args-temporaries-in-write.rs50
-rw-r--r--src/test/ui/macros/format-args-temporaries-in-write.stderr43
-rw-r--r--src/test/ui/macros/format-args-temporaries.rs16
-rw-r--r--src/test/ui/process/process-spawn-nonexistent.rs12
11 files changed, 215 insertions, 95 deletions
diff --git a/Cargo.toml b/Cargo.toml
index ed024192c15..ffc886d47f3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -60,7 +60,7 @@ exclude = [
 # verify that this is the case. This requires, however, that the crate is built
 # without overflow checks and debug assertions. Forcefully disable debug
 # assertions and overflow checks here which should ensure that even if these
-# assertions are enabled for libstd we won't enable then for compiler_builtins
+# assertions are enabled for libstd we won't enable them for compiler_builtins
 # which should ensure we still link everything correctly.
 debug-assertions = false
 overflow-checks = false
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 8e5ac9da4ac..a4bbdefbb87 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -566,9 +566,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.linker_is_gnu || self.sess.target.is_like_wasm {
+        if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm {
             self.linker_arg("--no-gc-sections");
         }
     }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 0bec38a877e..eae567cad00 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -892,7 +892,16 @@ impl char {
     ///
     /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
     /// characters, and `No` for other numeric characters) are specified in the [Unicode Character
-    /// Database][ucd] [`UnicodeData.txt`].
+    /// Database][ucd] [`UnicodeData.txt`]. Note that this means ideographic numbers like '三'
+    /// are considered alphabetic, not numeric. Please consider to use `is_ascii_digit` or `is_digit`.
+    ///
+    /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'.
+    /// If you want everything including characters with overlapping purposes then you might want to use
+    /// a unicode or language-processing library that exposes the appropriate character properties instead
+    /// of looking at the unicode categories.
+    ///
+    /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use
+    /// `is_ascii_digit` or `is_digit` instead.
     ///
     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
     /// [ucd]: https://www.unicode.org/reports/tr44/
@@ -911,6 +920,7 @@ impl char {
     /// assert!(!'K'.is_numeric());
     /// assert!(!'و'.is_numeric());
     /// assert!(!'藏'.is_numeric());
+    /// assert!(!'三'.is_numeric());
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index bd62bc5c305..3a115a8b8b6 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -496,10 +496,9 @@ macro_rules! r#try {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")]
 macro_rules! write {
-    ($dst:expr, $($arg:tt)*) => {{
-        let result = $dst.write_fmt($crate::format_args!($($arg)*));
-        result
-    }};
+    ($dst:expr, $($arg:tt)*) => {
+        $dst.write_fmt($crate::format_args!($($arg)*))
+    };
 }
 
 /// Write formatted data into a buffer, with a newline appended.
@@ -554,10 +553,9 @@ macro_rules! writeln {
     ($dst:expr $(,)?) => {
         $crate::write!($dst, "\n")
     };
-    ($dst:expr, $($arg:tt)*) => {{
-        let result = $dst.write_fmt($crate::format_args_nl!($($arg)*));
-        result
-    }};
+    ($dst:expr, $($arg:tt)*) => {
+        $dst.write_fmt($crate::format_args_nl!($($arg)*))
+    };
 }
 
 /// Indicates unreachable code.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2f3ca41723d..2f2fbc9d4ba 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -398,23 +398,19 @@ fn clean_type_outlives_predicate<'tcx>(
     })
 }
 
-impl<'tcx> Clean<'tcx, Term> for ty::Term<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> Term {
-        match self {
-            ty::Term::Ty(ty) => Term::Type(clean_middle_ty(*ty, cx, None)),
-            ty::Term::Const(c) => Term::Constant(clean_middle_const(*c, cx)),
-        }
+fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
+    match term {
+        ty::Term::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
+        ty::Term::Const(c) => Term::Constant(clean_middle_const(c, cx)),
     }
 }
 
-impl<'tcx> Clean<'tcx, Term> for hir::Term<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> Term {
-        match self {
-            hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
-            hir::Term::Const(c) => {
-                let def_id = cx.tcx.hir().local_def_id(c.hir_id);
-                Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
-            }
+fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
+    match term {
+        hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
+        hir::Term::Const(c) => {
+            let def_id = cx.tcx.hir().local_def_id(c.hir_id);
+            Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
         }
     }
 }
@@ -426,7 +422,7 @@ fn clean_projection_predicate<'tcx>(
     let ty::ProjectionPredicate { projection_ty, term } = pred;
     WherePredicate::EqPredicate {
         lhs: clean_projection(projection_ty, cx, None),
-        rhs: term.clean(cx),
+        rhs: clean_middle_term(term, cx),
     }
 }
 
@@ -474,47 +470,44 @@ fn projection_to_path_segment<'tcx>(
     }
 }
 
-impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef {
-        let (name, kind) = match self.kind {
-            ty::GenericParamDefKind::Lifetime => {
-                (self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
-            }
-            ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
-                let default = if has_default {
-                    Some(clean_middle_ty(cx.tcx.type_of(self.def_id), cx, Some(self.def_id)))
-                } else {
-                    None
-                };
-                (
-                    self.name,
-                    GenericParamDefKind::Type {
-                        did: self.def_id,
-                        bounds: vec![], // These are filled in from the where-clauses.
-                        default: default.map(Box::new),
-                        synthetic,
-                    },
-                )
-            }
-            ty::GenericParamDefKind::Const { has_default } => (
-                self.name,
-                GenericParamDefKind::Const {
-                    did: self.def_id,
-                    ty: Box::new(clean_middle_ty(
-                        cx.tcx.type_of(self.def_id),
-                        cx,
-                        Some(self.def_id),
-                    )),
-                    default: match has_default {
-                        true => Some(Box::new(cx.tcx.const_param_default(self.def_id).to_string())),
-                        false => None,
-                    },
+fn clean_generic_param_def<'tcx>(
+    def: &ty::GenericParamDef,
+    cx: &mut DocContext<'tcx>,
+) -> GenericParamDef {
+    let (name, kind) = match def.kind {
+        ty::GenericParamDefKind::Lifetime => {
+            (def.name, GenericParamDefKind::Lifetime { outlives: vec![] })
+        }
+        ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
+            let default = if has_default {
+                Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+            } else {
+                None
+            };
+            (
+                def.name,
+                GenericParamDefKind::Type {
+                    did: def.def_id,
+                    bounds: vec![], // These are filled in from the where-clauses.
+                    default: default.map(Box::new),
+                    synthetic,
                 },
-            ),
-        };
+            )
+        }
+        ty::GenericParamDefKind::Const { has_default } => (
+            def.name,
+            GenericParamDefKind::Const {
+                did: def.def_id,
+                ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+                default: match has_default {
+                    true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
+                    false => None,
+                },
+            },
+        ),
+    };
 
-        GenericParamDef { name, kind }
-    }
+    GenericParamDef { name, kind }
 }
 
 fn clean_generic_param<'tcx>(
@@ -672,7 +665,7 @@ fn clean_ty_generics<'tcx>(
         .iter()
         .filter_map(|param| match param.kind {
             ty::GenericParamDefKind::Lifetime if param.name == kw::UnderscoreLifetime => None,
-            ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
+            ty::GenericParamDefKind::Lifetime => Some(clean_generic_param_def(param, cx)),
             ty::GenericParamDefKind::Type { synthetic, .. } => {
                 if param.name == kw::SelfUpper {
                     assert_eq!(param.index, 0);
@@ -682,9 +675,9 @@ fn clean_ty_generics<'tcx>(
                     impl_trait.insert(param.index.into(), vec![]);
                     return None;
                 }
-                Some(param.clean(cx))
+                Some(clean_generic_param_def(param, cx))
             }
-            ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
+            ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)),
         })
         .collect::<Vec<GenericParamDef>>();
 
@@ -1682,7 +1675,9 @@ pub(crate) fn clean_middle_ty<'tcx>(
                             .projection_ty,
                         cx,
                     ),
-                    kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
+                    kind: TypeBindingKind::Equality {
+                        term: clean_middle_term(pb.skip_binder().term, cx),
+                    },
                 });
             }
 
@@ -1746,7 +1741,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
                                     Some(TypeBinding {
                                         assoc: projection_to_path_segment(proj.projection_ty, cx),
                                         kind: TypeBindingKind::Equality {
-                                            term: proj.term.clean(cx),
+                                            term: clean_middle_term(proj.term, cx),
                                         },
                                     })
                                 } else {
@@ -2283,7 +2278,7 @@ impl<'tcx> Clean<'tcx, TypeBindingKind> for hir::TypeBindingKind<'tcx> {
     fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBindingKind {
         match *self {
             hir::TypeBindingKind::Equality { ref term } => {
-                TypeBindingKind::Equality { term: term.clean(cx) }
+                TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
             }
             hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
                 bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
diff --git a/src/test/ui/linkage-attr/issue-10755.rs b/src/test/ui/linkage-attr/issue-10755.rs
index 5ce69bceed3..afd2dc46ca3 100644
--- a/src/test/ui/linkage-attr/issue-10755.rs
+++ b/src/test/ui/linkage-attr/issue-10755.rs
@@ -1,7 +1,10 @@
 // build-fail
 // dont-check-compiler-stderr
 // compile-flags: -C linker=llllll -C linker-flavor=ld
-// error-pattern: linker `llllll` not found
+// error-pattern: `llllll`
+
+// Before, the error-pattern checked for "not found". On WSL with appendWindowsPath=true, running
+// in invalid command returns a PermissionDenied instead.
 
 fn main() {
 }
diff --git a/src/test/ui/macros/format-args-temporaries-async.rs b/src/test/ui/macros/format-args-temporaries-async.rs
new file mode 100644
index 00000000000..d959329b9fc
--- /dev/null
+++ b/src/test/ui/macros/format-args-temporaries-async.rs
@@ -0,0 +1,37 @@
+// check-pass
+// edition:2021
+
+use std::fmt::{self, Display};
+use std::future::Future;
+use std::io;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+struct AsyncStdout;
+
+impl AsyncStdout {
+    fn write_fmt<'a>(&'a mut self, _args: fmt::Arguments) -> WriteFmtFuture<'a, Self>
+    where
+        Self: Unpin,
+    {
+        WriteFmtFuture(self)
+    }
+}
+
+struct WriteFmtFuture<'a, T>(&'a mut T);
+
+impl<'a, T> Future for WriteFmtFuture<'a, T> {
+    type Output = io::Result<()>;
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        unimplemented!()
+    }
+}
+
+async fn async_main() {
+    let _write = write!(&mut AsyncStdout, "...").await;
+    let _writeln = writeln!(&mut AsyncStdout, "...").await;
+}
+
+fn main() {
+    let _ = async_main;
+}
diff --git a/src/test/ui/macros/format-args-temporaries-in-write.rs b/src/test/ui/macros/format-args-temporaries-in-write.rs
new file mode 100644
index 00000000000..339ccbc33ac
--- /dev/null
+++ b/src/test/ui/macros/format-args-temporaries-in-write.rs
@@ -0,0 +1,50 @@
+// check-fail
+
+use std::fmt::{self, Display};
+
+struct Mutex;
+
+impl Mutex {
+    fn lock(&self) -> MutexGuard {
+        MutexGuard(self)
+    }
+}
+
+struct MutexGuard<'a>(&'a Mutex);
+
+impl<'a> Drop for MutexGuard<'a> {
+    fn drop(&mut self) {
+        // Empty but this is a necessary part of the repro. Otherwise borrow
+        // checker is fine with 'a dangling at the time that MutexGuard goes out
+        // of scope.
+    }
+}
+
+struct Out;
+
+impl Out {
+    fn write_fmt(&self, _args: fmt::Arguments) {}
+}
+
+impl<'a> Display for MutexGuard<'a> {
+    fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
+        Ok(())
+    }
+}
+
+fn main() {
+    // FIXME(dtolnay): We actually want both of these to work. I think it's
+    // sadly unimplementable today though.
+
+    let _write = {
+        let mutex = Mutex;
+        write!(Out, "{}", mutex.lock()) /* no semicolon */
+        //~^ ERROR `mutex` does not live long enough
+    };
+
+    let _writeln = {
+        let mutex = Mutex;
+        writeln!(Out, "{}", mutex.lock()) /* no semicolon */
+        //~^ ERROR `mutex` does not live long enough
+    };
+}
diff --git a/src/test/ui/macros/format-args-temporaries-in-write.stderr b/src/test/ui/macros/format-args-temporaries-in-write.stderr
new file mode 100644
index 00000000000..03ecc4b4418
--- /dev/null
+++ b/src/test/ui/macros/format-args-temporaries-in-write.stderr
@@ -0,0 +1,43 @@
+error[E0597]: `mutex` does not live long enough
+  --> $DIR/format-args-temporaries-in-write.rs:41:27
+   |
+LL |         write!(Out, "{}", mutex.lock()) /* no semicolon */
+   |                           ^^^^^^^^^^^^
+   |                           |
+   |                           borrowed value does not live long enough
+   |                           a temporary with access to the borrow is created here ...
+LL |
+LL |     };
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
+   |     |
+   |     `mutex` dropped here while still borrowed
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+LL |         $dst.write_fmt($crate::format_args!($($arg)*));
+   |                                                       +
+
+error[E0597]: `mutex` does not live long enough
+  --> $DIR/format-args-temporaries-in-write.rs:47:29
+   |
+LL |         writeln!(Out, "{}", mutex.lock()) /* no semicolon */
+   |                             ^^^^^^^^^^^^
+   |                             |
+   |                             borrowed value does not live long enough
+   |                             a temporary with access to the borrow is created here ...
+LL |
+LL |     };
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
+   |     |
+   |     `mutex` dropped here while still borrowed
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+LL |         $dst.write_fmt($crate::format_args_nl!($($arg)*));
+   |                                                          +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/macros/format-args-temporaries.rs b/src/test/ui/macros/format-args-temporaries.rs
index ddd4c9754bf..59323828bc3 100644
--- a/src/test/ui/macros/format-args-temporaries.rs
+++ b/src/test/ui/macros/format-args-temporaries.rs
@@ -20,10 +20,6 @@ impl<'a> Drop for MutexGuard<'a> {
     }
 }
 
-impl<'a> MutexGuard<'a> {
-    fn write_fmt(&self, _args: fmt::Arguments) {}
-}
-
 impl<'a> Display for MutexGuard<'a> {
     fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
         Ok(())
@@ -31,18 +27,6 @@ impl<'a> Display for MutexGuard<'a> {
 }
 
 fn main() {
-    let _write = {
-        let out = Mutex;
-        let mutex = Mutex;
-        write!(out.lock(), "{}", mutex.lock()) /* no semicolon */
-    };
-
-    let _writeln = {
-        let out = Mutex;
-        let mutex = Mutex;
-        writeln!(out.lock(), "{}", mutex.lock()) /* no semicolon */
-    };
-
     let _print = {
         let mutex = Mutex;
         print!("{}", mutex.lock()) /* no semicolon */
diff --git a/src/test/ui/process/process-spawn-nonexistent.rs b/src/test/ui/process/process-spawn-nonexistent.rs
index 70de7316a81..a513722639a 100644
--- a/src/test/ui/process/process-spawn-nonexistent.rs
+++ b/src/test/ui/process/process-spawn-nonexistent.rs
@@ -6,9 +6,11 @@ use std::io::ErrorKind;
 use std::process::Command;
 
 fn main() {
-    assert_eq!(Command::new("nonexistent")
-                   .spawn()
-                   .unwrap_err()
-                   .kind(),
-               ErrorKind::NotFound);
+    let result = Command::new("nonexistent").spawn().unwrap_err().kind();
+
+    assert!(matches!(
+        result,
+        // Under WSL with appendWindowsPath=true, this fails with PermissionDenied
+        ErrorKind::NotFound | ErrorKind::PermissionDenied
+    ));
 }