@@ -246,77 +246,92 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
246
246
Err ( ( ) ) => {
247
247
// error types are considered "builtin"
248
248
if !lhs_ty. references_error ( ) {
249
- if let IsAssign :: Yes = is_assign {
250
- struct_span_err ! ( self . tcx. sess, expr. span, E0368 ,
251
- "binary assignment operation `{}=` \
252
- cannot be applied to type `{}`",
253
- op. node. as_str( ) ,
254
- lhs_ty)
255
- . span_label ( lhs_expr. span ,
256
- format ! ( "cannot use `{}=` on type `{}`" ,
257
- op. node. as_str( ) , lhs_ty) )
258
- . emit ( ) ;
259
- } else {
260
- let mut err = struct_span_err ! ( self . tcx. sess, expr. span, E0369 ,
261
- "binary operation `{}` cannot be applied to type `{}`" ,
262
- op. node. as_str( ) ,
263
- lhs_ty) ;
264
-
265
- if let TypeVariants :: TyRef ( _, ref ty_mut) = lhs_ty. sty {
266
- if {
267
- !self . infcx . type_moves_by_default ( self . param_env ,
268
- ty_mut. ty ,
269
- lhs_expr. span ) &&
270
- self . lookup_op_method ( ty_mut. ty ,
271
- & [ rhs_ty] ,
272
- Op :: Binary ( op, is_assign) )
273
- . is_ok ( )
274
- } {
275
- err. note (
276
- & format ! (
277
- "this is a reference to a type that `{}` can be applied \
278
- to; you need to dereference this variable once for this \
279
- operation to work",
280
- op. node. as_str( ) ) ) ;
281
- }
249
+ let ( mut err, missing_trait) = match is_assign{
250
+ IsAssign :: Yes => {
251
+ let mut err = struct_span_err ! ( self . tcx. sess, expr. span, E0368 ,
252
+ "binary assignment operation `{}=` \
253
+ cannot be applied to type `{}`",
254
+ op. node. as_str( ) ,
255
+ lhs_ty) ;
256
+ err. span_label ( lhs_expr. span ,
257
+ format ! ( "cannot use `{}=` on type `{}`" ,
258
+ op. node. as_str( ) , lhs_ty) ) ;
259
+ let missing_trait = match op. node {
260
+ hir:: BiAdd => Some ( "std::ops::AddAssign" ) ,
261
+ hir:: BiSub => Some ( "std::ops::SubAssign" ) ,
262
+ hir:: BiMul => Some ( "std::ops::MulAssign" ) ,
263
+ hir:: BiDiv => Some ( "std::ops::DivAssign" ) ,
264
+ hir:: BiRem => Some ( "std::ops::RemAssign" ) ,
265
+ hir:: BiBitAnd => Some ( "std::ops::BitAndAssign" ) ,
266
+ hir:: BiBitXor => Some ( "std::ops::BitXorAssign" ) ,
267
+ hir:: BiBitOr => Some ( "std::ops::BitOrAssign" ) ,
268
+ hir:: BiShl => Some ( "std::ops::ShlAssign" ) ,
269
+ hir:: BiShr => Some ( "std::ops::ShrAssign" ) ,
270
+ _ => None
271
+ } ;
272
+ ( err, missing_trait)
282
273
}
283
-
284
- let missing_trait = match op. node {
285
- hir:: BiAdd => Some ( "std::ops::Add" ) ,
286
- hir:: BiSub => Some ( "std::ops::Sub" ) ,
287
- hir:: BiMul => Some ( "std::ops::Mul" ) ,
288
- hir:: BiDiv => Some ( "std::ops::Div" ) ,
289
- hir:: BiRem => Some ( "std::ops::Rem" ) ,
290
- hir:: BiBitAnd => Some ( "std::ops::BitAnd" ) ,
291
- hir:: BiBitOr => Some ( "std::ops::BitOr" ) ,
292
- hir:: BiShl => Some ( "std::ops::Shl" ) ,
293
- hir:: BiShr => Some ( "std::ops::Shr" ) ,
294
- hir:: BiEq | hir:: BiNe => Some ( "std::cmp::PartialEq" ) ,
295
- hir:: BiLt | hir:: BiLe | hir:: BiGt | hir:: BiGe =>
296
- Some ( "std::cmp::PartialOrd" ) ,
297
- _ => None
298
- } ;
299
-
300
- if let Some ( missing_trait) = missing_trait {
301
- if missing_trait == "std::ops::Add" &&
302
- self . check_str_addition ( expr, lhs_expr, rhs_expr, lhs_ty,
303
- rhs_ty, & mut err) {
304
- // This has nothing here because it means we did string
305
- // concatenation (e.g. "Hello " + "World!"). This means
306
- // we don't want the note in the else clause to be emitted
307
- } else if let ty:: TyParam ( _) = lhs_ty. sty {
308
- // FIXME: point to span of param
309
- err. note (
310
- & format ! ( "`{}` might need a bound for `{}`" ,
311
- lhs_ty, missing_trait) ) ;
312
- } else {
313
- err. note (
314
- & format ! ( "an implementation of `{}` might be missing for `{}`" ,
315
- missing_trait, lhs_ty) ) ;
274
+ IsAssign :: No => {
275
+ let mut err = struct_span_err ! ( self . tcx. sess, expr. span, E0369 ,
276
+ "binary operation `{}` cannot be applied to type `{}`" ,
277
+ op. node. as_str( ) ,
278
+ lhs_ty) ;
279
+ let missing_trait = match op. node {
280
+ hir:: BiAdd => Some ( "std::ops::Add" ) ,
281
+ hir:: BiSub => Some ( "std::ops::Sub" ) ,
282
+ hir:: BiMul => Some ( "std::ops::Mul" ) ,
283
+ hir:: BiDiv => Some ( "std::ops::Div" ) ,
284
+ hir:: BiRem => Some ( "std::ops::Rem" ) ,
285
+ hir:: BiBitAnd => Some ( "std::ops::BitAnd" ) ,
286
+ hir:: BiBitXor => Some ( "std::ops::BitXor" ) ,
287
+ hir:: BiBitOr => Some ( "std::ops::BitOr" ) ,
288
+ hir:: BiShl => Some ( "std::ops::Shl" ) ,
289
+ hir:: BiShr => Some ( "std::ops::Shr" ) ,
290
+ hir:: BiEq | hir:: BiNe => Some ( "std::cmp::PartialEq" ) ,
291
+ hir:: BiLt | hir:: BiLe | hir:: BiGt | hir:: BiGe =>
292
+ Some ( "std::cmp::PartialOrd" ) ,
293
+ _ => None
294
+ } ;
295
+ if let TypeVariants :: TyRef ( _, ref ty_mut) = lhs_ty. sty {
296
+ if {
297
+ !self . infcx . type_moves_by_default ( self . param_env ,
298
+ ty_mut. ty ,
299
+ lhs_expr. span ) &&
300
+ self . lookup_op_method ( ty_mut. ty ,
301
+ & [ rhs_ty] ,
302
+ Op :: Binary ( op, is_assign) )
303
+ . is_ok ( )
304
+ } {
305
+ err. note (
306
+ & format ! (
307
+ "this is a reference to a type that `{}` can be \
308
+ applied to; you need to dereference this variable \
309
+ once for this operation to work",
310
+ op. node. as_str( ) ) ) ;
311
+ }
316
312
}
313
+ ( err, missing_trait)
314
+ }
315
+ } ;
316
+ if let Some ( missing_trait) = missing_trait {
317
+ if missing_trait == "std::ops::Add" &&
318
+ self . check_str_addition ( expr, lhs_expr, rhs_expr, lhs_ty,
319
+ rhs_ty, & mut err) {
320
+ // This has nothing here because it means we did string
321
+ // concatenation (e.g. "Hello " + "World!"). This means
322
+ // we don't want the note in the else clause to be emitted
323
+ } else if let ty:: TyParam ( _) = lhs_ty. sty {
324
+ // FIXME: point to span of param
325
+ err. note (
326
+ & format ! ( "`{}` might need a bound for `{}`" ,
327
+ lhs_ty, missing_trait) ) ;
328
+ } else {
329
+ err. note (
330
+ & format ! ( "an implementation of `{}` might be missing for `{}`" ,
331
+ missing_trait, lhs_ty) ) ;
317
332
}
318
- err. emit ( ) ;
319
333
}
334
+ err. emit ( ) ;
320
335
}
321
336
self . tcx . types . err
322
337
}
@@ -393,9 +408,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
393
408
Err ( ( ) ) => {
394
409
let actual = self . resolve_type_vars_if_possible ( & operand_ty) ;
395
410
if !actual. references_error ( ) {
396
- struct_span_err ! ( self . tcx. sess, ex. span, E0600 ,
411
+ let mut err = struct_span_err ! ( self . tcx. sess, ex. span, E0600 ,
397
412
"cannot apply unary operator `{}` to type `{}`" ,
398
- op. as_str( ) , actual) . emit ( ) ;
413
+ op. as_str( ) , actual) ;
414
+ let missing_trait = match op {
415
+ hir:: UnNeg => "std::ops::Neg" ,
416
+ hir:: UnNot => "std::ops::Not" ,
417
+ hir:: UnDeref => "std::ops::UnDerf"
418
+ } ;
419
+ err. note ( & format ! ( "an implementation of `{}` might be missing for `{}`" ,
420
+ missing_trait, operand_ty) ) ;
421
+ err. emit ( ) ;
399
422
}
400
423
self . tcx . types . err
401
424
}
0 commit comments