diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2017-01-27 14:41:09 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2017-01-27 16:41:49 -0800 |
| commit | a2a3074fb3ae6c1e7f0ccb6b111f3e16f9312f8f (patch) | |
| tree | 50ee89fae80b4f34af743050c29a128f978be283 | |
| parent | 154c202afb256c379b7d454ec0244da69eaa2ced (diff) | |
| parent | b8669dff556a03ca37b39cbb81be65c94d24defe (diff) | |
| download | rust-a2a3074fb3ae6c1e7f0ccb6b111f3e16f9312f8f.tar.gz rust-a2a3074fb3ae6c1e7f0ccb6b111f3e16f9312f8f.zip | |
Rollup merge of #38617 - pnkfelix:double-reference, r=pnkfelix
Detect double reference when applying binary op
``` 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.
Fix #33877
----
Thanks to @estebank for providing the original PR #34420 (of which this is a tweaked rebase).
| -rw-r--r-- | src/librustc_typeck/check/op.rs | 18 | ||||
| -rw-r--r-- | src/test/compile-fail/binary-op-on-double-ref.rs | 20 | ||||
| -rw-r--r-- | src/test/compile-fail/str-concat-on-double-ref.rs | 18 |
3 files changed, 55 insertions, 1 deletions
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d1a9b8ef85a..925d28247b6 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -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,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "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.infcx.type_moves_by_default(ty_mut.ty, lhs_expr.span) && + self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty_var], + Symbol::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 index 00000000000..a49cfaa1760 --- /dev/null +++ b/src/test/compile-fail/binary-op-on-double-ref.rs @@ -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 `&&{integer}` + //~| NOTE this is a reference of type that `%` can be applied to + //~| NOTE an implementation of `std::ops::Rem` might be missing for `&&{integer}` + }); + 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 index 00000000000..f85422f76d4 --- /dev/null +++ b/src/test/compile-fail/str-concat-on-double-ref.rs @@ -0,0 +1,18 @@ +// 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 an implementation of `std::ops::Add` might be missing for `&std::string::String` + println!("{:?}", c); +} |
