[ https://issues.apache.org/jira/browse/GROOVY-8788?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17582810#comment-17582810 ]
Jochen Theodorou commented on GROOVY-8788: ------------------------------------------ [~emilles] I think your analysis so far is very spot on. Sorry for writing so much text all the time, but I think it is important that I explain you a bit my thinking, not only the result. {code:Java} void testPutWithWrongValueType() { shouldFailWithMessages ''' def map = new HashMap<String, Integer>() map.put('hello', new Object()) ''', 'Cannot find matching method java.util.HashMap#put(java.lang.String, java.lang.Object). Please check if the declared type is correct and if the method exists.' } {code} This test passes now, but should have failed. It is not about getAt though. Map#put(K,V) is then not the selected method here - which makes sense, since it is not fitting. But there is no DGM for this either. So what method is actually selected here? There might be more like this. Of course the majority is, as you mentioned because of Object#getAt(String):Object being selected over Map<K,V>#getAt(Object):V To solve this I see a couple of possibilities which I all don't like all that much. The problem is that the tests IMHO show the desired behavior. Changing them would not only mean breaking existing code most likely, but also - to avoid that - further work. So I am not really for this, unless we make that a blocking issue for the next release. So my take on this is, fix the tests if you want this PR going through, but document all the failing tests with a new blocking issue and there is the danger of having to revert more than just the test changes. What I would prefer is adding commits to this PR to try find a solution. but I think some more discussion is required. So maybe may thoughts on possible solutions: (1) replace Map<K,V>#getAt(Object):V with Map<K,V>#getAt(K):V. This raises of course the question of if this even shadows (and even should do so) the Object method. A Map<?,V> could be super troublesome here. And of course this signature is not aligned with the normal get-method Map has. I personally think that having getAt more specific would be no problem, you still have get for the strange things where you use a key from a different class with same hashcode and accordingly behaving equals method - which should be super rare. And I do not see a requirement to honor the old contract of Map here. But as I said.. should this really be preferred over the Object variant in case of Map<?,V>. Or maybe it would be worth it, even if this fails in method selection? I think it would. It is kind of my preferred solution without knowing all the implications of course (2) change Object#getAt(String) to Object#getAt(Object). This change would require that we try to convert the argument to String in the getAt method. As in (1) Map<String,V> would then be no problem. And as in (1) Map<?,V> could be a problem. Actually again we have to ask what method is preferred by the static compiler and which should be. And again I do not care about a method selection error during compile time here. But this would be a breaking change whenever somebody made at getAt(String) method with @Override - unless our implementation of this does not check for DGM. though the question here is then if that is correct. (3) add Map<K, V>#getAt(String). This would mean to have it additionally to Map<K,V>#getAt(Object). Here we would have to clear if there is a case of Map#get(String) being called instead of Object#getAt(String) as part of the MOP is possible. It is not get, but getAt, so there might be no conflict. But there are direct calls to getAt as part of the meta class to map property/attribute access I think. And is it then right to call Object#getAt(String) instead of Map#getAt(String)? For me all 3 of them have potential of breaking code. > Inconsistency in extension method selection with @CompileStatic > --------------------------------------------------------------- > > Key: GROOVY-8788 > URL: https://issues.apache.org/jira/browse/GROOVY-8788 > Project: Groovy > Issue Type: Bug > Components: Static compilation, Static Type Checker > Affects Versions: 2.4.15, 2.5.2 > Reporter: Daniil Ovchinnikov > Assignee: Eric Milles > Priority: Major > Labels: breaking > > Given properly registered extension class: > {code:java|title=MyExtensions.java} > public class MyExtensions { > public static void foo(Object self, String s) { > System.out.println("Object#foo(String)"); > } > public static void foo(String self, Object o) { > System.out.println("String#foo(Object)"); > } > } > {code} > Run > {code:java|title=playground.groovy} > void usageExt() { > "".foo("") // prints "Object#foo(String)" which is correct > } > @groovy.transform.CompileStatic > void usageExtStatic() { > "".foo("") // prints "String#foo(Object)" which is questionable > } > usageExt() > usageExtStatic() > {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)