From 5765819226ac8d4433dd8c99ba1dabd58e427485 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 26 Apr 2022 15:00:36 -0700 Subject: [PATCH 1/8] Add test of temporaries inside format_args of core/std macros --- src/test/ui/macros/format-args-temporaries.rs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/ui/macros/format-args-temporaries.rs diff --git a/src/test/ui/macros/format-args-temporaries.rs b/src/test/ui/macros/format-args-temporaries.rs new file mode 100644 index 0000000000000..ddd4c9754bfa4 --- /dev/null +++ b/src/test/ui/macros/format-args-temporaries.rs @@ -0,0 +1,70 @@ +// check-pass + +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. + } +} + +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(()) + } +} + +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 */ + }; + + let _println = { + let mutex = Mutex; + println!("{}", mutex.lock()) /* no semicolon */ + }; + + let _eprint = { + let mutex = Mutex; + eprint!("{}", mutex.lock()) /* no semicolon */ + }; + + let _eprintln = { + let mutex = Mutex; + eprintln!("{}", mutex.lock()) /* no semicolon */ + }; + + let _panic = { + let mutex = Mutex; + panic!("{}", mutex.lock()) /* no semicolon */ + }; +} From 6f10c0ac1a17130a454d65362c9cd59239c71812 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 26 Apr 2022 15:16:23 -0700 Subject: [PATCH 2/8] Make write/print macros eagerly drop temporaries --- library/core/src/macros/mod.rs | 14 ++++++++------ library/std/src/macros.rs | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 83f33ca007af1..88f225747d946 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -496,9 +496,10 @@ 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)*) => { - $dst.write_fmt($crate::format_args!($($arg)*)) - }; + ($dst:expr, $($arg:tt)*) => {{ + let result = $dst.write_fmt($crate::format_args!($($arg)*)); + result + }}; } /// Write formatted data into a buffer, with a newline appended. @@ -553,9 +554,10 @@ macro_rules! writeln { ($dst:expr $(,)?) => { $crate::write!($dst, "\n") }; - ($dst:expr, $($arg:tt)*) => { - $dst.write_fmt($crate::format_args_nl!($($arg)*)) - }; + ($dst:expr, $($arg:tt)*) => {{ + let result = $dst.write_fmt($crate::format_args_nl!($($arg)*)); + result + }}; } /// Indicates unreachable code. diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index c597fb5df45d2..1495dfc1409e2 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -60,9 +60,9 @@ macro_rules! panic { #[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")] #[allow_internal_unstable(print_internals)] macro_rules! print { - ($($arg:tt)*) => { - $crate::io::_print($crate::format_args!($($arg)*)) - }; + ($($arg:tt)*) => {{ + $crate::io::_print($crate::format_args!($($arg)*)); + }}; } /// Prints to the standard output, with a newline. @@ -99,9 +99,9 @@ macro_rules! println { () => { $crate::print!("\n") }; - ($($arg:tt)*) => { - $crate::io::_print($crate::format_args_nl!($($arg)*)) - }; + ($($arg:tt)*) => {{ + $crate::io::_print($crate::format_args_nl!($($arg)*)); + }}; } /// Prints to the standard error. @@ -130,9 +130,9 @@ macro_rules! println { #[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")] #[allow_internal_unstable(print_internals)] macro_rules! eprint { - ($($arg:tt)*) => { - $crate::io::_eprint($crate::format_args!($($arg)*)) - }; + ($($arg:tt)*) => {{ + $crate::io::_eprint($crate::format_args!($($arg)*)); + }}; } /// Prints to the standard error, with a newline. @@ -164,9 +164,9 @@ macro_rules! eprintln { () => { $crate::eprint!("\n") }; - ($($arg:tt)*) => { - $crate::io::_eprint($crate::format_args_nl!($($arg)*)) - }; + ($($arg:tt)*) => {{ + $crate::io::_eprint($crate::format_args_nl!($($arg)*)); + }}; } /// Prints and returns the value of a given expression for quick and dirty From a03f15a276b407197b78c4cf304801405f6d5e33 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 26 Apr 2022 15:44:39 -0700 Subject: [PATCH 3/8] Bless tests following write/print macros change --- src/test/pretty/dollar-crate.pp | 2 +- src/test/ui/macros/trace-macro.stderr | 2 +- .../ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/pretty/dollar-crate.pp b/src/test/pretty/dollar-crate.pp index 0c96fb593e659..3af37955f2380 100644 --- a/src/test/pretty/dollar-crate.pp +++ b/src/test/pretty/dollar-crate.pp @@ -9,5 +9,5 @@ // pp-exact:dollar-crate.pp fn main() { - ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &[])); + { ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &[])); }; } diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index c8a0fd684304e..43272248c280e 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,5 +5,5 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `$crate :: io :: _print($crate :: format_args_nl! ("Hello, World!"))` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")) ; }` diff --git a/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr index e2a65ff852404..fc0430d06fa1c 100644 --- a/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr +++ b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -12,7 +12,7 @@ LL | struct Foo(isize, isize); = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo(2, b) => println!("{}", b), +LL ~ Foo(2, b) => println!("{}", b) LL + Foo(_, _) => todo!() | From d369045aed63ac8b9de1ed71679fac9bb4b0340a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 13 May 2022 10:12:32 -0700 Subject: [PATCH 4/8] Use a pointer in cell::Ref so it's not noalias --- library/core/src/cell.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2a49017de3cc8..04bbef4844b6a 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -197,7 +197,7 @@ use crate::fmt::{self, Debug, Display}; use crate::marker::Unsize; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut}; -use crate::ptr; +use crate::ptr::{self, NonNull}; /// A mutable memory location. /// @@ -896,7 +896,8 @@ impl RefCell { // SAFETY: `BorrowRef` ensures that there is only immutable access // to the value while borrowed. - Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }) + let value = unsafe { NonNull::new_unchecked(self.value.get()) }; + Ok(Ref { value, borrow: b }) } None => Err(BorrowError { // If a borrow occurred, then we must already have an outstanding borrow, @@ -1314,7 +1315,9 @@ impl Clone for BorrowRef<'_> { #[stable(feature = "rust1", since = "1.0.0")] #[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"] pub struct Ref<'b, T: ?Sized + 'b> { - value: &'b T, + // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a + // `Ref` argument doesn't hold immutability for its whole scope, only until it drops. + value: NonNull, borrow: BorrowRef<'b>, } @@ -1324,7 +1327,8 @@ impl Deref for Ref<'_, T> { #[inline] fn deref(&self) -> &T { - self.value + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } } } @@ -1368,7 +1372,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { where F: FnOnce(&T) -> &U, { - Ref { value: f(orig.value), borrow: orig.borrow } + Ref { value: NonNull::from(f(&*orig)), borrow: orig.borrow } } /// Makes a new `Ref` for an optional component of the borrowed data. The @@ -1399,8 +1403,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { where F: FnOnce(&T) -> Option<&U>, { - match f(orig.value) { - Some(value) => Ok(Ref { value, borrow: orig.borrow }), + match f(&*orig) { + Some(value) => Ok(Ref { value: NonNull::from(value), borrow: orig.borrow }), None => Err(orig), } } @@ -1431,9 +1435,12 @@ impl<'b, T: ?Sized> Ref<'b, T> { where F: FnOnce(&T) -> (&U, &V), { - let (a, b) = f(orig.value); + let (a, b) = f(&*orig); let borrow = orig.borrow.clone(); - (Ref { value: a, borrow }, Ref { value: b, borrow: orig.borrow }) + ( + Ref { value: NonNull::from(a), borrow }, + Ref { value: NonNull::from(b), borrow: orig.borrow }, + ) } /// Convert into a reference to the underlying data. @@ -1467,7 +1474,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { // unique reference to the borrowed RefCell. No further mutable references can be created // from the original cell. mem::forget(orig.borrow); - orig.value + // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`. + unsafe { orig.value.as_ref() } } } From 2b8041f5746bdbd7c9f6ccf077544e1c77e927c0 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 13 May 2022 10:46:00 -0700 Subject: [PATCH 5/8] Use a pointer in cell::RefMut so it's not noalias --- library/core/src/cell.rs | 52 +++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 04bbef4844b6a..fa0206c349af6 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -194,7 +194,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::Unsize; +use crate::marker::{PhantomData, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut}; use crate::ptr::{self, NonNull}; @@ -981,8 +981,9 @@ impl RefCell { self.borrowed_at.set(Some(crate::panic::Location::caller())); } - // SAFETY: `BorrowRef` guarantees unique access. - Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }) + // SAFETY: `BorrowRefMut` guarantees unique access. + let value = unsafe { NonNull::new_unchecked(self.value.get()) }; + Ok(RefMut { value, borrow: b, marker: PhantomData }) } None => Err(BorrowMutError { // If a borrow occurred, then we must already have an outstanding borrow, @@ -1515,13 +1516,13 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// ``` #[stable(feature = "cell_map", since = "1.8.0")] #[inline] - pub fn map(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U> + pub fn map(mut orig: RefMut<'b, T>, f: F) -> RefMut<'b, U> where F: FnOnce(&mut T) -> &mut U, { // FIXME(nll-rfc#40): fix borrow-check - let RefMut { value, borrow } = orig; - RefMut { value: f(value), borrow } + let value = NonNull::from(f(&mut *orig)); + RefMut { value, borrow: orig.borrow, marker: PhantomData } } /// Makes a new `RefMut` for an optional component of the borrowed data. The @@ -1556,23 +1557,20 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// ``` #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")] #[inline] - pub fn filter_map(orig: RefMut<'b, T>, f: F) -> Result, Self> + pub fn filter_map(mut orig: RefMut<'b, T>, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>, { // FIXME(nll-rfc#40): fix borrow-check - let RefMut { value, borrow } = orig; - let value = value as *mut T; // SAFETY: function holds onto an exclusive reference for the duration // of its call through `orig`, and the pointer is only de-referenced // inside of the function call never allowing the exclusive reference to // escape. - match f(unsafe { &mut *value }) { - Some(value) => Ok(RefMut { value, borrow }), - None => { - // SAFETY: same as above. - Err(RefMut { value: unsafe { &mut *value }, borrow }) + match f(&mut *orig) { + Some(value) => { + Ok(RefMut { value: NonNull::from(value), borrow: orig.borrow, marker: PhantomData }) } + None => Err(orig), } } @@ -1604,15 +1602,18 @@ impl<'b, T: ?Sized> RefMut<'b, T> { #[stable(feature = "refcell_map_split", since = "1.35.0")] #[inline] pub fn map_split( - orig: RefMut<'b, T>, + mut orig: RefMut<'b, T>, f: F, ) -> (RefMut<'b, U>, RefMut<'b, V>) where F: FnOnce(&mut T) -> (&mut U, &mut V), { - let (a, b) = f(orig.value); let borrow = orig.borrow.clone(); - (RefMut { value: a, borrow }, RefMut { value: b, borrow: orig.borrow }) + let (a, b) = f(&mut *orig); + ( + RefMut { value: NonNull::from(a), borrow, marker: PhantomData }, + RefMut { value: NonNull::from(b), borrow: orig.borrow, marker: PhantomData }, + ) } /// Convert into a mutable reference to the underlying data. @@ -1638,14 +1639,15 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// assert!(cell.try_borrow_mut().is_err()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { + pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would // require a unique reference to the borrowed RefCell. No further references can be created // from the original cell within that lifetime, making the current borrow the only // reference for the remaining lifetime. mem::forget(orig.borrow); - orig.value + // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`. + unsafe { orig.value.as_mut() } } } @@ -1700,8 +1702,12 @@ impl<'b> BorrowRefMut<'b> { #[stable(feature = "rust1", since = "1.0.0")] #[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"] pub struct RefMut<'b, T: ?Sized + 'b> { - value: &'b mut T, + // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a + // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops. + value: NonNull, borrow: BorrowRefMut<'b>, + // NonNull is covariant over T, so we need to reintroduce invariance. + marker: PhantomData<&'b mut T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -1710,7 +1716,8 @@ impl Deref for RefMut<'_, T> { #[inline] fn deref(&self) -> &T { - self.value + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } } } @@ -1718,7 +1725,8 @@ impl Deref for RefMut<'_, T> { impl DerefMut for RefMut<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut T { - self.value + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_mut() } } } From 15d8c008203208402bd234aec66b07dbe2824ec7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 13 May 2022 11:25:51 -0700 Subject: [PATCH 6/8] Test RefCell aliasing --- src/test/codegen/noalias-refcell.rs | 14 +++++++++++ src/test/ui/issues/issue-63787.rs | 36 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/test/codegen/noalias-refcell.rs create mode 100644 src/test/ui/issues/issue-63787.rs diff --git a/src/test/codegen/noalias-refcell.rs b/src/test/codegen/noalias-refcell.rs new file mode 100644 index 0000000000000..dba73937abf17 --- /dev/null +++ b/src/test/codegen/noalias-refcell.rs @@ -0,0 +1,14 @@ +// compile-flags: -O -C no-prepopulate-passes -Z mutable-noalias=yes + +#![crate_type = "lib"] + +use std::cell::{Ref, RefCell, RefMut}; + +// Make sure that none of the arguments get a `noalias` attribute, because +// the `RefCell` might alias writes after either `Ref`/`RefMut` is dropped. + +// CHECK-LABEL: @maybe_aliased( +// CHECK-NOT: noalias +// CHECK-SAME: %_refcell +#[no_mangle] +pub unsafe fn maybe_aliased(_: Ref<'_, i32>, _: RefMut<'_, i32>, _refcell: &RefCell) {} diff --git a/src/test/ui/issues/issue-63787.rs b/src/test/ui/issues/issue-63787.rs new file mode 100644 index 0000000000000..cba079b231522 --- /dev/null +++ b/src/test/ui/issues/issue-63787.rs @@ -0,0 +1,36 @@ +// run-pass +// compile-flags: -O + +// Make sure that `Ref` and `RefMut` do not make false promises about aliasing, +// because once they drop, their reference/pointer can alias other writes. + +// Adapted from comex's proof of concept: +// https://github.com/rust-lang/rust/issues/63787#issuecomment-523588164 + +use std::cell::RefCell; +use std::ops::Deref; + +pub fn break_if_r_is_noalias(rc: &RefCell, r: impl Deref) -> i32 { + let ptr1 = &*r as *const i32; + let a = *r; + drop(r); + *rc.borrow_mut() = 2; + let r2 = rc.borrow(); + let ptr2 = &*r2 as *const i32; + if ptr2 != ptr1 { + panic!(); + } + // If LLVM knows the pointers are the same, and if `r` was `noalias`, + // then it may replace this with `a + a`, ignoring the earlier write. + a + *r2 +} + +fn main() { + let mut rc = RefCell::new(1); + let res = break_if_r_is_noalias(&rc, rc.borrow()); + assert_eq!(res, 3); + + *rc.get_mut() = 1; + let res = break_if_r_is_noalias(&rc, rc.borrow_mut()); + assert_eq!(res, 3); +} From 015e2ae76984144a7ece6d8169ff42b6dc7d6870 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 14 May 2022 03:41:06 +0200 Subject: [PATCH 7/8] Allow the unused_macro_rules lint for now This makes the transition easier as e.g. allow directives won't fire the unknown lint warning once it is turned to warn by default in the future. This is especially important compared to other lints in the unused group because the _ prefix trick doesn't exist for macro rules, so allowing is the only option (either of unused_macro_rules, or of the entire unused group, but that is not as informative to readers). Allowing the lint also makes it possible to work on possible heuristics for disabling the macro in specific cases. --- compiler/rustc_lint_defs/src/builtin.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7ebb1e85cdb23..f942970278399 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -790,6 +790,7 @@ declare_lint! { /// ### Example /// /// ```rust + /// #[warn(unused_macro_rules)] /// macro_rules! unused_empty { /// (hello) => { println!("Hello, world!") }; // This rule is unused /// () => { println!("empty") }; // This rule is used @@ -814,7 +815,7 @@ declare_lint! { /// /// [`macro_export` attribute]: https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope pub UNUSED_MACRO_RULES, - Warn, + Allow, "detects macro rules that were not used" } From 53b6bf496461bed9f5ae9e049dc1e137ca5363a8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 May 2022 13:50:52 +0200 Subject: [PATCH 8/8] Add new eslint rule about brace style --- src/librustdoc/html/static/.eslintrc.js | 5 ++ src/librustdoc/html/static/js/main.js | 4 +- .../html/static/js/scrape-examples.js | 4 +- src/librustdoc/html/static/js/search.js | 73 ++++++++++++------- 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index 52577b228aa13..7634a15b9bd19 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -29,5 +29,10 @@ module.exports = { "no-var": ["error"], "prefer-const": ["error"], "prefer-arrow-callback": ["error"], + "brace-style": [ + "error", + "1tbs", + { "allowSingleLine": false } + ], } }; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 336223ad28f32..f748616acca04 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -841,8 +841,8 @@ function loadCss(cssFileName) { onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && - !hasClass(e, "type-contents-toggle"))) - { + !hasClass(e, "type-contents-toggle")) + ) { e.open = false; } }); diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index 408b7e19feadd..7b9d86a851b19 100644 --- a/src/librustdoc/html/static/js/scrape-examples.js +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -98,7 +98,9 @@ // visible. This is necessary since updateScrapedExample calls scrollToLoc which // depends on offsetHeight, a property that requires an element to be visible to // compute correctly. - setTimeout(() => { onEachLazy(moreExamples, updateScrapedExample); }); + setTimeout(() => { + onEachLazy(moreExamples, updateScrapedExample); + }); }, {once: true}); }); })(); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b596adf32c6fd..0be70d77d06e4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -320,8 +320,8 @@ window.initSearch = rawSearchIndex => { if (foundExclamation) { throw new Error("Cannot have more than one `!` in an ident"); } else if (parserState.pos + 1 < parserState.length && - isIdentCharacter(parserState.userQuery[parserState.pos + 1])) - { + isIdentCharacter(parserState.userQuery[parserState.pos + 1]) + ) { throw new Error("`!` can only be at the end of an ident"); } foundExclamation = true; @@ -330,12 +330,10 @@ window.initSearch = rawSearchIndex => { } else if ( isStopCharacter(c) || isSpecialStartCharacter(c) || - isSeparatorCharacter(c)) - { + isSeparatorCharacter(c) + ) { break; - } - // If we allow paths ("str::string" for example). - else if (c === ":") { + } else if (c === ":") { // If we allow paths ("str::string" for example). if (!isPathStart(parserState)) { break; } @@ -372,8 +370,8 @@ window.initSearch = rawSearchIndex => { end = getIdentEndPosition(parserState); } if (parserState.pos < parserState.length && - parserState.userQuery[parserState.pos] === "<") - { + parserState.userQuery[parserState.pos] === "<" + ) { if (isInGenerics) { throw new Error("Unexpected `<` after `<`"); } else if (start >= end) { @@ -592,8 +590,8 @@ window.initSearch = rawSearchIndex => { if (elem && elem.value !== "All crates" && - hasOwnPropertyRustdoc(rawSearchIndex, elem.value)) - { + hasOwnPropertyRustdoc(rawSearchIndex, elem.value) + ) { return elem.value; } return null; @@ -786,37 +784,51 @@ window.initSearch = rawSearchIndex => { // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) a = (aaa.lev); b = (bbb.lev); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by crate (non-current crate goes later) a = (aaa.item.crate !== window.currentCrate); b = (bbb.item.crate !== window.currentCrate); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by item name length (longer goes later) a = aaa.word.length; b = bbb.word.length; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by item name (lexicographically larger goes later) a = aaa.word; b = bbb.word; - if (a !== b) { return (a > b ? +1 : -1); } + if (a !== b) { + return (a > b ? +1 : -1); + } // sort by index of keyword in item name (no literal occurrence goes later) a = (aaa.index < 0); b = (bbb.index < 0); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // (later literal occurrence, if any, goes later) a = aaa.index; b = bbb.index; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // special precedence for primitive and keyword pages if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) || @@ -831,17 +843,23 @@ window.initSearch = rawSearchIndex => { // sort by description (no description goes later) a = (aaa.item.desc === ""); b = (bbb.item.desc === ""); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by type (later occurrence in `itemTypes` goes later) a = aaa.item.ty; b = bbb.item.ty; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by path (lexicographically larger goes later) a = aaa.item.path; b = bbb.item.path; - if (a !== b) { return (a > b ? +1 : -1); } + if (a !== b) { + return (a > b ? +1 : -1); + } // que sera, sera return 0; @@ -1315,16 +1333,15 @@ window.initSearch = rawSearchIndex => { } if (searchWord.indexOf(elem.pathLast) > -1 || - row.normalizedName.indexOf(elem.pathLast) > -1) - { + row.normalizedName.indexOf(elem.pathLast) > -1 + ) { // filter type: ... queries if (!results_others[fullId] !== undefined) { index = row.normalizedName.indexOf(elem.pathLast); } } lev = levenshtein(searchWord, elem.pathLast); - if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) - { + if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) { if (elem.pathLast.length < 6) { lev = 1; } else { @@ -1670,8 +1687,8 @@ window.initSearch = rawSearchIndex => { // By default, the search DOM element is "empty" (meaning it has no children not // text content). Once a search has been run, it won't be empty, even if you press // ESC or empty the search input (which also "cancels" the search). - && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))) - { + && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)) + ) { const elem = document.createElement("a"); elem.href = results.others[0].href; removeClass(elem, "active"); @@ -1766,7 +1783,7 @@ window.initSearch = rawSearchIndex => { let i = 0; for (const elem of elems) { const j = i; - elem.onclick = () => { printTab(j); }; + elem.onclick = () => printTab(j); searchState.focusedByTab.push(null); i += 1; }