@@ -16,6 +16,7 @@ use rustc::traits::ObligationCause;
1616use syntax:: ast;
1717use syntax_pos:: { self , Span } ;
1818use rustc:: hir;
19+ use rustc:: hir:: print;
1920use rustc:: hir:: def:: Def ;
2021use rustc:: ty:: { self , Ty , AssociatedItem } ;
2122use errors:: { DiagnosticBuilder , CodeMapper } ;
@@ -94,6 +95,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9495 let cause = self . misc ( expr. span ) ;
9596 let expr_ty = self . resolve_type_vars_with_obligations ( checked_ty) ;
9697 let mut err = self . report_mismatched_types ( & cause, expected, expr_ty, e) ;
98+
99+ // If the expected type is an enum with any variants whose sole
100+ // field is of the found type, suggest such variants. See Issue
101+ // #42764.
102+ if let ty:: TyAdt ( expected_adt, substs) = expected. sty {
103+ let mut compatible_variants = vec ! [ ] ;
104+ for variant in & expected_adt. variants {
105+ if variant. fields . len ( ) == 1 {
106+ let sole_field = & variant. fields [ 0 ] ;
107+ let sole_field_ty = sole_field. ty ( self . tcx , substs) ;
108+ if self . can_coerce ( expr_ty, sole_field_ty) {
109+ compatible_variants. push ( variant. name ) ;
110+ }
111+ }
112+ }
113+ if !compatible_variants. is_empty ( ) {
114+ let expr_text = print:: to_string ( print:: NO_ANN , |s| s. print_expr ( expr) ) ;
115+ let suggestions = compatible_variants. iter ( )
116+ . map ( |v| format ! ( "{}({})" , v, expr_text) ) . collect :: < Vec < _ > > ( ) ;
117+ err. span_suggestions ( expr. span ,
118+ "perhaps you meant to use a variant of the expected type" ,
119+ suggestions) ;
120+ return Some ( err) ;
121+ }
122+ }
123+
97124 if let Some ( suggestion) = self . check_ref ( expr,
98125 checked_ty,
99126 expected) {
0 commit comments