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).
This commit is contained in:
commit
a2a3074fb3
@ -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"),
|
||||
|
20
src/test/compile-fail/binary-op-on-double-ref.rs
Normal file
20
src/test/compile-fail/binary-op-on-double-ref.rs
Normal file
@ -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);
|
||||
}
|
18
src/test/compile-fail/str-concat-on-double-ref.rs
Normal file
18
src/test/compile-fail/str-concat-on-double-ref.rs
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user