419 /** |
419 /** |
420 * A check context is an object that can be used to perform compatibility |
420 * A check context is an object that can be used to perform compatibility |
421 * checks - depending on the check context, meaning of 'compatibility' might |
421 * checks - depending on the check context, meaning of 'compatibility' might |
422 * vary significantly. |
422 * vary significantly. |
423 */ |
423 */ |
424 interface CheckContext { |
424 public interface CheckContext { |
425 /** |
425 /** |
426 * Is type 'found' compatible with type 'req' in given context |
426 * Is type 'found' compatible with type 'req' in given context |
427 */ |
427 */ |
428 boolean compatible(Type found, Type req, Warner warn); |
428 boolean compatible(Type found, Type req, Warner warn); |
429 /** |
429 /** |
436 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); |
436 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); |
437 |
437 |
438 public Infer.InferenceContext inferenceContext(); |
438 public Infer.InferenceContext inferenceContext(); |
439 |
439 |
440 public DeferredAttr.DeferredAttrContext deferredAttrContext(); |
440 public DeferredAttr.DeferredAttrContext deferredAttrContext(); |
|
441 |
|
442 public boolean allowBoxing(); |
441 } |
443 } |
442 |
444 |
443 /** |
445 /** |
444 * This class represent a check context that is nested within another check |
446 * This class represent a check context that is nested within another check |
445 * context - useful to check sub-expressions. The default behavior simply |
447 * context - useful to check sub-expressions. The default behavior simply |
493 return infer.emptyContext; |
499 return infer.emptyContext; |
494 } |
500 } |
495 |
501 |
496 public DeferredAttrContext deferredAttrContext() { |
502 public DeferredAttrContext deferredAttrContext() { |
497 return deferredAttr.emptyDeferredAttrContext; |
503 return deferredAttr.emptyDeferredAttrContext; |
|
504 } |
|
505 |
|
506 public boolean allowBoxing() { |
|
507 return true; |
498 } |
508 } |
499 }; |
509 }; |
500 |
510 |
501 /** Check that a given type is assignable to a given proto-type. |
511 /** Check that a given type is assignable to a given proto-type. |
502 * If it is, return the type, otherwise return errType. |
512 * If it is, return the type, otherwise return errType. |
555 /** Check for redundant casts (i.e. where source type is a subtype of target type) |
565 /** Check for redundant casts (i.e. where source type is a subtype of target type) |
556 * The problem should only be reported for non-292 cast |
566 * The problem should only be reported for non-292 cast |
557 */ |
567 */ |
558 public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) { |
568 public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) { |
559 if (!tree.type.isErroneous() && |
569 if (!tree.type.isErroneous() && |
560 (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) |
570 (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) |
561 && types.isSameType(tree.expr.type, tree.clazz.type) |
571 && types.isSameType(tree.expr.type, tree.clazz.type) |
562 && !is292targetTypeCast(tree)) { |
572 && !is292targetTypeCast(tree)) { |
563 log.warning(Lint.LintCategory.CAST, |
573 log.warning(Lint.LintCategory.CAST, |
564 tree.pos(), "redundant.cast", tree.expr.type); |
574 tree.pos(), "redundant.cast", tree.expr.type); |
565 } |
575 } |
566 } |
576 } |
567 //where |
577 //where |
904 && types.isSubtype(actual, types.supertype(formal)) |
914 && types.isSubtype(actual, types.supertype(formal)) |
905 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) |
915 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) |
906 return; |
916 return; |
907 } |
917 } |
908 |
918 |
|
919 void checkAccessibleFunctionalDescriptor(DiagnosticPosition pos, Env<AttrContext> env, Type desc) { |
|
920 AccessChecker accessChecker = new AccessChecker(env); |
|
921 //check args accessibility (only if implicit parameter types) |
|
922 for (Type arg : desc.getParameterTypes()) { |
|
923 if (!accessChecker.visit(arg)) { |
|
924 log.error(pos, "cant.access.arg.type.in.functional.desc", arg); |
|
925 return; |
|
926 } |
|
927 } |
|
928 //check return type accessibility |
|
929 if (!accessChecker.visit(desc.getReturnType())) { |
|
930 log.error(pos, "cant.access.return.in.functional.desc", desc.getReturnType()); |
|
931 return; |
|
932 } |
|
933 //check thrown types accessibility |
|
934 for (Type thrown : desc.getThrownTypes()) { |
|
935 if (!accessChecker.visit(thrown)) { |
|
936 log.error(pos, "cant.access.thrown.in.functional.desc", thrown); |
|
937 return; |
|
938 } |
|
939 } |
|
940 } |
|
941 |
|
942 class AccessChecker extends Types.UnaryVisitor<Boolean> { |
|
943 |
|
944 Env<AttrContext> env; |
|
945 |
|
946 AccessChecker(Env<AttrContext> env) { |
|
947 this.env = env; |
|
948 } |
|
949 |
|
950 Boolean visit(List<Type> ts) { |
|
951 for (Type t : ts) { |
|
952 if (!visit(t)) |
|
953 return false; |
|
954 } |
|
955 return true; |
|
956 } |
|
957 |
|
958 public Boolean visitType(Type t, Void s) { |
|
959 return true; |
|
960 } |
|
961 |
|
962 @Override |
|
963 public Boolean visitArrayType(ArrayType t, Void s) { |
|
964 return visit(t.elemtype); |
|
965 } |
|
966 |
|
967 @Override |
|
968 public Boolean visitClassType(ClassType t, Void s) { |
|
969 return rs.isAccessible(env, t, true) && |
|
970 visit(t.getTypeArguments()); |
|
971 } |
|
972 |
|
973 @Override |
|
974 public Boolean visitWildcardType(WildcardType t, Void s) { |
|
975 return visit(t.type); |
|
976 } |
|
977 }; |
909 /** |
978 /** |
910 * Check that type 't' is a valid instantiation of a generic class |
979 * Check that type 't' is a valid instantiation of a generic class |
911 * (see JLS 4.5) |
980 * (see JLS 4.5) |
912 * |
981 * |
913 * @param t class type to be checked |
982 * @param t class type to be checked |