-
-
Notifications
You must be signed in to change notification settings - Fork 656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Something is wrong with @:op(A.B) #8572
Comments
It can get even worse abstract Abstract({value:Dynamic, type:ValueType}) {
var value(get, set):Dynamic;
inline function get_value() return this.value;
inline function set_value(v) return this.value = v;
var type(get, set):ValueType;
inline function get_type() return this.type;
inline function set_type(v) return this.type = v;
@:from public static inline function from(v) return cast v;
@:op(A.B) public static inline function resolve(self, key, val:Dynamic):Dynamic {
return key == "value"? self.value = val : self.type = val;
}
} Idea to make individual private getters and setters over underlying type and call them in @:op(A.B) failed because @:op(A.B) doesn't have precedence over them. |
Inline is actually not working for @:op(A.B) in this case abstract Abstract(Dynamic) {
public inline function new(v) { this = v; }
@:from public static inline function from(v) { return new Abstract(v); }
@:op(A.B) public inline function resolve(key, val:Dynamic) {
return key == "value" ? this.value = val : this.type = val;
}
var a = new Abstract({ value:(null:Dynamic), type:TUnknown }); // this one doesn't inline
// var a = { value:(null:Dynamic), type:TUnknown }; // this one does
a.value = 10.0;
a.type = TFloat;
} |
But it's working for both new and @:from in this case abstract Abstract<T>(T) {
public inline function new(v:T) { this = v; }
@:from public static inline function from(v) { return new Abstract(v); }
@:op(A.B) public inline function resolve(key, val:Dynamic):Dynamic {
return untyped key == "value" ? this.value = val : this.type = val;
}
}
var a = new Abstract({ value:(null:Dynamic), type:TUnknown }); // inline
// var a:Abstract<Dynamic> = { value:(null:Dynamic), type:TUnknown }; inline
a.value = 10.0;
a.type = TFloat; Cool. It would be even better if inline could work without T and untyped |
I'm not sure if |
Oh, actually in your original sample you get a recursion because your abstract doesn't have |
Are you sure? I had to do this to get everything working abstract Under<T>(T) {
public inline function new(v:T) { this = v; }
@:from public static inline function from(v) { return new Under(v); }
@:op(A.B) public static inline function write(self, key, val:Dynamic):Dynamic {
var ths:{} = cast self;
return untyped key == "value" ? ths.value = val : ths.type = val;
}
}
@:forward
abstract Abstract(Under<Dynamic>)
{
public inline function new(v) this = new Under(v);
@:from public static inline function from(v) return new Abstract(v);
/*
@:op(A.B) public static inline function write(self, key, val:Dynamic):Dynamic {
var ths:Under<Dynamic> = self;
return untyped key == "value" ? ths.value = val : ths.type = val;
}
*/
}
// var a = new Abstract({ value:(null:Dynamic), type:TUnknown });
var a:Abstract = { value:(null:Dynamic), type:TUnknown };
a.value = 10.0;
a.type = TFloat;
Note need to cast self to underlying type |
Yes, I am sure. Your |
OK, fine with me. Except self is useless if setter of value/type is defined. Because @:op(A.B) doesn't have priority over individual setter. It only works for reflection, or manual call var u1 = new Under({ value:(null:Dynamic), type:TUnknown });
Under.write(u1, "value", 10.0);//u1.value = 10.0;
Under.write(u1, "type", TInt);//u1.type = TInt; Even if setter is defined as private, @:op(A.B) will not take priority. Put that into documentation, and case is closed. |
Sorry, I don't understand you :) |
And what if setter is private? Should compiler delegate to @:op(A.B)? If not, just mention that @:op(A.B) is always about resolve of unexisting fields into documentation. |
I'm not sure anymore if introducing all these pseudo-
I suppose we need a proper section in the manual about |
@Simn What's missing in https://haxe.org/manual/types-abstract-operator-overloading.html ? Could you open a HaxeManual issue with some bullet points that you can think of? |
Unlike any other operator, @:op(A.B) is forcing to declare additional parameter for setter or getter if function is declared as static. This parameter (self) is abstract itself and if used like above, it is causing recursion without warning:
Or it's a bug, or it needs more work to use it safely. BTW, @:op(A.B) can also be declared as macro (doing nothing), so it should be fixed like it was fixed in case of the constructor.
The text was updated successfully, but these errors were encountered: