]> git.lizzy.rs Git - rust.git/commitdiff
Detect double reference when applying binary op
authorEsteban Küber <esteban@kuber.com.ar>
Thu, 23 Jun 2016 01:29:16 +0000 (18:29 -0700)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Tue, 3 Jan 2017 15:05:20 +0000 (10:05 -0500)
```rust
let vr = v.iter().filter(|x| {
    x % 2 == 0
});
```

will now yield the following compiler output:

```bash
ERROR binary operation `%` cannot be applied to type `&&_`
NOTE this is a reference of a reference to a type that `%` can be applied to,
you need to dereference this variable once for this operation to work
NOTE an implementation of `std::ops::Rem` might be missing for `&&_`
```

The first NOTE is new.

Bug #33877

src/librustc_typeck/check/op.rs
src/test/compile-fail/binary-op-on-double-ref.rs [new file with mode: 0644]
src/test/compile-fail/str-concat-on-double-ref.rs [new file with mode: 0644]

index d1a9b8ef85ae48e5c990b55cec9d9825dc4c57ac..4202f65c44d4f1eba7b7bdd30b1522e410c2ad2b 100644 (file)
@@ -12,7 +12,7 @@
 
 use super::FnCtxt;
 use hir::def_id::DefId;
-use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue};
+use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue, TypeVariants};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use syntax::ast;
 use syntax::symbol::Symbol;
@@ -204,6 +204,21 @@ fn check_overloaded_binop(&self,
                             "binary operation `{}` cannot be applied to type `{}`",
                             op.node.as_str(),
                             lhs_ty);
+
+                        if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
+                            if self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty_var],
+                                    token::intern(name), trait_def_id,
+                                    lhs_expr).is_ok() {
+                                err.span_note(
+                                    lhs_expr.span,
+                                    &format!(
+                                        "this is a reference of type that `{}` can be applied to, \
+                                        you need to dereference this variable once for this \
+                                        operation to work",
+                                    op.node.as_str()));
+                            }
+                        }
+
                         let missing_trait = match op.node {
                             hir::BiAdd    => Some("std::ops::Add"),
                             hir::BiSub    => Some("std::ops::Sub"),
diff --git a/src/test/compile-fail/binary-op-on-double-ref.rs b/src/test/compile-fail/binary-op-on-double-ref.rs
new file mode 100644 (file)
index 0000000..5cc8e0f
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
+    let vr = v.iter().filter(|x| {
+        x % 2 == 0
+        //~^ ERROR binary operation `%` cannot be applied to type `&&_`
+        //~| NOTE this is a reference of type that `%` can be applied to
+        //~| NOTE an implementation of `std::ops::Rem` might be missing for `&&_`
+    });
+    println!("{:?}", vr);
+}
diff --git a/src/test/compile-fail/str-concat-on-double-ref.rs b/src/test/compile-fail/str-concat-on-double-ref.rs
new file mode 100644 (file)
index 0000000..d79ab6b
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let a: &String = &"1".to_owned();
+    let b: &str = &"2";
+    let c = a + b;
+    //~^ ERROR binary operation `+` cannot be applied to type `&std::string::String`
+    //~| NOTE this is a reference of type that `+` can be applied to
+    //~| NOTE an implementation of `std::ops::Add` might be missing for `&std::string::String`
+    println!("{:?}", c);
+}