List<PsiType> (PsiType declaredType, List<PsiType> uncaughtTypes) { List<PsiType> types = new SmartList<>(); for (PsiType type : uncaughtTypes) { if (type.isAssignableFrom(declaredType)) { types.add(declaredType); } else if (declaredType.isAssignableFrom(type) || // JLS 11.2.3 "Exception Checking": // "It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case // that the try block corresponding to the catch clause can throw a checked exception class that is // a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception." // So here unchecked exception can sneak through Exception or Throwable catch type only. ExceptionUtil.isGeneralExceptionType(declaredType) && type instanceof PsiClassType && ExceptionUtil.isUncheckedException((PsiClassType)type)) { types.add(type); } } // ... the throw statement throws precisely the set of exception types T. return types; }