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 }