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

[gaml] Wrong implicit casting when directly manipulating elements of a container of unknown type elements #385

Open
lesquoyb opened this issue Dec 17, 2024 · 1 comment · May be fixed by #435
Assignees
Labels
About GAML This issue concerns the GAML language 😱 Bug The issue reveals a bug in GAMA

Comments

@lesquoyb
Copy link
Contributor

Describe the bug
I was investigating the problems mentioned in this discussion and noticed that the type resolution for elements in a map is different when using directly map[key] than when passing by an intermediary variable.
Here is an example:

model inttofloat

global {

	init {
		map<string, unknown> m <- ['b'::1.0, 'a'::1];
		write type_of(m['a']);
		write type_of(int(m['a'])+1);
		write type_of(m['a']+1);
	}
	
}

experiment e;

The last type casting is wrong, my guess is that it is using the type of the first element in the map. You can test it by changing the first element by a string instead and you will notice that this time gama raises an exception at the last line, but the second works as expected.

The same also applies to list of unknown type:

model inttofloat

global {

	init {
		list<unknown> m <- [1.0, 1];
		write type_of(m[0]);
		write type_of(int(m[1])+1);
		write type_of(m[1]+1);
	}
	
}

experiment e;

To Reproduce
Steps to reproduce the behavior:

  1. Run the model
  2. See error

Expected behavior
That when accessing an element inside a map directly it behaves in the same way as when storing it in a variable.

Additional context
I've ruled out the unknown type alone as being the problem, as if you store an int inside an unknown and perform operations on it, everything works normally, so it really is about the maps and lists of unknown element types.

I think it's not the first time we have that kind of weird behaviours with types "changing" a bit on the fly depending on how variables are accessed. It could be a good idea to cover this by a dedicated unit test model

@lesquoyb lesquoyb added 😱 Bug The issue reveals a bug in GAMA About GAML This issue concerns the GAML language labels Dec 17, 2024
@AlexisDrogoul
Copy link
Member

First of all, the way type inference works in containers is by finding the common super type of all values. Here, it is float (the most general number representation), but if you write list<unknown> m <- [1.0, 1, "a"]; you will obtain unknown.

The semantics of unknown in the declaration is indeed a bit confusing. Instead of signifying "I want to create a list of unknown objects", it actually amounts to "I want to create a list and please do some type inference from the initial value to compute the type of its objects". It's easy to spot the difference with the declaration below :

list<unknown> m;
m <- [1.0,1];

In the latter case, m will remain a list of unknown objects as the assignment does not modify the type of objects. A bit confusing that this and list<unknown> m <- [1.0, 1]; produce such different operations and a different result.

It is also confusing because in some cases we want type inference and in other cases no. For instance, in another instance of var declaration, when I write loop i from: 1 to: 10 ..., I'm happy that i is actually considered of type int. In a closer type of declaration, e.g. let i <- 10;, I'm also happy that i is not an unknown.

What is the common denominator of all this ? Well, i think it is quite easy:

  • when there is an explicit type declaration (for instance, unknown a <- 10;, list<unknown> b <- [10];), we should not do any type inference from the initial value, i.e. we should not try to replace unknownwith a more precise type.
  • when there is not, for instance in let a <- 10;, loop i over: ["a", "b", "c"], we should infer the type, considering the modeler lets GAMA decide what type to use.

It is probably not too difficult to implement. The only drawback is that we do not allow (anymore) the var keyword for declaring attributes of species, meaning that we need to consider all attributes declarations to be explicit (and thus w/o type inference). I have begun to implement it here: #435

@AlexisDrogoul AlexisDrogoul self-assigned this Mar 16, 2025
AlexisDrogoul added a commit that referenced this issue Mar 16, 2025
- Declaration of attributes now systematically respect the type provided by the modeller (no type inference)
- if a local variable declaration provides a type, it is also respected (no type inference)
- type inference is however done when no explicit type is provide (let, loop, etc.)

Adjustments to various models of the library, which were relying on blind type inference, especially for files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
About GAML This issue concerns the GAML language 😱 Bug The issue reveals a bug in GAMA
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants