Skip to content

Commit d594910

Browse files
committed
Auto merge of #91933 - matthiaskrgr:rollup-cw9qolb, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #89825 (Make split_inclusive() on an empty slice yield an empty output) - #91239 (regression test for issue 87490) - #91597 (Recover on invalid operators `<>` and `<=>`) - #91774 (Fix typo for MutVisitor) - #91786 (Return an error when `eval_rvalue_with_identities` fails) - #91798 (Avoid suggest adding `self` in visibility spec) - #91856 (Looser check for overflowing_binary_op) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2f4da62 + bae9270 commit d594910

File tree

17 files changed

+198
-63
lines changed

17 files changed

+198
-63
lines changed

compiler/rustc_ast/src/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
2-
//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor`
2+
//! mutates it in place. So, for instance, macro expansion is a `MutVisitor`
33
//! that walks over an AST and modifies it.
44
//!
55
//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on

compiler/rustc_const_eval/src/interpret/operator.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
328328
self.binary_int_op(bin_op, l, left.layout, r, right.layout)
329329
}
330330
_ if left.layout.ty.is_any_ptr() => {
331-
// The RHS type must be the same *or an integer type* (for `Offset`).
331+
// The RHS type must be a `pointer` *or an integer type* (for `Offset`).
332+
// (Even when both sides are pointers, their type might differ, see issue #91636)
332333
assert!(
333-
right.layout.ty == left.layout.ty || right.layout.ty.is_integral(),
334+
right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(),
334335
"Unexpected types for BinOp: {:?} {:?} {:?}",
335336
left.layout.ty,
336337
bin_op,

compiler/rustc_mir_transform/src/const_prop.rs

+34-52
Original file line numberDiff line numberDiff line change
@@ -752,62 +752,44 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
752752
rvalue: &Rvalue<'tcx>,
753753
place: Place<'tcx>,
754754
) -> Option<()> {
755-
self.use_ecx(|this| {
756-
match rvalue {
757-
Rvalue::BinaryOp(op, box (left, right))
758-
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
759-
let l = this.ecx.eval_operand(left, None);
760-
let r = this.ecx.eval_operand(right, None);
761-
762-
let const_arg = match (l, r) {
763-
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
764-
(Err(e), Err(_)) => return Err(e),
765-
(Ok(_), Ok(_)) => {
766-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
767-
return Ok(());
768-
}
769-
};
770-
771-
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
772-
let dest = this.ecx.eval_place(place)?;
773-
774-
match op {
775-
BinOp::BitAnd => {
776-
if arg_value == 0 {
777-
this.ecx.write_immediate(*const_arg, &dest)?;
778-
}
779-
}
780-
BinOp::BitOr => {
781-
if arg_value == const_arg.layout.size.truncate(u128::MAX)
782-
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
783-
{
784-
this.ecx.write_immediate(*const_arg, &dest)?;
785-
}
786-
}
787-
BinOp::Mul => {
788-
if const_arg.layout.ty.is_integral() && arg_value == 0 {
789-
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
790-
let val = Immediate::ScalarPair(
791-
const_arg.to_scalar()?.into(),
792-
Scalar::from_bool(false).into(),
793-
);
794-
this.ecx.write_immediate(val, &dest)?;
795-
} else {
796-
this.ecx.write_immediate(*const_arg, &dest)?;
797-
}
798-
}
799-
}
800-
_ => {
801-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
755+
self.use_ecx(|this| match rvalue {
756+
Rvalue::BinaryOp(op, box (left, right))
757+
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
758+
let l = this.ecx.eval_operand(left, None);
759+
let r = this.ecx.eval_operand(right, None);
760+
761+
let const_arg = match (l, r) {
762+
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
763+
(Err(e), Err(_)) => return Err(e),
764+
(Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place),
765+
};
766+
767+
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
768+
let dest = this.ecx.eval_place(place)?;
769+
770+
match op {
771+
BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest),
772+
BinOp::BitOr
773+
if arg_value == const_arg.layout.size.truncate(u128::MAX)
774+
|| (const_arg.layout.ty.is_bool() && arg_value == 1) =>
775+
{
776+
this.ecx.write_immediate(*const_arg, &dest)
777+
}
778+
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
779+
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
780+
let val = Immediate::ScalarPair(
781+
const_arg.to_scalar()?.into(),
782+
Scalar::from_bool(false).into(),
783+
);
784+
this.ecx.write_immediate(val, &dest)
785+
} else {
786+
this.ecx.write_immediate(*const_arg, &dest)
802787
}
803788
}
804-
}
805-
_ => {
806-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
789+
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
807790
}
808791
}
809-
810-
Ok(())
792+
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
811793
})
812794
}
813795

compiler/rustc_parse/src/parser/expr.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,11 @@ impl<'a> Parser<'a> {
213213
}
214214
}
215215

