You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/07/29 13:37:33 UTC

[groovy] branch GROOVY_4_0_X updated (46bc5eedd7 -> baff9bd152)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


    from 46bc5eedd7 GROOVY-10704: retain order of field-related methods
     new 437ca6abf8 GROOVY-8487: SC: for-in loop over iterator
     new baff9bd152 minor edits

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 38 +++-------------------
 .../codehaus/groovy/classgen/ExtendedVerifier.java |  5 ++-
 .../org/codehaus/groovy/classgen/Verifier.java     |  2 +-
 .../asm/sc/StaticTypesStatementWriter.java         | 36 +++++++++++---------
 .../groovy/control/CompilerConfiguration.java      | 35 +++++++-------------
 .../codehaus/groovy/control/ProcessingUnit.java    |  1 +
 .../groovy/runtime/DefaultGroovyMethods.java       |  3 +-
 .../transform/RecordTypeASTTransformation.java     |  5 ++-
 .../TupleConstructorASTTransformation.java         |  9 +++--
 .../transform/stc/StaticTypeCheckingSupport.java   |  4 +++
 src/test/groovy/transform/stc/LoopsSTCTest.groovy  | 22 +++++++++++++
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 11 -------
 12 files changed, 75 insertions(+), 96 deletions(-)


[groovy] 02/02: minor edits

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit baff9bd152d3947c7b8038dc4ea14671e17ea972
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 29 08:14:06 2022 -0500

    minor edits
---
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 38 +++-------------------
 .../codehaus/groovy/classgen/ExtendedVerifier.java |  5 ++-
 .../org/codehaus/groovy/classgen/Verifier.java     |  2 +-
 .../groovy/control/CompilerConfiguration.java      | 35 +++++++-------------
 .../codehaus/groovy/control/ProcessingUnit.java    |  1 +
 .../transform/RecordTypeASTTransformation.java     |  5 ++-
 .../TupleConstructorASTTransformation.java         |  9 +++--
 .../transform/stc/StaticTypeCheckingSupport.java   |  4 +++
 8 files changed, 31 insertions(+), 68 deletions(-)

diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 485243c865..8997dedd43 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -35,7 +35,6 @@ import org.antlr.v4.runtime.misc.Interval;
 import org.antlr.v4.runtime.misc.ParseCancellationException;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
-import org.apache.groovy.parser.antlr4.GroovyParser.*;
 import org.apache.groovy.parser.antlr4.internal.DescriptiveErrorStrategy;
 import org.apache.groovy.parser.antlr4.internal.atnmanager.AtnManager;
 import org.apache.groovy.parser.antlr4.util.StringUtils;
@@ -149,34 +148,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static groovy.lang.Tuple.tuple;
-import static org.apache.groovy.parser.antlr4.GroovyParser.ADD;
-import static org.apache.groovy.parser.antlr4.GroovyParser.ARROW;
-import static org.apache.groovy.parser.antlr4.GroovyParser.AS;
-import static org.apache.groovy.parser.antlr4.GroovyParser.CASE;
-import static org.apache.groovy.parser.antlr4.GroovyParser.DEC;
-import static org.apache.groovy.parser.antlr4.GroovyParser.DEF;
-import static org.apache.groovy.parser.antlr4.GroovyParser.DEFAULT;
-import static org.apache.groovy.parser.antlr4.GroovyParser.FINAL;
-import static org.apache.groovy.parser.antlr4.GroovyParser.GE;
-import static org.apache.groovy.parser.antlr4.GroovyParser.GT;
-import static org.apache.groovy.parser.antlr4.GroovyParser.IN;
-import static org.apache.groovy.parser.antlr4.GroovyParser.INC;
-import static org.apache.groovy.parser.antlr4.GroovyParser.INSTANCEOF;
-import static org.apache.groovy.parser.antlr4.GroovyParser.LE;
-import static org.apache.groovy.parser.antlr4.GroovyParser.LT;
-import static org.apache.groovy.parser.antlr4.GroovyParser.NON_SEALED;
-import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_IN;
-import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_INSTANCEOF;
-import static org.apache.groovy.parser.antlr4.GroovyParser.PRIVATE;
-import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_FULL;
-import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_LEFT;
-import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_RIGHT;
-import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_INCLUSIVE;
-import static org.apache.groovy.parser.antlr4.GroovyParser.SAFE_INDEX;
-import static org.apache.groovy.parser.antlr4.GroovyParser.SEALED;
-import static org.apache.groovy.parser.antlr4.GroovyParser.STATIC;
-import static org.apache.groovy.parser.antlr4.GroovyParser.SUB;
-import static org.apache.groovy.parser.antlr4.GroovyParser.VAR;
+import static org.apache.groovy.parser.antlr4.GroovyParser.*;
 import static org.apache.groovy.parser.antlr4.util.PositionConfigureUtils.configureAST;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
@@ -429,6 +401,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
         // TODO: shared instances
         return node;
     }
+
     // statement { -------------------------------------------------------------
 
     @Override
@@ -1274,12 +1247,12 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
         boolean isRecord = asBoolean(ctx.RECORD());
         boolean hasRecordHeader = asBoolean(ctx.formalParameters());
         if (isRecord) {
-            if (asBoolean(ctx.EXTENDS())) {
-                throw createParsingFailedException("No extends clause allowed for record declaration", ctx.EXTENDS());
-            }
             if (!hasRecordHeader) {
                 throw createParsingFailedException("header declaration of record is expected", ctx.identifier());
             }
+            if (asBoolean(ctx.EXTENDS())) {
+                throw createParsingFailedException("No extends clause allowed for record declaration", ctx.EXTENDS());
+            }
             if (isSealed) {
                 throw createParsingFailedException("`sealed` is not allowed for record declaration", sealedModifier.get());
             }
@@ -4166,7 +4139,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
             if (!asBoolean(ctx.type())) {
                 GenericsType genericsType = new GenericsType(baseType);
                 genericsType.setWildcard(true);
-                genericsType.setName(QUESTION_STR);
 
                 return configureAST(genericsType, ctx);
             }
diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 715d641a4c..1d587c362d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -275,9 +275,8 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport {
         }
         this.currentClass.setAnnotated(true);
         Map<String, List<AnnotationNode>> nonSourceAnnotations = new LinkedHashMap<>();
-        boolean skippable = node.getNodeMetaData("_SKIPPABLE_ANNOTATIONS") != null;
-        Iterator<AnnotationNode> iterator = annotations.iterator();
-        while (iterator.hasNext()) {
+        boolean skippable = Boolean.TRUE.equals(node.getNodeMetaData("_SKIPPABLE_ANNOTATIONS"));
+        for (Iterator<AnnotationNode> iterator = annotations.iterator(); iterator.hasNext(); ) {
             AnnotationNode unvisited = iterator.next();
             AnnotationNode visited;
             {
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 404d8fcbb1..d29925b789 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -839,7 +839,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
 
     private static void copyAnnotations(final PropertyNode node, final MethodNode accessor) {
         accessor.addAnnotations(node.getAnnotations());
-        accessor.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
+        accessor.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
     }
 
     protected void addPropertyMethod(final MethodNode method) {
diff --git a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
index 1654281f6a..1a686cfc4e 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
@@ -482,10 +482,9 @@ public class CompilerConfiguration {
         handleOptimizationOption(RUNTIME_GROOVYDOC, getSystemPropertySafe("groovy.attach.runtime.groovydoc"));
         handleOptimizationOption(PARALLEL_PARSE, getSystemPropertySafe("groovy.parallel.parse", "true"));
 
-        boolean memStubEnabled = Boolean.parseBoolean(getSystemPropertySafe("groovy.mem.stub", "false"));
-        if (memStubEnabled) {
+        if (getBooleanSafe("groovy.mem.stub")) {
             jointCompilationOptions = new HashMap<>(2);
-            jointCompilationOptions.put(MEM_STUB, memStubEnabled);
+            jointCompilationOptions.put(MEM_STUB, Boolean.TRUE);
         }
     }
 
@@ -512,7 +511,7 @@ public class CompilerConfiguration {
     public CompilerConfiguration(final CompilerConfiguration configuration) {
         setWarningLevel(configuration.getWarningLevel());
         setTargetDirectory(configuration.getTargetDirectory());
-        setClasspathList(new LinkedList<>(configuration.getClasspath()));
+        setClasspathList(configuration.getClasspath());
         setVerbose(configuration.getVerbose());
         setDebug(configuration.getDebug());
         setParameters(configuration.getParameters());
@@ -832,7 +831,6 @@ public class CompilerConfiguration {
         }
     }
 
-
     /**
      * Gets the currently configured warning level. See {@link WarningMessage}
      * for level details.
@@ -1096,9 +1094,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns the ASM bytecode version
+     * Returns the ASM bytecode version.
      *
-     * @return ASM bytecode version
      * @since 4.0.0
      */
     public int getBytecodeVersion() {
@@ -1117,9 +1114,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns the default target bytecode compatibility level
+     * Returns the default target bytecode compatibility level.
      *
-     * @return the default target bytecode compatibility level
      * @since 4.0.0
      */
     private static String defaultTargetBytecode() {
@@ -1149,9 +1145,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns whether logging class generation is enabled
+     * Returns whether logging class generation is enabled.
      *
-     * @return whether logging class generation is enabled
      * @since 4.0.0
      */
     public boolean isLogClassgen() {
@@ -1159,9 +1154,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Sets whether logging class generation is enabled
+     * Sets whether logging class generation is enabled.
      *
-     * @param logClassgen whether to enable logging class generation
      * @since 4.0.0
      */
     public void setLogClassgen(boolean logClassgen) {
@@ -1169,9 +1163,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns stack trace max depth of logging class generation
+     * Returns stack trace max depth of logging class generation.
      *
-     * @return stack trace max depth of logging class generation
      * @since 4.0.0
      */
     public int getLogClassgenStackTraceMaxDepth() {
@@ -1179,9 +1172,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Sets stack trace max depth of logging class generation
+     * Sets stack trace max depth of logging class generation.
      *
-     * @param logClassgenStackTraceMaxDepth stack trace max depth of logging class generation
      * @since 4.0.0
      */
     public void setLogClassgenStackTraceMaxDepth(int logClassgenStackTraceMaxDepth) {
@@ -1284,23 +1276,20 @@ public class CompilerConfiguration {
      * Checks if invoke dynamic is enabled.
      */
     public boolean isIndyEnabled() {
-        Boolean indyEnabled = getOptimizationOptions().get(INVOKEDYNAMIC);
-        return Optional.ofNullable(indyEnabled).orElse(Boolean.TRUE);
+        return !Boolean.FALSE.equals(getOptimizationOptions().get(INVOKEDYNAMIC));
     }
 
     /**
      * Checks if groovydoc is enabled.
      */
     public boolean isGroovydocEnabled() {
-        Boolean groovydocEnabled = getOptimizationOptions().get(GROOVYDOC);
-        return Optional.ofNullable(groovydocEnabled).orElse(Boolean.FALSE);
+        return Boolean.TRUE.equals(getOptimizationOptions().get(GROOVYDOC));
     }
 
     /**
      * Checks if runtime groovydoc is enabled.
      */
     public boolean isRuntimeGroovydocEnabled() {
-        Boolean runtimeGroovydocEnabled = getOptimizationOptions().get(RUNTIME_GROOVYDOC);
-        return Optional.ofNullable(runtimeGroovydocEnabled).orElse(Boolean.FALSE);
+        return Boolean.TRUE.equals(getOptimizationOptions().get(RUNTIME_GROOVYDOC));
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java b/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
index 8aca4f8197..5c744f3cf4 100644
--- a/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
@@ -110,6 +110,7 @@ public abstract class ProcessingUnit {
             return new GroovyClassLoader(parent, getConfiguration());
         });
     }
+
     /**
      * Errors found during the compilation should be reported through the ErrorCollector.
      */
diff --git a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
index e60ccaadb5..0cefcbc5f2 100644
--- a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
@@ -93,7 +93,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafeWithGenerics;
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static org.objectweb.asm.Opcodes.ACC_FINAL;
 import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
@@ -152,7 +151,7 @@ public class RecordTypeASTTransformation extends AbstractASTTransformation imple
 
     private void doProcessRecordType(ClassNode cNode, PropertyHandler handler) {
         if (cNode.getNodeMetaData("_RECORD_HEADER") != null) {
-            cNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
+            cNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
         }
         List<AnnotationNode> annotations = cNode.getAnnotations(RECORD_OPTIONS_TYPE);
         AnnotationNode options = annotations.isEmpty() ? null : annotations.get(0);
@@ -185,7 +184,7 @@ public class RecordTypeASTTransformation extends AbstractASTTransformation imple
                 type.setGenericsPlaceHolder(pType.isGenericsPlaceHolder());
                 type.setGenericsTypes(pType.getGenericsTypes());
                 RecordComponentNode rec = new RecordComponentNode(cNode, pNode.getName(), type, pNode.getAnnotations());
-                rec.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
+                rec.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
                 cNode.getRecordComponents().add(rec);
             }
         } else if (mode == RecordTypeMode.NATIVE) {
diff --git a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
index ac2d2505ce..8762b5d867 100644
--- a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
@@ -88,7 +88,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.transform.ImmutableASTTransformation.makeImmutable;
 import static org.codehaus.groovy.transform.NamedVariantASTTransformation.processImplicitNamedParam;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 
 /**
  * Handles generation of code for the @TupleConstructor annotation.
@@ -250,8 +249,8 @@ public class TupleConstructorASTTransformation extends AbstractASTTransformation
             Parameter nextParam = createParam(fNode, name, defaultsMode, xform, makeImmutable);
             if (cNode.getNodeMetaData("_RECORD_HEADER") != null) {
                 nextParam.addAnnotations(pNode.getAnnotations());
-                nextParam.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
-                fNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
+                nextParam.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
+                fNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
             }
             params.add(nextParam);
         }
@@ -275,11 +274,11 @@ public class TupleConstructorASTTransformation extends AbstractASTTransformation
         }
 
         boolean hasMapCons = AnnotatedNodeUtils.hasAnnotation(cNode, MapConstructorASTTransformation.MY_TYPE);
-        int modifiers = getVisibility(anno, cNode, ConstructorNode.class, ACC_PUBLIC);
+        int modifiers = getVisibility(anno, cNode, ConstructorNode.class, org.objectweb.asm.Opcodes.ACC_PUBLIC);
         ConstructorNode consNode = addGeneratedConstructor(cNode, modifiers, params.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, body);
         if (cNode.getNodeMetaData("_RECORD_HEADER") != null) {
             consNode.addAnnotations(cNode.getAnnotations());
-            consNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", true);
+            consNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
         }
         if (namedVariant) {
             BlockStatement inner = new BlockStatement();
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 659c268baf..557cdb1805 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -260,6 +260,10 @@ public abstract class StaticTypeCheckingSupport {
         EXTENSION_METHOD_CACHE.cache.clearAll();
     }
 
+    public static void clearExtensionMethodCache(final ClassLoader loader) {
+        EXTENSION_METHOD_CACHE.cache.remove(loader);
+    }
+
     /**
      * Returns true for expressions of the form x[...]
      *


[groovy] 01/02: GROOVY-8487: SC: for-in loop over iterator

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 437ca6abf8e9386c0217a40c74d0950efb23d35c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jul 28 16:35:49 2022 -0500

    GROOVY-8487: SC: for-in loop over iterator
---
 .../asm/sc/StaticTypesStatementWriter.java         | 36 ++++++++++++----------
 .../groovy/runtime/DefaultGroovyMethods.java       |  3 +-
 src/test/groovy/transform/stc/LoopsSTCTest.groovy  | 22 +++++++++++++
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 11 -------
 4 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
index a61d4a27b8..7334f99a97 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
@@ -219,23 +219,27 @@ public class StaticTypesStatementWriter extends StatementWriter {
     }
 
     private void writeIteratorBasedForEachLoop(final ForStatement loop, final Expression collectionExpression, final ClassNode collectionType) {
-        // GROOVY-10476: BaseStream provides an iterator() but does not implement Iterable
-        MethodNode iterator = collectionType.getMethod("iterator", Parameter.EMPTY_ARRAY);
-        if (iterator == null) {
-            iterator = GeneralUtils.getInterfacesAndSuperInterfaces(collectionType).stream()
-                    .map(in -> in.getMethod("iterator", Parameter.EMPTY_ARRAY))
-                    .filter(Objects::nonNull).findFirst().orElse(null);
-        }
-        if (iterator != null && iterator.getReturnType().equals(ClassHelper.Iterator_TYPE)) {
-            MethodCallExpression call = GeneralUtils.callX(collectionExpression, "iterator");
-            call.setImplicitThis(false);
-            call.setMethodTarget(iterator);
-            call.setSafe(true);//GROOVY-8643
-            call.visit(controller.getAcg());
+        if (GeneralUtils.isOrImplements(collectionType, ClassHelper.Iterator_TYPE)) {
+            collectionExpression.visit(controller.getAcg()); // GROOVY-8487: iterator supplied
         } else {
-            collectionExpression.visit(controller.getAcg());
-            controller.getMethodVisitor().visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/DefaultGroovyMethods", "iterator", "(Ljava/lang/Object;)Ljava/util/Iterator;", false);
-            controller.getOperandStack().replace(ClassHelper.Iterator_TYPE);
+            // GROOVY-10476: BaseStream provides an iterator() but does not implement Iterable
+            MethodNode iterator = collectionType.getMethod("iterator", Parameter.EMPTY_ARRAY);
+            if (iterator == null) {
+                iterator = GeneralUtils.getInterfacesAndSuperInterfaces(collectionType).stream()
+                        .map(in -> in.getMethod("iterator", Parameter.EMPTY_ARRAY))
+                        .filter(Objects::nonNull).findFirst().orElse(null);
+            }
+            if (iterator != null && iterator.getReturnType().equals(ClassHelper.Iterator_TYPE)) {
+                MethodCallExpression call = GeneralUtils.callX(collectionExpression, "iterator");
+                call.setImplicitThis(false);
+                call.setMethodTarget(iterator);
+                call.setSafe(true);//GROOVY-8643
+                call.visit(controller.getAcg());
+            } else {
+                collectionExpression.visit(controller.getAcg());
+                controller.getMethodVisitor().visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/DefaultGroovyMethods", "iterator", "(Ljava/lang/Object;)Ljava/util/Iterator;", false);
+                controller.getOperandStack().replace(ClassHelper.Iterator_TYPE);
+            }
         }
         writeForInLoopControlAndBlock(loop);
     }
diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index f9260d6b66..9402610ac8 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -18158,7 +18158,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @see org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation#asCollection(java.lang.Object)
      * @since 1.0
      */
-    public static Iterator iterator(Object o) {
+    public static Iterator iterator(final Object o) {
+        if (o instanceof Iterator) return (Iterator)o;
         return DefaultTypeTransformation.asCollection(o).iterator();
     }
 
diff --git a/src/test/groovy/transform/stc/LoopsSTCTest.groovy b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
index 123232a179..70039d5b55 100644
--- a/src/test/groovy/transform/stc/LoopsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
@@ -215,6 +215,17 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10476
+    void testForInLoopOnStream() {
+        assertScript '''
+            def list = []
+            for (item in ['a','b','c'].stream()) {
+                list.add(item.toUpperCase())
+            }
+            assert list == ['A','B','C']
+        '''
+    }
+
     // GROOVY-8882
     void testForInLoopOnString() {
         assertScript '''
@@ -227,6 +238,17 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-8487
+    void testForInLoopOnIterator() {
+        assertScript '''
+            def list = []
+            for (item in ['a','b','c'].iterator()) {
+                list.add(item)
+            }
+            assert list.join('') == 'abc'
+        '''
+    }
+
     // GROOVY-6123
     void testForInLoopOnEnumeration() {
         assertScript '''
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 792b8e3b7d..01c3d1d27d 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -1196,17 +1196,6 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         'Cannot call closure that accepts [java.lang.String, java.lang.String, java.lang.String] with '
     }
 
-    // GROOVY-10476
-    void testForInLoop() {
-        assertScript '''
-            def list = []
-            for (item in ['a','b','c'].stream()) {
-                list.add(item.toUpperCase())
-            }
-            assert list == ['A', 'B', 'C']
-        '''
-    }
-
     void testBoxingShouldCostMore() {
         assertScript '''
             int foo(int x) { 1 }