langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 12334 29e1bfdcba4e
parent 12082 32bdf6ef6388
child 12335 4725d88691dd
equal deleted inserted replaced
12333:7b02d0529a97 12334:29e1bfdcba4e
    27 
    27 
    28 import com.sun.tools.javac.api.Formattable.LocalizedString;
    28 import com.sun.tools.javac.api.Formattable.LocalizedString;
    29 import com.sun.tools.javac.code.*;
    29 import com.sun.tools.javac.code.*;
    30 import com.sun.tools.javac.code.Type.*;
    30 import com.sun.tools.javac.code.Type.*;
    31 import com.sun.tools.javac.code.Symbol.*;
    31 import com.sun.tools.javac.code.Symbol.*;
       
    32 import com.sun.tools.javac.comp.Attr.ResultInfo;
       
    33 import com.sun.tools.javac.comp.Check.CheckContext;
    32 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
    34 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
    33 import com.sun.tools.javac.jvm.*;
    35 import com.sun.tools.javac.jvm.*;
    34 import com.sun.tools.javac.tree.*;
    36 import com.sun.tools.javac.tree.*;
    35 import com.sun.tools.javac.tree.JCTree.*;
    37 import com.sun.tools.javac.tree.JCTree.*;
    36 import com.sun.tools.javac.util.*;
    38 import com.sun.tools.javac.util.*;
    68         new Context.Key<Resolve>();
    70         new Context.Key<Resolve>();
    69 
    71 
    70     Names names;
    72     Names names;
    71     Log log;
    73     Log log;
    72     Symtab syms;
    74     Symtab syms;
       
    75     Attr attr;
    73     Check chk;
    76     Check chk;
    74     Infer infer;
    77     Infer infer;
    75     ClassReader reader;
    78     ClassReader reader;
    76     TreeInfo treeinfo;
    79     TreeInfo treeinfo;
    77     Types types;
    80     Types types;
    99         typeNotFound = new
   102         typeNotFound = new
   100             SymbolNotFoundError(ABSENT_TYP);
   103             SymbolNotFoundError(ABSENT_TYP);
   101 
   104 
   102         names = Names.instance(context);
   105         names = Names.instance(context);
   103         log = Log.instance(context);
   106         log = Log.instance(context);
       
   107         attr = Attr.instance(context);
   104         chk = Check.instance(context);
   108         chk = Check.instance(context);
   105         infer = Infer.instance(context);
   109         infer = Infer.instance(context);
   106         reader = ClassReader.instance(context);
   110         reader = ClassReader.instance(context);
   107         treeinfo = TreeInfo.instance(context);
   111         treeinfo = TreeInfo.instance(context);
   108         types = Types.instance(context);
   112         types = Types.instance(context);
   625                 argtypes.size() != formals.size()) {
   629                 argtypes.size() != formals.size()) {
   626             throw handler.arityMismatch(); // not enough args
   630             throw handler.arityMismatch(); // not enough args
   627         }
   631         }
   628 
   632 
   629         while (argtypes.nonEmpty() && formals.head != varargsFormal) {
   633         while (argtypes.nonEmpty() && formals.head != varargsFormal) {
   630             Type undetFormal = infer.asUndetType(formals.head, undetvars);
   634             ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, undetvars, handler, warn);
   631             Type capturedActual = types.capture(argtypes.head);
   635             checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
   632             boolean works = allowBoxing ?
       
   633                     types.isConvertible(capturedActual, undetFormal, warn) :
       
   634                     types.isSubtypeUnchecked(capturedActual, undetFormal, warn);
       
   635             if (!works) {
       
   636                 throw handler.argumentMismatch(false, argtypes.head, formals.head);
       
   637             }
       
   638             checkedArgs.append(capturedActual);
       
   639             argtypes = argtypes.tail;
   636             argtypes = argtypes.tail;
   640             formals = formals.tail;
   637             formals = formals.tail;
   641         }
   638         }
   642 
   639 
   643         if (formals.head != varargsFormal) {
   640         if (formals.head != varargsFormal) {
   646 
   643 
   647         if (useVarargs) {
   644         if (useVarargs) {
   648             //note: if applicability check is triggered by most specific test,
   645             //note: if applicability check is triggered by most specific test,
   649             //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
   646             //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
   650             Type elt = types.elemtype(varargsFormal);
   647             Type elt = types.elemtype(varargsFormal);
   651             Type eltUndet = infer.asUndetType(elt, undetvars);
       
   652             while (argtypes.nonEmpty()) {
   648             while (argtypes.nonEmpty()) {
   653                 Type capturedActual = types.capture(argtypes.head);
   649                 ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn);
   654                 if (!types.isConvertible(capturedActual, eltUndet, warn)) {
   650                 checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
   655                     throw handler.argumentMismatch(true, argtypes.head, elt);
       
   656                 }
       
   657                 checkedArgs.append(capturedActual);
       
   658                 argtypes = argtypes.tail;
   651                 argtypes = argtypes.tail;
   659             }
   652             }
   660             //check varargs element type accessibility
   653             //check varargs element type accessibility
   661             if (undetvars.isEmpty() && !isAccessible(env, elt)) {
   654             if (undetvars.isEmpty() && !isAccessible(env, elt)) {
   662                 Symbol location = env.enclClass.sym;
   655                 Symbol location = env.enclClass.sym;
   663                 throw handler.inaccessibleVarargs(location, elt);
   656                 throw handler.inaccessibleVarargs(location, elt);
   664             }
   657             }
   665         }
   658         }
   666         return checkedArgs.toList();
   659         return checkedArgs.toList();
   667     }
   660     }
   668     // where
   661 
   669         public static class InapplicableMethodException extends RuntimeException {
   662     /**
   670             private static final long serialVersionUID = 0;
   663      * Check context to be used during method applicability checks. A method check
   671 
   664      * context might contain inference variables.
   672             JCDiagnostic diagnostic;
   665      */
   673             JCDiagnostic.Factory diags;
   666     abstract class MethodCheckContext implements CheckContext {
   674 
   667 
   675             InapplicableMethodException(JCDiagnostic.Factory diags) {
   668         MethodCheckHandler handler;
   676                 this.diagnostic = null;
   669         boolean useVarargs;
   677                 this.diags = diags;
   670         List<Type> undetvars;
   678             }
   671         Warner rsWarner;
   679             InapplicableMethodException setMessage() {
   672 
   680                 this.diagnostic = null;
   673         public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
   681                 return this;
   674             this.handler = handler;
   682             }
   675             this.useVarargs = useVarargs;
   683             InapplicableMethodException setMessage(String key) {
   676             this.undetvars = undetvars;
   684                 this.diagnostic = key != null ? diags.fragment(key) : null;
   677             this.rsWarner = rsWarner;
   685                 return this;
   678         }
   686             }
   679 
   687             InapplicableMethodException setMessage(String key, Object... args) {
   680         public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) {
   688                 this.diagnostic = key != null ? diags.fragment(key, args) : null;
   681             throw handler.argumentMismatch(useVarargs, found, req);
   689                 return this;
   682         }
   690             }
   683 
   691             InapplicableMethodException setMessage(JCDiagnostic diag) {
   684         public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) {
   692                 this.diagnostic = diag;
   685             throw new AssertionError("ForAll in argument position");
   693                 return this;
   686         }
   694             }
   687 
   695 
   688         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
   696             public JCDiagnostic getDiagnostic() {
   689             return rsWarner;
   697                 return diagnostic;
   690         }
   698             }
   691     }
   699         }
   692 
   700         private final InapplicableMethodException inapplicableMethodException;
   693     /**
       
   694      * Subclass of method check context class that implements strict method conversion.
       
   695      * Strict method conversion checks compatibility between types using subtyping tests.
       
   696      */
       
   697     class StrictMethodContext extends MethodCheckContext {
       
   698 
       
   699         public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
       
   700             super(handler, useVarargs, undetvars, rsWarner);
       
   701         }
       
   702 
       
   703         public boolean compatible(Type found, Type req, Warner warn) {
       
   704             return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn);
       
   705         }
       
   706     }
       
   707 
       
   708     /**
       
   709      * Subclass of method check context class that implements loose method conversion.
       
   710      * Loose method conversion checks compatibility between types using method conversion tests.
       
   711      */
       
   712     class LooseMethodContext extends MethodCheckContext {
       
   713 
       
   714         public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
       
   715             super(handler, useVarargs, undetvars, rsWarner);
       
   716         }
       
   717 
       
   718         public boolean compatible(Type found, Type req, Warner warn) {
       
   719             return types.isConvertible(found, infer.asUndetType(req, undetvars), warn);
       
   720         }
       
   721     }
       
   722 
       
   723     /**
       
   724      * Create a method check context to be used during method applicability check
       
   725      */
       
   726     ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
       
   727             List<Type> undetvars, MethodCheckHandler methodHandler, Warner rsWarner) {
       
   728         MethodCheckContext checkContext = allowBoxing ?
       
   729                 new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) :
       
   730                 new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner);
       
   731         return attr.new ResultInfo(VAL, to, checkContext) {
       
   732             @Override
       
   733             protected Type check(DiagnosticPosition pos, Type found) {
       
   734                 return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found))));
       
   735             }
       
   736         };
       
   737     }
       
   738 
       
   739     public static class InapplicableMethodException extends RuntimeException {
       
   740         private static final long serialVersionUID = 0;
       
   741 
       
   742         JCDiagnostic diagnostic;
       
   743         JCDiagnostic.Factory diags;
       
   744 
       
   745         InapplicableMethodException(JCDiagnostic.Factory diags) {
       
   746             this.diagnostic = null;
       
   747             this.diags = diags;
       
   748         }
       
   749         InapplicableMethodException setMessage() {
       
   750             this.diagnostic = null;
       
   751             return this;
       
   752         }
       
   753         InapplicableMethodException setMessage(String key) {
       
   754             this.diagnostic = key != null ? diags.fragment(key) : null;
       
   755             return this;
       
   756         }
       
   757         InapplicableMethodException setMessage(String key, Object... args) {
       
   758             this.diagnostic = key != null ? diags.fragment(key, args) : null;
       
   759             return this;
       
   760         }
       
   761         InapplicableMethodException setMessage(JCDiagnostic diag) {
       
   762             this.diagnostic = diag;
       
   763             return this;
       
   764         }
       
   765 
       
   766         public JCDiagnostic getDiagnostic() {
       
   767             return diagnostic;
       
   768         }
       
   769     }
       
   770     private final InapplicableMethodException inapplicableMethodException;
   701 
   771 
   702 /* ***************************************************************************
   772 /* ***************************************************************************
   703  *  Symbol lookup
   773  *  Symbol lookup
   704  *  the following naming conventions for arguments are used
   774  *  the following naming conventions for arguments are used
   705  *
   775  *