Mon, 15 Nov 2010 13:50:53 +0000
6985719: Alike methods in interfaces (Inheritance and Overriding)
Summary: javac should report error when interface inherits unrelated method with same erasure
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.comp;
28 import java.util.*;
29 import java.util.Set;
31 import com.sun.tools.javac.code.*;
32 import com.sun.tools.javac.jvm.*;
33 import com.sun.tools.javac.tree.*;
34 import com.sun.tools.javac.util.*;
35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
36 import com.sun.tools.javac.util.List;
38 import com.sun.tools.javac.tree.JCTree.*;
39 import com.sun.tools.javac.code.Lint;
40 import com.sun.tools.javac.code.Lint.LintCategory;
41 import com.sun.tools.javac.code.Type.*;
42 import com.sun.tools.javac.code.Symbol.*;
44 import static com.sun.tools.javac.code.Flags.*;
45 import static com.sun.tools.javac.code.Kinds.*;
46 import static com.sun.tools.javac.code.TypeTags.*;
48 import static com.sun.tools.javac.main.OptionName.*;
50 /** Type checking helper class for the attribution phase.
51 *
52 * <p><b>This is NOT part of any supported API.
53 * If you write code that depends on this, you do so at your own risk.
54 * This code and its internal interfaces are subject to change or
55 * deletion without notice.</b>
56 */
57 public class Check {
58 protected static final Context.Key<Check> checkKey =
59 new Context.Key<Check>();
61 private final Names names;
62 private final Log log;
63 private final Symtab syms;
64 private final Enter enter;
65 private final Infer infer;
66 private final Types types;
67 private final JCDiagnostic.Factory diags;
68 private final boolean skipAnnotations;
69 private boolean warnOnSyntheticConflicts;
70 private boolean suppressAbortOnBadClassFile;
71 private final TreeInfo treeinfo;
73 // The set of lint options currently in effect. It is initialized
74 // from the context, and then is set/reset as needed by Attr as it
75 // visits all the various parts of the trees during attribution.
76 private Lint lint;
78 public static Check instance(Context context) {
79 Check instance = context.get(checkKey);
80 if (instance == null)
81 instance = new Check(context);
82 return instance;
83 }
85 protected Check(Context context) {
86 context.put(checkKey, this);
88 names = Names.instance(context);
89 log = Log.instance(context);
90 syms = Symtab.instance(context);
91 enter = Enter.instance(context);
92 infer = Infer.instance(context);
93 this.types = Types.instance(context);
94 diags = JCDiagnostic.Factory.instance(context);
95 Options options = Options.instance(context);
96 lint = Lint.instance(context);
97 treeinfo = TreeInfo.instance(context);
99 Source source = Source.instance(context);
100 allowGenerics = source.allowGenerics();
101 allowAnnotations = source.allowAnnotations();
102 allowCovariantReturns = source.allowCovariantReturns();
103 complexInference = options.isSet(COMPLEXINFERENCE);
104 skipAnnotations = options.isSet("skipAnnotations");
105 warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
106 suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
108 Target target = Target.instance(context);
109 syntheticNameChar = target.syntheticNameChar();
111 boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
112 boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
113 boolean verboseVarargs = lint.isEnabled(LintCategory.VARARGS);
114 boolean verboseSunApi = lint.isEnabled(LintCategory.SUNAPI);
115 boolean enforceMandatoryWarnings = source.enforceMandatoryWarnings();
117 deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
118 enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION);
119 uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked,
120 enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
121 unsafeVarargsHandler = new MandatoryWarningHandler(log, verboseVarargs,
122 enforceMandatoryWarnings, "varargs", LintCategory.VARARGS);
123 sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi,
124 enforceMandatoryWarnings, "sunapi", null);
125 }
127 /** Switch: generics enabled?
128 */
129 boolean allowGenerics;
131 /** Switch: annotations enabled?
132 */
133 boolean allowAnnotations;
135 /** Switch: covariant returns enabled?
136 */
137 boolean allowCovariantReturns;
139 /** Switch: -complexinference option set?
140 */
141 boolean complexInference;
143 /** Character for synthetic names
144 */
145 char syntheticNameChar;
147 /** A table mapping flat names of all compiled classes in this run to their
148 * symbols; maintained from outside.
149 */
150 public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>();
152 /** A handler for messages about deprecated usage.
153 */
154 private MandatoryWarningHandler deprecationHandler;
156 /** A handler for messages about unchecked or unsafe usage.
157 */
158 private MandatoryWarningHandler uncheckedHandler;
160 /** A handler for messages about unchecked or unsafe vararg method decl.
161 */
162 private MandatoryWarningHandler unsafeVarargsHandler;
164 /** A handler for messages about using proprietary API.
165 */
166 private MandatoryWarningHandler sunApiHandler;
168 /* *************************************************************************
169 * Errors and Warnings
170 **************************************************************************/
172 Lint setLint(Lint newLint) {
173 Lint prev = lint;
174 lint = newLint;
175 return prev;
176 }
178 /** Warn about deprecated symbol.
179 * @param pos Position to be used for error reporting.
180 * @param sym The deprecated symbol.
181 */
182 void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
183 if (!lint.isSuppressed(LintCategory.DEPRECATION))
184 deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
185 }
187 /** Warn about unchecked operation.
188 * @param pos Position to be used for error reporting.
189 * @param msg A string describing the problem.
190 */
191 public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) {
192 if (!lint.isSuppressed(LintCategory.UNCHECKED))
193 uncheckedHandler.report(pos, msg, args);
194 }
196 /** Warn about unsafe vararg method decl.
197 * @param pos Position to be used for error reporting.
198 * @param sym The deprecated symbol.
199 */
200 void warnUnsafeVararg(DiagnosticPosition pos, Type elemType) {
201 if (!lint.isSuppressed(LintCategory.VARARGS))
202 unsafeVarargsHandler.report(pos, "varargs.non.reifiable.type", elemType);
203 }
205 /** Warn about using proprietary API.
206 * @param pos Position to be used for error reporting.
207 * @param msg A string describing the problem.
208 */
209 public void warnSunApi(DiagnosticPosition pos, String msg, Object... args) {
210 if (!lint.isSuppressed(LintCategory.SUNAPI))
211 sunApiHandler.report(pos, msg, args);
212 }
214 public void warnStatic(DiagnosticPosition pos, String msg, Object... args) {
215 if (lint.isEnabled(LintCategory.STATIC))
216 log.warning(LintCategory.STATIC, pos, msg, args);
217 }
219 /**
220 * Report any deferred diagnostics.
221 */
222 public void reportDeferredDiagnostics() {
223 deprecationHandler.reportDeferredDiagnostic();
224 uncheckedHandler.reportDeferredDiagnostic();
225 unsafeVarargsHandler.reportDeferredDiagnostic();
226 sunApiHandler.reportDeferredDiagnostic();
227 }
230 /** Report a failure to complete a class.
231 * @param pos Position to be used for error reporting.
232 * @param ex The failure to report.
233 */
234 public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
235 log.error(pos, "cant.access", ex.sym, ex.getDetailValue());
236 if (ex instanceof ClassReader.BadClassFile
237 && !suppressAbortOnBadClassFile) throw new Abort();
238 else return syms.errType;
239 }
241 /** Report a type error.
242 * @param pos Position to be used for error reporting.
243 * @param problem A string describing the error.
244 * @param found The type that was found.
245 * @param req The type that was required.
246 */
247 Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) {
248 log.error(pos, "prob.found.req",
249 problem, found, req);
250 return types.createErrorType(found);
251 }
253 Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) {
254 log.error(pos, "prob.found.req.1", problem, found, req, explanation);
255 return types.createErrorType(found);
256 }
258 /** Report an error that wrong type tag was found.
259 * @param pos Position to be used for error reporting.
260 * @param required An internationalized string describing the type tag
261 * required.
262 * @param found The type that was found.
263 */
264 Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
265 // this error used to be raised by the parser,
266 // but has been delayed to this point:
267 if (found instanceof Type && ((Type)found).tag == VOID) {
268 log.error(pos, "illegal.start.of.type");
269 return syms.errType;
270 }
271 log.error(pos, "type.found.req", found, required);
272 return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
273 }
275 /** Report an error that symbol cannot be referenced before super
276 * has been called.
277 * @param pos Position to be used for error reporting.
278 * @param sym The referenced symbol.
279 */
280 void earlyRefError(DiagnosticPosition pos, Symbol sym) {
281 log.error(pos, "cant.ref.before.ctor.called", sym);
282 }
284 /** Report duplicate declaration error.
285 */
286 void duplicateError(DiagnosticPosition pos, Symbol sym) {
287 if (!sym.type.isErroneous()) {
288 log.error(pos, "already.defined", sym, sym.location());
289 }
290 }
292 /** Report array/varargs duplicate declaration
293 */
294 void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
295 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
296 log.error(pos, "array.and.varargs", sym1, sym2, sym2.location());
297 }
298 }
300 /* ************************************************************************
301 * duplicate declaration checking
302 *************************************************************************/
304 /** Check that variable does not hide variable with same name in
305 * immediately enclosing local scope.
306 * @param pos Position for error reporting.
307 * @param v The symbol.
308 * @param s The scope.
309 */
310 void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
311 if (s.next != null) {
312 for (Scope.Entry e = s.next.lookup(v.name);
313 e.scope != null && e.sym.owner == v.owner;
314 e = e.next()) {
315 if (e.sym.kind == VAR &&
316 (e.sym.owner.kind & (VAR | MTH)) != 0 &&
317 v.name != names.error) {
318 duplicateError(pos, e.sym);
319 return;
320 }
321 }
322 }
323 }
325 /** Check that a class or interface does not hide a class or
326 * interface with same name in immediately enclosing local scope.
327 * @param pos Position for error reporting.
328 * @param c The symbol.
329 * @param s The scope.
330 */
331 void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
332 if (s.next != null) {
333 for (Scope.Entry e = s.next.lookup(c.name);
334 e.scope != null && e.sym.owner == c.owner;
335 e = e.next()) {
336 if (e.sym.kind == TYP && e.sym.type.tag != TYPEVAR &&
337 (e.sym.owner.kind & (VAR | MTH)) != 0 &&
338 c.name != names.error) {
339 duplicateError(pos, e.sym);
340 return;
341 }
342 }
343 }
344 }
346 /** Check that class does not have the same name as one of
347 * its enclosing classes, or as a class defined in its enclosing scope.
348 * return true if class is unique in its enclosing scope.
349 * @param pos Position for error reporting.
350 * @param name The class name.
351 * @param s The enclosing scope.
352 */
353 boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
354 for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
355 if (e.sym.kind == TYP && e.sym.name != names.error) {
356 duplicateError(pos, e.sym);
357 return false;
358 }
359 }
360 for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
361 if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
362 duplicateError(pos, sym);
363 return true;
364 }
365 }
366 return true;
367 }
369 /* *************************************************************************
370 * Class name generation
371 **************************************************************************/
373 /** Return name of local class.
374 * This is of the form <enclClass> $ n <classname>
375 * where
376 * enclClass is the flat name of the enclosing class,
377 * classname is the simple name of the local class
378 */
379 Name localClassName(ClassSymbol c) {
380 for (int i=1; ; i++) {
381 Name flatname = names.
382 fromString("" + c.owner.enclClass().flatname +
383 syntheticNameChar + i +
384 c.name);
385 if (compiled.get(flatname) == null) return flatname;
386 }
387 }
389 /* *************************************************************************
390 * Type Checking
391 **************************************************************************/
393 /** Check that a given type is assignable to a given proto-type.
394 * If it is, return the type, otherwise return errType.
395 * @param pos Position to be used for error reporting.
396 * @param found The type that was found.
397 * @param req The type that was required.
398 */
399 Type checkType(DiagnosticPosition pos, Type found, Type req) {
400 return checkType(pos, found, req, "incompatible.types");
401 }
403 Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) {
404 if (req.tag == ERROR)
405 return req;
406 if (found.tag == FORALL)
407 return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req));
408 if (req.tag == NONE)
409 return found;
410 if (types.isAssignable(found, req, convertWarner(pos, found, req)))
411 return found;
412 if (found.tag <= DOUBLE && req.tag <= DOUBLE)
413 return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
414 if (found.isSuperBound()) {
415 log.error(pos, "assignment.from.super-bound", found);
416 return types.createErrorType(found);
417 }
418 if (req.isExtendsBound()) {
419 log.error(pos, "assignment.to.extends-bound", req);
420 return types.createErrorType(found);
421 }
422 return typeError(pos, diags.fragment(errKey), found, req);
423 }
425 /** Instantiate polymorphic type to some prototype, unless
426 * prototype is `anyPoly' in which case polymorphic type
427 * is returned unchanged.
428 */
429 Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
430 if (pt == Infer.anyPoly && complexInference) {
431 return t;
432 } else if (pt == Infer.anyPoly || pt.tag == NONE) {
433 Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType;
434 return instantiatePoly(pos, t, newpt, warn);
435 } else if (pt.tag == ERROR) {
436 return pt;
437 } else {
438 try {
439 return infer.instantiateExpr(t, pt, warn);
440 } catch (Infer.NoInstanceException ex) {
441 if (ex.isAmbiguous) {
442 JCDiagnostic d = ex.getDiagnostic();
443 log.error(pos,
444 "undetermined.type" + (d!=null ? ".1" : ""),
445 t, d);
446 return types.createErrorType(pt);
447 } else {
448 JCDiagnostic d = ex.getDiagnostic();
449 return typeError(pos,
450 diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d),
451 t, pt);
452 }
453 } catch (Infer.InvalidInstanceException ex) {
454 JCDiagnostic d = ex.getDiagnostic();
455 log.error(pos, "invalid.inferred.types", t.tvars, d);
456 return types.createErrorType(pt);
457 }
458 }
459 }
461 /** Check that a given type can be cast to a given target type.
462 * Return the result of the cast.
463 * @param pos Position to be used for error reporting.
464 * @param found The type that is being cast.
465 * @param req The target type of the cast.
466 */
467 Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
468 if (found.tag == FORALL) {
469 instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req));
470 return req;
471 } else if (types.isCastable(found, req, castWarner(pos, found, req))) {
472 return req;
473 } else {
474 return typeError(pos,
475 diags.fragment("inconvertible.types"),
476 found, req);
477 }
478 }
479 //where
480 /** Is type a type variable, or a (possibly multi-dimensional) array of
481 * type variables?
482 */
483 boolean isTypeVar(Type t) {
484 return t.tag == TYPEVAR || t.tag == ARRAY && isTypeVar(types.elemtype(t));
485 }
487 /** Check that a type is within some bounds.
488 *
489 * Used in TypeApply to verify that, e.g., X in V<X> is a valid
490 * type argument.
491 * @param pos Position to be used for error reporting.
492 * @param a The type that should be bounded by bs.
493 * @param bs The bound.
494 */
495 private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) {
496 if (a.isUnbound()) {
497 return;
498 } else if (a.tag != WILDCARD) {
499 a = types.upperBound(a);
500 for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
501 if (!types.isSubtype(a, l.head)) {
502 log.error(pos, "not.within.bounds", a);
503 return;
504 }
505 }
506 } else if (a.isExtendsBound()) {
507 if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings))
508 log.error(pos, "not.within.bounds", a);
509 } else if (a.isSuperBound()) {
510 if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()))
511 log.error(pos, "not.within.bounds", a);
512 }
513 }
515 /** Check that a type is within some bounds.
516 *
517 * Used in TypeApply to verify that, e.g., X in V<X> is a valid
518 * type argument.
519 * @param pos Position to be used for error reporting.
520 * @param a The type that should be bounded by bs.
521 * @param bs The bound.
522 */
523 private void checkCapture(JCTypeApply tree) {
524 List<JCExpression> args = tree.getTypeArguments();
525 for (Type arg : types.capture(tree.type).getTypeArguments()) {
526 if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
527 log.error(args.head.pos, "not.within.bounds", args.head.type);
528 break;
529 }
530 args = args.tail;
531 }
532 }
534 /** Check that type is different from 'void'.
535 * @param pos Position to be used for error reporting.
536 * @param t The type to be checked.
537 */
538 Type checkNonVoid(DiagnosticPosition pos, Type t) {
539 if (t.tag == VOID) {
540 log.error(pos, "void.not.allowed.here");
541 return types.createErrorType(t);
542 } else {
543 return t;
544 }
545 }
547 /** Check that type is a class or interface type.
548 * @param pos Position to be used for error reporting.
549 * @param t The type to be checked.
550 */
551 Type checkClassType(DiagnosticPosition pos, Type t) {
552 if (t.tag != CLASS && t.tag != ERROR)
553 return typeTagError(pos,
554 diags.fragment("type.req.class"),
555 (t.tag == TYPEVAR)
556 ? diags.fragment("type.parameter", t)
557 : t);
558 else
559 return t;
560 }
562 /** Check that type is a class or interface type.
563 * @param pos Position to be used for error reporting.
564 * @param t The type to be checked.
565 * @param noBounds True if type bounds are illegal here.
566 */
567 Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
568 t = checkClassType(pos, t);
569 if (noBounds && t.isParameterized()) {
570 List<Type> args = t.getTypeArguments();
571 while (args.nonEmpty()) {
572 if (args.head.tag == WILDCARD)
573 return typeTagError(pos,
574 diags.fragment("type.req.exact"),
575 args.head);
576 args = args.tail;
577 }
578 }
579 return t;
580 }
582 /** Check that type is a reifiable class, interface or array type.
583 * @param pos Position to be used for error reporting.
584 * @param t The type to be checked.
585 */
586 Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
587 if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) {
588 return typeTagError(pos,
589 diags.fragment("type.req.class.array"),
590 t);
591 } else if (!types.isReifiable(t)) {
592 log.error(pos, "illegal.generic.type.for.instof");
593 return types.createErrorType(t);
594 } else {
595 return t;
596 }
597 }
599 /** Check that type is a reference type, i.e. a class, interface or array type
600 * or a type variable.
601 * @param pos Position to be used for error reporting.
602 * @param t The type to be checked.
603 */
604 Type checkRefType(DiagnosticPosition pos, Type t) {
605 switch (t.tag) {
606 case CLASS:
607 case ARRAY:
608 case TYPEVAR:
609 case WILDCARD:
610 case ERROR:
611 return t;
612 default:
613 return typeTagError(pos,
614 diags.fragment("type.req.ref"),
615 t);
616 }
617 }
619 /** Check that each type is a reference type, i.e. a class, interface or array type
620 * or a type variable.
621 * @param trees Original trees, used for error reporting.
622 * @param types The types to be checked.
623 */
624 List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
625 List<JCExpression> tl = trees;
626 for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
627 l.head = checkRefType(tl.head.pos(), l.head);
628 tl = tl.tail;
629 }
630 return types;
631 }
633 /** Check that type is a null or reference type.
634 * @param pos Position to be used for error reporting.
635 * @param t The type to be checked.
636 */
637 Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
638 switch (t.tag) {
639 case CLASS:
640 case ARRAY:
641 case TYPEVAR:
642 case WILDCARD:
643 case BOT:
644 case ERROR:
645 return t;
646 default:
647 return typeTagError(pos,
648 diags.fragment("type.req.ref"),
649 t);
650 }
651 }
653 /** Check that flag set does not contain elements of two conflicting sets. s
654 * Return true if it doesn't.
655 * @param pos Position to be used for error reporting.
656 * @param flags The set of flags to be checked.
657 * @param set1 Conflicting flags set #1.
658 * @param set2 Conflicting flags set #2.
659 */
660 boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) {
661 if ((flags & set1) != 0 && (flags & set2) != 0) {
662 log.error(pos,
663 "illegal.combination.of.modifiers",
664 asFlagSet(TreeInfo.firstFlag(flags & set1)),
665 asFlagSet(TreeInfo.firstFlag(flags & set2)));
666 return false;
667 } else
668 return true;
669 }
671 /** Check that the type inferred using the diamond operator does not contain
672 * non-denotable types such as captured types or intersection types.
673 * @param t the type inferred using the diamond operator
674 */
675 List<Type> checkDiamond(ClassType t) {
676 DiamondTypeChecker dtc = new DiamondTypeChecker();
677 ListBuffer<Type> buf = ListBuffer.lb();
678 for (Type arg : t.getTypeArguments()) {
679 if (!dtc.visit(arg, null)) {
680 buf.append(arg);
681 }
682 }
683 return buf.toList();
684 }
686 static class DiamondTypeChecker extends Types.SimpleVisitor<Boolean, Void> {
687 public Boolean visitType(Type t, Void s) {
688 return true;
689 }
690 @Override
691 public Boolean visitClassType(ClassType t, Void s) {
692 if (t.isCompound()) {
693 return false;
694 }
695 for (Type targ : t.getTypeArguments()) {
696 if (!visit(targ, s)) {
697 return false;
698 }
699 }
700 return true;
701 }
702 @Override
703 public Boolean visitCapturedType(CapturedType t, Void s) {
704 return false;
705 }
706 }
708 void checkVarargMethodDecl(JCMethodDecl tree) {
709 MethodSymbol m = tree.sym;
710 //check the element type of the vararg
711 if (m.isVarArgs()) {
712 Type varargElemType = types.elemtype(tree.params.last().type);
713 if (!types.isReifiable(varargElemType)) {
714 warnUnsafeVararg(tree.params.head.pos(), varargElemType);
715 }
716 }
717 }
719 /**
720 * Check that vararg method call is sound
721 * @param pos Position to be used for error reporting.
722 * @param argtypes Actual arguments supplied to vararg method.
723 */
724 void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym, Env<AttrContext> env) {
725 Env<AttrContext> calleeLintEnv = env;
726 while (calleeLintEnv.info.lint == null)
727 calleeLintEnv = calleeLintEnv.next;
728 Lint calleeLint = calleeLintEnv.info.lint.augment(msym.attributes_field, msym.flags());
729 Type argtype = argtypes.last();
730 if (!types.isReifiable(argtype) && !calleeLint.isSuppressed(Lint.LintCategory.VARARGS)) {
731 warnUnchecked(pos,
732 "unchecked.generic.array.creation",
733 argtype);
734 }
735 }
737 /** Check that given modifiers are legal for given symbol and
738 * return modifiers together with any implicit modififiers for that symbol.
739 * Warning: we can't use flags() here since this method
740 * is called during class enter, when flags() would cause a premature
741 * completion.
742 * @param pos Position to be used for error reporting.
743 * @param flags The set of modifiers given in a definition.
744 * @param sym The defined symbol.
745 */
746 long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) {
747 long mask;
748 long implicit = 0;
749 switch (sym.kind) {
750 case VAR:
751 if (sym.owner.kind != TYP)
752 mask = LocalVarFlags;
753 else if ((sym.owner.flags_field & INTERFACE) != 0)
754 mask = implicit = InterfaceVarFlags;
755 else
756 mask = VarFlags;
757 break;
758 case MTH:
759 if (sym.name == names.init) {
760 if ((sym.owner.flags_field & ENUM) != 0) {
761 // enum constructors cannot be declared public or
762 // protected and must be implicitly or explicitly
763 // private
764 implicit = PRIVATE;
765 mask = PRIVATE;
766 } else
767 mask = ConstructorFlags;
768 } else if ((sym.owner.flags_field & INTERFACE) != 0)
769 mask = implicit = InterfaceMethodFlags;
770 else {
771 mask = MethodFlags;
772 }
773 // Imply STRICTFP if owner has STRICTFP set.
774 if (((flags|implicit) & Flags.ABSTRACT) == 0)
775 implicit |= sym.owner.flags_field & STRICTFP;
776 break;
777 case TYP:
778 if (sym.isLocal()) {
779 mask = LocalClassFlags;
780 if (sym.name.isEmpty()) { // Anonymous class
781 // Anonymous classes in static methods are themselves static;
782 // that's why we admit STATIC here.
783 mask |= STATIC;
784 // JLS: Anonymous classes are final.
785 implicit |= FINAL;
786 }
787 if ((sym.owner.flags_field & STATIC) == 0 &&
788 (flags & ENUM) != 0)
789 log.error(pos, "enums.must.be.static");
790 } else if (sym.owner.kind == TYP) {
791 mask = MemberClassFlags;
792 if (sym.owner.owner.kind == PCK ||
793 (sym.owner.flags_field & STATIC) != 0)
794 mask |= STATIC;
795 else if ((flags & ENUM) != 0)
796 log.error(pos, "enums.must.be.static");
797 // Nested interfaces and enums are always STATIC (Spec ???)
798 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC;
799 } else {
800 mask = ClassFlags;
801 }
802 // Interfaces are always ABSTRACT
803 if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
805 if ((flags & ENUM) != 0) {
806 // enums can't be declared abstract or final
807 mask &= ~(ABSTRACT | FINAL);
808 implicit |= implicitEnumFinalFlag(tree);
809 }
810 // Imply STRICTFP if owner has STRICTFP set.
811 implicit |= sym.owner.flags_field & STRICTFP;
812 break;
813 default:
814 throw new AssertionError();
815 }
816 long illegal = flags & StandardFlags & ~mask;
817 if (illegal != 0) {
818 if ((illegal & INTERFACE) != 0) {
819 log.error(pos, "intf.not.allowed.here");
820 mask |= INTERFACE;
821 }
822 else {
823 log.error(pos,
824 "mod.not.allowed.here", asFlagSet(illegal));
825 }
826 }
827 else if ((sym.kind == TYP ||
828 // ISSUE: Disallowing abstract&private is no longer appropriate
829 // in the presence of inner classes. Should it be deleted here?
830 checkDisjoint(pos, flags,
831 ABSTRACT,
832 PRIVATE | STATIC))
833 &&
834 checkDisjoint(pos, flags,
835 ABSTRACT | INTERFACE,
836 FINAL | NATIVE | SYNCHRONIZED)
837 &&
838 checkDisjoint(pos, flags,
839 PUBLIC,
840 PRIVATE | PROTECTED)
841 &&
842 checkDisjoint(pos, flags,
843 PRIVATE,
844 PUBLIC | PROTECTED)
845 &&
846 checkDisjoint(pos, flags,
847 FINAL,
848 VOLATILE)
849 &&
850 (sym.kind == TYP ||
851 checkDisjoint(pos, flags,
852 ABSTRACT | NATIVE,
853 STRICTFP))) {
854 // skip
855 }
856 return flags & (mask | ~StandardFlags) | implicit;
857 }
860 /** Determine if this enum should be implicitly final.
861 *
862 * If the enum has no specialized enum contants, it is final.
863 *
864 * If the enum does have specialized enum contants, it is
865 * <i>not</i> final.
866 */
867 private long implicitEnumFinalFlag(JCTree tree) {
868 if (tree.getTag() != JCTree.CLASSDEF) return 0;
869 class SpecialTreeVisitor extends JCTree.Visitor {
870 boolean specialized;
871 SpecialTreeVisitor() {
872 this.specialized = false;
873 };
875 @Override
876 public void visitTree(JCTree tree) { /* no-op */ }
878 @Override
879 public void visitVarDef(JCVariableDecl tree) {
880 if ((tree.mods.flags & ENUM) != 0) {
881 if (tree.init instanceof JCNewClass &&
882 ((JCNewClass) tree.init).def != null) {
883 specialized = true;
884 }
885 }
886 }
887 }
889 SpecialTreeVisitor sts = new SpecialTreeVisitor();
890 JCClassDecl cdef = (JCClassDecl) tree;
891 for (JCTree defs: cdef.defs) {
892 defs.accept(sts);
893 if (sts.specialized) return 0;
894 }
895 return FINAL;
896 }
898 /* *************************************************************************
899 * Type Validation
900 **************************************************************************/
902 /** Validate a type expression. That is,
903 * check that all type arguments of a parametric type are within
904 * their bounds. This must be done in a second phase after type attributon
905 * since a class might have a subclass as type parameter bound. E.g:
906 *
907 * class B<A extends C> { ... }
908 * class C extends B<C> { ... }
909 *
910 * and we can't make sure that the bound is already attributed because
911 * of possible cycles.
912 *
913 * Visitor method: Validate a type expression, if it is not null, catching
914 * and reporting any completion failures.
915 */
916 void validate(JCTree tree, Env<AttrContext> env) {
917 validate(tree, env, true);
918 }
919 void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) {
920 new Validator(env).validateTree(tree, checkRaw, true);
921 }
923 /** Visitor method: Validate a list of type expressions.
924 */
925 void validate(List<? extends JCTree> trees, Env<AttrContext> env) {
926 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
927 validate(l.head, env);
928 }
930 /** A visitor class for type validation.
931 */
932 class Validator extends JCTree.Visitor {
934 boolean isOuter;
935 Env<AttrContext> env;
937 Validator(Env<AttrContext> env) {
938 this.env = env;
939 }
941 @Override
942 public void visitTypeArray(JCArrayTypeTree tree) {
943 tree.elemtype.accept(this);
944 }
946 @Override
947 public void visitTypeApply(JCTypeApply tree) {
948 if (tree.type.tag == CLASS) {
949 List<Type> formals = tree.type.tsym.type.allparams();
950 List<Type> actuals = tree.type.allparams();
951 List<JCExpression> args = tree.arguments;
952 List<Type> forms = tree.type.tsym.type.getTypeArguments();
953 ListBuffer<Type> tvars_buf = new ListBuffer<Type>();
955 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
957 // For matching pairs of actual argument types `a' and
958 // formal type parameters with declared bound `b' ...
959 while (args.nonEmpty() && forms.nonEmpty()) {
960 validateTree(args.head,
961 !(isOuter && is_java_lang_Class),
962 false);
964 // exact type arguments needs to know their
965 // bounds (for upper and lower bound
966 // calculations). So we create new TypeVars with
967 // bounds substed with actuals.
968 tvars_buf.append(types.substBound(((TypeVar)forms.head),
969 formals,
970 actuals));
972 args = args.tail;
973 forms = forms.tail;
974 }
976 args = tree.arguments;
977 List<Type> tvars_cap = types.substBounds(formals,
978 formals,
979 types.capture(tree.type).allparams());
980 while (args.nonEmpty() && tvars_cap.nonEmpty()) {
981 // Let the actual arguments know their bound
982 args.head.type.withTypeVar((TypeVar)tvars_cap.head);
983 args = args.tail;
984 tvars_cap = tvars_cap.tail;
985 }
987 args = tree.arguments;
988 List<Type> tvars = tvars_buf.toList();
990 while (args.nonEmpty() && tvars.nonEmpty()) {
991 Type actual = types.subst(args.head.type,
992 tree.type.tsym.type.getTypeArguments(),
993 tvars_buf.toList());
994 checkExtends(args.head.pos(),
995 actual,
996 (TypeVar)tvars.head);
997 args = args.tail;
998 tvars = tvars.tail;
999 }
1001 checkCapture(tree);
1003 // Check that this type is either fully parameterized, or
1004 // not parameterized at all.
1005 if (tree.type.getEnclosingType().isRaw())
1006 log.error(tree.pos(), "improperly.formed.type.inner.raw.param");
1007 if (tree.clazz.getTag() == JCTree.SELECT)
1008 visitSelectInternal((JCFieldAccess)tree.clazz);
1009 }
1010 }
1012 @Override
1013 public void visitTypeParameter(JCTypeParameter tree) {
1014 validateTrees(tree.bounds, true, isOuter);
1015 checkClassBounds(tree.pos(), tree.type);
1016 }
1018 @Override
1019 public void visitWildcard(JCWildcard tree) {
1020 if (tree.inner != null)
1021 validateTree(tree.inner, true, isOuter);
1022 }
1024 @Override
1025 public void visitSelect(JCFieldAccess tree) {
1026 if (tree.type.tag == CLASS) {
1027 visitSelectInternal(tree);
1029 // Check that this type is either fully parameterized, or
1030 // not parameterized at all.
1031 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty())
1032 log.error(tree.pos(), "improperly.formed.type.param.missing");
1033 }
1034 }
1035 public void visitSelectInternal(JCFieldAccess tree) {
1036 if (tree.type.tsym.isStatic() &&
1037 tree.selected.type.isParameterized()) {
1038 // The enclosing type is not a class, so we are
1039 // looking at a static member type. However, the
1040 // qualifying expression is parameterized.
1041 log.error(tree.pos(), "cant.select.static.class.from.param.type");
1042 } else {
1043 // otherwise validate the rest of the expression
1044 tree.selected.accept(this);
1045 }
1046 }
1048 @Override
1049 public void visitAnnotatedType(JCAnnotatedType tree) {
1050 tree.underlyingType.accept(this);
1051 }
1053 /** Default visitor method: do nothing.
1054 */
1055 @Override
1056 public void visitTree(JCTree tree) {
1057 }
1059 public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) {
1060 try {
1061 if (tree != null) {
1062 this.isOuter = isOuter;
1063 tree.accept(this);
1064 if (checkRaw)
1065 checkRaw(tree, env);
1066 }
1067 } catch (CompletionFailure ex) {
1068 completionError(tree.pos(), ex);
1069 }
1070 }
1072 public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) {
1073 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
1074 validateTree(l.head, checkRaw, isOuter);
1075 }
1077 void checkRaw(JCTree tree, Env<AttrContext> env) {
1078 if (lint.isEnabled(Lint.LintCategory.RAW) &&
1079 tree.type.tag == CLASS &&
1080 !TreeInfo.isDiamond(tree) &&
1081 !env.enclClass.name.isEmpty() && //anonymous or intersection
1082 tree.type.isRaw()) {
1083 log.warning(Lint.LintCategory.RAW,
1084 tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
1085 }
1086 }
1087 }
1089 /* *************************************************************************
1090 * Exception checking
1091 **************************************************************************/
1093 /* The following methods treat classes as sets that contain
1094 * the class itself and all their subclasses
1095 */
1097 /** Is given type a subtype of some of the types in given list?
1098 */
1099 boolean subset(Type t, List<Type> ts) {
1100 for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1101 if (types.isSubtype(t, l.head)) return true;
1102 return false;
1103 }
1105 /** Is given type a subtype or supertype of
1106 * some of the types in given list?
1107 */
1108 boolean intersects(Type t, List<Type> ts) {
1109 for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1110 if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true;
1111 return false;
1112 }
1114 /** Add type set to given type list, unless it is a subclass of some class
1115 * in the list.
1116 */
1117 List<Type> incl(Type t, List<Type> ts) {
1118 return subset(t, ts) ? ts : excl(t, ts).prepend(t);
1119 }
1121 /** Remove type set from type set list.
1122 */
1123 List<Type> excl(Type t, List<Type> ts) {
1124 if (ts.isEmpty()) {
1125 return ts;
1126 } else {
1127 List<Type> ts1 = excl(t, ts.tail);
1128 if (types.isSubtype(ts.head, t)) return ts1;
1129 else if (ts1 == ts.tail) return ts;
1130 else return ts1.prepend(ts.head);
1131 }
1132 }
1134 /** Form the union of two type set lists.
1135 */
1136 List<Type> union(List<Type> ts1, List<Type> ts2) {
1137 List<Type> ts = ts1;
1138 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1139 ts = incl(l.head, ts);
1140 return ts;
1141 }
1143 /** Form the difference of two type lists.
1144 */
1145 List<Type> diff(List<Type> ts1, List<Type> ts2) {
1146 List<Type> ts = ts1;
1147 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1148 ts = excl(l.head, ts);
1149 return ts;
1150 }
1152 /** Form the intersection of two type lists.
1153 */
1154 public List<Type> intersect(List<Type> ts1, List<Type> ts2) {
1155 List<Type> ts = List.nil();
1156 for (List<Type> l = ts1; l.nonEmpty(); l = l.tail)
1157 if (subset(l.head, ts2)) ts = incl(l.head, ts);
1158 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1159 if (subset(l.head, ts1)) ts = incl(l.head, ts);
1160 return ts;
1161 }
1163 /** Is exc an exception symbol that need not be declared?
1164 */
1165 boolean isUnchecked(ClassSymbol exc) {
1166 return
1167 exc.kind == ERR ||
1168 exc.isSubClass(syms.errorType.tsym, types) ||
1169 exc.isSubClass(syms.runtimeExceptionType.tsym, types);
1170 }
1172 /** Is exc an exception type that need not be declared?
1173 */
1174 boolean isUnchecked(Type exc) {
1175 return
1176 (exc.tag == TYPEVAR) ? isUnchecked(types.supertype(exc)) :
1177 (exc.tag == CLASS) ? isUnchecked((ClassSymbol)exc.tsym) :
1178 exc.tag == BOT;
1179 }
1181 /** Same, but handling completion failures.
1182 */
1183 boolean isUnchecked(DiagnosticPosition pos, Type exc) {
1184 try {
1185 return isUnchecked(exc);
1186 } catch (CompletionFailure ex) {
1187 completionError(pos, ex);
1188 return true;
1189 }
1190 }
1192 /** Is exc handled by given exception list?
1193 */
1194 boolean isHandled(Type exc, List<Type> handled) {
1195 return isUnchecked(exc) || subset(exc, handled);
1196 }
1198 /** Return all exceptions in thrown list that are not in handled list.
1199 * @param thrown The list of thrown exceptions.
1200 * @param handled The list of handled exceptions.
1201 */
1202 List<Type> unhandled(List<Type> thrown, List<Type> handled) {
1203 List<Type> unhandled = List.nil();
1204 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1205 if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head);
1206 return unhandled;
1207 }
1209 /* *************************************************************************
1210 * Overriding/Implementation checking
1211 **************************************************************************/
1213 /** The level of access protection given by a flag set,
1214 * where PRIVATE is highest and PUBLIC is lowest.
1215 */
1216 static int protection(long flags) {
1217 switch ((short)(flags & AccessFlags)) {
1218 case PRIVATE: return 3;
1219 case PROTECTED: return 1;
1220 default:
1221 case PUBLIC: return 0;
1222 case 0: return 2;
1223 }
1224 }
1226 /** A customized "cannot override" error message.
1227 * @param m The overriding method.
1228 * @param other The overridden method.
1229 * @return An internationalized string.
1230 */
1231 Object cannotOverride(MethodSymbol m, MethodSymbol other) {
1232 String key;
1233 if ((other.owner.flags() & INTERFACE) == 0)
1234 key = "cant.override";
1235 else if ((m.owner.flags() & INTERFACE) == 0)
1236 key = "cant.implement";
1237 else
1238 key = "clashes.with";
1239 return diags.fragment(key, m, m.location(), other, other.location());
1240 }
1242 /** A customized "override" warning message.
1243 * @param m The overriding method.
1244 * @param other The overridden method.
1245 * @return An internationalized string.
1246 */
1247 Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) {
1248 String key;
1249 if ((other.owner.flags() & INTERFACE) == 0)
1250 key = "unchecked.override";
1251 else if ((m.owner.flags() & INTERFACE) == 0)
1252 key = "unchecked.implement";
1253 else
1254 key = "unchecked.clash.with";
1255 return diags.fragment(key, m, m.location(), other, other.location());
1256 }
1258 /** A customized "override" warning message.
1259 * @param m The overriding method.
1260 * @param other The overridden method.
1261 * @return An internationalized string.
1262 */
1263 Object varargsOverrides(MethodSymbol m, MethodSymbol other) {
1264 String key;
1265 if ((other.owner.flags() & INTERFACE) == 0)
1266 key = "varargs.override";
1267 else if ((m.owner.flags() & INTERFACE) == 0)
1268 key = "varargs.implement";
1269 else
1270 key = "varargs.clash.with";
1271 return diags.fragment(key, m, m.location(), other, other.location());
1272 }
1274 /** Check that this method conforms with overridden method 'other'.
1275 * where `origin' is the class where checking started.
1276 * Complications:
1277 * (1) Do not check overriding of synthetic methods
1278 * (reason: they might be final).
1279 * todo: check whether this is still necessary.
1280 * (2) Admit the case where an interface proxy throws fewer exceptions
1281 * than the method it implements. Augment the proxy methods with the
1282 * undeclared exceptions in this case.
1283 * (3) When generics are enabled, admit the case where an interface proxy
1284 * has a result type
1285 * extended by the result type of the method it implements.
1286 * Change the proxies result type to the smaller type in this case.
1287 *
1288 * @param tree The tree from which positions
1289 * are extracted for errors.
1290 * @param m The overriding method.
1291 * @param other The overridden method.
1292 * @param origin The class of which the overriding method
1293 * is a member.
1294 */
1295 void checkOverride(JCTree tree,
1296 MethodSymbol m,
1297 MethodSymbol other,
1298 ClassSymbol origin) {
1299 // Don't check overriding of synthetic methods or by bridge methods.
1300 if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) {
1301 return;
1302 }
1304 // Error if static method overrides instance method (JLS 8.4.6.2).
1305 if ((m.flags() & STATIC) != 0 &&
1306 (other.flags() & STATIC) == 0) {
1307 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static",
1308 cannotOverride(m, other));
1309 return;
1310 }
1312 // Error if instance method overrides static or final
1313 // method (JLS 8.4.6.1).
1314 if ((other.flags() & FINAL) != 0 ||
1315 (m.flags() & STATIC) == 0 &&
1316 (other.flags() & STATIC) != 0) {
1317 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth",
1318 cannotOverride(m, other),
1319 asFlagSet(other.flags() & (FINAL | STATIC)));
1320 return;
1321 }
1323 if ((m.owner.flags() & ANNOTATION) != 0) {
1324 // handled in validateAnnotationMethod
1325 return;
1326 }
1328 // Error if overriding method has weaker access (JLS 8.4.6.3).
1329 if ((origin.flags() & INTERFACE) == 0 &&
1330 protection(m.flags()) > protection(other.flags())) {
1331 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access",
1332 cannotOverride(m, other),
1333 other.flags() == 0 ?
1334 Flag.PACKAGE :
1335 asFlagSet(other.flags() & AccessFlags));
1336 return;
1337 }
1339 Type mt = types.memberType(origin.type, m);
1340 Type ot = types.memberType(origin.type, other);
1341 // Error if overriding result type is different
1342 // (or, in the case of generics mode, not a subtype) of
1343 // overridden result type. We have to rename any type parameters
1344 // before comparing types.
1345 List<Type> mtvars = mt.getTypeArguments();
1346 List<Type> otvars = ot.getTypeArguments();
1347 Type mtres = mt.getReturnType();
1348 Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
1350 overrideWarner.warned = false;
1351 boolean resultTypesOK =
1352 types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
1353 if (!resultTypesOK) {
1354 if (!allowCovariantReturns &&
1355 m.owner != origin &&
1356 m.owner.isSubClass(other.owner, types)) {
1357 // allow limited interoperability with covariant returns
1358 } else {
1359 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1360 "override.incompatible.ret",
1361 cannotOverride(m, other),
1362 mtres, otres);
1363 return;
1364 }
1365 } else if (overrideWarner.warned) {
1366 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1367 "override.unchecked.ret",
1368 uncheckedOverrides(m, other),
1369 mtres, otres);
1370 }
1372 // Error if overriding method throws an exception not reported
1373 // by overridden method.
1374 List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars);
1375 List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown));
1376 List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown);
1377 if (unhandledErased.nonEmpty()) {
1378 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1379 "override.meth.doesnt.throw",
1380 cannotOverride(m, other),
1381 unhandledUnerased.head);
1382 return;
1383 }
1384 else if (unhandledUnerased.nonEmpty()) {
1385 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1386 "override.unchecked.thrown",
1387 cannotOverride(m, other),
1388 unhandledUnerased.head);
1389 return;
1390 }
1392 // Optional warning if varargs don't agree
1393 if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
1394 && lint.isEnabled(Lint.LintCategory.OVERRIDES)) {
1395 log.warning(TreeInfo.diagnosticPositionFor(m, tree),
1396 ((m.flags() & Flags.VARARGS) != 0)
1397 ? "override.varargs.missing"
1398 : "override.varargs.extra",
1399 varargsOverrides(m, other));
1400 }
1402 // Warn if instance method overrides bridge method (compiler spec ??)
1403 if ((other.flags() & BRIDGE) != 0) {
1404 log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge",
1405 uncheckedOverrides(m, other));
1406 }
1408 // Warn if a deprecated method overridden by a non-deprecated one.
1409 if ((other.flags() & DEPRECATED) != 0
1410 && (m.flags() & DEPRECATED) == 0
1411 && m.outermostClass() != other.outermostClass()
1412 && !isDeprecatedOverrideIgnorable(other, origin)) {
1413 warnDeprecated(TreeInfo.diagnosticPositionFor(m, tree), other);
1414 }
1415 }
1416 // where
1417 private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) {
1418 // If the method, m, is defined in an interface, then ignore the issue if the method
1419 // is only inherited via a supertype and also implemented in the supertype,
1420 // because in that case, we will rediscover the issue when examining the method
1421 // in the supertype.
1422 // If the method, m, is not defined in an interface, then the only time we need to
1423 // address the issue is when the method is the supertype implemementation: any other
1424 // case, we will have dealt with when examining the supertype classes
1425 ClassSymbol mc = m.enclClass();
1426 Type st = types.supertype(origin.type);
1427 if (st.tag != CLASS)
1428 return true;
1429 MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false);
1431 if (mc != null && ((mc.flags() & INTERFACE) != 0)) {
1432 List<Type> intfs = types.interfaces(origin.type);
1433 return (intfs.contains(mc.type) ? false : (stimpl != null));
1434 }
1435 else
1436 return (stimpl != m);
1437 }
1440 // used to check if there were any unchecked conversions
1441 Warner overrideWarner = new Warner();
1443 /** Check that a class does not inherit two concrete methods
1444 * with the same signature.
1445 * @param pos Position to be used for error reporting.
1446 * @param site The class type to be checked.
1447 */
1448 public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) {
1449 Type sup = types.supertype(site);
1450 if (sup.tag != CLASS) return;
1452 for (Type t1 = sup;
1453 t1.tsym.type.isParameterized();
1454 t1 = types.supertype(t1)) {
1455 for (Scope.Entry e1 = t1.tsym.members().elems;
1456 e1 != null;
1457 e1 = e1.sibling) {
1458 Symbol s1 = e1.sym;
1459 if (s1.kind != MTH ||
1460 (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
1461 !s1.isInheritedIn(site.tsym, types) ||
1462 ((MethodSymbol)s1).implementation(site.tsym,
1463 types,
1464 true) != s1)
1465 continue;
1466 Type st1 = types.memberType(t1, s1);
1467 int s1ArgsLength = st1.getParameterTypes().length();
1468 if (st1 == s1.type) continue;
1470 for (Type t2 = sup;
1471 t2.tag == CLASS;
1472 t2 = types.supertype(t2)) {
1473 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name);
1474 e2.scope != null;
1475 e2 = e2.next()) {
1476 Symbol s2 = e2.sym;
1477 if (s2 == s1 ||
1478 s2.kind != MTH ||
1479 (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
1480 s2.type.getParameterTypes().length() != s1ArgsLength ||
1481 !s2.isInheritedIn(site.tsym, types) ||
1482 ((MethodSymbol)s2).implementation(site.tsym,
1483 types,
1484 true) != s2)
1485 continue;
1486 Type st2 = types.memberType(t2, s2);
1487 if (types.overrideEquivalent(st1, st2))
1488 log.error(pos, "concrete.inheritance.conflict",
1489 s1, t1, s2, t2, sup);
1490 }
1491 }
1492 }
1493 }
1494 }
1496 /** Check that classes (or interfaces) do not each define an abstract
1497 * method with same name and arguments but incompatible return types.
1498 * @param pos Position to be used for error reporting.
1499 * @param t1 The first argument type.
1500 * @param t2 The second argument type.
1501 */
1502 public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1503 Type t1,
1504 Type t2) {
1505 return checkCompatibleAbstracts(pos, t1, t2,
1506 types.makeCompoundType(t1, t2));
1507 }
1509 public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1510 Type t1,
1511 Type t2,
1512 Type site) {
1513 return firstIncompatibility(pos, t1, t2, site) == null;
1514 }
1516 /** Return the first method which is defined with same args
1517 * but different return types in two given interfaces, or null if none
1518 * exists.
1519 * @param t1 The first type.
1520 * @param t2 The second type.
1521 * @param site The most derived type.
1522 * @returns symbol from t2 that conflicts with one in t1.
1523 */
1524 private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
1525 Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>();
1526 closure(t1, interfaces1);
1527 Map<TypeSymbol,Type> interfaces2;
1528 if (t1 == t2)
1529 interfaces2 = interfaces1;
1530 else
1531 closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>());
1533 for (Type t3 : interfaces1.values()) {
1534 for (Type t4 : interfaces2.values()) {
1535 Symbol s = firstDirectIncompatibility(pos, t3, t4, site);
1536 if (s != null) return s;
1537 }
1538 }
1539 return null;
1540 }
1542 /** Compute all the supertypes of t, indexed by type symbol. */
1543 private void closure(Type t, Map<TypeSymbol,Type> typeMap) {
1544 if (t.tag != CLASS) return;
1545 if (typeMap.put(t.tsym, t) == null) {
1546 closure(types.supertype(t), typeMap);
1547 for (Type i : types.interfaces(t))
1548 closure(i, typeMap);
1549 }
1550 }
1552 /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */
1553 private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) {
1554 if (t.tag != CLASS) return;
1555 if (typesSkip.get(t.tsym) != null) return;
1556 if (typeMap.put(t.tsym, t) == null) {
1557 closure(types.supertype(t), typesSkip, typeMap);
1558 for (Type i : types.interfaces(t))
1559 closure(i, typesSkip, typeMap);
1560 }
1561 }
1563 /** Return the first method in t2 that conflicts with a method from t1. */
1564 private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
1565 for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
1566 Symbol s1 = e1.sym;
1567 Type st1 = null;
1568 if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types)) continue;
1569 Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false);
1570 if (impl != null && (impl.flags() & ABSTRACT) == 0) continue;
1571 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) {
1572 Symbol s2 = e2.sym;
1573 if (s1 == s2) continue;
1574 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types)) continue;
1575 if (st1 == null) st1 = types.memberType(t1, s1);
1576 Type st2 = types.memberType(t2, s2);
1577 if (types.overrideEquivalent(st1, st2)) {
1578 List<Type> tvars1 = st1.getTypeArguments();
1579 List<Type> tvars2 = st2.getTypeArguments();
1580 Type rt1 = st1.getReturnType();
1581 Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1);
1582 boolean compat =
1583 types.isSameType(rt1, rt2) ||
1584 rt1.tag >= CLASS && rt2.tag >= CLASS &&
1585 (types.covariantReturnType(rt1, rt2, Warner.noWarnings) ||
1586 types.covariantReturnType(rt2, rt1, Warner.noWarnings)) ||
1587 checkCommonOverriderIn(s1,s2,site);
1588 if (!compat) {
1589 log.error(pos, "types.incompatible.diff.ret",
1590 t1, t2, s2.name +
1591 "(" + types.memberType(t2, s2).getParameterTypes() + ")");
1592 return s2;
1593 }
1594 } else if (!checkNameClash((ClassSymbol)site.tsym, s1, s2)) {
1595 log.error(pos,
1596 "name.clash.same.erasure.no.override",
1597 s1, s1.location(),
1598 s2, s2.location());
1599 return s2;
1600 }
1601 }
1602 }
1603 return null;
1604 }
1605 //WHERE
1606 boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) {
1607 Map<TypeSymbol,Type> supertypes = new HashMap<TypeSymbol,Type>();
1608 Type st1 = types.memberType(site, s1);
1609 Type st2 = types.memberType(site, s2);
1610 closure(site, supertypes);
1611 for (Type t : supertypes.values()) {
1612 for (Scope.Entry e = t.tsym.members().lookup(s1.name); e.scope != null; e = e.next()) {
1613 Symbol s3 = e.sym;
1614 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue;
1615 Type st3 = types.memberType(site,s3);
1616 if (types.overrideEquivalent(st3, st1) && types.overrideEquivalent(st3, st2)) {
1617 if (s3.owner == site.tsym) {
1618 return true;
1619 }
1620 List<Type> tvars1 = st1.getTypeArguments();
1621 List<Type> tvars2 = st2.getTypeArguments();
1622 List<Type> tvars3 = st3.getTypeArguments();
1623 Type rt1 = st1.getReturnType();
1624 Type rt2 = st2.getReturnType();
1625 Type rt13 = types.subst(st3.getReturnType(), tvars3, tvars1);
1626 Type rt23 = types.subst(st3.getReturnType(), tvars3, tvars2);
1627 boolean compat =
1628 rt13.tag >= CLASS && rt23.tag >= CLASS &&
1629 (types.covariantReturnType(rt13, rt1, Warner.noWarnings) &&
1630 types.covariantReturnType(rt23, rt2, Warner.noWarnings));
1631 if (compat)
1632 return true;
1633 }
1634 }
1635 }
1636 return false;
1637 }
1639 /** Check that a given method conforms with any method it overrides.
1640 * @param tree The tree from which positions are extracted
1641 * for errors.
1642 * @param m The overriding method.
1643 */
1644 void checkOverride(JCTree tree, MethodSymbol m) {
1645 ClassSymbol origin = (ClassSymbol)m.owner;
1646 if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name))
1647 if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
1648 log.error(tree.pos(), "enum.no.finalize");
1649 return;
1650 }
1651 for (Type t = origin.type; t.tag == CLASS;
1652 t = types.supertype(t)) {
1653 if (t != origin.type) {
1654 checkOverride(tree, t, origin, m);
1655 }
1656 for (Type t2 : types.interfaces(t)) {
1657 checkOverride(tree, t2, origin, m);
1658 }
1659 }
1660 }
1662 void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) {
1663 TypeSymbol c = site.tsym;
1664 Scope.Entry e = c.members().lookup(m.name);
1665 while (e.scope != null) {
1666 if (m.overrides(e.sym, origin, types, false)) {
1667 if ((e.sym.flags() & ABSTRACT) == 0) {
1668 checkOverride(tree, m, (MethodSymbol)e.sym, origin);
1669 }
1670 }
1671 else if (!checkNameClash(origin, e.sym, m)) {
1672 log.error(tree,
1673 "name.clash.same.erasure.no.override",
1674 m, m.location(),
1675 e.sym, e.sym.location());
1676 }
1677 e = e.next();
1678 }
1679 }
1681 private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
1682 if (s1.kind == MTH &&
1683 s1.isInheritedIn(origin, types) &&
1684 (s1.flags() & SYNTHETIC) == 0 &&
1685 !s2.isConstructor()) {
1686 Type er1 = s2.erasure(types);
1687 Type er2 = s1.erasure(types);
1688 if (types.isSameTypes(er1.getParameterTypes(),
1689 er2.getParameterTypes())) {
1690 return false;
1691 }
1692 }
1693 return true;
1694 }
1697 /** Check that all abstract members of given class have definitions.
1698 * @param pos Position to be used for error reporting.
1699 * @param c The class.
1700 */
1701 void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) {
1702 try {
1703 MethodSymbol undef = firstUndef(c, c);
1704 if (undef != null) {
1705 if ((c.flags() & ENUM) != 0 &&
1706 types.supertype(c.type).tsym == syms.enumSym &&
1707 (c.flags() & FINAL) == 0) {
1708 // add the ABSTRACT flag to an enum
1709 c.flags_field |= ABSTRACT;
1710 } else {
1711 MethodSymbol undef1 =
1712 new MethodSymbol(undef.flags(), undef.name,
1713 types.memberType(c.type, undef), undef.owner);
1714 log.error(pos, "does.not.override.abstract",
1715 c, undef1, undef1.location());
1716 }
1717 }
1718 } catch (CompletionFailure ex) {
1719 completionError(pos, ex);
1720 }
1721 }
1722 //where
1723 /** Return first abstract member of class `c' that is not defined
1724 * in `impl', null if there is none.
1725 */
1726 private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) {
1727 MethodSymbol undef = null;
1728 // Do not bother to search in classes that are not abstract,
1729 // since they cannot have abstract members.
1730 if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
1731 Scope s = c.members();
1732 for (Scope.Entry e = s.elems;
1733 undef == null && e != null;
1734 e = e.sibling) {
1735 if (e.sym.kind == MTH &&
1736 (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) {
1737 MethodSymbol absmeth = (MethodSymbol)e.sym;
1738 MethodSymbol implmeth = absmeth.implementation(impl, types, true);
1739 if (implmeth == null || implmeth == absmeth)
1740 undef = absmeth;
1741 }
1742 }
1743 if (undef == null) {
1744 Type st = types.supertype(c.type);
1745 if (st.tag == CLASS)
1746 undef = firstUndef(impl, (ClassSymbol)st.tsym);
1747 }
1748 for (List<Type> l = types.interfaces(c.type);
1749 undef == null && l.nonEmpty();
1750 l = l.tail) {
1751 undef = firstUndef(impl, (ClassSymbol)l.head.tsym);
1752 }
1753 }
1754 return undef;
1755 }
1757 void checkNonCyclicDecl(JCClassDecl tree) {
1758 CycleChecker cc = new CycleChecker();
1759 cc.scan(tree);
1760 if (!cc.errorFound && !cc.partialCheck) {
1761 tree.sym.flags_field |= ACYCLIC;
1762 }
1763 }
1765 class CycleChecker extends TreeScanner {
1767 List<Symbol> seenClasses = List.nil();
1768 boolean errorFound = false;
1769 boolean partialCheck = false;
1771 private void checkSymbol(DiagnosticPosition pos, Symbol sym) {
1772 if (sym != null && sym.kind == TYP) {
1773 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym);
1774 if (classEnv != null) {
1775 DiagnosticSource prevSource = log.currentSource();
1776 try {
1777 log.useSource(classEnv.toplevel.sourcefile);
1778 scan(classEnv.tree);
1779 }
1780 finally {
1781 log.useSource(prevSource.getFile());
1782 }
1783 } else if (sym.kind == TYP) {
1784 checkClass(pos, sym, List.<JCTree>nil());
1785 }
1786 } else {
1787 //not completed yet
1788 partialCheck = true;
1789 }
1790 }
1792 @Override
1793 public void visitSelect(JCFieldAccess tree) {
1794 super.visitSelect(tree);
1795 checkSymbol(tree.pos(), tree.sym);
1796 }
1798 @Override
1799 public void visitIdent(JCIdent tree) {
1800 checkSymbol(tree.pos(), tree.sym);
1801 }
1803 @Override
1804 public void visitTypeApply(JCTypeApply tree) {
1805 scan(tree.clazz);
1806 }
1808 @Override
1809 public void visitTypeArray(JCArrayTypeTree tree) {
1810 scan(tree.elemtype);
1811 }
1813 @Override
1814 public void visitClassDef(JCClassDecl tree) {
1815 List<JCTree> supertypes = List.nil();
1816 if (tree.getExtendsClause() != null) {
1817 supertypes = supertypes.prepend(tree.getExtendsClause());
1818 }
1819 if (tree.getImplementsClause() != null) {
1820 for (JCTree intf : tree.getImplementsClause()) {
1821 supertypes = supertypes.prepend(intf);
1822 }
1823 }
1824 checkClass(tree.pos(), tree.sym, supertypes);
1825 }
1827 void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) {
1828 if ((c.flags_field & ACYCLIC) != 0)
1829 return;
1830 if (seenClasses.contains(c)) {
1831 errorFound = true;
1832 noteCyclic(pos, (ClassSymbol)c);
1833 } else if (!c.type.isErroneous()) {
1834 try {
1835 seenClasses = seenClasses.prepend(c);
1836 if (c.type.tag == CLASS) {
1837 if (supertypes.nonEmpty()) {
1838 scan(supertypes);
1839 }
1840 else {
1841 ClassType ct = (ClassType)c.type;
1842 if (ct.supertype_field == null ||
1843 ct.interfaces_field == null) {
1844 //not completed yet
1845 partialCheck = true;
1846 return;
1847 }
1848 checkSymbol(pos, ct.supertype_field.tsym);
1849 for (Type intf : ct.interfaces_field) {
1850 checkSymbol(pos, intf.tsym);
1851 }
1852 }
1853 if (c.owner.kind == TYP) {
1854 checkSymbol(pos, c.owner);
1855 }
1856 }
1857 } finally {
1858 seenClasses = seenClasses.tail;
1859 }
1860 }
1861 }
1862 }
1864 /** Check for cyclic references. Issue an error if the
1865 * symbol of the type referred to has a LOCKED flag set.
1866 *
1867 * @param pos Position to be used for error reporting.
1868 * @param t The type referred to.
1869 */
1870 void checkNonCyclic(DiagnosticPosition pos, Type t) {
1871 checkNonCyclicInternal(pos, t);
1872 }
1875 void checkNonCyclic(DiagnosticPosition pos, TypeVar t) {
1876 checkNonCyclic1(pos, t, List.<TypeVar>nil());
1877 }
1879 private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) {
1880 final TypeVar tv;
1881 if (t.tag == TYPEVAR && (t.tsym.flags() & UNATTRIBUTED) != 0)
1882 return;
1883 if (seen.contains(t)) {
1884 tv = (TypeVar)t;
1885 tv.bound = types.createErrorType(t);
1886 log.error(pos, "cyclic.inheritance", t);
1887 } else if (t.tag == TYPEVAR) {
1888 tv = (TypeVar)t;
1889 seen = seen.prepend(tv);
1890 for (Type b : types.getBounds(tv))
1891 checkNonCyclic1(pos, b, seen);
1892 }
1893 }
1895 /** Check for cyclic references. Issue an error if the
1896 * symbol of the type referred to has a LOCKED flag set.
1897 *
1898 * @param pos Position to be used for error reporting.
1899 * @param t The type referred to.
1900 * @returns True if the check completed on all attributed classes
1901 */
1902 private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) {
1903 boolean complete = true; // was the check complete?
1904 //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG
1905 Symbol c = t.tsym;
1906 if ((c.flags_field & ACYCLIC) != 0) return true;
1908 if ((c.flags_field & LOCKED) != 0) {
1909 noteCyclic(pos, (ClassSymbol)c);
1910 } else if (!c.type.isErroneous()) {
1911 try {
1912 c.flags_field |= LOCKED;
1913 if (c.type.tag == CLASS) {
1914 ClassType clazz = (ClassType)c.type;
1915 if (clazz.interfaces_field != null)
1916 for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail)
1917 complete &= checkNonCyclicInternal(pos, l.head);
1918 if (clazz.supertype_field != null) {
1919 Type st = clazz.supertype_field;
1920 if (st != null && st.tag == CLASS)
1921 complete &= checkNonCyclicInternal(pos, st);
1922 }
1923 if (c.owner.kind == TYP)
1924 complete &= checkNonCyclicInternal(pos, c.owner.type);
1925 }
1926 } finally {
1927 c.flags_field &= ~LOCKED;
1928 }
1929 }
1930 if (complete)
1931 complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null;
1932 if (complete) c.flags_field |= ACYCLIC;
1933 return complete;
1934 }
1936 /** Note that we found an inheritance cycle. */
1937 private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
1938 log.error(pos, "cyclic.inheritance", c);
1939 for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
1940 l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
1941 Type st = types.supertype(c.type);
1942 if (st.tag == CLASS)
1943 ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
1944 c.type = types.createErrorType(c, c.type);
1945 c.flags_field |= ACYCLIC;
1946 }
1948 /** Check that all methods which implement some
1949 * method conform to the method they implement.
1950 * @param tree The class definition whose members are checked.
1951 */
1952 void checkImplementations(JCClassDecl tree) {
1953 checkImplementations(tree, tree.sym);
1954 }
1955 //where
1956 /** Check that all methods which implement some
1957 * method in `ic' conform to the method they implement.
1958 */
1959 void checkImplementations(JCClassDecl tree, ClassSymbol ic) {
1960 ClassSymbol origin = tree.sym;
1961 for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
1962 ClassSymbol lc = (ClassSymbol)l.head.tsym;
1963 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) {
1964 for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) {
1965 if (e.sym.kind == MTH &&
1966 (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
1967 MethodSymbol absmeth = (MethodSymbol)e.sym;
1968 MethodSymbol implmeth = absmeth.implementation(origin, types, false);
1969 if (implmeth != null && implmeth != absmeth &&
1970 (implmeth.owner.flags() & INTERFACE) ==
1971 (origin.flags() & INTERFACE)) {
1972 // don't check if implmeth is in a class, yet
1973 // origin is an interface. This case arises only
1974 // if implmeth is declared in Object. The reason is
1975 // that interfaces really don't inherit from
1976 // Object it's just that the compiler represents
1977 // things that way.
1978 checkOverride(tree, implmeth, absmeth, origin);
1979 }
1980 }
1981 }
1982 }
1983 }
1984 }
1986 /** Check that all abstract methods implemented by a class are
1987 * mutually compatible.
1988 * @param pos Position to be used for error reporting.
1989 * @param c The class whose interfaces are checked.
1990 */
1991 void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
1992 List<Type> supertypes = types.interfaces(c);
1993 Type supertype = types.supertype(c);
1994 if (supertype.tag == CLASS &&
1995 (supertype.tsym.flags() & ABSTRACT) != 0)
1996 supertypes = supertypes.prepend(supertype);
1997 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
1998 if (allowGenerics && !l.head.getTypeArguments().isEmpty() &&
1999 !checkCompatibleAbstracts(pos, l.head, l.head, c))
2000 return;
2001 for (List<Type> m = supertypes; m != l; m = m.tail)
2002 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
2003 return;
2004 }
2005 checkCompatibleConcretes(pos, c);
2006 }
2008 void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) {
2009 for (Type ct = c.type; ct != Type.noType ; ct = types.supertype(ct)) {
2010 for (Scope.Entry e = ct.tsym.members().lookup(sym.name); e.scope == ct.tsym.members(); e = e.next()) {
2011 // VM allows methods and variables with differing types
2012 if (sym.kind == e.sym.kind &&
2013 types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) &&
2014 sym != e.sym &&
2015 (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) &&
2016 (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 &&
2017 (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) {
2018 syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym);
2019 return;
2020 }
2021 }
2022 }
2023 }
2025 /** Report a conflict between a user symbol and a synthetic symbol.
2026 */
2027 private void syntheticError(DiagnosticPosition pos, Symbol sym) {
2028 if (!sym.type.isErroneous()) {
2029 if (warnOnSyntheticConflicts) {
2030 log.warning(pos, "synthetic.name.conflict", sym, sym.location());
2031 }
2032 else {
2033 log.error(pos, "synthetic.name.conflict", sym, sym.location());
2034 }
2035 }
2036 }
2038 /** Check that class c does not implement directly or indirectly
2039 * the same parameterized interface with two different argument lists.
2040 * @param pos Position to be used for error reporting.
2041 * @param type The type whose interfaces are checked.
2042 */
2043 void checkClassBounds(DiagnosticPosition pos, Type type) {
2044 checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type);
2045 }
2046 //where
2047 /** Enter all interfaces of type `type' into the hash table `seensofar'
2048 * with their class symbol as key and their type as value. Make
2049 * sure no class is entered with two different types.
2050 */
2051 void checkClassBounds(DiagnosticPosition pos,
2052 Map<TypeSymbol,Type> seensofar,
2053 Type type) {
2054 if (type.isErroneous()) return;
2055 for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) {
2056 Type it = l.head;
2057 Type oldit = seensofar.put(it.tsym, it);
2058 if (oldit != null) {
2059 List<Type> oldparams = oldit.allparams();
2060 List<Type> newparams = it.allparams();
2061 if (!types.containsTypeEquivalent(oldparams, newparams))
2062 log.error(pos, "cant.inherit.diff.arg",
2063 it.tsym, Type.toString(oldparams),
2064 Type.toString(newparams));
2065 }
2066 checkClassBounds(pos, seensofar, it);
2067 }
2068 Type st = types.supertype(type);
2069 if (st != null) checkClassBounds(pos, seensofar, st);
2070 }
2072 /** Enter interface into into set.
2073 * If it existed already, issue a "repeated interface" error.
2074 */
2075 void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) {
2076 if (its.contains(it))
2077 log.error(pos, "repeated.interface");
2078 else {
2079 its.add(it);
2080 }
2081 }
2083 /* *************************************************************************
2084 * Check annotations
2085 **************************************************************************/
2087 /**
2088 * Recursively validate annotations values
2089 */
2090 void validateAnnotationTree(JCTree tree) {
2091 class AnnotationValidator extends TreeScanner {
2092 @Override
2093 public void visitAnnotation(JCAnnotation tree) {
2094 super.visitAnnotation(tree);
2095 validateAnnotation(tree);
2096 }
2097 }
2098 tree.accept(new AnnotationValidator());
2099 }
2101 /** Annotation types are restricted to primitives, String, an
2102 * enum, an annotation, Class, Class<?>, Class<? extends
2103 * Anything>, arrays of the preceding.
2104 */
2105 void validateAnnotationType(JCTree restype) {
2106 // restype may be null if an error occurred, so don't bother validating it
2107 if (restype != null) {
2108 validateAnnotationType(restype.pos(), restype.type);
2109 }
2110 }
2112 void validateAnnotationType(DiagnosticPosition pos, Type type) {
2113 if (type.isPrimitive()) return;
2114 if (types.isSameType(type, syms.stringType)) return;
2115 if ((type.tsym.flags() & Flags.ENUM) != 0) return;
2116 if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return;
2117 if (types.lowerBound(type).tsym == syms.classType.tsym) return;
2118 if (types.isArray(type) && !types.isArray(types.elemtype(type))) {
2119 validateAnnotationType(pos, types.elemtype(type));
2120 return;
2121 }
2122 log.error(pos, "invalid.annotation.member.type");
2123 }
2125 /**
2126 * "It is also a compile-time error if any method declared in an
2127 * annotation type has a signature that is override-equivalent to
2128 * that of any public or protected method declared in class Object
2129 * or in the interface annotation.Annotation."
2130 *
2131 * @jls3 9.6 Annotation Types
2132 */
2133 void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
2134 for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types.supertype(sup)) {
2135 Scope s = sup.tsym.members();
2136 for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) {
2137 if (e.sym.kind == MTH &&
2138 (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
2139 types.overrideEquivalent(m.type, e.sym.type))
2140 log.error(pos, "intf.annotation.member.clash", e.sym, sup);
2141 }
2142 }
2143 }
2145 /** Check the annotations of a symbol.
2146 */
2147 public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
2148 if (skipAnnotations) return;
2149 for (JCAnnotation a : annotations)
2150 validateAnnotation(a, s);
2151 }
2153 /** Check the type annotations
2154 */
2155 public void validateTypeAnnotations(List<JCTypeAnnotation> annotations, boolean isTypeParameter) {
2156 if (skipAnnotations) return;
2157 for (JCTypeAnnotation a : annotations)
2158 validateTypeAnnotation(a, isTypeParameter);
2159 }
2161 /** Check an annotation of a symbol.
2162 */
2163 public void validateAnnotation(JCAnnotation a, Symbol s) {
2164 validateAnnotationTree(a);
2166 if (!annotationApplicable(a, s))
2167 log.error(a.pos(), "annotation.type.not.applicable");
2169 if (a.annotationType.type.tsym == syms.overrideType.tsym) {
2170 if (!isOverrider(s))
2171 log.error(a.pos(), "method.does.not.override.superclass");
2172 }
2173 }
2175 public void validateTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) {
2176 if (a.type == null)
2177 throw new AssertionError("annotation tree hasn't been attributed yet: " + a);
2178 validateAnnotationTree(a);
2180 if (!isTypeAnnotation(a, isTypeParameter))
2181 log.error(a.pos(), "annotation.type.not.applicable");
2182 }
2184 /** Is s a method symbol that overrides a method in a superclass? */
2185 boolean isOverrider(Symbol s) {
2186 if (s.kind != MTH || s.isStatic())
2187 return false;
2188 MethodSymbol m = (MethodSymbol)s;
2189 TypeSymbol owner = (TypeSymbol)m.owner;
2190 for (Type sup : types.closure(owner.type)) {
2191 if (sup == owner.type)
2192 continue; // skip "this"
2193 Scope scope = sup.tsym.members();
2194 for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) {
2195 if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true))
2196 return true;
2197 }
2198 }
2199 return false;
2200 }
2202 /** Is the annotation applicable to type annotations */
2203 boolean isTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) {
2204 Attribute.Compound atTarget =
2205 a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
2206 if (atTarget == null) return true;
2207 Attribute atValue = atTarget.member(names.value);
2208 if (!(atValue instanceof Attribute.Array)) return true; // error recovery
2209 Attribute.Array arr = (Attribute.Array) atValue;
2210 for (Attribute app : arr.values) {
2211 if (!(app instanceof Attribute.Enum)) return true; // recovery
2212 Attribute.Enum e = (Attribute.Enum) app;
2213 if (!isTypeParameter && e.value.name == names.TYPE_USE)
2214 return true;
2215 else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER)
2216 return true;
2217 }
2218 return false;
2219 }
2221 /** Is the annotation applicable to the symbol? */
2222 boolean annotationApplicable(JCAnnotation a, Symbol s) {
2223 Attribute.Compound atTarget =
2224 a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
2225 if (atTarget == null) return true;
2226 Attribute atValue = atTarget.member(names.value);
2227 if (!(atValue instanceof Attribute.Array)) return true; // error recovery
2228 Attribute.Array arr = (Attribute.Array) atValue;
2229 for (Attribute app : arr.values) {
2230 if (!(app instanceof Attribute.Enum)) return true; // recovery
2231 Attribute.Enum e = (Attribute.Enum) app;
2232 if (e.value.name == names.TYPE)
2233 { if (s.kind == TYP) return true; }
2234 else if (e.value.name == names.FIELD)
2235 { if (s.kind == VAR && s.owner.kind != MTH) return true; }
2236 else if (e.value.name == names.METHOD)
2237 { if (s.kind == MTH && !s.isConstructor()) return true; }
2238 else if (e.value.name == names.PARAMETER)
2239 { if (s.kind == VAR &&
2240 s.owner.kind == MTH &&
2241 (s.flags() & PARAMETER) != 0)
2242 return true;
2243 }
2244 else if (e.value.name == names.CONSTRUCTOR)
2245 { if (s.kind == MTH && s.isConstructor()) return true; }
2246 else if (e.value.name == names.LOCAL_VARIABLE)
2247 { if (s.kind == VAR && s.owner.kind == MTH &&
2248 (s.flags() & PARAMETER) == 0)
2249 return true;
2250 }
2251 else if (e.value.name == names.ANNOTATION_TYPE)
2252 { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0)
2253 return true;
2254 }
2255 else if (e.value.name == names.PACKAGE)
2256 { if (s.kind == PCK) return true; }
2257 else if (e.value.name == names.TYPE_USE)
2258 { if (s.kind == TYP ||
2259 s.kind == VAR ||
2260 (s.kind == MTH && !s.isConstructor() &&
2261 s.type.getReturnType().tag != VOID))
2262 return true;
2263 }
2264 else
2265 return true; // recovery
2266 }
2267 return false;
2268 }
2270 /** Check an annotation value.
2271 */
2272 public void validateAnnotation(JCAnnotation a) {
2273 if (a.type.isErroneous()) return;
2275 // collect an inventory of the members (sorted alphabetically)
2276 Set<MethodSymbol> members = new TreeSet<MethodSymbol>(new Comparator<Symbol>() {
2277 public int compare(Symbol t, Symbol t1) {
2278 return t.name.compareTo(t1.name);
2279 }
2280 });
2281 for (Scope.Entry e = a.annotationType.type.tsym.members().elems;
2282 e != null;
2283 e = e.sibling)
2284 if (e.sym.kind == MTH)
2285 members.add((MethodSymbol) e.sym);
2287 // count them off as they're annotated
2288 for (JCTree arg : a.args) {
2289 if (arg.getTag() != JCTree.ASSIGN) continue; // recovery
2290 JCAssign assign = (JCAssign) arg;
2291 Symbol m = TreeInfo.symbol(assign.lhs);
2292 if (m == null || m.type.isErroneous()) continue;
2293 if (!members.remove(m))
2294 log.error(assign.lhs.pos(), "duplicate.annotation.member.value",
2295 m.name, a.type);
2296 }
2298 // all the remaining ones better have default values
2299 ListBuffer<Name> missingDefaults = ListBuffer.lb();
2300 for (MethodSymbol m : members) {
2301 if (m.defaultValue == null && !m.type.isErroneous()) {
2302 missingDefaults.append(m.name);
2303 }
2304 }
2305 if (missingDefaults.nonEmpty()) {
2306 String key = (missingDefaults.size() > 1)
2307 ? "annotation.missing.default.value.1"
2308 : "annotation.missing.default.value";
2309 log.error(a.pos(), key, a.type, missingDefaults);
2310 }
2312 // special case: java.lang.annotation.Target must not have
2313 // repeated values in its value member
2314 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
2315 a.args.tail == null)
2316 return;
2318 if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery
2319 JCAssign assign = (JCAssign) a.args.head;
2320 Symbol m = TreeInfo.symbol(assign.lhs);
2321 if (m.name != names.value) return;
2322 JCTree rhs = assign.rhs;
2323 if (rhs.getTag() != JCTree.NEWARRAY) return;
2324 JCNewArray na = (JCNewArray) rhs;
2325 Set<Symbol> targets = new HashSet<Symbol>();
2326 for (JCTree elem : na.elems) {
2327 if (!targets.add(TreeInfo.symbol(elem))) {
2328 log.error(elem.pos(), "repeated.annotation.target");
2329 }
2330 }
2331 }
2333 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
2334 if (allowAnnotations &&
2335 lint.isEnabled(Lint.LintCategory.DEP_ANN) &&
2336 (s.flags() & DEPRECATED) != 0 &&
2337 !syms.deprecatedType.isErroneous() &&
2338 s.attribute(syms.deprecatedType.tsym) == null) {
2339 log.warning(Lint.LintCategory.DEP_ANN,
2340 pos, "missing.deprecated.annotation");
2341 }
2342 }
2344 /* *************************************************************************
2345 * Check for recursive annotation elements.
2346 **************************************************************************/
2348 /** Check for cycles in the graph of annotation elements.
2349 */
2350 void checkNonCyclicElements(JCClassDecl tree) {
2351 if ((tree.sym.flags_field & ANNOTATION) == 0) return;
2352 assert (tree.sym.flags_field & LOCKED) == 0;
2353 try {
2354 tree.sym.flags_field |= LOCKED;
2355 for (JCTree def : tree.defs) {
2356 if (def.getTag() != JCTree.METHODDEF) continue;
2357 JCMethodDecl meth = (JCMethodDecl)def;
2358 checkAnnotationResType(meth.pos(), meth.restype.type);
2359 }
2360 } finally {
2361 tree.sym.flags_field &= ~LOCKED;
2362 tree.sym.flags_field |= ACYCLIC_ANN;
2363 }
2364 }
2366 void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
2367 if ((tsym.flags_field & ACYCLIC_ANN) != 0)
2368 return;
2369 if ((tsym.flags_field & LOCKED) != 0) {
2370 log.error(pos, "cyclic.annotation.element");
2371 return;
2372 }
2373 try {
2374 tsym.flags_field |= LOCKED;
2375 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
2376 Symbol s = e.sym;
2377 if (s.kind != Kinds.MTH)
2378 continue;
2379 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType());
2380 }
2381 } finally {
2382 tsym.flags_field &= ~LOCKED;
2383 tsym.flags_field |= ACYCLIC_ANN;
2384 }
2385 }
2387 void checkAnnotationResType(DiagnosticPosition pos, Type type) {
2388 switch (type.tag) {
2389 case TypeTags.CLASS:
2390 if ((type.tsym.flags() & ANNOTATION) != 0)
2391 checkNonCyclicElementsInternal(pos, type.tsym);
2392 break;
2393 case TypeTags.ARRAY:
2394 checkAnnotationResType(pos, types.elemtype(type));
2395 break;
2396 default:
2397 break; // int etc
2398 }
2399 }
2401 /* *************************************************************************
2402 * Check for cycles in the constructor call graph.
2403 **************************************************************************/
2405 /** Check for cycles in the graph of constructors calling other
2406 * constructors.
2407 */
2408 void checkCyclicConstructors(JCClassDecl tree) {
2409 Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>();
2411 // enter each constructor this-call into the map
2412 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
2413 JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head);
2414 if (app == null) continue;
2415 JCMethodDecl meth = (JCMethodDecl) l.head;
2416 if (TreeInfo.name(app.meth) == names._this) {
2417 callMap.put(meth.sym, TreeInfo.symbol(app.meth));
2418 } else {
2419 meth.sym.flags_field |= ACYCLIC;
2420 }
2421 }
2423 // Check for cycles in the map
2424 Symbol[] ctors = new Symbol[0];
2425 ctors = callMap.keySet().toArray(ctors);
2426 for (Symbol caller : ctors) {
2427 checkCyclicConstructor(tree, caller, callMap);
2428 }
2429 }
2431 /** Look in the map to see if the given constructor is part of a
2432 * call cycle.
2433 */
2434 private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor,
2435 Map<Symbol,Symbol> callMap) {
2436 if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
2437 if ((ctor.flags_field & LOCKED) != 0) {
2438 log.error(TreeInfo.diagnosticPositionFor(ctor, tree),
2439 "recursive.ctor.invocation");
2440 } else {
2441 ctor.flags_field |= LOCKED;
2442 checkCyclicConstructor(tree, callMap.remove(ctor), callMap);
2443 ctor.flags_field &= ~LOCKED;
2444 }
2445 ctor.flags_field |= ACYCLIC;
2446 }
2447 }
2449 /* *************************************************************************
2450 * Miscellaneous
2451 **************************************************************************/
2453 /**
2454 * Return the opcode of the operator but emit an error if it is an
2455 * error.
2456 * @param pos position for error reporting.
2457 * @param operator an operator
2458 * @param tag a tree tag
2459 * @param left type of left hand side
2460 * @param right type of right hand side
2461 */
2462 int checkOperator(DiagnosticPosition pos,
2463 OperatorSymbol operator,
2464 int tag,
2465 Type left,
2466 Type right) {
2467 if (operator.opcode == ByteCodes.error) {
2468 log.error(pos,
2469 "operator.cant.be.applied",
2470 treeinfo.operatorName(tag),
2471 List.of(left, right));
2472 }
2473 return operator.opcode;
2474 }
2477 /**
2478 * Check for division by integer constant zero
2479 * @param pos Position for error reporting.
2480 * @param operator The operator for the expression
2481 * @param operand The right hand operand for the expression
2482 */
2483 void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
2484 if (operand.constValue() != null
2485 && lint.isEnabled(Lint.LintCategory.DIVZERO)
2486 && operand.tag <= LONG
2487 && ((Number) (operand.constValue())).longValue() == 0) {
2488 int opc = ((OperatorSymbol)operator).opcode;
2489 if (opc == ByteCodes.idiv || opc == ByteCodes.imod
2490 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
2491 log.warning(Lint.LintCategory.DIVZERO, pos, "div.zero");
2492 }
2493 }
2494 }
2496 /**
2497 * Check for empty statements after if
2498 */
2499 void checkEmptyIf(JCIf tree) {
2500 if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY))
2501 log.warning(Lint.LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
2502 }
2504 /** Check that symbol is unique in given scope.
2505 * @param pos Position for error reporting.
2506 * @param sym The symbol.
2507 * @param s The scope.
2508 */
2509 boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
2510 if (sym.type.isErroneous())
2511 return true;
2512 if (sym.owner.name == names.any) return false;
2513 for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
2514 if (sym != e.sym &&
2515 sym.kind == e.sym.kind &&
2516 sym.name != names.error &&
2517 (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
2518 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS))
2519 varargsDuplicateError(pos, sym, e.sym);
2520 else if (sym.kind == MTH && !types.overrideEquivalent(sym.type, e.sym.type))
2521 duplicateErasureError(pos, sym, e.sym);
2522 else
2523 duplicateError(pos, e.sym);
2524 return false;
2525 }
2526 }
2527 return true;
2528 }
2529 //where
2530 /** Report duplicate declaration error.
2531 */
2532 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
2533 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
2534 log.error(pos, "name.clash.same.erasure", sym1, sym2);
2535 }
2536 }
2538 /** Check that single-type import is not already imported or top-level defined,
2539 * but make an exception for two single-type imports which denote the same type.
2540 * @param pos Position for error reporting.
2541 * @param sym The symbol.
2542 * @param s The scope
2543 */
2544 boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) {
2545 return checkUniqueImport(pos, sym, s, false);
2546 }
2548 /** Check that static single-type import is not already imported or top-level defined,
2549 * but make an exception for two single-type imports which denote the same type.
2550 * @param pos Position for error reporting.
2551 * @param sym The symbol.
2552 * @param s The scope
2553 * @param staticImport Whether or not this was a static import
2554 */
2555 boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) {
2556 return checkUniqueImport(pos, sym, s, true);
2557 }
2559 /** Check that single-type import is not already imported or top-level defined,
2560 * but make an exception for two single-type imports which denote the same type.
2561 * @param pos Position for error reporting.
2562 * @param sym The symbol.
2563 * @param s The scope.
2564 * @param staticImport Whether or not this was a static import
2565 */
2566 private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) {
2567 for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) {
2568 // is encountered class entered via a class declaration?
2569 boolean isClassDecl = e.scope == s;
2570 if ((isClassDecl || sym != e.sym) &&
2571 sym.kind == e.sym.kind &&
2572 sym.name != names.error) {
2573 if (!e.sym.type.isErroneous()) {
2574 String what = e.sym.toString();
2575 if (!isClassDecl) {
2576 if (staticImport)
2577 log.error(pos, "already.defined.static.single.import", what);
2578 else
2579 log.error(pos, "already.defined.single.import", what);
2580 }
2581 else if (sym != e.sym)
2582 log.error(pos, "already.defined.this.unit", what);
2583 }
2584 return false;
2585 }
2586 }
2587 return true;
2588 }
2590 /** Check that a qualified name is in canonical form (for import decls).
2591 */
2592 public void checkCanonical(JCTree tree) {
2593 if (!isCanonical(tree))
2594 log.error(tree.pos(), "import.requires.canonical",
2595 TreeInfo.symbol(tree));
2596 }
2597 // where
2598 private boolean isCanonical(JCTree tree) {
2599 while (tree.getTag() == JCTree.SELECT) {
2600 JCFieldAccess s = (JCFieldAccess) tree;
2601 if (s.sym.owner != TreeInfo.symbol(s.selected))
2602 return false;
2603 tree = s.selected;
2604 }
2605 return true;
2606 }
2608 private class ConversionWarner extends Warner {
2609 final String key;
2610 final Type found;
2611 final Type expected;
2612 public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) {
2613 super(pos);
2614 this.key = key;
2615 this.found = found;
2616 this.expected = expected;
2617 }
2619 @Override
2620 public void warnUnchecked() {
2621 boolean warned = this.warned;
2622 super.warnUnchecked();
2623 if (warned) return; // suppress redundant diagnostics
2624 Object problem = diags.fragment(key);
2625 Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected);
2626 }
2627 }
2629 public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
2630 return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);
2631 }
2633 public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) {
2634 return new ConversionWarner(pos, "unchecked.assign", found, expected);
2635 }
2636 }