[ 
https://issues.apache.org/jira/browse/GROOVY-11916?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18143265#comment-18143265
 ] 

ASF GitHub Bot commented on GROOVY-11916:
-----------------------------------------

daniellansun commented on code in PR #3227:
URL: https://github.com/apache/groovy/pull/3227#discussion_r4544238289


##########
src/main/java/org/codehaus/groovy/control/ResolveVisitor.java:
##########
@@ -750,7 +750,7 @@ protected boolean resolveFromDefaultImports(final ClassNode 
type, final String[]
             // WARNING: This code does not expect a class that has a static
             //          inner class in DEFAULT_IMPORTS
             ConstructedClassWithPackage tmp = new 
ConstructedClassWithPackage(packagePrefix, typeName);
-            if (resolve(tmp, false, false, false)) {
+            if (resolve(tmp, false, false, false) && 
isStarImportAccessible(tmp, null)) {

Review Comment:
   Jochen,
   
   You are right about both breaking changes, and the follow-up restores the 
older rule.
   
   A declared import shadows the default imports, including `java.lang`. 
`import pb.*; class Use { String s }` with a public `pb.String` is `pb.String` 
again. It is not ambiguous with `java.lang.String`, and it is not 
`java.lang.String`. Making that a tie was a breaking change. The 
program-structure page lists `java.lang.*` in the same default-import list as 
`java.util.*`, `java.io.*`, `java.net.*`, `java.time.*`, `groovy.lang.*`, 
`groovy.util.*`, `BigInteger`, and `BigDecimal`. Those are the imports Groovy 
adds so the boilerplate can be left out. A source import shadows that whole 
list. `java.lang` is not a special case that ties with a star the user wrote.
   
   That is also why the extra defaults were kept below a source star in the 
previous commit, and why they stay there. `import java.sql.*; Date` is 
`java.sql.Date`, not `java.util.Date`. `import java.awt.*; List` is 
`java.awt.List`. Under the same list, `java.lang` does not get a different rule 
from `java.util`.
   
   Two source star imports are first-match in source order again, not an 
ambiguity error. `import java.util.*; import java.sql.*; Date` is 
`java.util.Date`. The reverse order is `java.sql.Date`. The star-import 
section's answer to a cluttered namespace is aliasing. The error the page 
actually states is two simple imports of the same name (`import java.awt.List; 
import java.util.List`), or a simple import and a top-level type of that name. 
This is not the Generics section, so I am not applying the JLS on-demand tie 
here.
   
   An `ImportCustomizer` star sits below imports written in the source and 
above that language list. A source star or a source single-type import hides 
it. With no source import, `star 'java.sql'` still binds `Date` to 
`java.sql.Date`, and a customizer star of a public `pb.String` binds 
`pb.String`, without an ambiguity error against `java.lang` or `java.util`. It 
still does not bind an inaccessible type. A simple import added by the 
customizer stays a simple import: it still conflicts with another simple import 
of the same name, which is the case `ImportTest` already covers for `Proxy`.
   
   GROOVY-11916 itself stands. A star import, a module import, a default 
import, and a customizer star bind only a type that is accessible from the 
importing class. `import java.util.*` does not bind `java.util.TimSort`. An 
inaccessible type is not a candidate, so it does not hide a later accessible 
type and it is not reported as "not public" after being bound. A 
package-private type in the same package, a protected member type used from a 
subclass, and a private member type used from the enclosing nest stay visible. 
An explicit single-type import, a fully qualified name, and `Class.forName` 
still resolve `TimSort`. I am not adding an access diagnostic for those forms.
   
   `import static pb.Holder.*` follows the same idea. It shadows the defaults, 
so a public static member type `String` or `Date` is the member type, not 
`java.lang.String` or `java.util.Date`. Two source static stars use source 
order. A package-private static member type is not imported. The static-import 
section talks about overloading and about an imported method taking precedence 
when the signature matches. It does not make two stars an ambiguity error.
   
   A module import is the star imports of the packages that module exports, 
placed at that statement. `import module java.desktop` then `import 
java.util.*` keeps `java.awt.List`, because the module import is earlier. The 
reverse order keeps `java.util.List`. `import java.util.List` still wins over 
the module, which is the priority the documentation states. If one module 
exports two public types with the same simple name, the first accessible export 
is used rather than a compile error; a single-type import is how you name the 
other one. `import module java.base; String` remains `java.lang.String`, 
because `java.lang` is already a language default.
   
   The `NamedVariantTransformTest` and Guice tweaks were only there so those 
programs would compile under the ambiguity rule. Both are reverted. 
`NamedVariantTransformTest` is back to `star 'groovy.transform', 
'org.codehaus.groovy.ast'`. `ASTTest` is `groovy.transform.ASTTest` again 
because that star is configured first; the other candidate is the test class 
`org.codehaus.groovy.ast.ASTTest`. The Guice example says `as Module` again: 
`import com.google.inject.*` is a declared star, so `Module` is 
`com.google.inject.Module`, not `java.lang.Module`.
   
   The tests that were not on main are in the second commit on this PR, 
`4e761587`: `Groovy11916.groovy`, the qualified Guice `Module`, and the extra 
`ASTTest` import. This follow-up rewrites the cases that expected a javac-style 
tie (a source star against `java.lang`, two source stars, and two static stars) 
and restores those two test tweaks. The accessibility tests from the first 
commit stay.
   





> Star imports should not resolve package-private types
> -----------------------------------------------------
>
>                 Key: GROOVY-11916
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11916
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Priority: Major
>
> Groovy's star import resolution (e.g., import java.util.*) currently includes 
> package-private classes in name resolution. On modern JDKs (9+) with the 
> module system, these classes cannot actually be used — attempts result in 
> IllegalAccessError at runtime. This can lead to confusing errors and 
> inconsistency with Java's behaviour where star imports only resolve public 
> types.
> For example, import java.util.* allows def cls = TimSort to compile 
> (resolving the package-private java.util.TimSort), but any actual usage 
> (instanceof, construction, method calls) fails at runtime with 
> IllegalAccessError.
> {code:groovy}
> import java.util.*
> assert String.modifiers == 17
> def cls = TimSort     // fine
> assert cls.modifiers == 0
> println cls           // => class java.util.TimSort
> println Class.forName('java.util.TimSort') // => class java.util.TimSort
> println new Object() instanceof TimSort // IllegalAccessError
> {code}
> Having said that, as a counter example, is it really any different than being 
> able to get the class via Class.forName?
> If the Java behavior is deemed correct, the fix would be to filter non-public 
> classes during star import resolution in ResolveVisitor, producing a clean 
> compile-time error instead of a runtime error. This is technically a breaking 
> change but only affects code that was already failing at runtime on modular 
> JDKs.
> This also benefits the import module feature (GROOVY-11896), which expands to 
> star imports — filtering at the resolution level means module imports 
> correctly include only public types, matching Java's import module semantics.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to