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

Type inferencing error (only in Eclipse, not in groovyc) #1281

Closed
mauromol opened this issue Jul 20, 2021 · 7 comments
Closed

Type inferencing error (only in Eclipse, not in groovyc) #1281

mauromol opened this issue Jul 20, 2021 · 7 comments
Assignees
Labels
Milestone

Comments

@mauromol
Copy link

mauromol commented Jul 20, 2021

Consider this:

package test70

import groovy.transform.CompileStatic

@CompileStatic
class Test70 {

	void foo() {
		Object v1 = 'a'
		Object v2 = 'b'
		[v1, v2].each {
			v ->
			if(v instanceof Map) {
				v.entrySet().each { e ->
					def s = e.value
					if(s instanceof String)
					e.value = s.toUpperCase()
				}
			}
		}
	}
}

An error is given on both occurrences of e.value, because e is evaluated as Object instead of Map.Entry.
This used to work until some version of the Greclipse plugin (now I'm on 4.3.0.v202107132103-e2009).
If I compile this with Gradle/Groovy, the JAR is built successfully.

If I remove @CompileStatic, I get underlining for v.entrySet() and again on both occurrences of e.value.

If I try to give e a type in the closure:

				v.entrySet().each { Entry e ->
					def s = e.value
					if(s instanceof String)
					e.value = s.toUpperCase()
				}

I see this:

  • with @CompileStatic an additional error is given on Entry, saying it's expecting Object.
  • without @CompileStatic, instead, the underlining for e.value is fixed, so the situation improves.

image

@mauromol mauromol changed the title Type inferencing error (only in Eclipse) Type inferencing error (only in Eclipse, not in groovyc) Jul 20, 2021
@eric-milles
Copy link
Member

eric-milles commented Jul 20, 2021

It is this change where the raw type Map is causing the return type of v.entrySet() to be changed to Set.

returnType = returnType.getPlainNodeReference(); // GROOVY-10049: do not return "Stream<E>" for raw type "List#stream()"

As a workaround, you can add a cast: ((Map<?,?>)v).entrySet() and you may also need to add a cast to v1 to stop the flow type of String.

image

This will be an issue for groovyc as well wherever GROOVY-10049 is addressed.

@eric-milles eric-milles added this to the v4.3.0 milestone Jul 20, 2021
@eric-milles eric-milles self-assigned this Jul 20, 2021
@eric-milles
Copy link
Member

Here are forms that should work the same; v.entrySet().each { e -> can be expressed as v.each { e -> or for (e in v) {:

@groovy.transform.TypeChecked
void test() {
  Object v1 = 'a'
  Object v2 = 'b'
  [v1, v2].each { v ->
    if (v instanceof Map) {
      v.each { e ->
        def s = e.value
        if (s instanceof String)
          e.value = s.toUpperCase()
      }
    }
  }
}

STC should infer Entry for e through DGM static <K, V> Map<K, V> each(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure closure) for the first.

for (e in v) { and for (Map.Entry e in v) { both fail with similar errors but for (e in (Map)v) { does work. I'll have to investigate this later.

@eric-milles
Copy link
Member

ready to test

@mauromol
Copy link
Author

Version 4.3.0.v202107240018-e2009 fixes the problem for me, thank you!

@mauromol
Copy link
Author

Still, if I remove @CompileStatic, I get two underlinings that shouldn't be there IMHO:

immagine

Should I open a new issue for this?

@eric-milles
Copy link
Member

In this specific case, it can be determined that the only possible type for "v" is String. So an "instanceof Map" check presents an inconvertible type and so Map is ignored. You can add a typecast to the list: [(Object)v1, v2] or to the declaration Object v1 = (Object)'a' if you wish.

@mauromol
Copy link
Author

Still, it's unexpected that static type inference and dynamic type inference behave in different ways in this example...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants