src/share/classes/com/sun/tools/javac/comp/Check.java

changeset 1393
d7d932236fee
parent 1384
bf54daa9dcd8
child 1415
01c9d4161882
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Sat Nov 03 21:09:57 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Sun Nov 04 10:59:42 2012 +0000
     1.3 @@ -119,6 +119,9 @@
     1.4          allowAnnotations = source.allowAnnotations();
     1.5          allowCovariantReturns = source.allowCovariantReturns();
     1.6          allowSimplifiedVarargs = source.allowSimplifiedVarargs();
     1.7 +        allowDefaultMethods = source.allowDefaultMethods();
     1.8 +        allowStrictMethodClashCheck = source.allowStrictMethodClashCheck() &&
     1.9 +                options.isSet("strictMethodClashCheck"); //pre-lambda guard
    1.10          complexInference = options.isSet("complexinference");
    1.11          warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
    1.12          suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
    1.13 @@ -162,6 +165,14 @@
    1.14       */
    1.15      boolean allowSimplifiedVarargs;
    1.16  
    1.17 +    /** Switch: default methods enabled?
    1.18 +     */
    1.19 +    boolean allowDefaultMethods;
    1.20 +
    1.21 +    /** Switch: should unrelated return types trigger a method clash?
    1.22 +     */
    1.23 +    boolean allowStrictMethodClashCheck;
    1.24 +
    1.25      /** Switch: -complexinference option set?
    1.26       */
    1.27      boolean complexInference;
    1.28 @@ -1114,7 +1125,7 @@
    1.29              }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
    1.30                  if ((flags & DEFAULT) != 0) {
    1.31                      mask = InterfaceDefaultMethodMask;
    1.32 -                    implicit = PUBLIC;
    1.33 +                    implicit = PUBLIC | ABSTRACT;
    1.34                  } else {
    1.35                      mask = implicit = InterfaceMethodFlags;
    1.36                  }
    1.37 @@ -2047,11 +2058,21 @@
    1.38                       undef == null && e != null;
    1.39                       e = e.sibling) {
    1.40                      if (e.sym.kind == MTH &&
    1.41 -                        (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) {
    1.42 +                        (e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
    1.43                          MethodSymbol absmeth = (MethodSymbol)e.sym;
    1.44                          MethodSymbol implmeth = absmeth.implementation(impl, types, true);
    1.45 -                        if (implmeth == null || implmeth == absmeth)
    1.46 +                        if (implmeth == null || implmeth == absmeth) {
    1.47 +                            //look for default implementations
    1.48 +                            if (allowDefaultMethods) {
    1.49 +                                MethodSymbol prov = types.interfaceCandidates(impl.type, absmeth).head;
    1.50 +                                if (prov != null && prov.overrides(absmeth, impl, types, true)) {
    1.51 +                                    implmeth = prov;
    1.52 +                                }
    1.53 +                            }
    1.54 +                        }
    1.55 +                        if (implmeth == null || implmeth == absmeth) {
    1.56                              undef = absmeth;
    1.57 +                        }
    1.58                      }
    1.59                  }
    1.60                  if (undef == null) {
    1.61 @@ -2354,7 +2375,7 @@
    1.62                  if (m2 == m1) continue;
    1.63                  //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
    1.64                  //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
    1.65 -                if (!types.isSubSignature(sym.type, types.memberType(site, m2), false) &&
    1.66 +                if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
    1.67                          types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
    1.68                      sym.flags_field |= CLASH;
    1.69                      String key = m1 == sym ?
    1.70 @@ -2386,7 +2407,7 @@
    1.71          for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
    1.72              //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
    1.73              //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
    1.74 -            if (!types.isSubSignature(sym.type, types.memberType(site, s), false) &&
    1.75 +            if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
    1.76                      types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
    1.77                  log.error(pos,
    1.78                          "name.clash.same.erasure.no.hide",
    1.79 @@ -2420,6 +2441,62 @@
    1.80           }
    1.81       }
    1.82  
    1.83 +    void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
    1.84 +        DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
    1.85 +        for (Symbol m : types.membersClosure(site, false).getElements(dcf)) {
    1.86 +            Assert.check(m.kind == MTH);
    1.87 +            List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
    1.88 +            if (prov.size() > 1) {
    1.89 +                ListBuffer<Symbol> abstracts = ListBuffer.lb();
    1.90 +                ListBuffer<Symbol> defaults = ListBuffer.lb();
    1.91 +                for (MethodSymbol provSym : prov) {
    1.92 +                    if ((provSym.flags() & DEFAULT) != 0) {
    1.93 +                        defaults = defaults.append(provSym);
    1.94 +                    } else if ((provSym.flags() & ABSTRACT) != 0) {
    1.95 +                        abstracts = abstracts.append(provSym);
    1.96 +                    }
    1.97 +                    if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
    1.98 +                        //strong semantics - issue an error if two sibling interfaces
    1.99 +                        //have two override-equivalent defaults - or if one is abstract
   1.100 +                        //and the other is default
   1.101 +                        String errKey;
   1.102 +                        Symbol s1 = defaults.first();
   1.103 +                        Symbol s2;
   1.104 +                        if (defaults.size() > 1) {
   1.105 +                            errKey = "types.incompatible.unrelated.defaults";
   1.106 +                            s2 = defaults.toList().tail.head;
   1.107 +                        } else {
   1.108 +                            errKey = "types.incompatible.abstract.default";
   1.109 +                            s2 = abstracts.first();
   1.110 +                        }
   1.111 +                        log.error(pos, errKey,
   1.112 +                                Kinds.kindName(site.tsym), site,
   1.113 +                                m.name, types.memberType(site, m).getParameterTypes(),
   1.114 +                                s1.location(), s2.location());
   1.115 +                        break;
   1.116 +                    }
   1.117 +                }
   1.118 +            }
   1.119 +        }
   1.120 +    }
   1.121 +
   1.122 +    //where
   1.123 +     private class DefaultMethodClashFilter implements Filter<Symbol> {
   1.124 +
   1.125 +         Type site;
   1.126 +
   1.127 +         DefaultMethodClashFilter(Type site) {
   1.128 +             this.site = site;
   1.129 +         }
   1.130 +
   1.131 +         public boolean accepts(Symbol s) {
   1.132 +             return s.kind == MTH &&
   1.133 +                     (s.flags() & DEFAULT) != 0 &&
   1.134 +                     s.isInheritedIn(site.tsym, types) &&
   1.135 +                     !s.isConstructor();
   1.136 +         }
   1.137 +     }
   1.138 +
   1.139      /** Report a conflict between a user symbol and a synthetic symbol.
   1.140       */
   1.141      private void syntheticError(DiagnosticPosition pos, Symbol sym) {

mercurial