about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-07 13:02:31 +0000
committerbors <bors@rust-lang.org>2022-03-07 13:02:31 +0000
commitd137c3a7bd3b180317044f8ccb9a8b4b3bb07db3 (patch)
tree9d75ddcac7d9dff0929fb5db1cef5dea648f6531
parent297273c45b205820a4c055082c71677197a40b55 (diff)
parentc0c452ba9bd66eac4e6bee9508bbf5be273f5b13 (diff)
downloadrust-d137c3a7bd3b180317044f8ccb9a8b4b3bb07db3.tar.gz
rust-d137c3a7bd3b180317044f8ccb9a8b4b3bb07db3.zip
Auto merge of #94695 - matthiaskrgr:rollup-5pi3acz, r=matthiaskrgr
Rollup of 4 pull requests

Successful merges:

 - #94553 (add tests for #94502)
 - #94614 (Remove ordering traits from `rustc_span::hygiene::LocalExpnId`)
 - #94685 (interpret: move saturating_add/sub into (pub) helper method)
 - #94688 (Erase regions when checking for missing Copy predicates)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs84
-rw-r--r--compiler/rustc_span/src/hygiene.rs7
-rw-r--r--src/test/ui/borrowck/copy-suggestion-region-vid.rs17
-rw-r--r--src/test/ui/borrowck/copy-suggestion-region-vid.stderr14
-rw-r--r--src/test/ui/nll/lint-no-err.rs28
-rw-r--r--src/test/ui/nll/lint-no-err.stderr17
7 files changed, 138 insertions, 41 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 684a3ced5a0..2a74e1ce8b1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -448,8 +448,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 self.mir_hir_id(),
                                 rustc_infer::traits::ObligationCauseCode::MiscObligation,
                             );
