@@ -168,7 +168,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
168168 let Ok ( ( ) ) = self . visit_land ( ex, & mut chain_refutabilities) else { return } ;
169169 // Lint only single irrefutable let binding.
170170 if let [ Some ( ( _, Irrefutable ) ) ] = chain_refutabilities[ ..] {
171- self . lint_single_let ( ex. span , None ) ;
171+ self . lint_single_let ( ex. span , None , None ) ;
172172 }
173173 return ;
174174 }
@@ -438,7 +438,40 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
438438 if let LetSource :: PlainLet = self . let_source {
439439 self . check_binding_is_irrefutable ( pat, "local binding" , scrut, Some ( span) ) ;
440440 } else if let Ok ( Irrefutable ) = self . is_let_irrefutable ( pat, scrut) {
441- self . lint_single_let ( span, else_span) ;
441+ let let_else_span = self . check_irrefutable_option_some ( pat, scrut, span) ;
442+
443+ let sm = self . tcx . sess . source_map ( ) ;
444+ let next_token_start = sm. span_extend_while_whitespace ( span. clone ( ) ) . hi ( ) ;
445+ let line_span = sm. span_extend_to_line ( span. clone ( ) ) . with_lo ( next_token_start) ;
446+ let else_keyword_span = sm. span_until_whitespace ( line_span) ;
447+ self . lint_single_let ( pat. span , Some ( else_keyword_span) , let_else_span) ;
448+ }
449+ }
450+
451+ fn check_irrefutable_option_some (
452+ & self ,
453+ pat : & ' p Pat < ' tcx > ,
454+ initializer : Option < & Expr < ' tcx > > ,
455+ span : Span ,
456+ ) -> Option < BeReplacedLetElse > {
457+ if let sm = self . tcx . sess . source_map ( )
458+ && let Some ( initializer) = initializer
459+ && let Some ( s_ty) = initializer. ty . ty_adt_def ( )
460+ && self . tcx . is_diagnostic_item ( rustc_span:: sym:: Option , s_ty. did ( ) )
461+ && let ExprKind :: Scope { value, .. } = initializer. kind
462+ && let initializer_expr = & self . thir [ value]
463+ && let ExprKind :: Adt ( box AdtExpr { fields, .. } ) = & initializer_expr. kind
464+ && let Some ( field) = fields. first ( )
465+ && let inner = & self . thir [ field. expr ]
466+ && let Some ( inner_ty) = inner. ty . ty_adt_def ( )
467+ && self . tcx . is_diagnostic_item ( rustc_span:: sym:: Option , inner_ty. did ( ) )
468+ && let Ok ( rhs) = sm. span_to_snippet ( inner. span )
469+ && let Ok ( lhs) = sm. span_to_snippet ( pat. span )
470+ {
471+ let lhs = format ! ( "Some({})" , lhs) ;
472+ Some ( BeReplacedLetElse { span, lhs, rhs } )
473+ } else {
474+ None
442475 }
443476 }
444477
@@ -546,14 +579,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
546579 }
547580
548581 #[ instrument( level = "trace" , skip( self ) ) ]
549- fn lint_single_let ( & mut self , let_span : Span , else_span : Option < Span > ) {
582+ fn lint_single_let (
583+ & mut self ,
584+ let_span : Span ,
585+ else_keyword_span : Option < Span > ,
586+ let_else_span : Option < BeReplacedLetElse > ,
587+ ) {
550588 report_irrefutable_let_patterns (
551589 self . tcx ,
552590 self . hir_source ,
553591 self . let_source ,
554592 1 ,
555593 let_span,
556- else_span,
594+ else_keyword_span,
595+ let_else_span,
557596 ) ;
558597 }
559598
@@ -849,7 +888,8 @@ fn report_irrefutable_let_patterns(
849888 source : LetSource ,
850889 count : usize ,
851890 span : Span ,
852- else_span : Option < Span > ,
891+ else_keyword_span : Option < Span > ,
892+ let_else_span : Option < BeReplacedLetElse > ,
853893) {
854894 macro_rules! emit_diag {
855895 ( $lint: tt) => { {
@@ -862,11 +902,23 @@ fn report_irrefutable_let_patterns(
862902 LetSource :: IfLet | LetSource :: ElseIfLet => emit_diag ! ( IrrefutableLetPatternsIfLet ) ,
863903 LetSource :: IfLetGuard => emit_diag ! ( IrrefutableLetPatternsIfLetGuard ) ,
864904 LetSource :: LetElse => {
905+ let spans = match else_keyword_span {
906+ Some ( else_keyword_span) => {
907+ let mut spans = MultiSpan :: from_span ( else_keyword_span) ;
908+ spans. push_span_label (
909+ span,
910+ msg ! ( "assigning to binding pattern will always succeed" ) ,
911+ ) ;
912+ spans
913+ }
914+ None => span. into ( ) ,
915+ } ;
916+
865917 tcx. emit_node_span_lint (
866918 IRREFUTABLE_LET_PATTERNS ,
867919 id,
868- span ,
869- IrrefutableLetPatternsLetElse { count , else_span } ,
920+ spans ,
921+ IrrefutableLetPatternsLetElse { be_replaced : let_else_span } ,
870922 ) ;
871923 }
872924 LetSource :: WhileLet => emit_diag ! ( IrrefutableLetPatternsWhileLet ) ,
0 commit comments