@@ -3365,4 +3365,113 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3365
3365
err. span_label ( block. span , "this block is missing a tail expression" ) ;
3366
3366
}
3367
3367
}
3368
+
3369
+ pub ( crate ) fn annotate_incorrect_or_expr (
3370
+ & self ,
3371
+ diag : & mut Diag < ' _ > ,
3372
+ expr : & ' tcx hir:: Expr < ' tcx > ,
3373
+ expr_ty : Ty < ' tcx > ,
3374
+ expected_ty : Ty < ' tcx > ,
3375
+ ) {
3376
+ if expected_ty != self . tcx . types . bool {
3377
+ return ;
3378
+ }
3379
+ let hir:: Node :: Expr ( & hir:: Expr {
3380
+ kind :
3381
+ hir:: ExprKind :: Binary (
3382
+ hir:: BinOp { node : hir:: BinOpKind :: Or , span : binop_span } ,
3383
+ lhs,
3384
+ rhs,
3385
+ ) ,
3386
+ hir_id : parent_hir_id,
3387
+ span : full_span,
3388
+ ..
3389
+ } ) = self . tcx . parent_hir_node ( expr. hir_id )
3390
+ else {
3391
+ return ;
3392
+ } ;
3393
+ if rhs. hir_id != expr. hir_id {
3394
+ return ;
3395
+ }
3396
+ let hir:: Expr {
3397
+ kind :
3398
+ hir:: ExprKind :: Binary ( hir:: BinOp { node : hir:: BinOpKind :: Eq , span : eq_span } , lhs, _) ,
3399
+ ..
3400
+ } = * lhs
3401
+ else {
3402
+ return ;
3403
+ } ;
3404
+ let Some ( lhs_ty) = self . typeck_results . borrow ( ) . expr_ty_opt ( lhs) else {
3405
+ return ;
3406
+ } ;
3407
+ // Coercion here is not totally right, but w/e.
3408
+ if !self . can_coerce ( expr_ty, lhs_ty) {
3409
+ return ;
3410
+ }
3411
+
3412
+ // Track whether all of the exprs to the right, i.e. `|| a || b || c` are all pattern-like.
3413
+ let mut is_literal = rhs. is_approximately_pattern ( ) ;
3414
+ // Track the span of the outermost `||` expr.
3415
+ let mut full_span = full_span;
3416
+
3417
+ // Walk up the expr tree gathering up the binop spans of any subsequent `|| a || b || c`.
3418
+ let mut expr_hir_id = parent_hir_id;
3419
+ let mut binop_spans = vec ! [ binop_span] ;
3420
+ while let hir:: Node :: Expr ( & hir:: Expr {
3421
+ kind :
3422
+ hir:: ExprKind :: Binary (
3423
+ hir:: BinOp { node : hir:: BinOpKind :: Or , span : binop_span } ,
3424
+ lhs,
3425
+ rhs,
3426
+ ) ,
3427
+ hir_id : parent_hir_id,
3428
+ span,
3429
+ ..
3430
+ } ) = self . tcx . parent_hir_node ( expr_hir_id)
3431
+ && lhs. hir_id == expr_hir_id
3432
+ {
3433
+ binop_spans. push ( binop_span) ;
3434
+ expr_hir_id = parent_hir_id;
3435
+ full_span = span;
3436
+ is_literal |= rhs. is_approximately_pattern ( ) ;
3437
+ }
3438
+
3439
+ // If the type is structural peq, then suggest `matches!(x, a | b | c)`.
3440
+ // Otherwise, suggest adding `x == ` to every `||`.
3441
+ if is_literal
3442
+ // I know this logic may look a bit sketchy, but int vars don't implement
3443
+ // `StructuralPeq` b/c they're unconstrained, so just check for those manually.
3444
+ && ( self . tcx . lang_items ( ) . structural_peq_trait ( ) . is_some_and ( |structural_peq_def_id| {
3445
+ self . type_implements_trait ( structural_peq_def_id, [ lhs_ty] , self . param_env )
3446
+ . must_apply_modulo_regions ( )
3447
+ } ) || lhs_ty. is_integral ( ) )
3448
+ {
3449
+ let eq_span = lhs. span . shrink_to_hi ( ) . to ( eq_span) ;
3450
+ diag. multipart_suggestion_verbose (
3451
+ "use `matches!()` to match against multiple values" ,
3452
+ [
3453
+ ( full_span. shrink_to_lo ( ) , "matches!(" . to_string ( ) ) ,
3454
+ ( full_span. shrink_to_hi ( ) , ")" . to_string ( ) ) ,
3455
+ ( eq_span, "," . to_string ( ) ) ,
3456
+ ]
3457
+ . into_iter ( )
3458
+ . chain ( binop_spans. into_iter ( ) . map ( |span| ( span, "|" . to_string ( ) ) ) )
3459
+ . collect ( ) ,
3460
+ Applicability :: MachineApplicable ,
3461
+ ) ;
3462
+ } else if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = lhs. kind
3463
+ && let Res :: Local ( local) = path. res
3464
+ {
3465
+ let local = self . tcx . hir ( ) . name ( local) ;
3466
+ let local_name = format ! ( " {local} ==" ) ;
3467
+ diag. multipart_suggestion_verbose (
3468
+ "use `matches!()` to match against multiple values" ,
3469
+ binop_spans
3470
+ . into_iter ( )
3471
+ . map ( |span| ( span. shrink_to_hi ( ) , local_name. clone ( ) ) )
3472
+ . collect ( ) ,
3473
+ Applicability :: MachineApplicable ,
3474
+ ) ;
3475
+ }
3476
+ }
3368
3477
}
0 commit comments