@@ -16,6 +16,7 @@ use rustc::traits::ObligationCause;
16
16
use syntax:: ast;
17
17
use syntax_pos:: { self , Span } ;
18
18
use rustc:: hir;
19
+ use rustc:: hir:: print;
19
20
use rustc:: hir:: def:: Def ;
20
21
use rustc:: ty:: { self , Ty , AssociatedItem } ;
21
22
use errors:: { DiagnosticBuilder , CodeMapper } ;
@@ -94,6 +95,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
94
95
let cause = self . misc ( expr. span ) ;
95
96
let expr_ty = self . resolve_type_vars_with_obligations ( checked_ty) ;
96
97
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
+
97
124
if let Some ( suggestion) = self . check_ref ( expr,
98
125
checked_ty,
99
126
expected) {
0 commit comments