From cb0ed1bdaed082205c7da4375b78a112a0872ddf Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Jul 2022 11:06:54 -0700 Subject: [PATCH 01/12] Add regression test minimized from async-std write --- .../macros/format-args-temporaries-async.rs | 40 +++++++++++++++++++ .../format-args-temporaries-async.stderr | 27 +++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/test/ui/macros/format-args-temporaries-async.rs create mode 100644 src/test/ui/macros/format-args-temporaries-async.stderr 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 0000000000000..fc2e5e2190f33 --- /dev/null +++ b/src/test/ui/macros/format-args-temporaries-async.rs @@ -0,0 +1,40 @@ +// FIXME: check-pass +// check-fail +// 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 { + unimplemented!() + } +} + +async fn async_main() { + let _write = write!(&mut AsyncStdout, "...").await; + //~^ ERROR temporary value dropped while borrowed + let _writeln = writeln!(&mut AsyncStdout, "...").await; + //~^ ERROR temporary value dropped while borrowed +} + +fn main() { + let _ = async_main; +} diff --git a/src/test/ui/macros/format-args-temporaries-async.stderr b/src/test/ui/macros/format-args-temporaries-async.stderr new file mode 100644 index 0000000000000..73019d7eb6e49 --- /dev/null +++ b/src/test/ui/macros/format-args-temporaries-async.stderr @@ -0,0 +1,27 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/format-args-temporaries-async.rs:32:30 + | +LL | let _write = write!(&mut AsyncStdout, "...").await; + | ------------^^^^^^^^^^^-------- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0716]: temporary value dropped while borrowed + --> $DIR/format-args-temporaries-async.rs:34:34 + | +LL | let _writeln = writeln!(&mut AsyncStdout, "...").await; + | --------------^^^^^^^^^^^-------- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. From f1ca69d2453710587804b830182f3de76d9a9e70 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Jul 2022 10:44:00 -0700 Subject: [PATCH 02/12] Revert write! and writeln! to late drop temporaries --- library/core/src/macros/mod.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index bd62bc5c3056c..3a115a8b8b6c6 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. From 4d65048d4105da9b841c4d79aecdddf11bfc925e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Jul 2022 11:16:00 -0700 Subject: [PATCH 03/12] Regression in issue 99684 fixed --- .../macros/format-args-temporaries-async.rs | 5 +--- .../format-args-temporaries-async.stderr | 27 ------------------- 2 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 src/test/ui/macros/format-args-temporaries-async.stderr diff --git a/src/test/ui/macros/format-args-temporaries-async.rs b/src/test/ui/macros/format-args-temporaries-async.rs index fc2e5e2190f33..d959329b9fce2 100644 --- a/src/test/ui/macros/format-args-temporaries-async.rs +++ b/src/test/ui/macros/format-args-temporaries-async.rs @@ -1,5 +1,4 @@ -// FIXME: check-pass -// check-fail +// check-pass // edition:2021 use std::fmt::{self, Display}; @@ -30,9 +29,7 @@ impl<'a, T> Future for WriteFmtFuture<'a, T> { async fn async_main() { let _write = write!(&mut AsyncStdout, "...").await; - //~^ ERROR temporary value dropped while borrowed let _writeln = writeln!(&mut AsyncStdout, "...").await; - //~^ ERROR temporary value dropped while borrowed } fn main() { diff --git a/src/test/ui/macros/format-args-temporaries-async.stderr b/src/test/ui/macros/format-args-temporaries-async.stderr deleted file mode 100644 index 73019d7eb6e49..0000000000000 --- a/src/test/ui/macros/format-args-temporaries-async.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/format-args-temporaries-async.rs:32:30 - | -LL | let _write = write!(&mut AsyncStdout, "...").await; - | ------------^^^^^^^^^^^-------- - | | | - | | creates a temporary which is freed while still in use - | temporary value is freed at the end of this statement - | borrow later used here - | - = note: consider using a `let` binding to create a longer lived value - -error[E0716]: temporary value dropped while borrowed - --> $DIR/format-args-temporaries-async.rs:34:34 - | -LL | let _writeln = writeln!(&mut AsyncStdout, "...").await; - | --------------^^^^^^^^^^^-------- - | | | - | | creates a temporary which is freed while still in use - | temporary value is freed at the end of this statement - | borrow later used here - | - = note: consider using a `let` binding to create a longer lived value - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0716`. From ffab6bf10ffcb4b76042c96e339513fdba4c6009 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Jul 2022 11:01:01 -0700 Subject: [PATCH 04/12] Move write! and writeln! temporaries test to check-fail --- .../format-args-temporaries-in-write.rs | 50 +++++++++++++++++++ .../format-args-temporaries-in-write.stderr | 43 ++++++++++++++++ src/test/ui/macros/format-args-temporaries.rs | 16 ------ 3 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/macros/format-args-temporaries-in-write.rs create mode 100644 src/test/ui/macros/format-args-temporaries-in-write.stderr 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 0000000000000..339ccbc33ac98 --- /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 0000000000000..03ecc4b4418c6 --- /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 ddd4c9754bfa4..59323828bc37f 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 */ From 29cfefd35588535295d6d1f63b51e8a7cca0e738 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 27 Jul 2022 13:58:29 +0200 Subject: [PATCH 05/12] Fix process-spawn-nonexistent on WSL If appendWindowsPath is set to true (the default IIRC), running invalid commands returns PermissionDenied instead of NotFound. --- src/test/ui/process/process-spawn-nonexistent.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/test/ui/process/process-spawn-nonexistent.rs b/src/test/ui/process/process-spawn-nonexistent.rs index 70de7316a8170..a513722639adb 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 + )); } From 62ad16f1288649d715393eb300f0f3fea9be9663 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 27 Jul 2022 14:05:05 +0200 Subject: [PATCH 06/12] Fix linkage-attr/issue-10755.rs ui test on WSL It checked for a "not found", but on WSL with appendWindowsPath=true, PermissionDenied is the error instead. --- src/test/ui/linkage-attr/issue-10755.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/linkage-attr/issue-10755.rs b/src/test/ui/linkage-attr/issue-10755.rs index 5ce69bceed37a..afd2dc46ca3cb 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() { } From 8aca8835a0667c29e5d4af0c32bfae172c3b66fd Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 27 Jul 2022 11:04:54 -0700 Subject: [PATCH 07/12] rustdoc: remove Clean trait impl for ty::Term --- src/librustdoc/clean/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2f3ca41723d85..0c4851732f68b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -398,12 +398,10 @@ 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)), } } @@ -426,7 +424,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), } } @@ -1682,7 +1680,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 +1746,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 { From 3ea99166253021bd6f8c429b253d694572605bca Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 27 Jul 2022 11:08:22 -0700 Subject: [PATCH 08/12] rustdoc: remove Clean trait impl for hir::Term --- src/librustdoc/clean/mod.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0c4851732f68b..c7845172d48d6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -405,14 +405,12 @@ fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> T } } -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)) } } } @@ -2283,7 +2281,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(), From 2f03cbdc8e51e6af9b4cc2ef99818e826e76e8ac Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 27 Jul 2022 11:13:39 -0700 Subject: [PATCH 09/12] rustdoc: remove Clean trait impl for ty::GenericParamDef --- src/librustdoc/clean/mod.rs | 81 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c7845172d48d6..2f2fbc9d4ba8d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -470,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>( @@ -668,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); @@ -678,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::>(); From ee0ce346e84dc1bd2e95cfa750d5a3009a2d5a07 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 28 Jul 2022 14:29:58 +0300 Subject: [PATCH 10/12] Fix small typo in Cargo.toml comment --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ed024192c1503..ffc886d47f399 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 From 03f9efedb15ac5d4a697390a4bed00df23ee92d2 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 28 Jul 2022 22:22:13 +0800 Subject: [PATCH 11/12] fix: remove fake no_dead_strip for osx --- compiler/rustc_codegen_ssa/src/back/linker.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8e5ac9da4ac50..a4bbdefbb87f8 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"); } } From 47a0a56c1d0b7c0d7825a86e8a7ef7dded99e958 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Fri, 22 Jul 2022 22:48:45 +0000 Subject: [PATCH 12/12] add more docs regarding ideographic numbers Signed-off-by: Vincenzo Palazzo --- library/core/src/char/methods.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 0bec38a877ed5..eae567cad00e6 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")]