tink_sql icon indicating copy to clipboard operation
tink_sql copied to clipboard

Typing problems when using `final`

Open gene-pavlovsky opened this issue 5 years ago • 2 comments

typedef User = {
  @:primary @:autoIncrement final id:Id<User>;
  @:unique final username:VarChar<255>;
  final password:VarChar<64>;
  final salt:VarChar<32>;
  final displayName:VarChar<255>;
  final roles:Int;
}

...

typedef UserVo = {
  var id(default, never):Int;
  var username(default, never):String;
  var displayName(default, never):String;
  var isAdmin(default, never):Bool;
  var isSuperUser(default, never):Bool;
}

...

  public function list():Promise<Array<UserVo>>
    return db.User.all()
      .next(all -> all.map(parseUser));

  static function parseUser(u:User):UserVo
    return {
      id: u.id,
      username: u.username,
      displayName: u.displayName, 
      isAdmin: u.roles & UserRole.ADMIN != 0,
      isSuperUser: u.roles & UserRole.SUPERUSER != 0
    };

The following doesn't compile using the latest haxe nightly, complaining about:

src/server/api/UsersApi.hx:9: characters 31-34 : error: Cannot unify final and non-final fields
src/server/api/UsersApi.hx:9: characters 31-34 :  have: { displayName: Dynamic }
src/server/api/UsersApi.hx:9: characters 31-34 :  want: { displayName: Dynamic }
src/server/api/UsersApi.hx:9: characters 31-34 : For function argument 'u'

If I remove the finals, everything works. If I inline the code from parseUser into the .next(), everything works. The problem happens when trying to type the result of .all() (or .first()) as db.User. But in theory it should be db.User, why isn't it?

gene-pavlovsky avatar Feb 23 '19 11:02 gene-pavlovsky

I suspect the row type for the result set does not have final fields, mostly because https://github.com/haxetink/tink_macro/issues/17

back2dos avatar Feb 24 '19 07:02 back2dos

Also having this problem, and so does @kevinresol as he confirmed on gitter. Is it really because of the unimplemented default: linked by @back2dos last year? Issue has been fixed though, but I'm putting macro Sisyphus content here in order to try to attract interest on this issue:

class Sisyphus {
  static function nullable(complexType : ComplexType) : ComplexType return macro : Null<$complexType>;
  static function toField(cf : ClassField) : Field return {
    function varAccessToString(va : VarAccess, getOrSet : String) : String return {
      switch (va) {
        case AccNormal: "default";
        case AccNo: "null";
        case AccNever: "never";
        case AccResolve: throw "Invalid TAnonymous";
        case AccCall: getOrSet;
        case AccInline: "default";
        case AccRequire(_, _): "default";
        default: throw "not implemented";
      }
    }

Seeming to suggests in order to fix this issue toField(String):String could not be used anymore?

grepsuzette avatar Feb 28 '20 02:02 grepsuzette