[
https://issues.apache.org/jira/browse/GROOVY-11916?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18143177#comment-18143177
]
ASF GitHub Bot commented on GROOVY-11916:
-----------------------------------------
blackdrag commented on code in PR #3227:
URL: https://github.com/apache/groovy/pull/3227#discussion_r4542807437
##########
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:
> package pb;
> public class String {}
>
> package user;
> import pb.*;
> class Use { String s; }
>
> javac: `reference to String is ambiguous, both class pb.String in pb and
class java.lang.String in java.lang match`. An explicit `import java.lang.*` is
redundant with the implicit one (JLS 7.5.2) and does not change that. If
`pb.String` is package-private, the star imports nothing and the name is
`java.lang.String`. There is no access error on `pb.String`. Row 3's "resolved
to c.X, error if not accessible" is the opposite on both counts: the accessible
`java.lang` type is not hidden, and the inaccessible one is not bound.
Meaning this is a breaking change, and going away from the old guiding
principle: declared imports shadow default imports.
> Groovy's other default imports (`java.util`, `java.io`, `java.net`,
`java.time`, `groovy.lang`, `groovy.util`, plus `BigInteger` and `BigDecimal`)
are not the JLS implicit import. Putting them in the same tier as a star the
user wrote would reject programs javac accepts:
>
> import java.sql.*;
> class Use { Date d; } // javac: java.sql.Date
>
> import java.awt.*;
> class Use { List x; } // javac: java.awt.List
why do we special case them? Do we want to comply with the JLS or with how
javac behaves? What about custom default star imports?
> Both are one accessible type-import-on-demand. `java.util.Date` and
`java.util.List` are not in scope in Java. They stay below explicit stars here,
so those two programs keep the javac result. They also stay below module
imports: `import module java.desktop` binds `List` to `java.awt.List`, and an
explicit `import java.util.*` shadows that, which is the JLS 6.4.1 order
`ImportTest` already locks. What does become ambiguous is two stars the user
actually wrote:
>
> import java.util.*;
> import java.sql.*;
> class Use { Date d; } // javac: ambiguous, either order
current Groovy uses the first import to resolve Date. Another breaking
change.
> The cases above are `testExplicitStarImportMatrixMatchesJavac`,
`testSamePackageTypeShadowsOnDemandImports`,
`testJavaLangOnDemandTiesWithExplicitStars`,
`testStaticOnDemandImportsAreAmbiguous`,
`testExtraDefaultImportsDoNotTieWithExplicitStars`,
`testSingleTypeImportShadowsOnDemand` and `testJavaLangShadowsModuleImports`.
`NamedVariantTransformTest` and `testSingletonGuice` show case breaking
changes. The tests you name are not part of this PR. And at least
`testExplicitStarImportMatrixMatchesJavac` is not in main as far as I can tell.
I did not check the others
> 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)