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

changeset 1697
950e8ac120f0
parent 1674
b71a61d39cf7
child 1850
6debfa63a4a1
equal deleted inserted replaced
1696:c2315af9cc28 1697:950e8ac120f0
798 }; 798 };
799 lambdaScanner.scan(lambda.body); 799 lambdaScanner.scan(lambda.body);
800 } 800 }
801 } 801 }
802 } 802 }
803
804 /**
805 * Does the argument expression {@code expr} need speculative type-checking?
806 */
807 boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
808 DeferredChecker dc = new DeferredChecker(env);
809 dc.scan(expr);
810 return dc.result.isPoly();
811 }
812
813 /**
814 * The kind of an argument expression. This is used by the analysis that
815 * determines as to whether speculative attribution is necessary.
816 */
817 enum ArgumentExpressionKind {
818
819 /** kind that denotes poly argument expression */
820 POLY,
821 /** kind that denotes a standalone expression */
822 NO_POLY,
823 /** kind that denotes a primitive/boxed standalone expression */
824 PRIMITIVE;
825
826 /**
827 * Does this kind denote a poly argument expression
828 */
829 public final boolean isPoly() {
830 return this == POLY;
831 }
832
833 /**
834 * Does this kind denote a primitive standalone expression
835 */
836 public final boolean isPrimitive() {
837 return this == PRIMITIVE;
838 }
839
840 /**
841 * Compute the kind of a standalone expression of a given type
842 */
843 static ArgumentExpressionKind standaloneKind(Type type, Types types) {
844 return types.unboxedTypeOrType(type).isPrimitive() ?
845 ArgumentExpressionKind.PRIMITIVE :
846 ArgumentExpressionKind.NO_POLY;
847 }
848
849 /**
850 * Compute the kind of a method argument expression given its symbol
851 */
852 static ArgumentExpressionKind methodKind(Symbol sym, Types types) {
853 Type restype = sym.type.getReturnType();
854 if (sym.type.hasTag(FORALL) &&
855 restype.containsAny(((ForAll)sym.type).tvars)) {
856 return ArgumentExpressionKind.POLY;
857 } else {
858 return ArgumentExpressionKind.standaloneKind(restype, types);
859 }
860 }
861 }
862
863 /**
864 * Tree scanner used for checking as to whether an argument expression
865 * requires speculative attribution
866 */
867 final class DeferredChecker extends FilterScanner {
868
869 Env<AttrContext> env;
870 ArgumentExpressionKind result;
871
872 public DeferredChecker(Env<AttrContext> env) {
873 super(deferredCheckerTags);
874 this.env = env;
875 }
876
877 @Override
878 public void visitLambda(JCLambda tree) {
879 //a lambda is always a poly expression
880 result = ArgumentExpressionKind.POLY;
881 }
882
883 @Override
884 public void visitReference(JCMemberReference tree) {
885 //a method reference is always a poly expression
886 result = ArgumentExpressionKind.POLY;
887 }
888
889 @Override
890 public void visitTypeCast(JCTypeCast tree) {
891 //a cast is always a standalone expression
892 result = ArgumentExpressionKind.NO_POLY;
893 }
894
895 @Override
896 public void visitConditional(JCConditional tree) {
897 scan(tree.truepart);
898 if (!result.isPrimitive()) {
899 result = ArgumentExpressionKind.POLY;
900 return;
901 }
902 scan(tree.falsepart);
903 result = reduce(ArgumentExpressionKind.PRIMITIVE);
904 }
905
906 @Override
907 public void visitNewClass(JCNewClass tree) {
908 result = (TreeInfo.isDiamond(tree) || attr.findDiamonds) ?
909 ArgumentExpressionKind.POLY : ArgumentExpressionKind.NO_POLY;
910 }
911
912 @Override
913 public void visitApply(JCMethodInvocation tree) {
914 Name name = TreeInfo.name(tree.meth);
915
916 //fast path
917 if (tree.typeargs.nonEmpty() ||
918 name == name.table.names._this ||
919 name == name.table.names._super) {
920 result = ArgumentExpressionKind.NO_POLY;
921 return;
922 }
923
924 //slow path
925 final JCExpression rec = tree.meth.hasTag(SELECT) ?
926 ((JCFieldAccess)tree.meth).selected :
927 null;
928
929 if (rec != null && !isSimpleReceiver(rec)) {
930 //give up if receiver is too complex (to cut down analysis time)
931 result = ArgumentExpressionKind.POLY;
932 return;
933 }
934
935 Type site = rec != null ?
936 attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
937 env.enclClass.sym.type;
938
939 ListBuffer<Type> args = ListBuffer.lb();
940 for (int i = 0; i < tree.args.length(); i ++) {
941 args.append(Type.noType);
942 }
943
944 Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.<Type>nil(), MethodResolutionPhase.VARARITY) {
945 @Override
946 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
947 return rec == null ?
948 rs.findFun(env, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
949 rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
950 }
951 @Override
952 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
953 return sym;
954 }
955 };
956
957 Symbol sym = rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh);
958
959 if (sym.kind == Kinds.AMBIGUOUS) {
960 Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym.baseSymbol();
961 result = ArgumentExpressionKind.PRIMITIVE;
962 for (List<Symbol> ambigousSyms = err.ambiguousSyms ;
963 ambigousSyms.nonEmpty() && !result.isPoly() ;
964 ambigousSyms = ambigousSyms.tail) {
965 Symbol s = ambigousSyms.head;
966 if (s.kind == Kinds.MTH) {
967 result = reduce(ArgumentExpressionKind.methodKind(s, types));
968 }
969 }
970 } else {
971 result = (sym.kind == Kinds.MTH) ?
972 ArgumentExpressionKind.methodKind(sym, types) :
973 ArgumentExpressionKind.NO_POLY;
974 }
975 }
976 //where
977 private boolean isSimpleReceiver(JCTree rec) {
978 switch (rec.getTag()) {
979 case IDENT:
980 return true;
981 case SELECT:
982 return isSimpleReceiver(((JCFieldAccess)rec).selected);
983 case TYPEAPPLY:
984 case TYPEARRAY:
985 return true;
986 case ANNOTATED_TYPE:
987 return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
988 default:
989 return false;
990 }
991 }
992 private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) {
993 switch (result) {
994 case PRIMITIVE: return kind;
995 case NO_POLY: return kind.isPoly() ? kind : result;
996 case POLY: return result;
997 default:
998 Assert.error();
999 return null;
1000 }
1001 }
1002
1003 @Override
1004 public void visitLiteral(JCLiteral tree) {
1005 Type litType = attr.litType(tree.typetag);
1006 result = ArgumentExpressionKind.standaloneKind(litType, types);
1007 }
1008
1009 @Override
1010 void skip(JCTree tree) {
1011 result = ArgumentExpressionKind.NO_POLY;
1012 }
1013 }
1014 //where
1015 private EnumSet<JCTree.Tag> deferredCheckerTags =
1016 EnumSet.of(LAMBDA, REFERENCE, PARENS, TYPECAST,
1017 CONDEXPR, NEWCLASS, APPLY, LITERAL);
803 } 1018 }

mercurial