about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs3
-rw-r--r--compiler/rustc_mir/src/transform/early_otherwise_branch.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs76
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs6
-rw-r--r--library/alloc/src/collections/btree/node/tests.rs9
-rw-r--r--library/alloc/src/vec.rs4
-rw-r--r--library/std/Cargo.toml1
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs2
-rw-r--r--library/test/Cargo.toml1
-rwxr-xr-xsrc/ci/run.sh2
m---------src/doc/embedded-book0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md8
-rw-r--r--src/test/ui/const-generics/issue-74906.rs25
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-74761.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-74761.stderr15
-rw-r--r--src/tools/compiletest/src/header.rs7
17 files changed, 125 insertions, 52 deletions
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs b/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
index 711271a63fb..8513e5e531b 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
@@ -62,8 +62,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         // `self.constraints`, but we also want to be mutating
         // `self.member_constraints`. For now, just swap out the value
         // we want and replace at the end.
-        let mut tmp =
-            std::mem::replace(&mut self.constraints.member_constraints, Default::default());
+        let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
         for member_constraint in member_constraints {
             tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
         }
diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
index 67e679a8b08..7a9089d0f36 100644
--- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
+++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
@@ -91,7 +91,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
             let not_equal_rvalue = Rvalue::BinaryOp(
                 not_equal,
                 Operand::Copy(Place::from(second_discriminant_temp)),
-                Operand::Copy(Place::from(first_descriminant_place)),
+                Operand::Copy(first_descriminant_place),
             );
             patch.add_statement(
                 end_of_block_location,
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 3446ca11f02..e8b97d7dc7d 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -62,13 +62,13 @@
 //! - `reader`: the `LiveNode` ID of some node which will read the value
 //!    that `V` holds on entry to `N`. Formally: a node `M` such
 //!    that there exists a path `P` from `N` to `M` where `P` does not
-//!    write `V`. If the `reader` is `INVALID_NODE`, then the current
+//!    write `V`. If the `reader` is `None`, then the current
 //!    value will never be read (the variable is dead, essentially).
 //!
 //! - `writer`: the `LiveNode` ID of some node which will write the
 //!    variable `V` and which is reachable from `N`. Formally: a node `M`
 //!    such that there exists a path `P` from `N` to `M` and `M` writes
-//!    `V`. If the `writer` is `INVALID_NODE`, then there is no writer
+//!    `V`. If the `writer` is `None`, then there is no writer
 //!    of `V` that follows `N`.
 //!
 //! - `used`: a boolean value indicating whether `V` is *used*. We
@@ -114,7 +114,6 @@ rustc_index::newtype_index! {
 rustc_index::newtype_index! {
     pub struct LiveNode {
         DEBUG_FORMAT = "ln({})",
-        const INVALID_NODE = LiveNode::MAX_AS_U32,
     }
 }
 
@@ -168,12 +167,6 @@ pub fn provide(providers: &mut Providers) {
 // variable must not be assigned if there is some successor
 // assignment.  And so forth.
 
-impl LiveNode {
-    fn is_valid(self) -> bool {
-        self != INVALID_NODE
-    }
-}
-
 struct CaptureInfo {
     ln: LiveNode,
     var_hid: HirId,
@@ -467,8 +460,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
 
 #[derive(Clone, Copy)]
 struct RWU {
-    reader: LiveNode,
-    writer: LiveNode,
+    reader: Option<LiveNode>,
+    writer: Option<LiveNode>,
     used: bool,
 }
 
@@ -490,10 +483,10 @@ struct RWUTable {
     unpacked_rwus: Vec<RWU>,
 }
 
-// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: false }`.
+// A constant representing `RWU { reader: None; writer: None; used: false }`.
 const INV_INV_FALSE: u32 = u32::MAX;
 
-// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: true }`.
+// A constant representing `RWU { reader: None; writer: None; used: true }`.
 const INV_INV_TRUE: u32 = u32::MAX - 1;
 
 impl RWUTable {
@@ -504,24 +497,24 @@ impl RWUTable {
     fn get(&self, idx: usize) -> RWU {
         let packed_rwu = self.packed_rwus[idx];
         match packed_rwu {
-            INV_INV_FALSE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: false },
-            INV_INV_TRUE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: true },
+            INV_INV_FALSE => RWU { reader: None, writer: None, used: false },
+            INV_INV_TRUE => RWU { reader: None, writer: None, used: true },
             _ => self.unpacked_rwus[packed_rwu as usize],
         }
     }
 
-    fn get_reader(&self, idx: usize) -> LiveNode {
+    fn get_reader(&self, idx: usize) -> Option<LiveNode> {
         let packed_rwu = self.packed_rwus[idx];
         match packed_rwu {
-            INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE,
+            INV_INV_FALSE | INV_INV_TRUE => None,
             _ => self.unpacked_rwus[packed_rwu as usize].reader,
         }
     }
 
-    fn get_writer(&self, idx: usize) -> LiveNode {
+    fn get_writer(&self, idx: usize) -> Option<LiveNode> {
         let packed_rwu = self.packed_rwus[idx];
         match packed_rwu {
-            INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE,
+            INV_INV_FALSE | INV_INV_TRUE => None,
             _ => self.unpacked_rwus[packed_rwu as usize].writer,
         }
     }
@@ -541,7 +534,7 @@ impl RWUTable {
     }
 
     fn assign_unpacked(&mut self, idx: usize, rwu: RWU) {
-        if rwu.reader == INVALID_NODE && rwu.writer == INVALID_NODE {
+        if rwu.reader == None && rwu.writer == None {
             // When we overwrite an indexing entry in `self.packed_rwus` with
             // `INV_INV_{TRUE,FALSE}` we don't remove the corresponding entry
             // from `self.unpacked_rwus`; it's not worth the effort, and we
@@ -570,7 +563,7 @@ struct Liveness<'a, 'tcx> {
     typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
-    successors: IndexVec<LiveNode, LiveNode>,
+    successors: IndexVec<LiveNode, Option<LiveNode>>,
     rwu_table: RWUTable,
 
     /// A live node representing a point of execution before closure entry &
@@ -606,7 +599,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             typeck_results,
             param_env,
             upvars,
-            successors: IndexVec::from_elem_n(INVALID_NODE, num_live_nodes),
+            successors: IndexVec::from_elem_n(None, num_live_nodes),
             rwu_table: RWUTable::new(num_live_nodes * num_vars),
             closure_ln,
             exit_ln,
@@ -651,30 +644,33 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
-        assert!(ln.is_valid());
-        let reader = self.rwu_table.get_reader(self.idx(ln, var));
-        if reader.is_valid() { Some(self.ir.lnks[reader]) } else { None }
+        if let Some(reader) = self.rwu_table.get_reader(self.idx(ln, var)) {
+            Some(self.ir.lnks[reader])
+        } else {
+            None
+        }
     }
 
     // Is this variable live on entry to any of its successor nodes?
     fn live_on_exit(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
-        let successor = self.successors[ln];
+        let successor = self.successors[ln].unwrap();
         self.live_on_entry(successor, var)
     }
 
     fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
-        assert!(ln.is_valid());
         self.rwu_table.get_used(self.idx(ln, var))
     }
 
     fn assigned_on_entry(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
-        assert!(ln.is_valid());
-        let writer = self.rwu_table.get_writer(self.idx(ln, var));
-        if writer.is_valid() { Some(self.ir.lnks[writer]) } else { None }
+        if let Some(writer) = self.rwu_table.get_writer(self.idx(ln, var)) {
+            Some(self.ir.lnks[writer])
+        } else {
+            None
+        }
     }
 
     fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
-        let successor = self.successors[ln];
+        let successor = self.successors[ln].unwrap();
         self.assigned_on_entry(successor, var)
     }
 
@@ -709,9 +705,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         {
             let wr = &mut wr as &mut dyn Write;
             write!(wr, "[{:?} of kind {:?} reads", ln, self.ir.lnks[ln]);
-            self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_valid());
+            self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_some());
             write!(wr, "  writes");
-            self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_valid());
+            self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_some());
             write!(wr, "  uses");
             self.write_vars(wr, ln, |idx| self.rwu_table.get_used(idx));
 
@@ -735,7 +731,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) {
-        self.successors[ln] = succ_ln;
+        self.successors[ln] = Some(succ_ln);
 
         // It is not necessary to initialize the RWUs here because they are all
         // set to INV_INV_FALSE when they are created, and the sets only grow
@@ -744,7 +740,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) {
         // more efficient version of init_empty() / merge_from_succ()
-        self.successors[ln] = succ_ln;
+        self.successors[ln] = Some(succ_ln);
 
         self.indices2(ln, succ_ln, |this, idx, succ_idx| {
             this.rwu_table.copy_packed(idx, succ_idx);
@@ -768,12 +764,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             let mut changed = false;
             let mut rwu = this.rwu_table.get(idx);
             let succ_rwu = this.rwu_table.get(succ_idx);
-            if succ_rwu.reader.is_valid() && !rwu.reader.is_valid() {
+            if succ_rwu.reader.is_some() && rwu.reader.is_none() {
                 rwu.reader = succ_rwu.reader;
                 changed = true
             }
 
-            if succ_rwu.writer.is_valid() && !rwu.writer.is_valid() {
+            if succ_rwu.writer.is_some() && rwu.writer.is_none() {
                 rwu.writer = succ_rwu.writer;
                 changed = true
             }
@@ -817,14 +813,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         let mut rwu = self.rwu_table.get(idx);
 
         if (acc & ACC_WRITE) != 0 {
-            rwu.reader = INVALID_NODE;
-            rwu.writer = ln;
+            rwu.reader = None;
+            rwu.writer = Some(ln);
         }
 
         // Important: if we both read/write, must do read second
         // or else the write will override.
         if (acc & ACC_READ) != 0 {
-            rwu.reader = ln;
+            rwu.reader = Some(ln);
         }
 
         if (acc & ACC_USE) != 0 {
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 6fd7277a1c3..5363702a5be 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -70,10 +70,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
         wbcx.typeck_results.used_trait_imports = used_trait_imports;
 
-        wbcx.typeck_results.closure_captures = mem::replace(
-            &mut self.typeck_results.borrow_mut().closure_captures,
-            Default::default(),
-        );
+        wbcx.typeck_results.closure_captures =
+            mem::take(&mut self.typeck_results.borrow_mut().closure_captures);
 
         if self.is_tainted_by_errors() {
             // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index e2416974ddc..54c3709821a 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -23,3 +23,12 @@ fn test_splitpoint() {
         assert!(left_len + right_len == CAPACITY);
     }
 }
+
+#[test]
+#[cfg(target_arch = "x86_64")]
+fn test_sizes() {
+    assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16);
+    assert_eq!(core::mem::size_of::<LeafNode<i64, i64>>(), 16 + CAPACITY * 8 * 2);
+    assert_eq!(core::mem::size_of::<InternalNode<(), ()>>(), 112);
+    assert_eq!(core::mem::size_of::<InternalNode<i64, i64>>(), 112 + CAPACITY * 8 * 2);
+}
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index fec4c1e0e50..5114f578f02 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -2281,14 +2281,14 @@ where
 
         // use try-fold since
         // - it vectorizes better for some iterator adapters
-        // - unlike most internal iteration methods methods it only takes a &mut self
+        // - unlike most internal iteration methods, it only takes a &mut self
         // - it lets us thread the write pointer through its innards and get it back in the end
         let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf };
         let sink = iterator
             .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end))
             .unwrap();
         // iteration succeeded, don't drop head
-        let dst = mem::ManuallyDrop::new(sink).dst;
+        let dst = ManuallyDrop::new(sink).dst;
 
         let src = unsafe { iterator.as_inner().as_into_iter() };
         // check if SourceIter contract was upheld
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 01babeffd98..b27b056086a 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -59,6 +59,7 @@ gimli-symbolize = []
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
+compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 
 # Make panics and failed asserts immediately abort without formatting any message
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 08efe154e4c..c3625d306ab 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -67,7 +67,7 @@ impl Command {
                     // pipe I/O up to PIPE_BUF bytes should be atomic, and then
                     // we want to be sure we *don't* run at_exit destructors as
                     // we're being torn down regardless
-                    assert!(output.write(&bytes).is_ok());
+                    rtassert!(output.write(&bytes).is_ok());
                     libc::_exit(1)
                 }
                 n => n,
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index 7b76dc83aa2..e44c7811135 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -25,6 +25,7 @@ proc_macro = { path = "../proc_macro" }
 default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
 backtrace = ["std/backtrace"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
+compiler-builtins-mem = ["std/compiler-builtins-mem"]
 llvm-libunwind = ["std/llvm-libunwind"]
 panic-unwind = ["std/panic_unwind"]
 panic_immediate_abort = ["std/panic_immediate_abort"]
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 5231aa2e766..181a7fcb732 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -104,6 +104,8 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools"
 fi
 
+export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1
+
 # Print the date from the local machine and the date from an external source to
 # check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure
 # Pipelines it happened that the certificates were marked as expired.
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 0cd2ca116274b915924c3a7e07c1e046b6f19b7
+Subproject dd310616308e01f6cf227f46347b744aa56b77d
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 19f0a0372af497b34369cf182d9d16156cab296
+Subproject 7d3ff1c12db08a847a57a054be4a7951ce532d2
diff --git a/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md b/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md
new file mode 100644
index 00000000000..8e46e227c25
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md
@@ -0,0 +1,8 @@
+# `unsound-mir-opts`
+
+--------------------
+
+The `-Zunsound-mir-opts` compiler flag enables [MIR optimization passes] which can cause unsound behavior.
+This flag should only be used by MIR optimization tests in the rustc test suite.
+
+[MIR optimization passes]: https://rustc-dev-guide.rust-lang.org/mir/optimizations.html
diff --git a/src/test/ui/const-generics/issue-74906.rs b/src/test/ui/const-generics/issue-74906.rs
new file mode 100644
index 00000000000..9162d1142b6
--- /dev/null
+++ b/src/test/ui/const-generics/issue-74906.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+const SIZE: usize = 16;
+
+struct Bar<const H: usize> {}
+
+struct Foo<const H: usize> {}
+
+impl<const H: usize> Foo<H> {
+    async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
+        vec![]
+    }
+
+    pub async fn baz(&self) -> Bar<H> {
+        Self::biz(&vec![]).await;
+        Bar {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761.rs b/src/test/ui/type-alias-impl-trait/issue-74761.rs
new file mode 100644
index 00000000000..4345b5d886e
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-74761.rs
@@ -0,0 +1,16 @@
+#![feature(member_constraints)]
+#![feature(type_alias_impl_trait)]
+
+pub trait A {
+    type B;
+    fn f(&self) -> Self::B;
+}
+impl<'a, 'b> A for () {
+    //~^ ERROR the lifetime parameter `'a` is not constrained
+    //~| ERROR the lifetime parameter `'b` is not constrained
+    type B = impl core::fmt::Debug;
+
+    fn f(&self) -> Self::B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761.stderr b/src/test/ui/type-alias-impl-trait/issue-74761.stderr
new file mode 100644
index 00000000000..3f38fa4de01
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-74761.stderr
@@ -0,0 +1,15 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761.rs:8:6
+   |
+LL | impl<'a, 'b> A for () {
+   |      ^^ unconstrained lifetime parameter
+
+error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761.rs:8:10
+   |
+LL | impl<'a, 'b> A for () {
+   |          ^^ unconstrained lifetime parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 17649dfab37..59f64e7df0f 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -208,10 +208,13 @@ impl EarlyProps {
                 config.parse_name_value_directive(line, "needs-llvm-components")
             {
                 let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
-                if !needed_components
+                if let Some(missing_component) = needed_components
                     .split_whitespace()
-                    .all(|needed_component| components.contains(needed_component))
+                    .find(|needed_component| !components.contains(needed_component))
                 {
+                    if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
+                        panic!("missing LLVM component: {}", missing_component);
+                    }
                     return true;
                 }
             }