src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
changeset 50898 12133a6e2613
parent 50564 ef7c4c77d9fa
child 51563 de411d537aae
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Jun 28 17:49:13 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Jun 29 10:41:10 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.source.tree.NewClassTree;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Type.ErrorType;
+import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Type.StructuralTypeMapping;
 import com.sun.tools.javac.code.Types.TypeMapping;
 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
@@ -59,6 +61,7 @@
 import java.util.function.Function;
 
 import com.sun.source.tree.MemberReferenceTree;
+import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.tree.JCTree.JCMemberReference.OverloadKind;
 
 import static com.sun.tools.javac.code.TypeTag.*;
@@ -1002,7 +1005,7 @@
      * where T is computed by retrieving the type that has already been
      * computed for D during a previous deferred attribution round of the given kind.
      */
-    class DeferredTypeMap extends StructuralTypeMapping<Void> {
+    class DeferredTypeMap<T> extends StructuralTypeMapping<T> {
         DeferredAttrContext deferredAttrContext;
 
         protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
@@ -1011,16 +1014,16 @@
         }
 
         @Override
-        public Type visitType(Type t, Void _unused) {
+        public Type visitType(Type t, T p) {
             if (!t.hasTag(DEFERRED)) {
-                return super.visitType(t, null);
+                return super.visitType(t, p);
             } else {
                 DeferredType dt = (DeferredType)t;
-                return typeOf(dt);
+                return typeOf(dt, p);
             }
         }
 
-        protected Type typeOf(DeferredType dt) {
+        protected Type typeOf(DeferredType dt, T p) {
             switch (deferredAttrContext.mode) {
                 case CHECK:
                     return dt.tree.type == null ? Type.noType : dt.tree.type;
@@ -1039,17 +1042,35 @@
      * attribution round (as before), or (ii) by synthesizing a new type R for D
      * (the latter step is useful in a recovery scenario).
      */
-    public class RecoveryDeferredTypeMap extends DeferredTypeMap {
+    public class RecoveryDeferredTypeMap extends DeferredTypeMap<Type> {
 
         public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
             super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
         }
 
         @Override
-        protected Type typeOf(DeferredType dt) {
-            Type owntype = super.typeOf(dt);
+        protected Type typeOf(DeferredType dt, Type pt) {
+            Type owntype = super.typeOf(dt, pt);
             return owntype == Type.noType ?
-                        recover(dt) : owntype;
+                        recover(dt, pt) : owntype;
+        }
+
+        @Override
+        public Type visitMethodType(Type.MethodType t, Type pt) {
+            if (t.hasTag(METHOD) && deferredAttrContext.mode == AttrMode.CHECK) {
+                Type mtype = deferredAttrContext.msym.type;
+                mtype = mtype.hasTag(ERROR) ? ((ErrorType)mtype).getOriginalType() : null;
+                if (mtype != null && mtype.hasTag(METHOD)) {
+                    List<Type> argtypes1 = map(t.getParameterTypes(), mtype.getParameterTypes());
+                    Type restype1 = visit(t.getReturnType(), mtype.getReturnType());
+                    List<Type> thrown1 = map(t.getThrownTypes(), mtype.getThrownTypes());
+                    if (argtypes1 == t.getParameterTypes() &&
+                        restype1 == t.getReturnType() &&
+                        thrown1 == t.getThrownTypes()) return t;
+                    else return new MethodType(argtypes1, restype1, thrown1, t.tsym);
+                }
+            }
+            return super.visitMethodType(t, pt);
         }
 
         /**
@@ -1059,8 +1080,8 @@
          * representation. Remaining deferred types are attributed using
          * a default expected type (j.l.Object).
          */
-        private Type recover(DeferredType dt) {
-            dt.check(attr.new RecoveryInfo(deferredAttrContext) {
+        private Type recover(DeferredType dt, Type pt) {
+            dt.check(attr.new RecoveryInfo(deferredAttrContext, pt != null ? pt : Type.recoveryType) {
                 @Override
                 protected Type check(DiagnosticPosition pos, Type found) {
                     return chk.checkNonVoid(pos, super.check(pos, found));
@@ -1068,6 +1089,16 @@
             });
             return super.visit(dt);
         }
+
+        private List<Type> map(List<Type> ts, List<Type> pts) {
+            if (ts.nonEmpty()) {
+                List<Type> tail1 = map(ts.tail, pts != null ? pts.tail : null);
+                Type t = visit(ts.head, pts != null && pts.nonEmpty() ? pts.head : null);
+                if (tail1 != ts.tail || t != ts.head)
+                    return tail1.prepend(t);
+            }
+            return ts;
+        }
     }
 
     /**