cadence icon indicating copy to clipboard operation
cadence copied to clipboard

Add convenience function on `Type` for checking interface conformance at runtime

Open dreamsmasher opened this issue 3 years ago • 2 comments

Currently, the only way to check whether a runtime Type object conforms to an interface is to do a subtype check on a dummy restricted type, e.g.

struct SmolBean {
  
  init() {}
  
  fun uwu(): Void {}
}

struct interface SmolLittleGuy {
  fun uwu(): Void
}

...

let smolBeanTy: Type = Type<SmolBean>()
let smolBeanIsSmolLilGuy: Bool = smolBeanTy.isSubType(of: Type<AnyStruct{SmolLittleGuy}>())
assert(smolBeanIsSmolLilGuy, "oh nooooo")

Having to wrap interfaces up in a restricted type obscures developer intentions and harms readability. This issue proposes a new type marker for interfaces:

pub struct Interface {
  pub let identifier: String
}

and a new method on Types:

Type.conformsTo(_ interface_: Interface): Bool

With this, the above conformance check could be rewritten as:

let smolBeanTy: Type = Type<SmolBean>()
let smolBeanIsSmolLilGuy: Bool = smolBeanTy.conformsTo(Interface<SmolLittleGuy>())

dreamsmasher avatar Jan 06 '23 22:01 dreamsmasher

Currently waiting for a decision on whether to replace restricted types with interface intersections, which will obviate the need for this convenience fn. Intersection types will significantly simplify the creation of intersection type objects.

https://github.com/onflow/flips/pull/54

I put some time into implementing this PR the regular way, which involves defining another builtin type identical to that of Type objects with a ton of duplicated code. It would require some parser refactoring in order to use allow interfaces to be used in type parameter position, which currently isn't allowed. I'm banking on FLIP #54 to obsolete this issue.

dreamsmasher avatar Feb 03 '23 19:02 dreamsmasher

With restricted types being replaced with interface-set, the proposed method looks very similar to the existing .isSubType() method:

Proposed:

smolBeanTy.conformsTo(Interface<SmolLittleGuy>())

Existing:

smolBeanTy.isSubType(of: Type<{SmolLittleGuy}>())

Thus, I don't really see any advantage of adding a new method for the same functionality.

SupunS avatar Aug 29 '24 19:08 SupunS