@@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
676676 }
677677 } else {
678678 // Pattern has wrong number of fields.
679- self . e0023 ( pat. span , res, & subpats, & variant. fields , expected) ;
679+ self . e0023 ( pat. span , res, qpath , subpats, & variant. fields , expected) ;
680680 on_error ( ) ;
681681 return tcx. types . err ;
682682 }
@@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
687687 & self ,
688688 pat_span : Span ,
689689 res : Res ,
690+ qpath : & hir:: QPath ,
690691 subpats : & ' tcx [ P < Pat > ] ,
691692 fields : & [ ty:: FieldDef ] ,
692693 expected : Ty < ' tcx >
693694 ) {
694695 let subpats_ending = pluralise ! ( subpats. len( ) ) ;
695696 let fields_ending = pluralise ! ( fields. len( ) ) ;
696- let missing_parenthesis = match expected. sty {
697- ty:: Adt ( _, substs) if fields. len ( ) == 1 => {
698- let field_ty = fields[ 0 ] . ty ( self . tcx , substs) ;
699- match field_ty. sty {
700- ty:: Tuple ( _) => field_ty. tuple_fields ( ) . count ( ) == subpats. len ( ) ,
701- _ => false ,
702- }
703- }
704- _ => false ,
705- } ;
706697 let res_span = self . tcx . def_span ( res. def_id ( ) ) ;
707698 let mut err = struct_span_err ! (
708699 self . tcx. sess,
@@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
723714 ) )
724715 . span_label ( res_span, format ! ( "{} defined here" , res. descr( ) ) ) ;
725716
717+ // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
718+ // More generally, the expected type wants a tuple variant with one field of an
719+ // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
720+ // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
721+ let missing_parenthesis = match expected. sty {
722+ ty:: Adt ( _, substs) if fields. len ( ) == 1 => {
723+ let field_ty = fields[ 0 ] . ty ( self . tcx , substs) ;
724+ match field_ty. sty {
725+ ty:: Tuple ( _) => field_ty. tuple_fields ( ) . count ( ) == subpats. len ( ) ,
726+ _ => false ,
727+ }
728+ }
729+ _ => false ,
730+ } ;
726731 if missing_parenthesis {
732+ let ( left, right) = match subpats {
733+ // This is the zero case; we aim to get the "hi" part of the `QPath`'s
734+ // span as the "lo" and then the "hi" part of the pattern's span as the "hi".
735+ // This looks like:
736+ //
737+ // help: missing parenthesis
738+ // |
739+ // L | let A(()) = A(());
740+ // | ^ ^
741+ [ ] => {
742+ let qpath_span = match qpath {
743+ hir:: QPath :: Resolved ( _, path) => path. span ,
744+ hir:: QPath :: TypeRelative ( _, ps) => ps. ident . span ,
745+ } ;
746+ ( qpath_span. shrink_to_hi ( ) , pat_span)
747+ } ,
748+ // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
749+ // last sub-pattern. In the case of `A(x)` the first and last may coincide.
750+ // This looks like:
751+ //
752+ // help: missing parenthesis
753+ // |
754+ // L | let A((x, y)) = A((1, 2));
755+ // | ^ ^
756+ [ first, ..] => ( first. span . shrink_to_lo ( ) , subpats. last ( ) . unwrap ( ) . span ) ,
757+ } ;
727758 err. multipart_suggestion (
728759 "missing parenthesis" ,
729- vec ! [ ( subpats[ 0 ] . span. shrink_to_lo( ) , "(" . to_string( ) ) ,
730- ( subpats[ subpats. len( ) -1 ] . span. shrink_to_hi( ) , ")" . to_string( ) ) ] ,
760+ vec ! [
761+ ( left, "(" . to_string( ) ) ,
762+ ( right. shrink_to_hi( ) , ")" . to_string( ) ) ,
763+ ] ,
731764 Applicability :: MachineApplicable ,
732765 ) ;
733766 }
0 commit comments