After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 596861 - Invalid C code when declaring multiple variables of the same name in async methods
Invalid C code when declaring multiple variables of the same name in async me...
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Async
0.7.x
Other All
: Normal minor
: ---
Assigned To: Vala maintainers
Vala maintainers
: 606725 606783 645788 660652 664392 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2009-09-30 12:12 UTC by Michael 'Mickey' Lauer
Modified: 2011-11-20 10:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Detect name collision in coroutine methods (7.10 KB, patch)
2010-01-19 10:50 UTC, Luca Bruno
none Details | Review
inner structs (2.64 KB, patch)
2010-01-20 12:01 UTC, Luca Bruno
none Details | Review
codegen: Avoid name clashes in the closure struct (14.16 KB, patch)
2011-04-11 16:17 UTC, Luca Bruno
none Details | Review
codegen: Use CatchClause.error_variable over variable_name (2.39 KB, patch)
2011-04-22 20:08 UTC, Luca Bruno
none Details | Review
codegen: Avoid name clashes in the closure struct (19.71 KB, patch)
2011-05-06 19:27 UTC, Luca Bruno
none Details | Review
codegen: Avoid name clashes in the closure struct (20.70 KB, patch)
2011-05-06 19:30 UTC, Luca Bruno
none Details | Review

Description Michael 'Mickey' Lauer 2009-09-30 12:12:16 UTC
async string[] func()
{
        return new string[] { "yo", "kurt" };
}

async void func2()
{
        if (true)
        {
                var response = yield func();
        }
        var response = yield func();
}

void main()
{
}

======================================================
mickey@opal:/local/pkg/vala/test$ LANG=C valac --pkg gio-2.0 doubledeclaration.vala 
doubledeclaration.vala:6.1-6.16: warning: method `func2' never used
async void func2()
^^^^^^^^^^^^^^^^
doubledeclaration.vala:10.7-10.29: warning: local variable `response' declared but never used
		var response = yield func();
		    ^^^^^^^^^^^^^^^^^^^^^^^
