about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md4
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs13
-rw-r--r--library/std/src/sys/unix/fs.rs10
-rw-r--r--src/bootstrap/flags.rs1
-rw-r--r--src/bootstrap/setup.rs2
-rw-r--r--src/librustdoc/clean/mod.rs20
-rw-r--r--src/test/ui/drop/drop_order.rs145
-rw-r--r--src/test/ui/parser/issue-100197-mut-let.fixed6
-rw-r--r--src/test/ui/parser/issue-100197-mut-let.rs6
-rw-r--r--src/test/ui/parser/issue-100197-mut-let.stderr8
10 files changed, 196 insertions, 19 deletions
diff --git a/RELEASES.md b/RELEASES.md
index e66bf60b7f7..147ff3561a3 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -27,6 +27,7 @@ Libraries
 - [Extend `ptr::null` and `null_mut` to all thin (including extern) types.][94954]
 - [`impl Read and Write for VecDeque<u8>`.][95632]
 - [STD support for the Nintendo 3DS.][95897]
+- [Use rounding in float to Duration conversion methods.][96051]
 - [Make write/print macros eagerly drop temporaries.][96455]
 - [Implement internal traits that enable `[OsStr]::join`.][96881]
 - [Implement `Hash` for `core::alloc::Layout`.][97034]
@@ -99,6 +100,8 @@ Compatibility Notes
 
 - [`#[link]` attributes are now checked more strictly,][96885] which may introduce
   errors for invalid attribute arguments that were previously ignored.
+- [Rounding is now used when converting a float to a `Duration`.][96051] The converted
+  duration can differ slightly from what it was.
 
 Internal Changes
 ----------------
@@ -118,6 +121,7 @@ and related tools.
 [95818]: https://github.com/rust-lang/rust/pull/95818/
 [95897]: https://github.com/rust-lang/rust/pull/95897/
 [95953]: https://github.com/rust-lang/rust/pull/95953/
+[96051]: https://github.com/rust-lang/rust/pull/96051/
 [96296]: https://github.com/rust-lang/rust/pull/96296/
 [96455]: https://github.com/rust-lang/rust/pull/96455/
 [96737]: https://github.com/rust-lang/rust/pull/96737/
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 6990d0782b7..d8b39a406cc 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -55,6 +55,19 @@ impl<'a> Parser<'a> {
             return Ok(Some(stmt.into_inner()));
         }
 
+        if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
+            self.bump();
+            let mut_let_span = lo.to(self.token.span);
+            self.struct_span_err(mut_let_span, "invalid variable declaration")
+                .span_suggestion(
+                    mut_let_span,
+                    "switch the order of `mut` and `let`",
+                    "let mut",
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
+        }
+
         Ok(Some(if self.token.is_keyword(kw::Let) {
             self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
         } else if self.is_kw_followed_by_ident(kw::Mut) {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 1f2f9d97bdd..7778033eaa9 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -544,11 +544,11 @@ impl Default for FileTimes {
     fn default() -> Self {
         // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return
         // an error in `set_times`.
-        // ESP-IDF does not support `futimens` at all and the behavior for that OS is therefore
+        // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
         // the same as for Redox.
-        #[cfg(any(target_os = "redox", target_os = "espidf"))]
+        #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))]
         let omit = libc::timespec { tv_sec: 0, tv_nsec: 0 };
-        #[cfg(not(any(target_os = "redox", target_os = "espidf")))]
+        #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
         let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ };
         Self([omit; 2])
     }
@@ -1083,9 +1083,9 @@ impl File {
 
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "redox", target_os = "espidf"))] {
+            if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] {
                 // Redox doesn't appear to support `UTIME_OMIT`.
-                // ESP-IDF does not support `futimens` at all and the behavior for that OS is therefore
+                // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
                 // the same as for Redox.
                 drop(times);
                 Err(io::const_io_error!(
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 39d9ce1621b..1edb513f0b6 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -80,6 +80,7 @@ pub struct Flags {
     pub llvm_profile_generate: bool,
 }
 
+#[derive(Debug)]
 #[cfg_attr(test, derive(Clone))]
 pub enum Subcommand {
     Build {
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index a5a39a5a3cf..eb7da1bda73 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -11,7 +11,7 @@ use std::{
     io::{self, Write},
 };
 
-#[derive(Clone, Copy, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum Profile {
     Compiler,
     Codegen,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index addd6ffa11e..971617a8400 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -44,10 +44,6 @@ use utils::*;
 pub(crate) use self::types::*;
 pub(crate) use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
 
-pub(crate) trait Clean<'tcx, T> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> T;
-}
-
 pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
     let mut items: Vec<Item> = vec![];
     let mut inserted = FxHashSet::default();
@@ -1925,7 +1921,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 }))
             }
             ItemKind::Enum(ref def, generics) => EnumItem(Enum {
-                variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
+                variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
                 generics: clean_generics(generics, cx),
             }),
             ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
@@ -1978,14 +1974,12 @@ fn clean_maybe_renamed_item<'tcx>(
     })
 }
 