-                            fulfill_cx.register_bound(&infcx, self.param_env, ty, copy_did, cause);
-                            let errors = fulfill_cx.select_where_possible(&infcx);
+                            fulfill_cx.register_bound(
+                                &infcx,
+                                self.param_env,
+                                // Erase any region vids from the type, which may not be resolved
+                                infcx.tcx.erase_regions(ty),
+                                copy_did,
+                                cause,
+                            );
+                            // Select all, including ambiguous predicates
+                            let errors = fulfill_cx.select_all_or_error(&infcx);
 
                             // Only emit suggestion if all required predicates are on generic
                             errors
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 9b58e25d330..715b174491b 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -219,48 +219,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::saturating_add | sym::saturating_sub => {
                 let l = self.read_immediate(&args[0])?;
                 let r = self.read_immediate(&args[1])?;
-                let is_add = intrinsic_name == sym::saturating_add;
-                let (val, overflowed, _ty) = self.overflowing_binary_op(
-                    if is_add { BinOp::Add } else { BinOp::Sub },
+                let val = self.saturating_arith(
+                    if intrinsic_name == sym::saturating_add { BinOp::Add } else { BinOp::Sub },
                     &l,
                     &r,
                 )?;
-                let val = if overflowed {
-                    let size = l.layout.size;
-                    let num_bits = size.bits();
-                    if l.layout.abi.is_signed() {
-                        // For signed ints the saturated value depends on the sign of the first
-                        // term since the sign of the second term can be inferred from this and
-                        // the fact that the operation has overflowed (if either is 0 no
-                        // overflow can occur)
-                        let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
-                        let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
-                        if first_term_positive {
-                            // Negative overflow not possible since the positive first term
-                            // can only increase an (in range) negative term for addition
-                            // or corresponding negated positive term for subtraction
-                            Scalar::from_uint(
-                                (1u128 << (num_bits - 1)) - 1, // max positive
-                                Size::from_bits(num_bits),
-                            )
-                        } else {
-                            // Positive overflow not possible for similar reason
-                            // max negative
-                            Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
-                        }
-                    } else {
-                        // unsigned
-                        if is_add {
-                            // max unsigned
-                            Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
-                        } else {
-                            // underflow to 0
-                            Scalar::from_uint(0u128, Size::from_bits(num_bits))
-                        }
-                    }
-                } else {
-                    val
-                };
                 self.write_scalar(val, dest)?;
             }
             sym::discriminant_value => {
@@ -508,6 +471,49 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
     }
 
+    pub fn saturating_arith(
+        &self,
+        mir_op: BinOp,
+        l: &ImmTy<'tcx, M::PointerTag>,
+        r: &ImmTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+        assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
+        let (val, overflowed, _ty) = self.overflowing_binary_op(mir_op, l, r)?;
+        Ok(if overflowed {
+            let size = l.layout.size;
+            let num_bits = size.bits();
+            if l.layout.abi.is_signed() {
+                // For signed ints the saturated value depends on the sign of the first
+                // term since the sign of the second term can be inferred from this and
+                // the fact that the operation has overflowed (if either is 0 no
+                // overflow can occur)
+                let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
+                let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
+                if first_term_positive {
+                    // Negative overflow not possible since the positive first term
+                    // can only increase an (in range) negative term for addition
+                    // or corresponding negated positive term for subtraction
+                    Scalar::from_int(size.signed_int_max(), size)
+                } else {
+                    // Positive overflow not possible for similar reason
+                    // max negative
+                    Scalar::from_int(size.signed_int_min(), size)
+                }
+            } else {
+                // unsigned
+                if matches!(mir_op, BinOp::Add) {
+                    // max unsigned
+                    Scalar::from_uint(size.unsigned_int_max(), size)
+                } else {
+                    // underflow to 0
+                    Scalar::from_uint(0u128, size)
+                }
+            }
+        } else {
+            val
+        })
+    }
+
     /// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
     /// allocation. For integer pointers, we consider each of them their own tiny allocation of size
     /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 5fae46d5fd8..86adfa7a18c 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -85,10 +85,17 @@ rustc_index::newtype_index! {
     /// A unique ID associated with a macro invocation and expansion.
     pub struct LocalExpnId {
         ENCODABLE = custom
+        ORD_IMPL = custom
         DEBUG_FORMAT = "expn{}"
     }
 }
 
+// To ensure correctness of incremental compilation,
+// `LocalExpnId` must not implement `Ord` or `PartialOrd`.
+// See https://github.com/rust-lang/rust/issues/90317.
+impl !Ord for LocalExpnId {}
+impl !PartialOrd for LocalExpnId {}
+
 /// Assert that the provided `HashStableContext` is configured with the 'default'
 /// `HashingControls`. We should always have bailed out before getting to here
 /// with a non-default mode. With this check in place, we can avoid the need
diff --git a/src/test/ui/borrowck/copy-suggestion-region-vid.rs b/src/test/ui/borrowck/copy-suggestion-region-vid.rs
new file mode 100644
index 00000000000..dff95283459
--- /dev/null
+++ b/src/test/ui/borrowck/copy-suggestion-region-vid.rs
@@ -0,0 +1,17 @@
+pub struct DataStruct();
+
+pub struct HelperStruct<'n> {
+    pub helpers: [Vec<&'n i64>; 2],
+    pub is_empty: bool,
+}
+
+impl DataStruct {
+    pub fn f(&self) -> HelperStruct {
+        let helpers = [vec![], vec![]];
+
+        HelperStruct { helpers, is_empty: helpers[0].is_empty() }
+        //~^ ERROR borrow of moved value
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/copy-suggestion-region-vid.stderr b/src/test/ui/borrowck/copy-suggestion-region-vid.stderr
new file mode 100644
index 00000000000..f03cdd84d75
--- /dev/null
+++ b/src/test/ui/borrowck/copy-suggestion-region-vid.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `helpers`
+  --> $DIR/copy-suggestion-region-vid.rs:12:43
+   |
+LL |         let helpers = [vec![], vec![]];
+   |             ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait
+LL | 
+LL |         HelperStruct { helpers, is_empty: helpers[0].is_empty() }
+   |                        -------            ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
+   |                        |
+   |                        value moved here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/lint-no-err.rs b/src/test/ui/nll/lint-no-err.rs
new file mode 100644
index 00000000000..4b4169faadf
--- /dev/null
+++ b/src/test/ui/nll/lint-no-err.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+// mir borrowck previously incorrectly set `tainted_by_errors`
+// when buffering lints, which resulted in ICE later on,
+// see #94502.
+
+// Errors with `nll` which is already tested in enough other tests,
+// so we ignore it here.
+//
+// ignore-compare-mode-nll
+
+struct Repro;
+impl Repro {
+    fn get(&self) -> &i32 {
+        &3
+    }
+
+    fn insert(&mut self, _: i32) {}
+}
+
+fn main() {
+    let x = &0;
+    let mut conflict = Repro;
+    let prev = conflict.get();
+    conflict.insert(*prev + *x);
+    //~^ WARN cannot borrow `conflict` as mutable because it is also borrowed as immutable
+    //~| WARN this borrowing pattern was not meant to be accepted
+}
diff --git a/src/test/ui/nll/lint-no-err.stderr b/src/test/ui/nll/lint-no-err.stderr
new file mode 100644
index 00000000000..1e7aecfaa64
--- /dev/null
+++ b/src/test/ui/nll/lint-no-err.stderr
@@ -0,0 +1,17 @@
+warning: cannot borrow `conflict` as mutable because it is also borrowed as immutable
+  --> $DIR/lint-no-err.rs:25:5
+   |
+LL |     let prev = conflict.get();
+   |                -------------- immutable borrow occurs here
+LL |     conflict.insert(*prev + *x);
+   |     ^^^^^^^^^^^^^^^^-----^^^^^^
+   |     |               |
+   |     |               immutable borrow later used here
+   |     mutable borrow occurs here
+   |
+   = note: `#[warn(mutable_borrow_reservation_conflict)]` on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+warning: 1 warning emitted
+