001    /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com>
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     *     * Redistributions of source code must retain the above copyright notice,
008     *       this list of conditions and the following disclaimer.
009     *     * Redistributions in binary form must reproduce the above copyright
010     *       notice, this list of conditions and the following disclaimer in the
011     *       documentation and/or other materials provided with the distribution.
012     *     * Neither the name of the Lund University nor the names of its
013     *       contributors may be used to endorse or promote products derived from
014     *       this software without specific prior written permission.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026     * POSSIBILITY OF SUCH DAMAGE.
027     */
028    aspect MethodSignature18 {
029    
030      /* Used to compute compatibility during phase 1 of overload resolution */
031    
032      syn lazy boolean Expr.compatibleStrictContext(TypeDecl type) {
033        return type().instanceOf(type)
034            || type().withinBounds(type, Parameterization.RAW); // Test subtype of type bounds.
035      }
036    
037      eq LambdaExpr.compatibleStrictContext(TypeDecl type) {
038        if (!type.isFunctionalInterface()) {
039          return false;
040        }
041        InterfaceDecl iDecl = (InterfaceDecl) type;
042        return congruentTo(iDecl.functionDescriptor());
043      }
044    
045      eq MethodReference.compatibleStrictContext(TypeDecl type) {
046        if (!type.isFunctionalInterface()) {
047          return false;
048        }
049        InterfaceDecl iDecl = (InterfaceDecl) type;
050        return congruentTo(iDecl.functionDescriptor());
051      }
052    
053      eq ConstructorReference.compatibleStrictContext(TypeDecl type) {
054        if (!type.isFunctionalInterface()) {
055          return false;
056        }
057        InterfaceDecl iDecl = (InterfaceDecl) type;
058        return congruentTo(iDecl.functionDescriptor());
059      }
060    
061      eq ParExpr.compatibleStrictContext(TypeDecl type) = getExpr().compatibleStrictContext(type);
062    
063      eq ConditionalExpr.compatibleStrictContext(TypeDecl type) {
064        if (isPolyExpression()) {
065          return getTrueExpr().compatibleStrictContext(type)
066              && getFalseExpr().compatibleStrictContext(type);
067        } else {
068          return super.compatibleStrictContext(type);
069        }
070      }
071    
072      eq ClassInstanceExpr.compatibleStrictContext(TypeDecl type) =
073          isPolyExpression()
074          ? assignConversionTo(type)
075          : super.compatibleStrictContext(type);
076    
077      /* Used to compute compatibility during phase 2 of overload resolution */
078    
079      syn lazy boolean Expr.compatibleLooseContext(TypeDecl type) =
080          type().methodInvocationConversionTo(type)
081          || type().boxed().withinBounds(type, Parameterization.RAW);
082    
083      eq LambdaExpr.compatibleLooseContext(TypeDecl type) = compatibleStrictContext(type);
084    
085      eq MethodReference.compatibleLooseContext(TypeDecl type) = compatibleStrictContext(type);
086    
087      eq ConstructorReference.compatibleLooseContext(TypeDecl type) = compatibleStrictContext(type);
088    
089      eq ParExpr.compatibleLooseContext(TypeDecl type) = getExpr().compatibleLooseContext(type);
090    
091      eq ConditionalExpr.compatibleLooseContext(TypeDecl type) {
092        if (isPolyExpression()) {
093          return getTrueExpr().compatibleLooseContext(type)
094              && getFalseExpr().compatibleLooseContext(type);
095        } else {
096          return super.compatibleLooseContext(type);
097        }
098      }
099    
100      eq ClassInstanceExpr.compatibleLooseContext(TypeDecl type) =
101          isPolyExpression()
102          ? assignConversionTo(type)
103          : super.compatibleLooseContext(type);
104    
105      /* Computes pertinent to applicability, defined in 15.12.2.2 */
106    
107      syn lazy boolean Expr.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) = true;
108    
109      eq LambdaExpr.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) {
110        if (isImplicit()) {
111          return false;
112        }
113        if (decl instanceof MethodDecl
114            && decl.isGeneric()
115            && !(access instanceof ParMethodAccess)
116            && ((MethodDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
117          GenericMethodDecl genericDecl = ((MethodDecl) decl).genericDecl();
118          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
119          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
120            if (typeVar == genericDecl.getTypeParameter(i)) {
121              return false;
122            }
123          }
124        } else if (decl instanceof ConstructorDecl
125            && decl.isGeneric()
126            && !(access instanceof ParConstructorAccess)
127            && !(access instanceof ParSuperConstructorAccess)
128            && !(access instanceof ParClassInstanceExpr)
129            && ((ConstructorDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
130          GenericConstructorDecl genericDecl = ((ConstructorDecl) decl).genericDecl();
131          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
132          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
133            if (typeVar == genericDecl.getTypeParameter(i)) {
134              return false;
135            }
136          }
137        }
138        if (getLambdaBody() instanceof ExprLambdaBody) {
139          ExprLambdaBody exprBody = (ExprLambdaBody) getLambdaBody();
140          if (!exprBody.getExpr().pertinentToApplicability(access, decl, argIndex)) {
141            return false;
142          }
143        } else {
144          BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
145          ArrayList<ReturnStmt> returnList = blockBody.lambdaReturns();
146          for (ReturnStmt returnStmt : returnList) {
147            if (returnStmt.hasResult()
148                && !returnStmt.getResult().pertinentToApplicability(access, decl, argIndex)) {
149              return false;
150            }
151          }
152        }
153        return true;
154      }
155    
156      eq MethodReference.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) {
157        if (!isExact()) {
158          return false;
159        }
160        if (decl instanceof MethodDecl
161            && decl.isGeneric()
162            && !(access instanceof ParMethodAccess)
163            && ((MethodDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
164          GenericMethodDecl genericDecl = ((MethodDecl) decl).genericDecl();
165          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
166          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
167            if (typeVar == genericDecl.getTypeParameter(i)) {
168              return false;
169            }
170          }
171        } else if (decl instanceof ConstructorDecl
172            && decl.isGeneric()
173            && !(access instanceof ParConstructorAccess)
174            && !(access instanceof ParSuperConstructorAccess)
175            && !(access instanceof ParClassInstanceExpr)
176            && ((ConstructorDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
177          GenericConstructorDecl genericDecl = ((ConstructorDecl) decl).genericDecl();
178          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
179          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
180            if (typeVar == genericDecl.getTypeParameter(i)) {
181              return false;
182            }
183          }
184        }
185        return true;
186      }
187    
188      eq ConstructorReference.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) {
189        if (!isExact()) {
190          return false;
191        }
192        if (decl instanceof MethodDecl
193            && decl.isGeneric()
194            && !(access instanceof ParMethodAccess)
195            && ((MethodDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
196          GenericMethodDecl genericDecl = ((MethodDecl) decl).genericDecl();
197          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
198          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
199            if (typeVar == genericDecl.getTypeParameter(i)) {
200              return false;
201            }
202          }
203        } else if (decl instanceof ConstructorDecl
204            && decl.isGeneric()
205            && !(access instanceof ParConstructorAccess)
206            && !(access instanceof ParSuperConstructorAccess)
207            && !(access instanceof ParClassInstanceExpr)
208            && ((ConstructorDecl) decl).genericDecl().getParameter(argIndex).type().isTypeVariable()) {
209          GenericConstructorDecl genericDecl = ((ConstructorDecl) decl).genericDecl();
210          TypeVariable typeVar = (TypeVariable) genericDecl.getParameter(argIndex).type();
211          for (int i = 0; i < genericDecl.getNumTypeParameter(); i++) {
212            if (typeVar == genericDecl.getTypeParameter(i)) {
213              return false;
214            }
215          }
216        }
217        return true;
218      }
219    
220      eq ParExpr.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) =
221          getExpr().pertinentToApplicability(access, decl, argIndex);
222    
223      eq ConditionalExpr.pertinentToApplicability(Expr access, BodyDecl decl, int argIndex) =
224          getFalseExpr().pertinentToApplicability(access, decl, argIndex)
225          && getTrueExpr().pertinentToApplicability(access, decl, argIndex);
226    
227      /**
228       * Computes which type is more specific for a specific argument, as defined in 15.12.2.5
229       * @param type1
230       * @param type2
231       * @return {@code true} if type1 is more specific than type2, {@code false} otherwise
232       */
233      syn lazy boolean Expr.moreSpecificThan(TypeDecl type1, TypeDecl type2) =
234          type1.instanceOf(type2) || type1.withinBounds(type2, Parameterization.RAW);
235          // TODO(jesper): Does not check proper subtype... should it?
236    
237      // 15.12.2.5
238      eq LambdaExpr.moreSpecificThan(TypeDecl type1, TypeDecl type2) {
239        if (super.moreSpecificThan(type1, type2)) {
240          return true;
241        }
242        if (!type1.isFunctionalInterface() || !type2.isFunctionalInterface()) {
243          return false;
244        }
245        if (type2.instanceOf(type1)) {
246          // type1 can not be more specific than type2 if it is a subtype of type2
247          return false;
248        }
249        InterfaceDecl iDecl1 = (InterfaceDecl) type1;
250        InterfaceDecl iDecl2 = (InterfaceDecl) type2;
251    
252        if (isImplicit()) {
253          return false;
254        }
255    
256        FunctionDescriptor f1 = iDecl1.functionDescriptor();
257        FunctionDescriptor f2 = iDecl2.functionDescriptor();
258    
259        // First bullet
260        if (f2.method.type().isVoid()) {
261          return true;
262        }
263    
264        // Second bullet
265        if (f1.method.type().instanceOf(f2.method.type())) {
266          return true;
267        }
268    
269        // Third bullet
270        if (f1.method.type().isFunctionalInterface() && f2.method.type().isFunctionalInterface()) {
271          if (getLambdaBody().isBlockBody()) {
272            BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
273            boolean allMoreSpecific = true;
274            ArrayList<ReturnStmt> returnList = blockBody.lambdaReturns();
275            for (ReturnStmt returnStmt : returnList) {
276              if (returnStmt.hasResult() && !returnStmt.getResult().moreSpecificThan(f1.method.type(), f2.method.type())) {
277                allMoreSpecific = false;
278                break;
279              }
280            }
281            return allMoreSpecific;
282          } else {
283            ExprLambdaBody exprBody = (ExprLambdaBody) getLambdaBody();
284            return exprBody.getExpr().moreSpecificThan(f1.method.type(), f2.method.type());
285          }
286        }
287    
288        // Fourth bullet
289        if (f1.method.type().isPrimitiveType() && f2.method.type().isReferenceType()) {
290          if (getLambdaBody().isBlockBody()) {
291            BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
292            boolean allPrimitive = true;
293            ArrayList<ReturnStmt> returnList = blockBody.lambdaReturns();
294            for (ReturnStmt returnStmt : returnList) {
295              if (returnStmt.hasResult() && returnStmt.getResult().isPolyExpression()) {
296                allPrimitive = false;
297                break;
298              } else if (returnStmt.hasResult() && !returnStmt.getResult().type().isPrimitiveType()) {
299                allPrimitive = false;
300                break;
301              }
302            }
303            return allPrimitive;
304          } else {
305            ExprLambdaBody exprBody = (ExprLambdaBody) getLambdaBody();
306            if (exprBody.getExpr().isPolyExpression()) {
307              return false;
308            }
309            return exprBody.getExpr().type().isPrimitiveType();
310          }
311        }
312    
313        // Fifth bullet
314        if (f1.method.type().isReferenceType() && f2.method.type().isPrimitiveType()) {
315          if (getLambdaBody().isBlockBody()) {
316            BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
317            boolean allReference = true;
318            ArrayList<ReturnStmt> returnList = blockBody.lambdaReturns();
319            for (ReturnStmt returnStmt : returnList) {
320              if (returnStmt.hasResult() && !returnStmt.getResult().isPolyExpression()
321                  && !returnStmt.getResult().type().isReferenceType()) {
322                allReference = false;
323                break;
324              }
325            }
326            return allReference;
327          } else {
328            ExprLambdaBody exprBody = (ExprLambdaBody) getLambdaBody();
329            if (exprBody.getExpr().isPolyExpression()) {
330              return true;
331            }
332            return exprBody.getExpr().type().isReferenceType();
333          }
334        }
335        return false;
336      }
337    
338      // 15.12.2.5
339      eq MethodReference.moreSpecificThan(TypeDecl type1, TypeDecl type2) {
340        if (super.moreSpecificThan(type1, type2)) {
341          return true;
342        }
343        if (!type1.isFunctionalInterface() || !type2.isFunctionalInterface()) {
344          return false;
345        }
346        if (type2.instanceOf(type1)) {
347          return false;
348        }
349        InterfaceDecl iDecl1 = (InterfaceDecl) type1;
350        InterfaceDecl iDecl2 = (InterfaceDecl) type2;
351    
352        if (!isExact()) {
353          return false;
354        }
355    
356        FunctionDescriptor f1 = iDecl1.functionDescriptor();
357        FunctionDescriptor f2 = iDecl2.functionDescriptor();
358    
359        if (f1.method.arity() != f2.method.arity()) {
360          return false;
361        }
362    
363        for (int i = 0; i < f1.method.getNumParameter(); i++) {
364          if (f1.method.getParameter(i).type() != f2.method.getParameter(i).type()) {
365            return false;
366          }
367        }
368    
369        // First bullet
370        if (f2.method.type().isVoid()) {
371          return true;
372        }
373    
374        // Second bullet
375        if (f1.method.type().instanceOf(f2.method.type())) {
376          return true;
377        }
378    
379        // Third bullet
380        if (f1.method.type().isPrimitiveType() && f2.method.type().isReferenceType()) {
381          return exactCompileTimeDeclaration().type().isPrimitiveType();
382        }
383    
384        // Fourth bullet
385        if (f1.method.type().isReferenceType() && f2.method.type().isPrimitiveType()) {
386          return exactCompileTimeDeclaration().type().isReferenceType();
387        }
388    
389        return false;
390      }
391    
392      // 15.12.2.5
393      eq ConstructorReference.moreSpecificThan(TypeDecl type1, TypeDecl type2) {
394        if (super.moreSpecificThan(type1, type2)) {
395          return true;
396        }
397        if (!type1.isFunctionalInterface() || !type2.isFunctionalInterface()) {
398          return false;
399        }
400        if (type2.instanceOf(type1)) {
401          return false;
402        }
403        InterfaceDecl iDecl1 = (InterfaceDecl) type1;
404        InterfaceDecl iDecl2 = (InterfaceDecl) type2;
405    
406        if (!isExact()) {
407          return false;
408        }
409    
410        FunctionDescriptor f1 = iDecl1.functionDescriptor();
411        FunctionDescriptor f2 = iDecl2.functionDescriptor();
412    
413        if (f1.method.arity() != f2.method.arity()) {
414          return false;
415        }
416    
417        for (int i = 0; i < f1.method.getNumParameter(); i++) {
418          if (f1.method.getParameter(i).type() != f2.method.getParameter(i).type()) {
419            return false;
420          }
421        }
422    
423        // First bullet
424        if (f2.method.type().isVoid()) {
425          return true;
426        }
427    
428        // Second bullet
429        if (f1.method.type().instanceOf(f2.method.type())) {
430          return true;
431        }
432    
433        // Third bullet
434        if (f1.method.type().isPrimitiveType() && f2.method.type().isReferenceType()) {
435          // A constructor can never have primitive return type
436          return false;
437        }
438    
439        // Fourth bullet
440        if (f1.method.type().isReferenceType() && f2.method.type().isPrimitiveType()) {
441          // A constructor always have reference return type
442          return true;
443        }
444    
445        return false;
446    
447      }
448    
449      eq ParExpr.moreSpecificThan(TypeDecl type1, TypeDecl type2) {
450        if (super.moreSpecificThan(type1, type2)) {
451          return true;
452        }
453        return getExpr().moreSpecificThan(type1, type2);
454      }
455    
456      eq ConditionalExpr.moreSpecificThan(TypeDecl type1, TypeDecl type2) {
457        if (super.moreSpecificThan(type1, type2)) {
458          return true;
459        }
460        return getTrueExpr().moreSpecificThan(type1, type2) && getFalseExpr().moreSpecificThan(type1, type2);
461      }
462    
463      /* Computes whether a certain candidate method or constructor is potentially compatible
464         as defined in 15.12.2.1 */
465    
466      syn lazy boolean Expr.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) = true;
467    
468      eq LambdaExpr.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
469        if (type.isTypeVariable()) {
470          if (candidateDecl.isGeneric()) {
471            boolean foundTypeVariable = false;
472            List<TypeVariable> typeParams = candidateDecl.typeParameters();
473            for (int i = 0; i < typeParams.getNumChild(); i++) {
474              if (type == typeParams.getChild(i)) {
475                foundTypeVariable = true;
476                break;
477              }
478            }
479            return foundTypeVariable;
480          } else {
481            return false;
482          }
483        }
484    
485        if (!type.isFunctionalInterface()) {
486          return false;
487        }
488        InterfaceDecl iDecl = (InterfaceDecl) type;
489    
490        if (arity() != iDecl.functionDescriptor().method.arity()) {
491          return false;
492        }
493        if (iDecl.functionDescriptor().method.type().isVoid()) {
494          if (getLambdaBody().isExprBody()) {
495            ExprLambdaBody exprBody = (ExprLambdaBody) getLambdaBody();
496            if (!exprBody.getExpr().stmtCompatible()) {
497              return false;
498            }
499          } else {
500            BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
501            if (!blockBody.voidCompatible()) {
502              return false;
503            }
504          }
505        } else {
506          if (getLambdaBody().isBlockBody()) {
507            BlockLambdaBody blockBody = (BlockLambdaBody) getLambdaBody();
508            if (!blockBody.valueCompatible()) {
509              return false;
510            }
511          }
512        }
513        return true;
514      }
515    
516      eq MethodReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
517        if (type.isTypeVariable()) {
518          if (candidateDecl.isGeneric()) {
519            boolean foundTypeVariable = false;
520            List<TypeVariable> typeParams = candidateDecl.typeParameters();
521            for (int i = 0; i < typeParams.getNumChild(); i++) {
522              if (type == typeParams.getChild(i)) {
523                foundTypeVariable = true;
524                break;
525              }
526            }
527            return foundTypeVariable;
528          } else {
529            return false;
530          }
531        }
532    
533        if (!type.isFunctionalInterface()) {
534          return false;
535        }
536        return true;
537      }
538    
539      eq ExprMethodReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
540        if (super.potentiallyCompatible(type, candidateDecl) && type.isTypeVariable()) {
541          return true;
542        } else if (!super.potentiallyCompatible(type, candidateDecl)) {
543          return false;
544        }
545    
546        InterfaceDecl iDecl = (InterfaceDecl) type;
547        FunctionDescriptor f = iDecl.functionDescriptor();
548    
549        boolean foundMethod = false;
550        for (MethodDecl decl : potentiallyApplicableMethods(f)) {
551          if (!decl.isStatic() && f.method.arity() == decl.arity()) {
552            foundMethod = true;
553            break;
554          }
555        }
556        return foundMethod;
557      }
558    
559      eq TypeMethodReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
560        if (super.potentiallyCompatible(type, candidateDecl) && type.isTypeVariable()) {
561          return true;
562        } else if (!super.potentiallyCompatible(type, candidateDecl)) {
563          return false;
564        }
565    
566        InterfaceDecl iDecl = (InterfaceDecl) type;
567        FunctionDescriptor f = iDecl.functionDescriptor();
568    
569        boolean foundMethod = false;
570        for (MethodDecl decl : potentiallyApplicableMethods(f)) {
571          if (decl.isStatic() && f.method.arity() == decl.arity()) {
572            foundMethod = true;
573            break;
574          } else if (!decl.isStatic() && f.method.arity() - 1 == decl.arity()) {
575            foundMethod = true;
576            break;
577          }
578        }
579        return foundMethod;
580      }
581    
582      eq ConstructorReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
583        if (type.isTypeVariable()) {
584          if (candidateDecl.isGeneric()) {
585            boolean foundTypeVariable = false;
586            List<TypeVariable> typeParams = candidateDecl.typeParameters();
587            for (int i = 0; i < typeParams.getNumChild(); i++) {
588              if (type == typeParams.getChild(i)) {
589                foundTypeVariable = true;
590                break;
591              }
592            }
593            return foundTypeVariable;
594          } else {
595            return false;
596          }
597        }
598    
599        if (!type.isFunctionalInterface()) {
600          return false;
601        }
602        return true;
603      }
604    
605      eq ClassReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
606        if (super.potentiallyCompatible(type, candidateDecl) && type.isTypeVariable()) {
607          return true;
608        } else if (!super.potentiallyCompatible(type, candidateDecl)) {
609          return false;
610        }
611    
612        InterfaceDecl iDecl = (InterfaceDecl) type;
613        FunctionDescriptor f = iDecl.functionDescriptor();
614    
615        boolean foundMethod = false;
616        for (ConstructorDecl decl : potentiallyApplicableConstructors(f)) {
617          if (f.method.arity() == decl.arity()) {
618            foundMethod = true;
619            break;
620          }
621        }
622        return foundMethod;
623      }
624    
625      eq ArrayReference.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
626        if (super.potentiallyCompatible(type, candidateDecl) && type.isTypeVariable()) {
627          return true;
628        } else if (!super.potentiallyCompatible(type, candidateDecl)) {
629          return false;
630        }
631        InterfaceDecl iDecl = (InterfaceDecl) type;
632        FunctionDescriptor f = iDecl.functionDescriptor();
633        return f.method.arity() == 1;
634      }
635    
636      eq ParExpr.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) =
637          getExpr().potentiallyCompatible(type, candidateDecl);
638    
639      eq ConditionalExpr.potentiallyCompatible(TypeDecl type, BodyDecl candidateDecl) {
640        if (!isPolyExpression()) {
641          return true;
642        }
643        return getTrueExpr().potentiallyCompatible(type, candidateDecl)
644            && getFalseExpr().potentiallyCompatible(type, candidateDecl);
645      }
646    
647    
648    
649      /* Below are the relevant overload resolution computations for choosing a method */
650    
651      refine MethodSignature15
652      eq MethodAccess.applicableBySubtyping(MethodDecl m) {
653        if (m.getNumParameter() != getNumArg()) {
654          return false;
655        }
656        for (int i = 0; i < m.getNumParameter(); i++) {
657          if (!getArg(i).pertinentToApplicability(this, m, i)) {
658            continue;
659          } else if (!getArg(i).compatibleStrictContext(m.getParameter(i).type())) {
660            return false;
661          }
662        }
663        return true;
664      }
665    
666      refine MethodSignature15
667      eq MethodAccess.applicableByMethodInvocationConversion(MethodDecl m) {
668        if (m.getNumParameter() != getNumArg()) {
669          return false;
670        }
671        for (int i = 0; i < m.getNumParameter(); i++) {
672          if (!getArg(i).pertinentToApplicability(this, m, i)) {
673            continue;
674          } else if (!getArg(i).compatibleLooseContext(m.getParameter(i).type())) {
675            return false;
676          }
677        }
678        return true;
679      }
680    
681      refine MethodSignature15
682      eq MethodAccess.applicableVariableArity(MethodDecl m) {
683        for (int i = 0; i < m.getNumParameter() - 1; i++) {
684          if (!getArg(i).pertinentToApplicability(this, m, i)) {
685            continue;
686          }
687          if (!getArg(i).compatibleLooseContext(m.getParameter(i).type())) {
688            return false;
689          }
690        }
691        for (int i = m.getNumParameter() - 1; i < getNumArg(); i++) {
692          if (!getArg(i).pertinentToApplicability(this, m, i)) {
693            continue;
694          }
695          if (!getArg(i).compatibleLooseContext(m.lastParameter().type().componentType())) {
696            return false;
697          }
698        }
699        return true;
700      }
701    
702      protected boolean MethodAccess.moreSpecificThan(MethodDecl m1, MethodDecl m2) {
703        if (m1 instanceof ParMethodDecl) {
704          return m1.moreSpecificThan(m2);
705        }
706        if (m1.getNumParameter() == 0) {
707          return false;
708        }
709        if (!m1.isVariableArity() && !m2.isVariableArity()) {
710          for (int i = 0; i < m1.getNumParameter(); i++) {
711            if (!getArg(i).moreSpecificThan(m1.getParameter(i).type(), m2.getParameter(i).type())) {
712              return false;
713            }
714          }
715          return true;
716        }
717    
718        int num = getNumArg();
719        for (int i = 0; i < num; i++) {
720          TypeDecl t1 = i < m1.getNumParameter() - 1
721              ? m1.getParameter(i).type()
722              : m1.getParameter(m1.getNumParameter()-1).type().componentType();
723          TypeDecl t2 = i < m2.getNumParameter() - 1
724              ? m2.getParameter(i).type()
725              : m2.getParameter(m2.getNumParameter()-1).type().componentType();
726          if (!getArg(i).moreSpecificThan(t1, t2)) {
727              return false;
728          }
729    
730        }
731        num++;
732        if (m2.getNumParameter() == num) {
733          TypeDecl t1 = num < m1.getNumParameter() - 1
734              ? m1.getParameter(num).type()
735              : m1.getParameter(m1.getNumParameter()-1).type().componentType();
736          TypeDecl t2 = num < m2.getNumParameter() - 1
737              ? m2.getParameter(num).type()
738              : m2.getParameter(m2.getNumParameter()-1).type().componentType();
739          if (!t1.instanceOf(t2) && !t1.withinBounds(t2, Parameterization.RAW)) {
740            return false;
741          }
742        }
743        return true;
744      }
745    
746      refine MethodSignature15
747      private SimpleSet MethodAccess.mostSpecific(SimpleSet maxSpecific, MethodDecl decl) {
748        SimpleSet newMax;
749        if (maxSpecific.isEmpty()) {
750          newMax = maxSpecific.add(decl);
751        } else {
752          boolean foundStricter = false;
753          newMax = SimpleSet.emptySet;
754          Iterator<MethodDecl> iter = maxSpecific.iterator();
755          while (iter.hasNext()) {
756            MethodDecl toCompare = iter.next();
757            if (!(moreSpecificThan(decl, toCompare) && !moreSpecificThan(toCompare, decl))) {
758              newMax = newMax.add(toCompare);
759            }
760    
761            if (!moreSpecificThan(decl, toCompare) && moreSpecificThan(toCompare, decl)) {
762              foundStricter = true;
763            }
764    
765          }
766    
767          if (!foundStricter) {
768            newMax = newMax.add(decl);
769          }
770        }
771        return newMax;
772      }
773    
774      refine MethodSignature15
775      eq MethodAccess.potentiallyApplicable(MethodDecl m) {
776        if (!m.name().equals(name())) {
777          return false;
778        }
779        if (!m.accessibleFrom(hostType())) {
780          return false;
781        }
782        if (!m.isVariableArity()) {
783          if (arity() != m.arity()) {
784            return false;
785          }
786          for (int i = 0; i < getNumArg(); i++) {
787            if (!getArg(i).potentiallyCompatible(m.getParameter(i).type(), m)) {
788              return false;
789            }
790          }
791        }
792        if (m.isVariableArity()) {
793          if (!(arity() >= m.arity()-1)) {
794            return false;
795          }
796          for (int i = 0; i < m.arity() - 2; i++) {
797            if (!getArg(i).potentiallyCompatible(m.getParameter(i).type(), m)) {
798              return false;
799            }
800          }
801          TypeDecl varArgType = m.getParameter(m.arity()-1).type();
802          if (arity() == m.arity()) {
803            if (!getArg(arity()-1).potentiallyCompatible(varArgType, m)
804                && !getArg(arity()-1).potentiallyCompatible(varArgType.componentType(), m)) {
805              return false;
806            }
807          } else if (arity() > m.arity()) {
808            for (int i = m.arity()-1; i < arity(); i++) {
809              if (!getArg(i).potentiallyCompatible(varArgType.componentType(), m)) {
810                return false;
811              }
812            }
813          }
814        }
815    
816        if (m.isGeneric()) {
817          GenericMethodDecl gm = m.genericDecl();
818          ArrayList<TypeDecl> typeArguments = inferTypeArguments(
819              gm.type(),
820              gm.getParameterList(),
821              getArgList(),
822              gm.getTypeParameterList());
823          if (!typeArguments.isEmpty()) {
824            if (gm.getNumTypeParameter() != typeArguments.size()) {
825              return false;
826            }
827            Parameterization par = new SimpleParameterization(gm.getTypeParameterList(), typeArguments);
828            for (int i = 0; i < gm.getNumTypeParameter(); i++) {
829              if (!((TypeDecl) typeArguments.get(i)).withinBounds(gm.original().getTypeParameter(i), par)) {
830                return false;
831              }
832            }
833          }
834        }
835    
836        return true;
837      }
838    
839    
840      /* Below are the relevant overload resolution computations for choosing a constructor */
841    
842      refine MethodSignature15
843      protected SimpleSet Expr.chooseConstructor(Collection constructors, List<Expr> argList) {
844        SimpleSet potentiallyApplicable = SimpleSet.emptySet;
845    
846        // Select potentially applicable constructors.
847        for (Iterator iter = constructors.iterator(); iter.hasNext(); ) {
848          ConstructorDecl decl = (ConstructorDecl) iter.next();
849          if (decl.potentiallyApplicable(argList) && decl.accessibleFrom(hostType())) {
850            if (decl.isGeneric()) {
851              GenericConstructorDecl gc = decl.genericDecl();
852              decl = gc.lookupParConstructorDecl(
853                  inferTypeArguments(
854                      gc.type(),
855                      gc.getParameterList(),
856                      argList,
857                      gc.getTypeParameterList()));
858            }
859            potentiallyApplicable = potentiallyApplicable.add(decl);
860          }
861        }
862    
863        // First phase.
864        SimpleSet maxSpecific = SimpleSet.emptySet;
865        for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
866          ConstructorDecl decl = (ConstructorDecl) iter.next();
867          if (decl.applicableByStrictInvocation(this, argList)) {
868            maxSpecific = mostSpecific(maxSpecific, decl, argList);
869          }
870        }
871    
872        // Second phase.
873        if (maxSpecific.isEmpty()) {
874          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
875            ConstructorDecl decl = (ConstructorDecl) iter.next();
876            if (decl.applicableByLooseInvocation(this, argList)) {
877              maxSpecific = mostSpecific(maxSpecific, decl, argList);
878            }
879          }
880        }
881    
882        // Third phase.
883        if (maxSpecific.isEmpty()) {
884          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
885            ConstructorDecl decl = (ConstructorDecl) iter.next();
886            if (decl.isVariableArity() && decl.applicableByVariableArityInvocation(this, argList)) {
887              maxSpecific = mostSpecific(maxSpecific, decl, argList);
888            }
889          }
890        }
891        return maxSpecific;
892      }
893    
894      refine MethodSignature15
895      eq ConstructorDecl.potentiallyApplicable(List<Expr> argList) {
896        int argArity = argList.getNumChild();
897        if (!isVariableArity()) {
898          if (argArity != arity()) {
899            return false;
900          }
901          for (int i = 0; i < argArity; i++) {
902            Expr expr = argList.getChild(i);
903            if (!expr.potentiallyCompatible(getParameter(i).type(), this)) {
904              return false;
905            }
906          }
907        } else {
908        //if (isVariableArity()) {
909          if (!(argArity >= arity()-1)) {
910            return false;
911          }
912          for (int i = 0; i < arity() - 2; i++) {
913            Expr expr = argList.getChild(i);
914            if (!expr.potentiallyCompatible(getParameter(i).type(), this)) {
915              return false;
916            }
917          }
918          TypeDecl varArgType = getParameter(arity()-1).type();
919          if (argArity == arity()) {
920            Expr expr = argList.getChild(argArity - 1);
921            if (!expr.potentiallyCompatible(varArgType, this)
922                && !expr.potentiallyCompatible(varArgType.componentType(), this)) {
923              return false;
924            }
925          } else if (argArity > arity()) {
926            for (int i = arity()-1; i < argArity; i++) {
927              Expr expr = argList.getChild(i);
928              if (!expr.potentiallyCompatible(varArgType.componentType(), this)) {
929                return false;
930              }
931            }
932          }
933        }
934    
935        return true;
936      }
937    
938      syn boolean ConstructorDecl.applicableByStrictInvocation(Expr expr, List<Expr> argList) {
939        if (getNumParameter() != argList.getNumChild()) {
940          return false;
941        }
942        for (int i = 0; i < getNumParameter(); i++) {
943          Expr arg = argList.getChild(i);
944          if (!arg.pertinentToApplicability(expr, this, i)) {
945            continue;
946          }
947          if (!arg.compatibleStrictContext(getParameter(i).type())) {
948            return false;
949          }
950        }
951        return true;
952      }
953    
954      syn boolean ConstructorDecl.applicableByLooseInvocation(Expr expr, List<Expr> argList) {
955        if (getNumParameter() != argList.getNumChild()) {
956          return false;
957        }
958        for (int i = 0; i < getNumParameter(); i++) {
959          Expr arg = argList.getChild(i);
960          if (!arg.pertinentToApplicability(expr, this, i)) {
961            continue;
962          }
963          if (!arg.compatibleLooseContext(getParameter(i).type())) {
964            return false;
965          }
966        }
967        return true;
968      }
969    
970      syn boolean ConstructorDecl.applicableByVariableArityInvocation(Expr expr, List<Expr> argList) {
971        for (int i = 0; i < getNumParameter() - 1; i++) {
972          Expr arg = argList.getChild(i);
973          if (!arg.pertinentToApplicability(expr, this, i)) {
974            continue;
975          }
976          if (!arg.compatibleLooseContext(getParameter(i).type())) {
977            return false;
978          }
979        }
980        for (int i = getNumParameter() - 1; i < argList.getNumChild(); i++) {
981          Expr arg = argList.getChild(i);
982          if (!arg.pertinentToApplicability(expr, this, i)) {
983            continue;
984          }
985          if (!arg.compatibleLooseContext(lastParameter().type().componentType())) {
986            return false;
987          }
988        }
989        return true;
990      }
991    
992      protected static boolean Expr.moreSpecificThan(ConstructorDecl m1, ConstructorDecl m2, List<Expr> argList) {
993        if (m1 instanceof ParConstructorDecl) {
994          return m1.moreSpecificThan(m2);
995        }
996        if (m1.getNumParameter() == 0) {
997          return false;
998        }
999        if (!m1.isVariableArity() && !m2.isVariableArity()) {
1000          for (int i = 0; i < m1.getNumParameter(); i++) {
1001            Expr arg = argList.getChild(i);
1002            if (!arg.moreSpecificThan(m1.getParameter(i).type(), m2.getParameter(i).type())) {
1003              return false;
1004            }
1005          }
1006          return true;
1007        }
1008    
1009        int num = argList.getNumChild();
1010        for (int i = 0; i < num; i++) {
1011          TypeDecl t1 = i < m1.getNumParameter() - 1 ? m1.getParameter(i).type() : m1.getParameter(m1.getNumParameter()-1).type().componentType();
1012          TypeDecl t2 = i < m2.getNumParameter() - 1 ? m2.getParameter(i).type() : m2.getParameter(m2.getNumParameter()-1).type().componentType();
1013    
1014          Expr arg = (Expr) argList.getChild(i);
1015          if (!arg.moreSpecificThan(t1, t2)) {
1016              return false;
1017          }
1018        }
1019        return true;
1020      }
1021    
1022      protected static SimpleSet Expr.mostSpecific(SimpleSet maxSpecific, ConstructorDecl decl, List<Expr> argList) {
1023        SimpleSet newMax;
1024        if (maxSpecific.isEmpty()) {
1025          newMax = maxSpecific.add(decl);
1026        } else {
1027          boolean foundStricter = false;
1028          newMax = SimpleSet.emptySet;
1029          Iterator<ConstructorDecl> iter = maxSpecific.iterator();
1030          while (iter.hasNext()) {
1031            ConstructorDecl toCompare = iter.next();
1032            if (!(moreSpecificThan(decl, toCompare, argList) && !moreSpecificThan(toCompare, decl, argList))) {
1033              newMax = newMax.add(toCompare);
1034            }
1035    
1036            if (!moreSpecificThan(decl, toCompare, argList) && moreSpecificThan(toCompare, decl, argList)) {
1037              foundStricter = true;
1038            }
1039    
1040          }
1041    
1042          if (!foundStricter) {
1043            newMax = newMax.add(decl);
1044          }
1045        }
1046        return newMax;
1047      }
1048    
1049    
1050    
1051      /* Overload resolution ends here */
1052    
1053      syn lazy boolean InterfaceDecl.hasOverridingMethodInSuper(MethodDecl m) {
1054        for (Iterator<TypeDecl> outerIter = interfacesIterator(); outerIter.hasNext(); ) {
1055          TypeDecl typeDecl = outerIter.next();
1056          for (Iterator iter = typeDecl.methodsIterator(); iter.hasNext(); ) {
1057            MethodDecl superMethod = (MethodDecl) iter.next();
1058            if (m != superMethod && superMethod.overrides(m)) {
1059              return true;
1060            }
1061          }
1062        }
1063        return false;
1064      }
1065    
1066      syn lazy boolean ClassDecl.hasOverridingMethodInSuper(MethodDecl m) {
1067        for (Iterator<MethodDecl> outerIter = interfacesMethodsIterator(); outerIter.hasNext(); ) {
1068          MethodDecl superMethod = outerIter.next();
1069          if (m != superMethod && superMethod.overrides(m)) {
1070            return true;
1071          }
1072    
1073        }
1074        if (hasSuperclass()) {
1075          for (Iterator iter = superclass().methodsIterator(); iter.hasNext(); ) {
1076            MethodDecl superMethod = (MethodDecl) iter.next();
1077            if (m != superMethod && superMethod.overrides(m)) {
1078              return true;
1079            }
1080          }
1081        }
1082    
1083        return false;
1084      }
1085    
1086    
1087      refine MethodSignature15
1088      eq InterfaceDecl.methodsSignatureMap() {
1089        Map<String,SimpleSet> localMap = localMethodsSignatureMap();
1090        Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(localMap);
1091        for (Iterator<MethodDecl> iter = interfacesMethodsIterator(); iter.hasNext(); ) {
1092          MethodDecl m = iter.next();
1093          if (!m.isStatic() && m.accessibleFrom(this)
1094              && !localMap.containsKey(m.signature())
1095              && !hasOverridingMethodInSuper(m)) {
1096            putSimpleSetElement(map, m.signature(), m);
1097          }
1098        }
1099        for (Iterator<MethodDecl> iter = typeObject().methodsIterator(); iter.hasNext(); ) {
1100          MethodDecl m = iter.next();
1101          if (m.isPublic() && !map.containsKey(m.signature())) {
1102            putSimpleSetElement(map, m.signature(), m);
1103          }
1104        }
1105        return map;
1106      }
1107    
1108      refine MethodSignature15
1109      eq ClassDecl.methodsSignatureMap() {
1110        Map<String,SimpleSet> localMap = localMethodsSignatureMap();
1111        Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(localMap);
1112        HashMap fromSuperClass = new HashMap();
1113        if (hasSuperclass()) {
1114          for (Iterator<MethodDecl> iter = superclass().methodsIterator(); iter.hasNext(); ) {
1115            MethodDecl m = iter.next();
1116            if (!m.isPrivate() && m.accessibleFrom(this) && !localMap.containsKey(m.signature())) {
1117              putSimpleSetElement(map, m.signature(), m);
1118              if (!m.isAbstract()) {
1119                putSimpleSetElement(fromSuperClass, m.signature(), m);
1120              }
1121            }
1122          }
1123        }
1124        for (Iterator<MethodDecl> iter = interfacesMethodsIterator(); iter.hasNext(); ) {
1125          MethodDecl m = iter.next();
1126          if (!m.isStatic()
1127              && m.accessibleFrom(this) && !localMap.containsKey(m.signature())
1128              && !hasOverridingMethodInSuper(m)) {
1129            if (!fromSuperClass.containsKey(m.signature())) {
1130              putSimpleSetElement(map, m.signature(), m);
1131            }
1132          }
1133        }
1134        return map;
1135      }
1136    }