daniellansun commented on PR #3259: URL: https://github.com/apache/groovy/pull/3259#issuecomment-6781911494
(3) The example I answered last time really was two locals, and `VariableScopeVisitor` rejects that with or without the bridge. What you meant is a field or a property and a local of the same name. That does compile, and the bridge does not treat them as one name. The lowered query is spliced into the method, `VariableScopeVisitor` links each reference to the declaration in scope, and the original call is put back. A `FieldNode` or a `PropertyNode` is not copied. It is read when the closure runs. A local or a closure parameter declared inside the query is a different declaration, and that is the one the references in that scope use. A `DynamicVariable` is not copied either. At conversion that is what an import alias still is, including a lower-case alias such as `import java.util.concurrent.TimeUnit as threshold`, and the alias then resolves to the class. I ran that shape under `@CompileStatic`. A field `threshold` of 10 is set to 4 after the `GQ` expression and before `toList()`. The `where` clause sees 4. A closure parameter `threshold` of 5 in the same query's `select` stays 5. A getter/setter property behaves the same way: the getter runs at the terminal, not when the expression is built. `@TypeChecked` does this too. `GQL` still materializes at the expression, so a later write of the field is not observed. A closure parameter of the same name as the field wins over the field. Two locals of the same name are still rejected. `STRATEGY.md` now says this explicitly. There is still no name walk in the bridge. (5) You are right that I answered a different question. The problem is not that the GINQ operators are dynamic. `DYNAMIC_RESOLUTION = Boolean.TRUE` is set on the lowered query closure, and `StaticTypesClosureWriter` compiles that whole closure with the dynamic writer. Every expression in it is dynamic, including a call written in `where` or `select`. A target another transform already chose for that call is not what is emitted. The call is dispatched at runtime. A concrete case: an extension's `onMethodSelection` forces `choose(CharSequence)` when the argument is a `String`. In the enclosing `@CompileStatic` method that is the method that runs. The same call inside `select` hits `choose(String)`, because the runtime type wins. The same is true of any other call in the clause whose static target differs from the runtime dispatch. I tried not to mark the closure. Clause parameters stayed dynamic, so a map row is not inferred as a bean. A call the checker could resolve kept its target, and only an operator whose target was a stand-in became a dynamic call. The read-only snapshot was passed into the result lambda as a parameter, because a static lambda still cannot capture a local of an enclosing closure: the bytecode loads the outer class and casts it to `GroovyObject`. `orderby n in desc` and the join tests in the static suite still passed, and the `choose(CharSequence)` target was honoured inside the query. The rest of the dynamic query did not. On the groovy-ginq suite, 71 tests failed. `where note(n)`, `note` being a method of the enclosing class, was emitted as `invokevirtual` of `Object.note()`, which does not exist. A join alias was resolved against `QueryableCollection`. A parallel join that returns rows dynamically returned an empty list. Group, window, aggregate, and hash-join scripts failed in the same way. Parallel `submit` also cannot take the snapshot as an extra parameter, because that lambda is a `Supplier`. So the closure stays dynamic. The enclosing method does not. I have written that limitation into `STRATEGY.md` and the CompileStatic section of the user guide, including the `choose(CharSequence)` example. I would rather the clause bodies stayed on the static writer. I do not have a way to do that which still runs the queries that pass today. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
