@@ -1046,19 +1046,12 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
1046
1046
let ( synth_term, synth_type) = self . synth_and_insert_implicit_apps ( surface_term) ;
1047
1047
self . coerce ( surface_range, synth_term, & synth_type, & expected_type)
1048
1048
}
1049
- ( Term :: RecordLiteral ( _ , expr_fields) , Value :: RecordType ( labels, types) ) => {
1049
+ ( Term :: RecordLiteral ( range , expr_fields) , Value :: RecordType ( labels, types) ) => {
1050
1050
// TODO: improve handling of duplicate labels
1051
- if expr_fields . len ( ) != labels . len ( )
1052
- || Iterator :: zip ( expr_fields . iter ( ) , labels. iter ( ) )
1053
- . any ( | ( expr_field , type_label ) | expr_field . label . 1 != * type_label )
1051
+ if self
1052
+ . check_record_fields ( * range , expr_fields , |field| field . label , labels)
1053
+ . is_err ( )
1054
1054
{
1055
- self . push_message ( Message :: MismatchedFieldLabels {
1056
- range : file_range,
1057
- expr_labels : ( expr_fields. iter ( ) )
1058
- . map ( |ExprField { label, .. } | ( self . file_range ( label. 0 ) , label. 1 ) )
1059
- . collect ( ) ,
1060
- type_labels : labels. to_vec ( ) ,
1061
- } ) ;
1062
1055
return core:: Term :: Prim ( file_range. into ( ) , Prim :: ReportedError ) ;
1063
1056
}
1064
1057
@@ -1121,33 +1114,11 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
1121
1114
core:: Term :: FormatRecord ( file_range. into ( ) , labels, formats)
1122
1115
} )
1123
1116
}
1124
- ( Term :: Tuple ( _, elem_exprs) , Value :: RecordType ( labels, types) ) => {
1125
- if elem_exprs. len ( ) != labels. len ( ) {
1126
- let mut expr_labels = Vec :: with_capacity ( elem_exprs. len ( ) ) ;
1127
- let mut elem_exprs = elem_exprs. iter ( ) . enumerate ( ) . peekable ( ) ;
1128
- let mut label_iter = labels. iter ( ) ;
1129
-
1130
- // use the label names from the expected type
1131
- while let Some ( ( ( _, elem_expr) , label) ) =
1132
- Option :: zip ( elem_exprs. peek ( ) , label_iter. next ( ) )
1133
- {
1134
- expr_labels. push ( ( self . file_range ( elem_expr. range ( ) ) , * label) ) ;
1135
- elem_exprs. next ( ) ;
1136
- }
1137
-
1138
- // use numeric labels for excess elems
1139
- for ( index, elem_expr) in elem_exprs {
1140
- expr_labels. push ( (
1141
- self . file_range ( elem_expr. range ( ) ) ,
1142
- self . interner . borrow_mut ( ) . get_tuple_label ( index) ,
1143
- ) ) ;
1144
- }
1145
-
1146
- self . push_message ( Message :: MismatchedFieldLabels {
1147
- range : file_range,
1148
- expr_labels,
1149
- type_labels : labels. to_vec ( ) ,
1150
- } ) ;
1117
+ ( Term :: Tuple ( range, elem_exprs) , Value :: RecordType ( labels, types) ) => {
1118
+ if self
1119
+ . check_tuple_fields ( * range, elem_exprs, |term| term. range ( ) , labels)
1120
+ . is_err ( )
1121
+ {
1151
1122
return core:: Term :: Prim ( file_range. into ( ) , Prim :: ReportedError ) ;
1152
1123
}
1153
1124
@@ -2218,6 +2189,76 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
2218
2189
( labels, formats. into ( ) )
2219
2190
}
2220
2191
2192
+ fn check_tuple_fields < F > (
2193
+ & mut self ,
2194
+ range : ByteRange ,
2195
+ fields : & [ F ] ,
2196
+ get_range : fn ( & F ) -> ByteRange ,
2197
+ expected_labels : & [ StringId ] ,
2198
+ ) -> Result < ( ) , ( ) > {
2199
+ if fields. len ( ) == expected_labels. len ( ) {
2200
+ return Ok ( ( ) ) ;
2201
+ }
2202
+
2203
+ let mut found_labels = Vec :: with_capacity ( fields. len ( ) ) ;
2204
+ let mut fields_iter = fields. iter ( ) . enumerate ( ) . peekable ( ) ;
2205
+ let mut expected_labels_iter = expected_labels. iter ( ) ;
2206
+
2207
+ // use the label names from the expected labels
2208
+ while let Some ( ( ( _, field) , label) ) =
2209
+ Option :: zip ( fields_iter. peek ( ) , expected_labels_iter. next ( ) )
2210
+ {
2211
+ found_labels. push ( ( self . file_range ( get_range ( field) ) , * label) ) ;
2212
+ fields_iter. next ( ) ;
2213
+ }
2214
+
2215
+ // use numeric labels for excess fields
2216
+ for ( index, field) in fields_iter {
2217
+ found_labels. push ( (
2218
+ self . file_range ( get_range ( field) ) ,
2219
+ self . interner . borrow_mut ( ) . get_tuple_label ( index) ,
2220
+ ) ) ;
2221
+ }
2222
+
2223
+ self . push_message ( Message :: MismatchedFieldLabels {
2224
+ range : self . file_range ( range) ,
2225
+ found_labels,
2226
+ expected_labels : expected_labels. to_vec ( ) ,
2227
+ } ) ;
2228
+ Err ( ( ) )
2229
+ }
2230
+
2231
+ fn check_record_fields < F > (
2232
+ & mut self ,
2233
+ range : ByteRange ,
2234
+ fields : & [ F ] ,
2235
+ get_label : impl Fn ( & F ) -> ( ByteRange , StringId ) ,
2236
+ labels : & ' arena [ StringId ] ,
2237
+ ) -> Result < ( ) , ( ) > {
2238
+ if fields. len ( ) == labels. len ( )
2239
+ && fields
2240
+ . iter ( )
2241
+ . zip ( labels. iter ( ) )
2242
+ . all ( |( field, type_label) | get_label ( field) . 1 == * type_label)
2243
+ {
2244
+ return Ok ( ( ) ) ;
2245
+ }
2246
+
2247
+ // TODO: improve handling of duplicate labels
2248
+ self . push_message ( Message :: MismatchedFieldLabels {
2249
+ range : self . file_range ( range) ,
2250
+ found_labels : fields
2251
+ . iter ( )
2252
+ . map ( |field| {
2253
+ let ( range, label) = get_label ( field) ;
2254
+ ( self . file_range ( range) , label)
2255
+ } )
2256
+ . collect ( ) ,
2257
+ expected_labels : labels. to_vec ( ) ,
2258
+ } ) ;
2259
+ Err ( ( ) )
2260
+ }
2261
+
2221
2262
/// Elaborate a match expression in checking mode
2222
2263
fn check_match (
2223
2264
& mut self ,
0 commit comments