@@ -38,7 +38,7 @@ pub type TypeName = SmolStr;
38
38
pub type TypeNameRef = str ;
39
39
40
40
/// The kinds of edges in a HUGR, excluding Hierarchy.
41
- #[ derive( Clone , PartialEq , Eq , Debug , serde:: Serialize , serde:: Deserialize ) ]
41
+ #[ derive( Clone , PartialEq , Debug , serde:: Serialize , serde:: Deserialize ) ]
42
42
#[ non_exhaustive]
43
43
pub enum EdgeKind {
44
44
/// Control edges of a CFG region.
@@ -130,7 +130,7 @@ pub enum SumType {
130
130
Unit { size : u8 } ,
131
131
/// General case of a Sum type.
132
132
#[ allow( missing_docs) ]
133
- General { rows : Vec < TypeRow > } ,
133
+ General { rows : Vec < TypeRow < true > > } ,
134
134
}
135
135
136
136
impl std:: fmt:: Display for SumType {
@@ -152,7 +152,7 @@ impl SumType {
152
152
/// Initialize a new sum type.
153
153
pub fn new < V > ( variants : impl IntoIterator < Item = V > ) -> Self
154
154
where
155
- V : Into < TypeRow > ,
155
+ V : Into < TypeRow < true > > ,
156
156
{
157
157
let rows = variants. into_iter ( ) . map ( Into :: into) . collect_vec ( ) ;
158
158
@@ -170,7 +170,7 @@ impl SumType {
170
170
}
171
171
172
172
/// Report the tag'th variant, if it exists.
173
- pub fn get_variant ( & self , tag : usize ) -> Option < & TypeRow > {
173
+ pub fn get_variant ( & self , tag : usize ) -> Option < & TypeRow < true > > {
174
174
match self {
175
175
SumType :: Unit { size } if tag < ( * size as usize ) => Some ( Type :: EMPTY_TYPEROW_REF ) ,
176
176
SumType :: General { rows } => rows. get ( tag) ,
@@ -187,8 +187,8 @@ impl SumType {
187
187
}
188
188
}
189
189
190
- impl From < SumType > for Type {
191
- fn from ( sum : SumType ) -> Type {
190
+ impl < const RV : bool > From < SumType > for Type < RV > {
191
+ fn from ( sum : SumType ) -> Self {
192
192
match sum {
193
193
SumType :: Unit { size } => Type :: new_unit_sum ( size) ,
194
194
SumType :: General { rows } => Type :: new_sum ( rows) ,
@@ -199,7 +199,7 @@ impl From<SumType> for Type {
199
199
#[ derive( Clone , PartialEq , Debug , Eq , derive_more:: Display ) ]
200
200
#[ cfg_attr( test, derive( Arbitrary ) , proptest( params = "RecursionDepth" ) ) ]
201
201
/// Core types
202
- pub enum TypeEnum {
202
+ pub enum TypeEnum < const ROWVARS : bool =false > {
203
203
// TODO optimise with Box<CustomType> ?
204
204
// or some static version of this?
205
205
#[ allow( missing_docs) ]
@@ -223,14 +223,29 @@ pub enum TypeEnum {
223
223
#[ display( fmt = "Variable({})" , _0) ]
224
224
Variable ( usize , TypeBound ) ,
225
225
/// Variable index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type]
226
- /// of this bound (checked in validation)
226
+ /// of this bound (checked in validation). Should only exist for `Type<true>` and `TypeEnum<true>`.
227
227
#[ display( fmt = "RowVar({})" , _0) ]
228
228
RowVariable ( usize , TypeBound ) ,
229
229
#[ allow( missing_docs) ]
230
230
#[ display( fmt = "{}" , "_0" ) ]
231
231
Sum ( #[ cfg_attr( test, proptest( strategy = "any_with::<SumType>(params)" ) ) ] SumType ) ,
232
232
}
233
- impl TypeEnum {
233
+
234
+ /*impl <const RV:bool> PartialEq<TypeEnum> for TypeEnum<RV> {
235
+ fn eq(&self, other: &TypeEnum) -> bool {
236
+ match (self, other) {
237
+ (TypeEnum::Extension(e1), TypeEnum::Extension(e2)) => e1 == e2,
238
+ (TypeEnum::Alias(a1), TypeEnum::Alias(a2)) => a1 == a2,
239
+ (TypeEnum::Function(f1), TypeEnum::Function(f2)) => f1==f2,
240
+ (TypeEnum::Variable(i1, b1), TypeEnum::Variable(i2, b2)) => i1==i2 && b1==b2,
241
+ (TypeEnum::RowVariable(i1, b1), TypeEnum::RowVariable(i2, b2)) => i1==i2 && b1==b2,
242
+ (TypeEnum::Sum(s1), TypeEnum::Sum(s2)) => s1 == s2,
243
+ _ => false
244
+ }
245
+ }
246
+ }*/
247
+
248
+ impl < const RV : bool > TypeEnum < RV > {
234
249
/// The smallest type bound that covers the whole type.
235
250
fn least_upper_bound ( & self ) -> TypeBound {
236
251
match self {
@@ -249,10 +264,10 @@ impl TypeEnum {
249
264
}
250
265
251
266
#[ derive(
252
- Clone , PartialEq , Debug , Eq , derive_more:: Display , serde:: Serialize , serde:: Deserialize ,
267
+ Clone , Debug , PartialEq , Eq , derive_more:: Display , serde:: Serialize , serde:: Deserialize ,
253
268
) ]
254
269
#[ display( fmt = "{}" , "_0" ) ]
255
- #[ serde( into = "serialize::SerSimpleType" , from = "serialize::SerSimpleType" ) ]
270
+ #[ serde( into = "serialize::SerSimpleType" , try_from = "serialize::SerSimpleType" ) ]
256
271
/// A HUGR type - the valid types of [EdgeKind::Value] and [EdgeKind::Const] edges.
257
272
/// Such an edge is valid if the ports on either end agree on the [Type].
258
273
/// Types have an optional [TypeBound] which places limits on the valid
@@ -273,24 +288,30 @@ impl TypeEnum {
273
288
/// let func_type = Type::new_function(FunctionType::new_endo(vec![]));
274
289
/// assert_eq!(func_type.least_upper_bound(), TypeBound::Copyable);
275
290
/// ```
276
- pub struct Type ( TypeEnum , TypeBound ) ;
291
+ pub struct Type < const ROWVARS : bool =false > ( TypeEnum < ROWVARS > , TypeBound ) ;
277
292
278
- impl Type {
293
+ /*impl<const RV:bool> PartialEq<Type> for Type<RV> {
294
+ fn eq(&self, other: &Type) -> bool {
295
+ self.0 == other.0 && self.1 == other.1
296
+ }
297
+ }*/
298
+
299
+ impl < const RV : bool > Type < RV > {
279
300
/// An empty `TypeRow`. Provided here for convenience
280
- pub const EMPTY_TYPEROW : TypeRow = type_row ! [ ] ;
301
+ pub const EMPTY_TYPEROW : TypeRow < RV > = type_row ! [ ] ;
281
302
/// Unit type (empty tuple).
282
303
pub const UNIT : Self = Self ( TypeEnum :: Sum ( SumType :: Unit { size : 1 } ) , TypeBound :: Eq ) ;
283
304
284
- const EMPTY_TYPEROW_REF : & ' static TypeRow = & Self :: EMPTY_TYPEROW ;
305
+ const EMPTY_TYPEROW_REF : & ' static TypeRow < RV > = & Self :: EMPTY_TYPEROW ;
285
306
286
307
/// Initialize a new function type.
287
- pub fn new_function ( fun_ty : impl Into < FunctionType > ) -> Self {
308
+ pub fn new_function ( fun_ty : impl Into < FunctionType < true > > ) -> Self {
288
309
Self :: new ( TypeEnum :: Function ( Box :: new ( fun_ty. into ( ) ) ) )
289
310
}
290
311
291
312
/// Initialize a new tuple type by providing the elements.
292
313
#[ inline( always) ]
293
- pub fn new_tuple ( types : impl Into < TypeRow > ) -> Self {
314
+ pub fn new_tuple ( types : impl Into < TypeRow < true > > ) -> Self {
294
315
let row = types. into ( ) ;
295
316
match row. len ( ) {
296
317
0 => Self :: UNIT ,
@@ -300,7 +321,7 @@ impl Type {
300
321
301
322
/// Initialize a new sum type by providing the possible variant types.
302
323
#[ inline( always) ]
303
- pub fn new_sum ( variants : impl IntoIterator < Item = TypeRow > ) -> Self where {
324
+ pub fn new_sum ( variants : impl IntoIterator < Item = TypeRow < true > > ) -> Self where {
304
325
Self :: new ( TypeEnum :: Sum ( SumType :: new ( variants) ) )
305
326
}
306
327
@@ -316,7 +337,7 @@ impl Type {
316
337
Self :: new ( TypeEnum :: Alias ( alias) )
317
338
}
318
339
319
- fn new ( type_e : TypeEnum ) -> Self {
340
+ fn new ( type_e : TypeEnum < RV > ) -> Self {
320
341
let bound = type_e. least_upper_bound ( ) ;
321
342
Self ( type_e, bound)
322
343
}
@@ -335,19 +356,6 @@ impl Type {
335
356
Self ( TypeEnum :: Variable ( idx, bound) , bound)
336
357
}
337
358
338
- /// New use (occurrence) of the row variable with specified index.
339
- /// `bound` must be exactly that with which the variable was declared
340
- /// (i.e. as a [TypeParam::List]` of a `[TypeParam::Type]` of that bound),
341
- /// which may be narrower than required for the use.
342
- /// For use in [OpDef] type schemes, or function types, only,
343
- /// not [FuncDefn] type schemes or as a Hugr port type.
344
- ///
345
- /// [OpDef]: crate::extension::OpDef
346
- /// [FuncDefn]: crate::ops::FuncDefn
347
- pub const fn new_row_var_use ( idx : usize , bound : TypeBound ) -> Self {
348
- Self ( TypeEnum :: RowVariable ( idx, bound) , bound)
349
- }
350
-
351
359
/// Report the least upper [TypeBound]
352
360
#[ inline( always) ]
353
361
pub const fn least_upper_bound ( & self ) -> TypeBound {
@@ -356,7 +364,7 @@ impl Type {
356
364
357
365
/// Report the component TypeEnum.
358
366
#[ inline( always) ]
359
- pub const fn as_type_enum ( & self ) -> & TypeEnum {
367
+ pub const fn as_type_enum ( & self ) -> & TypeEnum < RV > {
360
368
& self . 0
361
369
}
362
370
@@ -382,7 +390,6 @@ impl Type {
382
390
/// [TypeDef]: crate::extension::TypeDef
383
391
pub ( crate ) fn validate (
384
392
& self ,
385
- allow_row_vars : bool ,
386
393
extension_registry : & ExtensionRegistry ,
387
394
var_decls : & [ TypeParam ] ,
388
395
) -> Result < ( ) , SignatureError > {
@@ -391,16 +398,16 @@ impl Type {
391
398
match & self . 0 {
392
399
TypeEnum :: Sum ( SumType :: General { rows } ) => rows
393
400
. iter ( )
394
- . try_for_each ( |row| row. validate_var_len ( extension_registry, var_decls) ) ,
401
+ . try_for_each ( |row| row. validate ( extension_registry, var_decls) ) ,
395
402
TypeEnum :: Sum ( SumType :: Unit { .. } ) => Ok ( ( ) ) , // No leaves there
396
403
TypeEnum :: Alias ( _) => Ok ( ( ) ) ,
397
404
TypeEnum :: Extension ( custy) => custy. validate ( extension_registry, var_decls) ,
398
405
// Function values may be passed around without knowing their arity
399
406
// (i.e. with row vars) as long as they are not called:
400
- TypeEnum :: Function ( ft) => ft. validate_var_len ( extension_registry, var_decls) ,
407
+ TypeEnum :: Function ( ft) => ft. validate ( extension_registry, var_decls) ,
401
408
TypeEnum :: Variable ( idx, bound) => check_typevar_decl ( var_decls, * idx, & ( * bound) . into ( ) ) ,
402
409
TypeEnum :: RowVariable ( idx, bound) => {
403
- if allow_row_vars {
410
+ if RV {
404
411
check_typevar_decl ( var_decls, * idx, & TypeParam :: new_list ( * bound) )
405
412
} else {
406
413
Err ( SignatureError :: RowVarWhereTypeExpected { idx : * idx } )
@@ -411,29 +418,68 @@ impl Type {
411
418
412
419
/// Applies a substitution to a type.
413
420
/// This may result in a row of types, if this [Type] is not really a single type but actually a row variable
414
- /// Invariants may be confirmed by validation:
415
- /// * If [Type::validate]`(false)` returns successfully, this method will return a Vec containing exactly one type
416
- /// * If [Type::validate]`(false)` fails, but `(true)` succeeds, this method may (depending on structure of self)
417
- /// return a Vec containing any number of [Type]s. These may (or not) pass [Type::validate]
418
- fn substitute ( & self , t : & Substitution ) -> Vec < Self > {
421
+ /// (of course this can only occur for a `Type<true``). For a `Type<false>`, will always return exactly one element.
422
+ fn subst_vec ( & self , s : & Substitution ) -> Vec < Self > {
419
423
match & self . 0 {
420
- TypeEnum :: RowVariable ( idx, bound) => t. apply_rowvar ( * idx, * bound) ,
421
- TypeEnum :: Alias ( _) | TypeEnum :: Sum ( SumType :: Unit { .. } ) => vec ! [ self . clone( ) ] ,
424
+ TypeEnum :: RowVariable ( idx, bound) =>
425
+ if RV { s. apply_rowvar ( idx, bound) } // ALAN Argh, type error here as Type<true> != Type<RV> even inside "if RV"
426
+ else { panic ! ( "Row Variable outside Row - should not have validated?" ) } ,
427
+ TypeEnum :: Alias ( _) | TypeEnum :: Sum ( SumType :: Unit { .. } ) => vec ! [ self . clone( ) . into( ) ] ,
422
428
TypeEnum :: Variable ( idx, bound) => {
423
- let TypeArg :: Type { ty } = t . apply_var ( * idx, & ( ( * bound) . into ( ) ) ) else {
429
+ let TypeArg :: Type { ty } = s . apply_var ( * idx, & ( ( * bound) . into ( ) ) ) else {
424
430
panic ! ( "Variable was not a type - try validate() first" )
425
431
} ;
426
- vec ! [ ty]
432
+ vec ! [ ty] // ALAN argh, can't convert parametrically from Type<false> to Type<RV>
427
433
}
428
- TypeEnum :: Extension ( cty) => vec ! [ Type :: new_extension( cty. substitute( t ) ) ] ,
429
- TypeEnum :: Function ( bf) => vec ! [ Type :: new_function( bf. substitute( t ) ) ] ,
434
+ TypeEnum :: Extension ( cty) => vec ! [ Type :: new_extension( cty. substitute( s ) ) ] ,
435
+ TypeEnum :: Function ( bf) => vec ! [ Type :: new_function( bf. substitute( s ) ) ] ,
430
436
TypeEnum :: Sum ( SumType :: General { rows } ) => {
431
- vec ! [ Type :: new_sum( rows. iter( ) . map( |r| r. substitute( t ) ) ) ]
437
+ vec ! [ Type :: new_sum( rows. iter( ) . map( |r| r. substitute( s ) ) ) ]
432
438
}
433
439
}
434
440
}
435
441
}
436
442
443
+ impl TryFrom < Type < true > > for Type < false > {
444
+ type Error = ConvertError ;
445
+ fn try_from ( value : Type < true > ) -> Result < Self , Self :: Error > {
446
+ Ok ( Self ( match value. 0 {
447
+ TypeEnum :: Extension ( e) => TypeEnum :: Extension ( e) ,
448
+ TypeEnum :: Alias ( a) => TypeEnum :: Alias ( a) ,
449
+ TypeEnum :: Function ( ft) => TypeEnum :: Function ( ft) ,
450
+ TypeEnum :: Variable ( i, b) => TypeEnum :: Variable ( i, b) ,
451
+ TypeEnum :: RowVariable ( _, _) => return Err ( ConvertError ) ,
452
+ TypeEnum :: Sum ( st) => TypeEnum :: Sum ( st)
453
+ } , value. 1 ) )
454
+ }
455
+ }
456
+
457
+ impl Type < false > {
458
+ fn substitute ( & self , s : & Substitution ) -> Self {
459
+ let v = self . subst_vec ( s) ;
460
+ let [ r] = v. try_into ( ) . unwrap ( ) ; // No row vars, so every Type<false> produces exactly one
461
+ r
462
+ }
463
+ }
464
+
465
+ impl Type < true > {
466
+ /// New use (occurrence) of the row variable with specified index.
467
+ /// `bound` must match that with which the variable was declared
468
+ /// (i.e. as a [TypeParam::List]` of a `[TypeParam::Type]` of that bound).
469
+ /// For use in [OpDef], not [FuncDefn], type schemes only.
470
+ ///
471
+ /// [OpDef]: crate::extension::OpDef
472
+ /// [FuncDefn]: crate::ops::FuncDefn
473
+ pub const fn new_row_var ( idx : usize , bound : TypeBound ) -> Self {
474
+ Self ( TypeEnum :: RowVariable ( idx, bound) , bound)
475
+ }
476
+
477
+ fn substitute ( & self , s : & Substitution ) -> Vec < Self > {
478
+ self . subst_vec ( s)
479
+ }
480
+
481
+ }
482
+
437
483
/// Details a replacement of type variables with a finite list of known values.
438
484
/// (Variables out of the range of the list will result in a panic)
439
485
pub ( crate ) struct Substitution < ' a > ( & ' a [ TypeArg ] , & ' a ExtensionRegistry ) ;
@@ -448,7 +494,7 @@ impl<'a> Substitution<'a> {
448
494
arg. clone ( )
449
495
}
450
496
451
- fn apply_rowvar ( & self , idx : usize , bound : TypeBound ) -> Vec < Type > {
497
+ fn apply_rowvar ( & self , idx : usize , bound : TypeBound ) -> Vec < Type < true > > {
452
498
let arg = self
453
499
. 0
454
500
. get ( idx)
@@ -476,6 +522,19 @@ impl<'a> Substitution<'a> {
476
522
}
477
523
}
478
524
525
+ impl From < Type < false > > for Type < true > {
526
+ fn from ( value : Type < false > ) -> Self {
527
+ Self ( match value. 0 {
528
+ TypeEnum :: Alias ( a) => TypeEnum :: Alias ( a) ,
529
+ TypeEnum :: Extension ( e) => TypeEnum :: Extension ( e) ,
530
+ TypeEnum :: Function ( ft) => TypeEnum :: Function ( ft) ,
531
+ TypeEnum :: Variable ( idx, bound) => TypeEnum :: Variable ( idx, bound) ,
532
+ TypeEnum :: RowVariable ( _, _) => panic ! ( "Type<false> should not contain row variables" ) ,
533
+ TypeEnum :: Sum ( st) => TypeEnum :: Sum ( st) ,
534
+ } , value. 1 )
535
+ }
536
+ }
537
+
479
538
pub ( crate ) fn check_typevar_decl (
480
539
decls : & [ TypeParam ] ,
481
540
idx : usize ,
0 commit comments