-impl<'tcx> Clean<'tcx, Item> for hir::Variant<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
-        let kind = VariantItem(clean_variant_data(&self.data, cx));
-        let what_rustc_thinks =
-            Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
-        // don't show `pub` for variants, which are always public
-        Item { visibility: Inherited, ..what_rustc_thinks }
-    }
+fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
+    let kind = VariantItem(clean_variant_data(&variant.data, cx));
+    let what_rustc_thinks =
+        Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
+    // don't show `pub` for variants, which are always public
+    Item { visibility: Inherited, ..what_rustc_thinks }
 }
 
 fn clean_impl<'tcx>(
diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs
new file mode 100644
index 00000000000..e42150dcc09
--- /dev/null
+++ b/src/test/ui/drop/drop_order.rs
@@ -0,0 +1,145 @@
+// run-pass
+
+use std::cell::RefCell;
+use std::convert::TryInto;
+
+#[derive(Default)]
+struct DropOrderCollector(RefCell<Vec<u32>>);
+
+struct LoudDrop<'a>(&'a DropOrderCollector, u32);
+
+impl Drop for LoudDrop<'_> {
+    fn drop(&mut self) {
+        println!("{}", self.1);
+        self.0.0.borrow_mut().push(self.1);
+    }
+}
+
+impl DropOrderCollector {
+    fn option_loud_drop(&self, n: u32) -> Option<LoudDrop> {
+        Some(LoudDrop(self, n))
+    }
+
+    fn loud_drop(&self, n: u32) -> LoudDrop {
+        LoudDrop(self, n)
+    }
+
+    fn print(&self, n: u32) {
+        println!("{}", n);
+        self.0.borrow_mut().push(n)
+    }
+
+    fn if_(&self) {
+        if self.option_loud_drop(1).is_some() {
+            self.print(2);
+        }
+
+        if self.option_loud_drop(3).is_none() {
+            unreachable!();
+        } else if self.option_loud_drop(4).is_some() {
+            self.print(5);
+        }
+
+        if {
+            if self.option_loud_drop(7).is_some() && self.option_loud_drop(6).is_some() {
+                self.loud_drop(8);
+                true
+            } else {
+                false
+            }
+        } {
+            self.print(9);
+        }
+    }
+
+    fn if_let(&self) {
+        if let None = self.option_loud_drop(2) {
+            unreachable!();
+        } else {
+            self.print(1);
+        }
+
+        if let Some(_) = self.option_loud_drop(4) {
+            self.print(3);
+        }
+
+        if let Some(_d) = self.option_loud_drop(6) {
+            self.print(5);
+        }
+    }
+
+    fn match_(&self) {
+        match self.option_loud_drop(2) {
+            _any => self.print(1),
+        }
+
+        match self.option_loud_drop(4) {
+            _ => self.print(3),
+        }
+
+        match self.option_loud_drop(6) {
+            Some(_) => self.print(5),
+            _ => unreachable!(),
+        }
+
+        match {
+            let _ = self.loud_drop(7);
+            let _d = self.loud_drop(9);
+            self.print(8);
+            ()
+        } {
+            () => self.print(10),
+        }
+
+        match {
+            match self.option_loud_drop(14) {
+                _ => {
+                    self.print(11);
+                    self.option_loud_drop(13)
+                }
+            }
+        } {
+            _ => self.print(12),
+        }
+
+        match {
+            loop {
+                break match self.option_loud_drop(16) {
+                    _ => {
+                        self.print(15);
+                        self.option_loud_drop(18)
+                    }
+                };
+            }
+        } {
+            _ => self.print(17),
+        }
+    }
+
+    fn assert_sorted(self) {
+        assert!(
+            self.0
+                .into_inner()
+                .into_iter()
+                .enumerate()
+                .all(|(idx, item)| idx + 1 == item.try_into().unwrap())
+        );
+    }
+}
+
+fn main() {
+    println!("-- if --");
+    let collector = DropOrderCollector::default();
+    collector.if_();
+    collector.assert_sorted();
+
+    println!("-- if let --");
+    let collector = DropOrderCollector::default();
+    collector.if_let();
+    collector.assert_sorted();
+
+    println!("-- match --");
+    let collector = DropOrderCollector::default();
+    collector.match_();
+    collector.assert_sorted();
+}
diff --git a/src/test/ui/parser/issue-100197-mut-let.fixed b/src/test/ui/parser/issue-100197-mut-let.fixed
new file mode 100644
index 00000000000..5a895622200
--- /dev/null
+++ b/src/test/ui/parser/issue-100197-mut-let.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    let mut _x = 123;
+    //~^ ERROR invalid variable declaration
+}
diff --git a/src/test/ui/parser/issue-100197-mut-let.rs b/src/test/ui/parser/issue-100197-mut-let.rs
new file mode 100644
index 00000000000..71103813a6e
--- /dev/null
+++ b/src/test/ui/parser/issue-100197-mut-let.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    mut let _x = 123;
+    //~^ ERROR invalid variable declaration
+}
diff --git a/src/test/ui/parser/issue-100197-mut-let.stderr b/src/test/ui/parser/issue-100197-mut-let.stderr
new file mode 100644
index 00000000000..86658e4f39f
--- /dev/null
+++ b/src/test/ui/parser/issue-100197-mut-let.stderr
@@ -0,0 +1,8 @@
+error: invalid variable declaration
+  --> $DIR/issue-100197-mut-let.rs:4:5
+   |
+LL |     mut let _x = 123;
+   |     ^^^^^^^ help: switch the order of `mut` and `let`: `let mut`
+
+error: aborting due to previous error
+