diff -r 475eb15dfdad -r f91144b7da75 src/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Jan 21 01:27:42 2013 -0500 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Feb 04 18:08:53 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package com.sun.tools.javac.comp; import java.util.*; -import java.util.Set; + import javax.tools.JavaFileManager; import com.sun.tools.javac.code.*; @@ -36,7 +36,6 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Type.*; @@ -44,6 +43,8 @@ import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.ANNOTATION; @@ -101,6 +102,9 @@ context.put(checkKey, this); names = Names.instance(context); + dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE, + names.FIELD, names.METHOD, names.CONSTRUCTOR, + names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER}; log = Log.instance(context); rs = Resolve.instance(context); syms = Symtab.instance(context); @@ -574,34 +578,27 @@ if (!tree.type.isErroneous() && (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) && types.isSameType(tree.expr.type, tree.clazz.type) + && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) && !is292targetTypeCast(tree)) { log.warning(Lint.LintCategory.CAST, tree.pos(), "redundant.cast", tree.expr.type); } } //where - private boolean is292targetTypeCast(JCTypeCast tree) { - boolean is292targetTypeCast = false; - JCExpression expr = TreeInfo.skipParens(tree.expr); - if (expr.hasTag(APPLY)) { - JCMethodInvocation apply = (JCMethodInvocation)expr; - Symbol sym = TreeInfo.symbol(apply.meth); - is292targetTypeCast = sym != null && - sym.kind == MTH && - (sym.flags() & HYPOTHETICAL) != 0; - } - return is292targetTypeCast; + private boolean is292targetTypeCast(JCTypeCast tree) { + boolean is292targetTypeCast = false; + JCExpression expr = TreeInfo.skipParens(tree.expr); + if (expr.hasTag(APPLY)) { + JCMethodInvocation apply = (JCMethodInvocation)expr; + Symbol sym = TreeInfo.symbol(apply.meth); + is292targetTypeCast = sym != null && + sym.kind == MTH && + (sym.flags() & HYPOTHETICAL) != 0; } + return is292targetTypeCast; + } - - -//where - /** Is type a type variable, or a (possibly multi-dimensional) array of - * type variables? - */ - boolean isTypeVar(Type t) { - return t.hasTag(TYPEVAR) || t.hasTag(ARRAY) && isTypeVar(types.elemtype(t)); - } + private static final boolean ignoreAnnotatedCasts = true; /** Check that a type is within some bounds. * @@ -637,25 +634,40 @@ } } + Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { + if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { + return typeTagError(pos, + diags.fragment("type.req.class.array"), + asTypeParam(t)); + } else { + return t; + } + } + /** Check that type is a class or interface type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkClassType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) + if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { return typeTagError(pos, diags.fragment("type.req.class"), - (t.hasTag(TYPEVAR)) - ? diags.fragment("type.parameter", t) - : t); - else + asTypeParam(t)); + } else { return t; + } } + //where + private Object asTypeParam(Type t) { + return (t.hasTag(TYPEVAR)) + ? diags.fragment("type.parameter", t) + : t; + } /** Check that type is a valid qualifier for a constructor reference expression */ Type checkConstructorRefType(DiagnosticPosition pos, Type t) { - t = checkClassType(pos, t); + t = checkClassOrArrayType(pos, t); if (t.hasTag(CLASS)) { if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { log.error(pos, "abstract.cant.be.instantiated"); @@ -693,11 +705,8 @@ * @param t The type to be checked. */ Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { - return typeTagError(pos, - diags.fragment("type.req.class.array"), - t); - } else if (!types.isReifiable(t)) { + t = checkClassOrArrayType(pos, t); + if (!t.isErroneous() && !types.isReifiable(t)) { log.error(pos, "illegal.generic.type.for.instof"); return types.createErrorType(t); } else { @@ -843,7 +852,7 @@ // System.out.println("actuals: " + argtypes); List formals = owntype.getParameterTypes(); Type last = useVarargs ? formals.last() : null; - if (sym.name==names.init && + if (sym.name == names.init && sym.owner == syms.enumSym) formals = formals.tail.tail; List args = argtrees; @@ -891,7 +900,6 @@ syms.methodClass); } if (useVarargs) { - JCTree tree = env.tree; Type argtype = owntype.getParameterTypes().last(); if (!types.isReifiable(argtype) && (!allowSimplifiedVarargs || @@ -902,22 +910,13 @@ argtype); } if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) { - Type elemtype = types.elemtype(argtype); - switch (tree.getTag()) { - case APPLY: - ((JCMethodInvocation) tree).varargsElement = elemtype; - break; - case NEWCLASS: - ((JCNewClass) tree).varargsElement = elemtype; - break; - case REFERENCE: - ((JCMemberReference) tree).varargsElement = elemtype; - break; - default: - throw new AssertionError(""+tree); - } + TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype)); } } + PolyKind pkind = (sym.type.hasTag(FORALL) && + sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ? + PolyKind.POLY : PolyKind.STANDALONE; + TreeInfo.setPolyKind(env.tree, pkind); return owntype; } //where @@ -1058,9 +1057,12 @@ } else mask = ConstructorFlags; } else if ((sym.owner.flags_field & INTERFACE) != 0) { - if ((flags & DEFAULT) != 0) { - mask = InterfaceDefaultMethodMask; - implicit = PUBLIC | ABSTRACT; + if ((flags & (DEFAULT | STATIC)) != 0) { + mask = InterfaceMethodMask; + implicit = PUBLIC; + if ((flags & DEFAULT) != 0) { + implicit |= ABSTRACT; + } } else { mask = implicit = InterfaceMethodFlags; } @@ -1130,6 +1132,10 @@ PRIVATE | STATIC | DEFAULT)) && checkDisjoint(pos, flags, + STATIC, + DEFAULT) + && + checkDisjoint(pos, flags, ABSTRACT | INTERFACE, FINAL | NATIVE | SYNCHRONIZED) && @@ -1319,6 +1325,11 @@ } } + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.underlyingType.accept(this); + } + /** Default visitor method: do nothing. */ @Override @@ -2239,7 +2250,7 @@ void checkImplementations(JCClassDecl tree) { checkImplementations(tree, tree.sym, tree.sym); } -//where + //where /** Check that all methods which implement some * method in `ic' conform to the method they implement. */ @@ -2580,6 +2591,13 @@ validateAnnotation(a, s); } + /** Check the type annotations. + */ + public void validateTypeAnnotations(List annotations, boolean isTypeParameter) { + for (JCAnnotation a : annotations) + validateTypeAnnotation(a, isTypeParameter); + } + /** Check an annotation of a symbol. */ private void validateAnnotation(JCAnnotation a, Symbol s) { @@ -2592,33 +2610,53 @@ if (!isOverrider(s)) log.error(a.pos(), "method.does.not.override.superclass"); } + + if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { + if (s.kind != TYP) { + log.error(a.pos(), "bad.functional.intf.anno"); + } else { + try { + types.findDescriptorSymbol((TypeSymbol)s); + } catch (Types.FunctionDescriptorLookupError ex) { + log.error(a.pos(), "bad.functional.intf.anno.1", ex.getDiagnostic()); + } + } + } + } + + public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a); + validateAnnotationTree(a); + + if (!isTypeAnnotation(a, isTypeParameter)) + log.error(a.pos(), "annotation.type.not.applicable"); } /** - * Validate the proposed container 'containedBy' on the + * Validate the proposed container 'repeatable' on the * annotation type symbol 's'. Report errors at position * 'pos'. * - * @param s The (annotation)type declaration annotated with a @ContainedBy - * @param containedBy the @ContainedBy on 's' + * @param s The (annotation)type declaration annotated with a @Repeatable + * @param repeatable the @Repeatable on 's' * @param pos where to report errors */ - public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) { - Assert.check(types.isSameType(containedBy.type, syms.containedByType)); + public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { + Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); Type t = null; - List> l = containedBy.values; + List> l = repeatable.values; if (!l.isEmpty()) { Assert.check(l.head.fst.name == names.value); t = ((Attribute.Class)l.head.snd).getValue(); } if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", s, containedBy); + // errors should already have been reported during Annotate return; } - validateHasContainerFor(t.tsym, s, pos); + validateValue(t.tsym, s, pos); validateRetention(t.tsym, s, pos); validateDocumented(t.tsym, s, pos); validateInherited(t.tsym, s, pos); @@ -2626,79 +2664,18 @@ validateDefault(t.tsym, s, pos); } - /** - * Validate the proposed container 'containerFor' on the - * annotation type symbol 's'. Report errors at position - * 'pos'. - * - * @param s The (annotation)type declaration annotated with a @ContainerFor - * @param containerFor the @ContainedFor on 's' - * @param pos where to report errors - */ - public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) { - Assert.check(types.isSameType(containerFor.type, syms.containerForType)); - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); + private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { + Scope.Entry e = container.members().lookup(names.value); + if (e.scope != null && e.sym.kind == MTH) { + MethodSymbol m = (MethodSymbol) e.sym; + Type ret = m.getReturnType(); + if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { + log.error(pos, "invalid.repeatable.annotation.value.return", + container, ret, types.makeArrayType(contained.type)); + } + } else { + log.error(pos, "invalid.repeatable.annotation.no.value", container); } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", s, containerFor); - return; - } - - validateHasContainedBy(t.tsym, s, pos); - } - - private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym); - - if (containedBy == null) { - log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym); - return; - } - - Type t = null; - List> l = containedBy.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained); - } - - private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym); - - if (containerFor == null) { - log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym); - return; - } - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained); } private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { @@ -2718,7 +2695,7 @@ } } if (error ) { - log.error(pos, "invalid.containedby.annotation.retention", + log.error(pos, "invalid.repeatable.annotation.retention", container, containerRetention, contained, containedRetention); } @@ -2727,7 +2704,7 @@ private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.documentedType.tsym) != null) { if (container.attribute(syms.documentedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.documented", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained); } } } @@ -2735,7 +2712,7 @@ private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.inheritedType.tsym) != null) { if (container.attribute(syms.inheritedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained); } } } @@ -2755,7 +2732,7 @@ // contained has target, but container has not, error Attribute.Array containerTarget = getAttributeTargetAttribute(container); if (containerTarget == null) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); return; } @@ -2778,7 +2755,7 @@ } if (!isTargetSubset(containedTargets, containerTargets)) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); } } @@ -2812,7 +2789,7 @@ elm.kind == Kinds.MTH && ((MethodSymbol)elm).defaultValue == null) { log.error(pos, - "invalid.containedby.annotation.elem.nondefault", + "invalid.repeatable.annotation.elem.nondefault", container, elm); } @@ -2837,45 +2814,90 @@ return false; } + /** Is the annotation applicable to type annotations? */ + protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Attribute.Compound atTarget = + a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) { + // An annotation without @Target is not a type annotation. + return false; + } + + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) { + return false; // error recovery + } + + Attribute.Array arr = (Attribute.Array) atValue; + for (Attribute app : arr.values) { + if (!(app instanceof Attribute.Enum)) { + return false; // recovery + } + Attribute.Enum e = (Attribute.Enum) app; + + if (e.value.name == names.TYPE_USE) + return true; + else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER) + return true; + } + return false; + } + /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); + Name[] targets; + if (arr == null) { - return true; + targets = defaultTargetMetaInfo(a, s); + } else { + // TODO: can we optimize this? + targets = new Name[arr.values.length]; + for (int i=0; i