Skip to content
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

Cannot use structure inititialisation (from @:structInit) to declare a new entry in a map #10655

Open
Nales0 opened this issue Mar 30, 2022 · 3 comments

Comments

@Nales0
Copy link

Nales0 commented Mar 30, 2022

Using Haxe version 4.0.5. Here is the content of the file Main.hx.

package;

@:structInit
class Student
{
    public final name:String;
    public final score:Int;
}

class Main
{
    public static function main()
    {
        var map = new Map<String, Student>();

        var student1:Student = { name: "Boris", score: 20 };
        map["the best"] = student1;

        map["the worst"] = { name: "Vianney", score: -1 };  // Compilation error here
    }
}

When trying to launch this code using haxe --run Main, the compiler gives this error:

Main.hx:19: characters 9-58 : No @:arrayAccess function for haxe.ds.Map<String, Student> accepts arguments of String and { score : Int, name : String }

We must use a temporary variable to insert a new value in the map when using the way to construct an instance given by @:structInit.

@kLabz
Copy link
Contributor

kLabz commented Mar 30, 2022

Interestingly, var map:Map<String, Student> = ["the worst" => { name: "Vianney", score: -1 }]; does work

Edit: type hint makes it work too (map["the worst"] = ({ name: "Vianney", score: -1 } :Student);) but I suppose it should be handled without it

@Simn
Copy link
Member

Simn commented Aug 3, 2022

This is a top-down inference problem which we can reduce to this:

abstract A(String) {
	public function new() {
		this = "";
	}

	@:arrayAccess public function arrayWrite(k:String, v:Array<Dynamic>) {}
}

class Main {
	public static function main() {
		var a = new A();
		a["foo"] = [1, "foo"];
	}
}

This fails with Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>, which means that there is no expected type when typing the rhs of the assignment.

I suppose we can do the same we do for from-casts here: If there's only a single @:arrayAccess on the abstract, we can use its types for top-down inference.

@Simn
Copy link
Member

Simn commented Aug 3, 2022

Come to think of it, for consistency we would want this to work for the keys as well:

abstract A(String) {
	public function new() {
		this = "";
	}

	@:arrayAccess public function arrayRead(k:Array<Dynamic>) {}
}

class Main {
	public static function main() {
		var a = new A();
		a[[1, "foo"]];
	}
}

This gets pretty tricky due to some internal architecture concerns.

@Simn Simn added this to the Later milestone Mar 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants