8005179: Cleanup Resolve.AmbiguityError

Tue, 08 Jan 2013 10:16:26 +0100

author
mcimadamore
date
Tue, 08 Jan 2013 10:16:26 +0100
changeset 1480
db91d860156a
parent 1479
38d3d1027f5a
child 1481
d07340b61e6a

8005179: Cleanup Resolve.AmbiguityError
Summary: Linearize nested ambiguity errors
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/comp/Resolve.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType21.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType21.out file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Jan 08 10:15:30 2013 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Jan 08 10:16:26 2013 +0100
     1.3 @@ -1122,52 +1122,20 @@
     1.4                  if (m1Abstract && !m2Abstract) return m2;
     1.5                  if (m2Abstract && !m1Abstract) return m1;
     1.6                  // both abstract or both concrete
     1.7 -                if (!m1Abstract && !m2Abstract)
     1.8 -                    return ambiguityError(m1, m2);
     1.9 -                // check that both signatures have the same erasure
    1.10 -                if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
    1.11 -                                       m2.erasure(types).getParameterTypes()))
    1.12 -                    return ambiguityError(m1, m2);
    1.13 -                // both abstract, neither overridden; merge throws clause and result type
    1.14 -                Type mst = mostSpecificReturnType(mt1, mt2);
    1.15 -                if (mst == null) {
    1.16 -                    // Theoretically, this can't happen, but it is possible
    1.17 -                    // due to error recovery or mixing incompatible class files
    1.18 -                    return ambiguityError(m1, m2);
    1.19 -                }
    1.20 -                Symbol mostSpecific = mst == mt1 ? m1 : m2;
    1.21 -                List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
    1.22 -                Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
    1.23 -                MethodSymbol result = new MethodSymbol(
    1.24 -                        mostSpecific.flags(),
    1.25 -                        mostSpecific.name,
    1.26 -                        newSig,
    1.27 -                        mostSpecific.owner) {
    1.28 -                    @Override
    1.29 -                    public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
    1.30 -                        if (origin == site.tsym)
    1.31 -                            return this;
    1.32 -                        else
    1.33 -                            return super.implementation(origin, types, checkResult);
    1.34 -                        }
    1.35 -                    };
    1.36 -                return result;
    1.37 +                return ambiguityError(m1, m2);
    1.38              }
    1.39              if (m1SignatureMoreSpecific) return m1;
    1.40              if (m2SignatureMoreSpecific) return m2;
    1.41              return ambiguityError(m1, m2);
    1.42          case AMBIGUOUS:
    1.43 +            //check if m1 is more specific than all ambiguous methods in m2
    1.44              AmbiguityError e = (AmbiguityError)m2;
    1.45 -            Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
    1.46 -            Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
    1.47 -            if (err1 == err2) return err1;
    1.48 -            if (err1 == e.sym && err2 == e.sym2) return m2;
    1.49 -            if (err1 instanceof AmbiguityError &&
    1.50 -                err2 instanceof AmbiguityError &&
    1.51 -                ((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
    1.52 -                return ambiguityError(m1, m2);
    1.53 -            else
    1.54 -                return ambiguityError(err1, err2);
    1.55 +            for (Symbol s : e.ambiguousSyms) {
    1.56 +                if (mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs) != m1) {
    1.57 +                    return e.addAmbiguousSymbol(m1);
    1.58 +                }
    1.59 +            }
    1.60 +            return m1;
    1.61          default:
    1.62              throw new AssertionError();
    1.63          }
    1.64 @@ -2504,6 +2472,10 @@
    1.65  
    1.66          @Override
    1.67          Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
    1.68 +            if (sym.kind == AMBIGUOUS) {
    1.69 +                AmbiguityError a_err = (AmbiguityError)sym;
    1.70 +                sym = a_err.mergeAbstracts(site);
    1.71 +            }
    1.72              if (sym.kind >= AMBIGUOUS) {
    1.73                  //if nothing is found return the 'first' error
    1.74                  sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
    1.75 @@ -2559,6 +2531,10 @@
    1.76          abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
    1.77  
    1.78          Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
    1.79 +            if (sym.kind == AMBIGUOUS) {
    1.80 +                AmbiguityError a_err = (AmbiguityError)sym;
    1.81 +                sym = a_err.mergeAbstracts(site);
    1.82 +            }
    1.83              //skip error reporting
    1.84              return sym;
    1.85          }
    1.86 @@ -2994,9 +2970,7 @@
    1.87  
    1.88          @Override
    1.89          public Symbol access(Name name, TypeSymbol location) {
    1.90 -            if (sym.kind >= AMBIGUOUS)
    1.91 -                return ((ResolveError)sym).access(name, location);
    1.92 -            else if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
    1.93 +            if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
    1.94                  return types.createErrorType(name, location, sym.type).tsym;
    1.95              else
    1.96                  return sym;
    1.97 @@ -3318,14 +3292,32 @@
    1.98       * (either methods, constructors or operands) are ambiguous
    1.99       * given an actual arguments/type argument list.
   1.100       */
   1.101 -    class AmbiguityError extends InvalidSymbolError {
   1.102 +    class AmbiguityError extends ResolveError {
   1.103  
   1.104          /** The other maximally specific symbol */
   1.105 -        Symbol sym2;
   1.106 +        List<Symbol> ambiguousSyms = List.nil();
   1.107 +
   1.108 +        @Override
   1.109 +        public boolean exists() {
   1.110 +            return true;
   1.111 +        }
   1.112  
   1.113          AmbiguityError(Symbol sym1, Symbol sym2) {
   1.114 -            super(AMBIGUOUS, sym1, "ambiguity error");
   1.115 -            this.sym2 = sym2;
   1.116 +            super(AMBIGUOUS, "ambiguity error");
   1.117 +            ambiguousSyms = flatten(sym2).appendList(flatten(sym1));
   1.118 +        }
   1.119 +
   1.120 +        private List<Symbol> flatten(Symbol sym) {
   1.121 +            if (sym.kind == AMBIGUOUS) {
   1.122 +                return ((AmbiguityError)sym).ambiguousSyms;
   1.123 +            } else {
   1.124 +                return List.of(sym);
   1.125 +            }
   1.126 +        }
   1.127 +
   1.128 +        AmbiguityError addAmbiguousSymbol(Symbol s) {
   1.129 +            ambiguousSyms = ambiguousSyms.prepend(s);
   1.130 +            return this;
   1.131          }
   1.132  
   1.133          @Override
   1.134 @@ -3336,24 +3328,60 @@
   1.135                  Name name,
   1.136                  List<Type> argtypes,
   1.137                  List<Type> typeargtypes) {
   1.138 -            AmbiguityError pair = this;
   1.139 -            while (true) {
   1.140 -                if (pair.sym.kind == AMBIGUOUS)
   1.141 -                    pair = (AmbiguityError)pair.sym;
   1.142 -                else if (pair.sym2.kind == AMBIGUOUS)
   1.143 -                    pair = (AmbiguityError)pair.sym2;
   1.144 -                else break;
   1.145 -            }
   1.146 -            Name sname = pair.sym.name;
   1.147 -            if (sname == names.init) sname = pair.sym.owner.name;
   1.148 +            List<Symbol> diagSyms = ambiguousSyms.reverse();
   1.149 +            Symbol s1 = diagSyms.head;
   1.150 +            Symbol s2 = diagSyms.tail.head;
   1.151 +            Name sname = s1.name;
   1.152 +            if (sname == names.init) sname = s1.owner.name;
   1.153              return diags.create(dkind, log.currentSource(),
   1.154                        pos, "ref.ambiguous", sname,
   1.155 -                      kindName(pair.sym),
   1.156 -                      pair.sym,
   1.157 -                      pair.sym.location(site, types),
   1.158 -                      kindName(pair.sym2),
   1.159 -                      pair.sym2,
   1.160 -                      pair.sym2.location(site, types));
   1.161 +                      kindName(s1),
   1.162 +                      s1,
   1.163 +                      s1.location(site, types),
   1.164 +                      kindName(s2),
   1.165 +                      s2,
   1.166 +                      s2.location(site, types));
   1.167 +        }
   1.168 +
   1.169 +        /**
   1.170 +         * If multiple applicable methods are found during overload and none of them
   1.171 +         * is more specific than the others, attempt to merge their signatures.
   1.172 +         */
   1.173 +        Symbol mergeAbstracts(Type site) {
   1.174 +            Symbol fst = ambiguousSyms.last();
   1.175 +            Symbol res = fst;
   1.176 +            for (Symbol s : ambiguousSyms.reverse()) {
   1.177 +                Type mt1 = types.memberType(site, res);
   1.178 +                Type mt2 = types.memberType(site, s);
   1.179 +                if ((s.flags() & ABSTRACT) == 0 ||
   1.180 +                        !types.overrideEquivalent(mt1, mt2) ||
   1.181 +                        !types.isSameTypes(fst.erasure(types).getParameterTypes(),
   1.182 +                                       s.erasure(types).getParameterTypes())) {
   1.183 +                    //ambiguity cannot be resolved
   1.184 +                    return this;
   1.185 +                } else {
   1.186 +                    Type mst = mostSpecificReturnType(mt1, mt2);
   1.187 +                    if (mst == null) {
   1.188 +                        // Theoretically, this can't happen, but it is possible
   1.189 +                        // due to error recovery or mixing incompatible class files
   1.190 +                        return this;
   1.191 +                    }
   1.192 +                    Symbol mostSpecific = mst == mt1 ? res : s;
   1.193 +                    List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
   1.194 +                    Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
   1.195 +                    res = new MethodSymbol(
   1.196 +                            mostSpecific.flags(),
   1.197 +                            mostSpecific.name,
   1.198 +                            newSig,
   1.199 +                            mostSpecific.owner);
   1.200 +                }
   1.201 +            }
   1.202 +            return res;
   1.203 +        }
   1.204 +
   1.205 +        @Override
   1.206 +        protected Symbol access(Name name, TypeSymbol location) {
   1.207 +            return ambiguousSyms.last();
   1.208          }
   1.209      }
   1.210  
     2.1 --- a/test/tools/javac/lambda/TargetType21.java	Tue Jan 08 10:15:30 2013 +0100
     2.2 +++ b/test/tools/javac/lambda/TargetType21.java	Tue Jan 08 10:16:26 2013 +0100
     2.3 @@ -25,7 +25,7 @@
     2.4      <R,A> void call(SAM3<R,A> sam) { }
     2.5  
     2.6      void test() {
     2.7 -        call(x -> { throw new Exception(); }); //ok - resolves to call(SAM1)
     2.8 +        call(x -> { throw new Exception(); }); //ambiguous
     2.9          call(x -> { System.out.println(""); }); //ok - resolves to call(SAM2)
    2.10          call(x -> { return (Object) null; }); //error - call(SAM3) is not applicable because of cyclic inference
    2.11          call(x -> { return null; }); ////ok - resolves to call(SAM1)
     3.1 --- a/test/tools/javac/lambda/TargetType21.out	Tue Jan 08 10:15:30 2013 +0100
     3.2 +++ b/test/tools/javac/lambda/TargetType21.out	Tue Jan 08 10:16:26 2013 +0100
     3.3 @@ -1,3 +1,3 @@
     3.4  TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM2), TargetType21
     3.5 -TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @755,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
     3.6 +TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @737,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
     3.7  2 errors

mercurial