216+
// Look for JS' `===` and `!==` and recover
216217
if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual)
217218
&& self.token.kind == token::Eq
218219
&& self.prev_token.span.hi() == self.token.span.lo()
219220
{
220-
// Look for JS' `===` and `!==` and recover 😇
221221
let sp = op.span.to(self.token.span);
222222
let sugg = match op.node {
223223
AssocOp::Equal => "==",
@@ -235,6 +235,38 @@ impl<'a> Parser<'a> {
235235
self.bump();
236236
}
237237

238+
// Look for PHP's `<>` and recover
239+
if op.node == AssocOp::Less
240+
&& self.token.kind == token::Gt
241+
&& self.prev_token.span.hi() == self.token.span.lo()
242+
{
243+
let sp = op.span.to(self.token.span);
244+
self.struct_span_err(sp, "invalid comparison operator `<>`")
245+
.span_suggestion_short(
246+
sp,
247+
"`<>` is not a valid comparison operator, use `!=`",
248+
"!=".to_string(),
249+
Applicability::MachineApplicable,
250+
)
251+
.emit();
252+
self.bump();
253+
}
254+
255+
// Look for C++'s `<=>` and recover
256+
if op.node == AssocOp::LessEqual
257+
&& self.token.kind == token::Gt
258+
&& self.prev_token.span.hi() == self.token.span.lo()
259+
{
260+
let sp = op.span.to(self.token.span);
261+
self.struct_span_err(sp, "invalid comparison operator `<=>`")
262+
.span_label(
263+
sp,
264+
"`<=>` is not a valid comparison operator, use `std::cmp::Ordering`",
265+
)
266+
.emit();
267+
self.bump();
268+
}
269+
238270
let op = op.node;
239271
// Special cases:
240272
if op == AssocOp::As {

compiler/rustc_resolve/src/late/diagnostics.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
298298
.get(0)
299299
.map(|p| (p.span.shrink_to_lo(), "&self, "))
300300
.unwrap_or_else(|| {
301+
// Try to look for the "(" after the function name, if possible.
302+
// This avoids placing the suggestion into the visibility specifier.
303+
let span = fn_kind
304+
.ident()
305+
.map_or(*span, |ident| span.with_lo(ident.span.hi()));
301306
(
302307
self.r
303308
.session
304309
.source_map()
305-
.span_through_char(*span, '(')
310+
.span_through_char(span, '(')
306311
.shrink_to_hi(),
307312
"&self",
308313
)

library/alloc/tests/slice.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ fn test_splitator_inclusive() {
863863
assert_eq!(xs.split_inclusive(|_| true).collect::<Vec<&[i32]>>(), splits);
864864

865865
let xs: &[i32] = &[];
866-
let splits: &[&[i32]] = &[&[]];
866+
let splits: &[&[i32]] = &[];
867867
assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
868868
}
869869

@@ -883,7 +883,7 @@ fn test_splitator_inclusive_reverse() {
883883
assert_eq!(xs.split_inclusive(|_| true).rev().collect::<Vec<_>>(), splits);
884884

885885
let xs: &[i32] = &[];
886-
let splits: &[&[i32]] = &[&[]];
886+
let splits: &[&[i32]] = &[];
887887
assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
888888
}
889889

@@ -903,7 +903,7 @@ fn test_splitator_mut_inclusive() {
903903
assert_eq!(xs.split_inclusive_mut(|_| true).collect::<Vec<_>>(), splits);
904904

905905
let xs: &mut [i32] = &mut [];
906-
let splits: &[&[i32]] = &[&[]];
906+
let splits: &[&[i32]] = &[];
907907
assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
908908
}
909909

@@ -923,7 +923,7 @@ fn test_splitator_mut_inclusive_reverse() {
923923
assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits);
924924

925925
let xs: &mut [i32] = &mut [];
926-
let splits: &[&[i32]] = &[&[]];
926+
let splits: &[&[i32]] = &[];
927927
assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
928928
}
929929

library/core/src/slice/iter.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ where
481481
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> {
482482
#[inline]
483483
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
484-
Self { v: slice, pred, finished: false }
484+
let finished = slice.is_empty();
485+
Self { v: slice, pred, finished }
485486
}
486487
}
487488

@@ -729,7 +730,8 @@ where
729730
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> {
730731
#[inline]
731732
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
732-
Self { v: slice, pred, finished: false }
733+
let finished = slice.is_empty();
734+
Self { v: slice, pred, finished }
733735
}
734736
}
735737

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-pass
2+
// Tests equality between supertype and subtype of a function
3+
// See the issue #91636
4+
fn foo(_a: &str) {}
5+
6+
fn main() {
7+
let x = foo as fn(&'static str);
8+
let _ = x == foo;
9+
}

src/test/ui/issues/issue-87490.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn main() {}
2+
trait StreamOnce {
3+
type Position;
4+
}
5+
impl StreamOnce for &str {
6+
type Position = usize;
7+
}
8+
fn follow(_: &str) -> <&str as StreamOnce>::Position {
9+
String::new //~ ERROR mismatched types
10+
}

src/test/ui/issues/issue-87490.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-87490.rs:9:5
3+
|
4+
LL | fn follow(_: &str) -> <&str as StreamOnce>::Position {
5+
| ------------------------------ expected `usize` because of return type
6+
LL | String::new
7+
| ^^^^^^^^^^^ expected `usize`, found fn item
8+
|
9+
= note: expected type `usize`
10+
found fn item `fn() -> String {String::new}`
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0308`.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Regression test for issue #91725.
2+
//
3+
// run-pass
4+
// compile-flags: -Zmir-opt-level=4
5+
6+
fn main() {
7+
let a = true;
8+
let _ = &a;
9+
let mut b = false;
10+
b |= a;
11+
assert!(b);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
println!("{}", 1 <> 2);
3+
//~^ERROR invalid comparison operator `<>`
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: invalid comparison operator `<>`
2+
--> $DIR/less-than-greater-than.rs:2:22
3+
|
4+
LL | println!("{}", 1 <> 2);
5+
| ^^ help: `<>` is not a valid comparison operator, use `!=`
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
println!("{}", 1 <=> 2);
3+
//~^ERROR invalid comparison operator `<=>`
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: invalid comparison operator `<=>`
2+
--> $DIR/spaceship.rs:2:22
3+
|
4+
LL | println!("{}", 1 <=> 2);
5+
| ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
struct X(i32);
2+
3+
impl X {
4+
pub(crate) fn f() {
5+
self.0
6+
//~^ ERROR expected value, found module `self`
7+
}
8+
9+
pub fn g() {
10+
self.0
11+
//~^ ERROR expected value, found module `self`
12+
}
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0424]: expected value, found module `self`
2+
--> $DIR/suggest-add-self.rs:5:9
3+
|
4+
LL | pub(crate) fn f() {
5+
| - this function doesn't have a `self` parameter
6+
LL | self.0
7+
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
8+
|
9+
help: add a `self` receiver parameter to make the associated `fn` a method
10+
|
11+
LL | pub(crate) fn f(&self) {
12+
| +++++
13+
14+
error[E0424]: expected value, found module `self`
15+
--> $DIR/suggest-add-self.rs:10:9
16+
|
17+
LL | pub fn g() {
18+
| - this function doesn't have a `self` parameter
19+
LL | self.0
20+
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
21+
|
22+
help: add a `self` receiver parameter to make the associated `fn` a method
23+
|
24+
LL | pub fn g(&self) {
25+
| +++++
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0424`.

0 commit comments

Comments
 (0)