Skip to content

Commit d137c3a

Browse files
committed
Auto merge of rust-lang#94695 - matthiaskrgr:rollup-5pi3acz, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang#94553 (add tests for rust-lang#94502) - rust-lang#94614 (Remove ordering traits from `rustc_span::hygiene::LocalExpnId`) - rust-lang#94685 (interpret: move saturating_add/sub into (pub) helper method) - rust-lang#94688 (Erase regions when checking for missing Copy predicates) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 297273c + c0c452b commit d137c3a

File tree

7 files changed

+138
-41
lines changed

7 files changed

+138
-41
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
448448
self.mir_hir_id(),
449449
rustc_infer::traits::ObligationCauseCode::MiscObligation,
450450
);
451-
fulfill_cx.register_bound(&infcx, self.param_env, ty, copy_did, cause);
452-
let errors = fulfill_cx.select_where_possible(&infcx);
451+
fulfill_cx.register_bound(
452+
&infcx,
453+
self.param_env,
454+
// Erase any region vids from the type, which may not be resolved
455+
infcx.tcx.erase_regions(ty),
456+
copy_did,
457+
cause,
458+
);
459+
// Select all, including ambiguous predicates
460+
let errors = fulfill_cx.select_all_or_error(&infcx);
453461

454462
// Only emit suggestion if all required predicates are on generic
455463
errors

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+45-39
Original file line numberDiff line numberDiff line change
@@ -219,48 +219,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
219219
sym::saturating_add | sym::saturating_sub => {
220220
let l = self.read_immediate(&args[0])?;
221221
let r = self.read_immediate(&args[1])?;
222-
let is_add = intrinsic_name == sym::saturating_add;
223-
let (val, overflowed, _ty) = self.overflowing_binary_op(
224-
if is_add { BinOp::Add } else { BinOp::Sub },
222+
let val = self.saturating_arith(
223+
if intrinsic_name == sym::saturating_add { BinOp::Add } else { BinOp::Sub },
225224
&l,
226225
&r,
227226
)?;
228-
let val = if overflowed {
229-
let size = l.layout.size;
230-
let num_bits = size.bits();
231-
if l.layout.abi.is_signed() {
232-
// For signed ints the saturated value depends on the sign of the first
233-
// term since the sign of the second term can be inferred from this and
234-
// the fact that the operation has overflowed (if either is 0 no
235-
// overflow can occur)
236-
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
237-
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
238-
if first_term_positive {
239-
// Negative overflow not possible since the positive first term
240-
// can only increase an (in range) negative term for addition
241-
// or corresponding negated positive term for subtraction
242-
Scalar::from_uint(
243-
(1u128 << (num_bits - 1)) - 1, // max positive
244-
Size::from_bits(num_bits),
245-
)
246-
} else {
247-
// Positive overflow not possible for similar reason
248-
// max negative
249-
Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
250-
}
251-
} else {
252-
// unsigned
253-
if is_add {
254-
// max unsigned
255-
Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
256-
} else {
257-
// underflow to 0
258-
Scalar::from_uint(0u128, Size::from_bits(num_bits))
259-
}
260-
}
261-
} else {
262-
val
263-
};
264227
self.write_scalar(val, dest)?;
265228
}
266229
sym::discriminant_value => {
@@ -508,6 +471,49 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
508471
self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
509472
}
510473

474+
pub fn saturating_arith(
475+
&self,
476+
mir_op: BinOp,
477+
l: &ImmTy<'tcx, M::PointerTag>,
478+
r: &ImmTy<'tcx, M::PointerTag>,
479+
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
480+
assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
481+
let (val, overflowed, _ty) = self.overflowing_binary_op(mir_op, l, r)?;
482+
Ok(if overflowed {
483+
let size = l.layout.size;
484+
let num_bits = size.bits();
485+
if l.layout.abi.is_signed() {
486+
// For signed ints the saturated value depends on the sign of the first
487+
// term since the sign of the second term can be inferred from this and
488+
// the fact that the operation has overflowed (if either is 0 no
489+
// overflow can occur)
490+
let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
491+
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
492+
if first_term_positive {
493+
// Negative overflow not possible since the positive first term
494+
// can only increase an (in range) negative term for addition
495+
// or corresponding negated positive term for subtraction
496+
Scalar::from_int(size.signed_int_max(), size)
497+
} else {
498+
// Positive overflow not possible for similar reason
499+
// max negative
500+
Scalar::from_int(size.signed_int_min(), size)
501+
}
502+
} else {
503+
// unsigned
504+
if matches!(mir_op, BinOp::Add) {
505+
// max unsigned
506+
Scalar::from_uint(size.unsigned_int_max(), size)
507+
} else {
508+
// underflow to 0
509+
Scalar::from_uint(0u128, size)
510+
}
511+
}
512+
} else {
513+
val
514+
})
515+
}
516+
511517
/// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
512518
/// allocation. For integer pointers, we consider each of them their own tiny allocation of size
513519
/// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.

compiler/rustc_span/src/hygiene.rs

+7
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,17 @@ rustc_index::newtype_index! {
8585
/// A unique ID associated with a macro invocation and expansion.
8686
pub struct LocalExpnId {
8787
ENCODABLE = custom
88+
ORD_IMPL = custom
8889
DEBUG_FORMAT = "expn{}"
8990
}
9091
}
9192

93+
// To ensure correctness of incremental compilation,
94+
// `LocalExpnId` must not implement `Ord` or `PartialOrd`.
95+
// See https://github.com/rust-lang/rust/issues/90317.
96+
impl !Ord for LocalExpnId {}
97+
impl !PartialOrd for LocalExpnId {}
98+
9299
/// Assert that the provided `HashStableContext` is configured with the 'default'
93100
/// `HashingControls`. We should always have bailed out before getting to here
94101
/// with a non-default mode. With this check in place, we can avoid the need
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pub struct DataStruct();
2+
3+
pub struct HelperStruct<'n> {
4+
pub helpers: [Vec<&'n i64>; 2],
5+
pub is_empty: bool,
6+
}
7+
8+
impl DataStruct {
9+
pub fn f(&self) -> HelperStruct {
10+
let helpers = [vec![], vec![]];
11+
12+
HelperStruct { helpers, is_empty: helpers[0].is_empty() }
13+
//~^ ERROR borrow of moved value
14+
}
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0382]: borrow of moved value: `helpers`
2+
--> $DIR/copy-suggestion-region-vid.rs:12:43
3+
|
4+
LL | let helpers = [vec![], vec![]];
5+
| ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait
6+
LL |
7+
LL | HelperStruct { helpers, is_empty: helpers[0].is_empty() }
8+
| ------- ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
9+
| |
10+
| value moved here
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0382`.

src/test/ui/nll/lint-no-err.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// check-pass
2+
3+
// mir borrowck previously incorrectly set `tainted_by_errors`
4+
// when buffering lints, which resulted in ICE later on,
5+
// see #94502.
6+
7+
// Errors with `nll` which is already tested in enough other tests,
8+
// so we ignore it here.
9+
//
10+
// ignore-compare-mode-nll
11+
12+
struct Repro;
13+
impl Repro {
14+
fn get(&self) -> &i32 {
15+
&3
16+
}
17+
18+
fn insert(&mut self, _: i32) {}
19+
}
20+
21+
fn main() {
22+
let x = &0;
23+
let mut conflict = Repro;
24+
let prev = conflict.get();
25+
conflict.insert(*prev + *x);
26+
//~^ WARN cannot borrow `conflict` as mutable because it is also borrowed as immutable
27+
//~| WARN this borrowing pattern was not meant to be accepted
28+
}

src/test/ui/nll/lint-no-err.stderr

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: cannot borrow `conflict` as mutable because it is also borrowed as immutable
2+
--> $DIR/lint-no-err.rs:25:5
3+
|
4+
LL | let prev = conflict.get();
5+
| -------------- immutable borrow occurs here
6+
LL | conflict.insert(*prev + *x);
7+
| ^^^^^^^^^^^^^^^^-----^^^^^^
8+
| | |
9+
| | immutable borrow later used here
10+
| mutable borrow occurs here
11+
|
12+
= note: `#[warn(mutable_borrow_reservation_conflict)]` on by default
13+
= warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
14+
= note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
15+
16+
warning: 1 warning emitted
17+

0 commit comments

Comments
 (0)