doubledeclaration.vala:12.6-12.28: warning: local variable `response' declared but never used
	var response = yield func();
	    ^^^^^^^^^^^^^^^^^^^^^^^
/local/pkg/vala/test/doubledeclaration.vala.c:33: error: duplicate member 'response'
/local/pkg/vala/test/doubledeclaration.vala.c:36: error: duplicate member 'response_size'
/local/pkg/vala/test/doubledeclaration.vala.c:37: error: duplicate member 'response_length1'
error: cc exited with status 256
Compilation failed: 1 error(s), 3 warning(s)
Comment 1 Michael 'Mickey' Lauer 2009-10-15 23:26:43 UTC
Confirming. async methods have problems with local temp. variables. Lowering priority as there is an easy workaround though.
Comment 2 Luca Bruno 2010-01-12 20:45:43 UTC
*** Bug 606725 has been marked as a duplicate of this bug. ***
Comment 3 Sandino Flores-Moreno 2010-01-14 22:02:07 UTC
*** Bug 606783 has been marked as a duplicate of this bug. ***
Comment 4 Luca Bruno 2010-01-19 09:28:16 UTC
It's not that trivial.
The workaround would be to use a map to detect collisions when declaring local variables. The problem comes with delegates and related temp variables and their initialization. It's not that easy and requires much testing.

Another solution would be to mangle the name when creating the first tree, so the problem would be solved by the parser. But I think you're against it? :)
Comment 5 Luca Bruno 2010-01-19 10:50:23 UTC
Created attachment 151751 [details] [review]
Detect name collision in coroutine methods

This works until:
- temp_vars are generated by the ccode visitor (makes _local and _tmp check sane)
- hiding outer local variables is forbidden (i.e. var a; { var a; })

Looks like this is not working when an async local variable is captured in a lambda expression (maybe some get_variable_cname is missing?)
Comment 6 Luca Bruno 2010-01-19 11:10:03 UTC
I think the above solution is somewhat skipping the syntax work. Therefore, I'd suggest to mangle names right when working with scopes (parser? semantic? I don't know). It would be expected for a coroutine to mangle names because it flatten the scope.

Otherwise I was thinking about a solution using inner structs representing scopes:
struct Data {
  struct local_scope {
    struct inner_scope {
      gint var;
    gint var;
  }
}
But I wouldn't have any clue on how to implement that :)
Comment 7 zarevucky.jiri 2010-01-19 17:31:48 UTC
Isn't it possible to simply build a variable list first, remove duplicates and build the struct afterwards?
Comment 8 zarevucky.jiri 2010-01-19 17:33:53 UTC
About the inner structs you are proposing - that looks like an ugly hack and/or sneaky attempt to add support for hiding outer scope variables.
Comment 9 Jürg Billeter 2010-01-19 17:35:00 UTC
(In reply to comment #7)
> Isn't it possible to simply build a variable list first, remove duplicates and
> build the struct afterwards?

No, the variable types might not match.
Comment 10 zarevucky.jiri 2010-01-19 17:38:08 UTC
Ah, right. I keep forgetting that. Sorry about the noise.
Comment 11 zarevucky.jiri 2010-01-19 17:38:46 UTC
Unions?
Comment 12 zarevucky.jiri 2010-01-19 17:40:48 UTC
{
  int a = 5;
}

string a = "hello";

~~>

union {
  char* string_value;
  int int_value;
} a;
Comment 13 Luca Bruno 2010-01-19 20:18:38 UTC
Well your union solution is just like mine, but you add strange mangling and unions instead of structs and still depend on the syntax as I said above.
Also inner structs are not a way to support hiding outer variables, I don't know why are you talking about that. So please, care about the bug not what I attempt to do (which I didn't even think about that).

The problem is: in C code you have C scopes so you didn't care of it until now. In a struct they're flattened, so you _necessarily need_ to unflatten them in order keep syntax and codegen concepts more separated.
I don't propose a fully inner structs solution, it would be overkill, I propose to create one-level inner structs named with a counter: scope1, scope2, ...

This requires this change:
- refactor get_variable_cexpression (string name) to be get_variable_cexpression (string name, Scope? scope)
- a coroutine_scope_map<Scope,CCodeStruct>
Comment 14 Luca Bruno 2010-01-20 12:01:09 UTC
Created attachment 151827 [details] [review]
inner structs

This patch creates inner structs inside the coroutine data block. Also it adds _scope%d_ variables in the cblock so that access is faster. After this, get_variable_cexpression must be refactored to accept a Block, where the block is the block supposing to hold the variable whose cexpression is requested.
Comment 15 Michael 'Mickey' Lauer 2010-07-17 17:18:21 UTC
The first attachement no longer applies to Vala master, could you please rebase this, so we have a chance to get it in? Thanks a lot!
Comment 16 Luca Bruno 2010-07-17 17:46:57 UTC
(In reply to comment #15)
> The first attachement no longer applies to Vala master, could you please rebase
> this, so we have a chance to get it in? Thanks a lot!

It's not a full patch, it's only a proof of having inner structs per block but does not fix the problem. Just to have an ack of type "yes this can be done this way" before actually digging into full patch writing.
Comment 17 Jürg Billeter 2011-03-27 15:40:37 UTC
*** Bug 645788 has been marked as a duplicate of this bug. ***
Comment 18 Luca Bruno 2011-04-11 16:17:55 UTC
Created attachment 185726 [details] [review]
codegen: Avoid name clashes in the closure struct

Partially fixes bug 596861.

This patch partially fix the problem, and it's almost sure that it wouldn't produce any regression. This is because the first variable is always named with the original name, while other names producing clashes will be mangled. So existing code will just work.                                                        
Non fixed code are try/catch and foreach due to:                               
1) CatchClause does not accept error_variable as its child
2) ForeachStatement hardcodes variable_name too much instead of using iterator_variable (which is defined but completely unused).                             

So if the above two are real issues, I think the patch correctly addresses the problem.
Comment 19 Jürg Billeter 2011-04-17 19:38:41 UTC
The patch looks fine to me, seems quite safe. It would make sense to use the regular local variable code path for error and iterator variables as well, assuming it can be done without a significant increase in code complexity.
Comment 20 Luca Bruno 2011-04-22 20:08:55 UTC
Created attachment 186497 [details] [review]
codegen: Use CatchClause.error_variable over variable_name

Notice visit_local_variable will be hopefully replaced with create_local in the future.
Comment 21 Luca Bruno 2011-05-06 19:27:11 UTC
Created attachment 187380 [details] [review]
codegen: Avoid name clashes in the closure struct

Fixes bug 596861.
Comment 22 Luca Bruno 2011-05-06 19:30:22 UTC
Created attachment 187381 [details] [review]
codegen: Avoid name clashes in the closure struct

Fixes bug 596861.

Added regression test case.
Comment 23 Luca Bruno 2011-10-01 20:59:22 UTC
*** Bug 660652 has been marked as a duplicate of this bug. ***
Comment 24 Luca Bruno 2011-10-02 11:45:30 UTC
commit 335636be07c27950791179dc77354d2916c9468a
Author: Luca Bruno <lucabru@src.gnome.org>
Date:   Mon Apr 11 18:08:23 2011 +0200

    codegen: Avoid name clashes in the closure struct
    
    Fixes bug 596861.

This problem has been fixed in the development version. The fix will be available in the next major software release. Thank you for your bug report.
Comment 25 Luca Bruno 2011-11-20 10:17:43 UTC
*** Bug 664392 has been marked as a duplicate of this bug. ***