Skip to content

Commit

Permalink
Auto merge of rust-lang#91933 - matthiaskrgr:rollup-cw9qolb, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#89825 (Make split_inclusive() on an empty slice yield an empty output)
 - rust-lang#91239 (regression test for issue 87490)
 - rust-lang#91597 (Recover on invalid operators `<>` and `<=>`)
 - rust-lang#91774 (Fix typo for MutVisitor)
 - rust-lang#91786 (Return an error when `eval_rvalue_with_identities` fails)
 - rust-lang#91798 (Avoid suggest adding `self` in visibility spec)
 - rust-lang#91856 (Looser check for overflowing_binary_op)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 15, 2021
2 parents 2f4da62 + bae9270 commit d594910
Show file tree
Hide file tree
Showing 17 changed files with 198 additions and 63 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor`
//! mutates it in place. So, for instance, macro expansion is a `MutVisitor`
//! that walks over an AST and modifies it.
//!
//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_const_eval/src/interpret/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.binary_int_op(bin_op, l, left.layout, r, right.layout)
}
_ if left.layout.ty.is_any_ptr() => {
// The RHS type must be the same *or an integer type* (for `Offset`).
// The RHS type must be a `pointer` *or an integer type* (for `Offset`).
// (Even when both sides are pointers, their type might differ, see issue #91636)
assert!(
right.layout.ty == left.layout.ty || right.layout.ty.is_integral(),
right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(),
"Unexpected types for BinOp: {:?} {:?} {:?}",
left.layout.ty,
bin_op,
Expand Down
86 changes: 34 additions & 52 deletions compiler/rustc_mir_transform/src/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,62 +752,44 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
rvalue: &Rvalue<'tcx>,
place: Place<'tcx>,
) -> Option<()> {
self.use_ecx(|this| {
match rvalue {
Rvalue::BinaryOp(op, box (left, right))
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
let l = this.ecx.eval_operand(left, None);
let r = this.ecx.eval_operand(right, None);

let const_arg = match (l, r) {
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
(Err(e), Err(_)) => return Err(e),
(Ok(_), Ok(_)) => {
this.ecx.eval_rvalue_into_place(rvalue, place)?;
return Ok(());
}
};

let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
let dest = this.ecx.eval_place(place)?;

match op {
BinOp::BitAnd => {
if arg_value == 0 {
this.ecx.write_immediate(*const_arg, &dest)?;
}
}
BinOp::BitOr => {
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
{
this.ecx.write_immediate(*const_arg, &dest)?;
}
}
BinOp::Mul => {
if const_arg.layout.ty.is_integral() && arg_value == 0 {
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
let val = Immediate::ScalarPair(
const_arg.to_scalar()?.into(),
Scalar::from_bool(false).into(),
);
this.ecx.write_immediate(val, &dest)?;
} else {
this.ecx.write_immediate(*const_arg, &dest)?;
}
}
}
_ => {
this.ecx.eval_rvalue_into_place(rvalue, place)?;
self.use_ecx(|this| match rvalue {
Rvalue::BinaryOp(op, box (left, right))
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
let l = this.ecx.eval_operand(left, None);
let r = this.ecx.eval_operand(right, None);

let const_arg = match (l, r) {
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
(Err(e), Err(_)) => return Err(e),
(Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place),
};

let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
let dest = this.ecx.eval_place(place)?;

match op {
BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest),
BinOp::BitOr
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|| (const_arg.layout.ty.is_bool() && arg_value == 1) =>
{
this.ecx.write_immediate(*const_arg, &dest)
}
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
let val = Immediate::ScalarPair(
const_arg.to_scalar()?.into(),
Scalar::from_bool(false).into(),
);
this.ecx.write_immediate(val, &dest)
} else {
this.ecx.write_immediate(*const_arg, &dest)
}
}
}
_ => {
this.ecx.eval_rvalue_into_place(rvalue, place)?;
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
}
}

Ok(())
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
})
}

Expand Down
34 changes: 33 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,11 @@ impl<'a> Parser<'a> {
}
}

// Look for JS' `===` and `!==` and recover
if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual)
&& self.token.kind == token::Eq
&& self.prev_token.span.hi() == self.token.span.lo()
{
// Look for JS' `===` and `!==` and recover 😇
let sp = op.span.to(self.token.span);
let sugg = match op.node {
AssocOp::Equal => "==",
Expand All @@ -235,6 +235,38 @@ impl<'a> Parser<'a> {
self.bump();
}

// Look for PHP's `<>` and recover
if op.node == AssocOp::Less
&& self.token.kind == token::Gt
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
self.struct_span_err(sp, "invalid comparison operator `<>`")
.span_suggestion_short(
sp,
"`<>` is not a valid comparison operator, use `!=`",
"!=".to_string(),
Applicability::MachineApplicable,
)
.emit();
self.bump();
}

// Look for C++'s `<=>` and recover
if op.node == AssocOp::LessEqual
&& self.token.kind == token::Gt
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
self.struct_span_err(sp, "invalid comparison operator `<=>`")
.span_label(
sp,
"`<=>` is not a valid comparison operator, use `std::cmp::Ordering`",
)
.emit();
self.bump();
}

let op = op.node;
// Special cases:
if op == AssocOp::As {
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.get(0)
.map(|p| (p.span.shrink_to_lo(), "&self, "))
.unwrap_or_else(|| {
// Try to look for the "(" after the function name, if possible.
// This avoids placing the suggestion into the visibility specifier.
let span = fn_kind
.ident()
.map_or(*span, |ident| span.with_lo(ident.span.hi()));
(
self.r
.session
.source_map()
.span_through_char(*span, '(')
.span_through_char(span, '(')
.shrink_to_hi(),
"&self",
)
Expand Down
8 changes: 4 additions & 4 deletions library/alloc/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ fn test_splitator_inclusive() {
assert_eq!(xs.split_inclusive(|_| true).collect::<Vec<&[i32]>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[&[]];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
}

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

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

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

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

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

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

Expand Down
6 changes: 4 additions & 2 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,8 @@ where
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> {
#[inline]
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
Self { v: slice, pred, finished: false }
let finished = slice.is_empty();
Self { v: slice, pred, finished }
}
}

Expand Down Expand Up @@ -729,7 +730,8 @@ where
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> {
#[inline]
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
Self { v: slice, pred, finished: false }
let finished = slice.is_empty();
Self { v: slice, pred, finished }
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/binop/binary-op-on-fn-ptr-eq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// run-pass
// Tests equality between supertype and subtype of a function
// See the issue #91636
fn foo(_a: &str) {}

fn main() {
let x = foo as fn(&'static str);
let _ = x == foo;
}
10 changes: 10 additions & 0 deletions src/test/ui/issues/issue-87490.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn main() {}
trait StreamOnce {
type Position;
}
impl StreamOnce for &str {
type Position = usize;
}
fn follow(_: &str) -> <&str as StreamOnce>::Position {
String::new //~ ERROR mismatched types
}
14 changes: 14 additions & 0 deletions src/test/ui/issues/issue-87490.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/issue-87490.rs:9:5
|
LL | fn follow(_: &str) -> <&str as StreamOnce>::Position {
| ------------------------------ expected `usize` because of return type
LL | String::new
| ^^^^^^^^^^^ expected `usize`, found fn item
|
= note: expected type `usize`
found fn item `fn() -> String {String::new}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
12 changes: 12 additions & 0 deletions src/test/ui/mir/mir_const_prop_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Regression test for issue #91725.
//
// run-pass
// compile-flags: -Zmir-opt-level=4

fn main() {
let a = true;
let _ = &a;
let mut b = false;
b |= a;
assert!(b);
}
4 changes: 4 additions & 0 deletions src/test/ui/operator-recovery/less-than-greater-than.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
println!("{}", 1 <> 2);
//~^ERROR invalid comparison operator `<>`
}
8 changes: 8 additions & 0 deletions src/test/ui/operator-recovery/less-than-greater-than.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: invalid comparison operator `<>`
--> $DIR/less-than-greater-than.rs:2:22
|
LL | println!("{}", 1 <> 2);
| ^^ help: `<>` is not a valid comparison operator, use `!=`

error: aborting due to previous error

4 changes: 4 additions & 0 deletions src/test/ui/operator-recovery/spaceship.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
println!("{}", 1 <=> 2);
//~^ERROR invalid comparison operator `<=>`
}
8 changes: 8 additions & 0 deletions src/test/ui/operator-recovery/spaceship.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: invalid comparison operator `<=>`
--> $DIR/spaceship.rs:2:22
|
LL | println!("{}", 1 <=> 2);
| ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering`

error: aborting due to previous error

15 changes: 15 additions & 0 deletions src/test/ui/suggestions/suggest-add-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
struct X(i32);

impl X {
pub(crate) fn f() {
self.0
//~^ ERROR expected value, found module `self`
}

pub fn g() {
self.0
//~^ ERROR expected value, found module `self`
}
}

fn main() {}
29 changes: 29 additions & 0 deletions src/test/ui/suggestions/suggest-add-self.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0424]: expected value, found module `self`
--> $DIR/suggest-add-self.rs:5:9
|
LL | pub(crate) fn f() {
| - this function doesn't have a `self` parameter
LL | self.0
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
help: add a `self` receiver parameter to make the associated `fn` a method
|
LL | pub(crate) fn f(&self) {
| +++++

error[E0424]: expected value, found module `self`
--> $DIR/suggest-add-self.rs:10:9
|
LL | pub fn g() {
| - this function doesn't have a `self` parameter
LL | self.0
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
help: add a `self` receiver parameter to make the associated `fn` a method
|
LL | pub fn g(&self) {
| +++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0424`.

0 comments on commit d594910

Please sign in to comment.