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 assign INVALID_FUNCTION to a non-function type #338

Closed
kossolax opened this issue Jun 2, 2019 · 3 comments
Closed

cannot assign INVALID_FUNCTION to a non-function type #338

kossolax opened this issue Jun 2, 2019 · 3 comments

Comments

@kossolax
Copy link

kossolax commented Jun 2, 2019

Environment

SourceMod Version: 1.10.0.6423
SourcePawn Engine: 1.10.0.6423, jit-x86 (build 1.10.0.6423)
SourcePawn API: v1 = 5, v2 = 12
Compiled on: May 30 2019 20:12:51

Description

This doesn't compile en SM 1.10, but works on SM 1.9. I could not find any documentation about this. It should be declared before the native declaration, it wasn't the case before. Is this intended ?

Problematic Code

native void Foo(Bar callback = INVALID_FUNCTION);
typedef Bar = function bool(int client); // either
typeset Bar {
	function bool(int client);
}

Working Code

typedef Bar = function bool(int client); // either
typeset Bar {
	function bool(int client);
}
native void Foo(Bar callback = INVALID_FUNCTION);
@asherkin asherkin transferred this issue from alliedmodders/sourcemod Jun 2, 2019
dvander added a commit that referenced this issue Aug 21, 2019
Bug: issue #338
Test: tests/compile-only/fail-redefine-typedef.sp
@dvander
Copy link
Member

dvander commented Aug 21, 2019

This is not supported, unfortunately - types must be declared before they are used. This was inconsistent before, and this particular case only worked coincidentally. It's easy to show an example that wouldn't work on 1.9. The code below won't compile because "Bar" is a placeholder type at the point we typecheck the call to "Foo":

native void Foo(Bar b);

bool f(int x) {}

public main() {
  Foo(f);
}

typedef Bar = function bool(int x); // either

Pawn uses a two-pass compiler, and type information is thrown away in between passes. Your example worked because in 1.9, the placeholder for "Bar" retained the fact that it was a function, but did not retain the function's prototype. So relying on the prototype before the definition would fail. In 1.10, placeholders do not retain any information across reparses, so both examples fail.

Now, I bet you're thinking: "what is this garbage and why doesn't it just work?" I agree. I think we should support types declared in any order. But we're not there yet, and I'd rather it work 100% of the time instead of 27% of the time.

There is a real bug here though - "typeset Bar" should be illegal since it was already declared as a typedef.

@kossolax
Copy link
Author

kossolax commented Aug 21, 2019

Well, it's been a while, thanks for your answer. Of course both declaration should be illegal. I guess the main issue was this is accepted

native void Foo(Bar callback);

but not this

native void Foo(Bar callback = INVALID_FUNCTION);

in case of "Bar" is declared afterward.

@dvander
Copy link
Member

dvander commented Aug 24, 2019

Right - the difference is that the compiler is trying to do typechecks in the second version but not the first version.

Hopefully it's more clear now. I'd like to improve this, but it's pretty difficult in the current design.

@dvander dvander closed this as completed Aug 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants