@@ -27,7 +27,7 @@ use crate::{
27
27
} ;
28
28
use acvm:: { FieldElement , acir:: AcirField } ;
29
29
use ast:: { GlobalId , While } ;
30
- use fxhash:: FxHashMap as HashMap ;
30
+ use fxhash:: { FxHashMap as HashMap , FxHashSet as HashSet } ;
31
31
use iter_extended:: { btree_map, try_vecmap, vecmap} ;
32
32
use noirc_errors:: Location ;
33
33
use noirc_printable_type:: PrintableType ;
@@ -48,6 +48,7 @@ mod debug;
48
48
pub mod debug_types;
49
49
pub mod errors;
50
50
pub mod printer;
51
+ pub mod tests;
51
52
52
53
struct LambdaContext {
53
54
env_ident : ast:: Ident ,
@@ -378,7 +379,10 @@ impl<'interner> Monomorphizer<'interner> {
378
379
other => other,
379
380
} ;
380
381
381
- let return_type = Self :: convert_type ( return_type, meta. location ) ?;
382
+ // If `convert_type` fails here it is most likely because of generics at the
383
+ // call site after instantiating this function's type. So show the error there
384
+ // instead of at the function definition.
385
+ let return_type = Self :: convert_type ( return_type, location) ?;
382
386
let unconstrained = self . in_unconstrained_function ;
383
387
384
388
let attributes = self . interner . function_attributes ( & f) ;
@@ -1120,6 +1124,14 @@ impl<'interner> Monomorphizer<'interner> {
1120
1124
1121
1125
/// Convert a non-tuple/struct type to a monomorphized type
1122
1126
fn convert_type ( typ : & HirType , location : Location ) -> Result < ast:: Type , MonomorphizationError > {
1127
+ Self :: convert_type_helper ( typ, location, & mut HashSet :: default ( ) )
1128
+ }
1129
+
1130
+ fn convert_type_helper (
1131
+ typ : & HirType ,
1132
+ location : Location ,
1133
+ seen_types : & mut HashSet < Type > ,
1134
+ ) -> Result < ast:: Type , MonomorphizationError > {
1123
1135
let typ = typ. follow_bindings_shallow ( ) ;
1124
1136
Ok ( match typ. as_ref ( ) {
1125
1137
HirType :: FieldElement => ast:: Type :: Field ,
@@ -1155,12 +1167,14 @@ impl<'interner> Monomorphizer<'interner> {
1155
1167
} ) ;
1156
1168
}
1157
1169
} ;
1158
- let fields = Box :: new ( Self :: convert_type ( fields. as_ref ( ) , location) ?) ;
1170
+ let fields =
1171
+ Box :: new ( Self :: convert_type_helper ( fields. as_ref ( ) , location, seen_types) ?) ;
1159
1172
ast:: Type :: FmtString ( size, fields)
1160
1173
}
1161
1174
HirType :: Unit => ast:: Type :: Unit ,
1162
1175
HirType :: Array ( length, element) => {
1163
- let element = Box :: new ( Self :: convert_type ( element. as_ref ( ) , location) ?) ;
1176
+ let element =
1177
+ Box :: new ( Self :: convert_type_helper ( element. as_ref ( ) , location, seen_types) ?) ;
1164
1178
let length = match length. evaluate_to_u32 ( location) {
1165
1179
Ok ( length) => length,
1166
1180
Err ( err) => {
@@ -1175,15 +1189,16 @@ impl<'interner> Monomorphizer<'interner> {
1175
1189
ast:: Type :: Array ( length, element)
1176
1190
}
1177
1191
HirType :: Slice ( element) => {
1178
- let element = Box :: new ( Self :: convert_type ( element. as_ref ( ) , location) ?) ;
1192
+ let element =
1193
+ Box :: new ( Self :: convert_type_helper ( element. as_ref ( ) , location, seen_types) ?) ;
1179
1194
ast:: Type :: Slice ( element)
1180
1195
}
1181
1196
HirType :: TraitAsType ( ..) => {
1182
1197
unreachable ! ( "All TraitAsType should be replaced before calling convert_type" ) ;
1183
1198
}
1184
1199
HirType :: NamedGeneric ( binding, _) => {
1185
1200
if let TypeBinding :: Bound ( binding) = & * binding. borrow ( ) {
1186
- return Self :: convert_type ( binding, location) ;
1201
+ return Self :: convert_type_helper ( binding, location, seen_types ) ;
1187
1202
}
1188
1203
1189
1204
// Default any remaining unbound type variables.
@@ -1195,13 +1210,21 @@ impl<'interner> Monomorphizer<'interner> {
1195
1210
1196
1211
HirType :: CheckedCast { from, to } => {
1197
1212
Self :: check_checked_cast ( from, to, location) ?;
1198
- Self :: convert_type ( to, location) ?
1213
+ Self :: convert_type_helper ( to, location, seen_types ) ?
1199
1214
}
1200
1215
1201
1216
HirType :: TypeVariable ( binding) => {
1217
+ let input_type = typ. as_ref ( ) . clone ( ) ;
1218
+ if !seen_types. insert ( input_type. clone ( ) ) {
1219
+ let typ = input_type;
1220
+ return Err ( MonomorphizationError :: RecursiveType { typ, location } ) ;
1221
+ }
1222
+
1202
1223
let type_var_kind = match & * binding. borrow ( ) {
1203
1224
TypeBinding :: Bound ( binding) => {
1204
- return Self :: convert_type ( binding, location) ;
1225
+ let typ = Self :: convert_type_helper ( binding, location, seen_types) ;
1226
+ seen_types. remove ( & input_type) ;
1227
+ return typ;
1205
1228
}
1206
1229
TypeBinding :: Unbound ( _, type_var_kind) => type_var_kind. clone ( ) ,
1207
1230
} ;
@@ -1214,7 +1237,8 @@ impl<'interner> Monomorphizer<'interner> {
1214
1237
None => return Err ( MonomorphizationError :: NoDefaultType { location } ) ,
1215
1238
} ;
1216
1239
1217
- let monomorphized_default = Self :: convert_type ( & default, location) ?;
1240
+ let monomorphized_default =
1241
+ Self :: convert_type_helper ( & default, location, seen_types) ?;
1218
1242
binding. bind ( default) ;
1219
1243
monomorphized_default
1220
1244
}
@@ -1226,19 +1250,30 @@ impl<'interner> Monomorphizer<'interner> {
1226
1250
Self :: check_type ( arg, location) ?;
1227
1251
}
1228
1252
1253
+ let input_type = typ. as_ref ( ) . clone ( ) ;
1254
+ if !seen_types. insert ( input_type. clone ( ) ) {
1255
+ let typ = input_type;
1256
+ return Err ( MonomorphizationError :: RecursiveType { typ, location } ) ;
1257
+ }
1258
+
1229
1259
let def = def. borrow ( ) ;
1230
1260
if let Some ( fields) = def. get_fields ( args) {
1231
- let fields =
1232
- try_vecmap ( fields, |( _, field) | Self :: convert_type ( & field, location) ) ?;
1261
+ let fields = try_vecmap ( fields, |( _, field) | {
1262
+ Self :: convert_type_helper ( & field, location, seen_types)
1263
+ } ) ?;
1264
+
1265
+ seen_types. remove ( & input_type) ;
1233
1266
ast:: Type :: Tuple ( fields)
1234
1267
} else if let Some ( variants) = def. get_variants ( args) {
1235
1268
// Enums are represented as (tag, variant1, variant2, .., variantN)
1236
1269
let mut fields = vec ! [ ast:: Type :: Field ] ;
1237
1270
for ( _, variant_fields) in variants {
1238
- let variant_fields =
1239
- try_vecmap ( variant_fields, |typ| Self :: convert_type ( & typ, location) ) ?;
1271
+ let variant_fields = try_vecmap ( variant_fields, |typ| {
1272
+ Self :: convert_type_helper ( & typ, location, seen_types)
1273
+ } ) ?;
1240
1274
fields. push ( ast:: Type :: Tuple ( variant_fields) ) ;
1241
1275
}
1276
+ seen_types. remove ( & input_type) ;
1242
1277
ast:: Type :: Tuple ( fields)
1243
1278
} else {
1244
1279
unreachable ! ( "Data type has no body" )
@@ -1252,18 +1287,20 @@ impl<'interner> Monomorphizer<'interner> {
1252
1287
Self :: check_type ( arg, location) ?;
1253
1288
}
1254
1289
1255
- Self :: convert_type ( & def. borrow ( ) . get_type ( args) , location) ?
1290
+ Self :: convert_type_helper ( & def. borrow ( ) . get_type ( args) , location, seen_types ) ?
1256
1291
}
1257
1292
1258
1293
HirType :: Tuple ( fields) => {
1259
- let fields = try_vecmap ( fields, |x| Self :: convert_type ( x, location) ) ?;
1294
+ let fields =
1295
+ try_vecmap ( fields, |x| Self :: convert_type_helper ( x, location, seen_types) ) ?;
1260
1296
ast:: Type :: Tuple ( fields)
1261
1297
}
1262
1298
1263
1299
HirType :: Function ( args, ret, env, unconstrained) => {
1264
- let args = try_vecmap ( args, |x| Self :: convert_type ( x, location) ) ?;
1265
- let ret = Box :: new ( Self :: convert_type ( ret, location) ?) ;
1266
- let env = Self :: convert_type ( env, location) ?;
1300
+ let args =
1301
+ try_vecmap ( args, |x| Self :: convert_type_helper ( x, location, seen_types) ) ?;
1302
+ let ret = Box :: new ( Self :: convert_type_helper ( ret, location, seen_types) ?) ;
1303
+ let env = Self :: convert_type_helper ( env, location, seen_types) ?;
1267
1304
match & env {
1268
1305
ast:: Type :: Unit => {
1269
1306
ast:: Type :: Function ( args, ret, Box :: new ( env) , * unconstrained)
@@ -1282,7 +1319,7 @@ impl<'interner> Monomorphizer<'interner> {
1282
1319
1283
1320
// Lower both mutable & immutable references to the same reference type
1284
1321
HirType :: Reference ( element, _mutable) => {
1285
- let element = Self :: convert_type ( element, location) ?;
1322
+ let element = Self :: convert_type_helper ( element, location, seen_types ) ?;
1286
1323
ast:: Type :: MutableReference ( Box :: new ( element) )
1287
1324
}
1288
1325
0 commit comments