typetools / checker-framework

Pluggable type-checking for Java
http://checkerframework.org/
Other
1.01k stars 352 forks source link

BugInCF type is not an erased subtype of supertype #6762

Open nickbreen opened 4 weeks ago

nickbreen commented 4 weeks ago

Note, rs is a java.sql.ResultSet.

Code stanza:

final IntSet roleIds = Optional.ofNullable(rs.getString("role_ids"))
                .map(rids -> Arrays.stream(rids.split(","))
                        .map(Integer::parseInt)
                        .collect(Collectors.collectingAndThen(Collectors.toSet(), IntArraySet::new)))
                .orElse(new IntArraySet());
error: AsSuperVisitor: type is not an erased subtype of supertype.
  type: @UnknownUnits Object
  superType: @UnknownUnits IntSet
  ; The Checker Framework crashed.  Please report the crash.  Version: Checker Framework 3.46.0. 
  Compilation unit: [elided]
  Last visited tree at line 46 column 9:
          final IntSet roleIds = Optional.ofNullable(rs.getString("role_ids"))
  Exception: java.lang.Throwable; java.lang.Throwable
        at org.checkerframework.javacutil.BugInCF.<init>(BugInCF.java:38)
        at org.checkerframework.framework.type.AsSuperVisitor.errorTypeNotErasedSubtypeOfSuperType(AsSuperVisitor.java:148)
        at org.checkerframework.framework.type.AsSuperVisitor.visitDeclared_Declared(AsSuperVisitor.java:338)
        at org.checkerframework.framework.type.AsSuperVisitor.visitDeclared_Declared(AsSuperVisitor.java:30)
        at org.checkerframework.framework.util.AtmCombo.accept(AtmCombo.java:313)
        at org.checkerframework.framework.type.visitor.AbstractAtmComboVisitor.visit(AbstractAtmComboVisitor.java:34)
        at org.checkerframework.framework.type.AsSuperVisitor.visit(AsSuperVisitor.java:107)
        at org.checkerframework.framework.type.AsSuperVisitor.asSuper(AsSuperVisitor.java:88)
        at org.checkerframework.framework.util.AnnotatedTypes.asSuper(AnnotatedTypes.java:118)
        at org.checkerframework.framework.util.AnnotatedTypes.castedAsSuper(AnnotatedTypes.java:154)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitTypeArgs(DefaultTypeHierarchy.java:570)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitDeclared_Declared(DefaultTypeHierarchy.java:542)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitDeclared_Declared(DefaultTypeHierarchy.java:49)
        at org.checkerframework.framework.util.AtmCombo.accept(AtmCombo.java:313)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.isSubtype(DefaultTypeHierarchy.java:259)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.isSubtypeCaching(DefaultTypeHierarchy.java:315)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitTypevar_Type(DefaultTypeHierarchy.java:1184)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitTypevar_Declared(DefaultTypeHierarchy.java:928)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.visitTypevar_Declared(DefaultTypeHierarchy.java:49)
        at org.checkerframework.framework.util.AtmCombo.accept(AtmCombo.java:589)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.isSubtype(DefaultTypeHierarchy.java:259)
        at org.checkerframework.framework.type.DefaultTypeHierarchy.isSubtype(DefaultTypeHierarchy.java:137)
        at org.checkerframework.common.basetype.BaseTypeVisitor.commonAssignmentCheck(BaseTypeVisitor.java:3139)
        at org.checkerframework.common.basetype.BaseTypeVisitor.commonAssignmentCheck(BaseTypeVisitor.java:3114)
        at org.checkerframework.common.basetype.BaseTypeVisitor.commonAssignmentCheck(BaseTypeVisitor.java:3033)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitVariable(BaseTypeVisitor.java:1617)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitVariable(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:990)
        at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
        at org.checkerframework.framework.source.SourceVisitor.scan(SourceVisitor.java:92)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:408)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
        at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
        at jdk.compiler/com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:248)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1048)
        at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
        at org.checkerframework.framework.source.SourceVisitor.scan(SourceVisitor.java:92)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:408)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
        at jdk.compiler/com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:206)
        at org.checkerframework.framework.source.SourceVisitor.visitMethod(SourceVisitor.java:110)
        at org.checkerframework.common.basetype.BaseTypeVisitor.processMethodTree(BaseTypeVisitor.java:1067)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitMethod(BaseTypeVisitor.java:963)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitMethod(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:898)
        at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
        at org.checkerframework.framework.source.SourceVisitor.scan(SourceVisitor.java:92)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:408)
        at org.checkerframework.common.basetype.BaseTypeVisitor.scan(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
        at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
        at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
        at jdk.compiler/com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:187)
        at org.checkerframework.framework.source.SourceVisitor.visitClass(SourceVisitor.java:98)
        at org.checkerframework.common.basetype.BaseTypeVisitor.processClassTree(BaseTypeVisitor.java:612)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitClass(BaseTypeVisitor.java:558)
        at org.checkerframework.common.basetype.BaseTypeVisitor.visitClass(BaseTypeVisitor.java:189)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:808)
        at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:56)
        at org.checkerframework.framework.source.SourceVisitor.visit(SourceVisitor.java:86)
        at org.checkerframework.framework.source.SourceChecker.typeProcess(SourceChecker.java:1094)
        at org.checkerframework.common.basetype.BaseTypeChecker.typeProcess(BaseTypeChecker.java:559)
        at org.checkerframework.javacutil.AbstractTypeProcessor$AttributionTaskListener.finished(AbstractTypeProcessor.java:188)
        at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$WrappedTaskListener.finished(ClientCodeWrapper.java:828)
        at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:132)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1414)
        at com.google.devtools.build.buildjar.javac.BlazeJavaCompiler.flow(BlazeJavaCompiler.java:102)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1361)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:960)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:147)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
        at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:149)
        at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.fallback(ReducedClasspathJavaLibraryBuilder.java:105)
        at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:67)
        at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:110)
        at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:118)
        at com.google.devtools.build.buildjar.BazelJavaBuilder.build(BazelJavaBuilder.java:105)
        at com.google.devtools.build.buildjar.BazelJavaBuilder.parseAndBuild(BazelJavaBuilder.java:85)
        at com.google.devtools.build.lib.worker.WorkRequestHandler$WorkRequestHandlerBuilder.lambda$new$0(WorkRequestHandler.java:287)
        at com.google.devtools.build.lib.worker.WorkRequestHandler$WorkRequestCallback.apply(WorkRequestHandler.java:252)
        at com.google.devtools.build.lib.worker.WorkRequestHandler.respondToRequest(WorkRequestHandler.java:480)
        at com.google.devtools.build.lib.worker.WorkRequestHandler.lambda$startResponseThread$1(WorkRequestHandler.java:433)
        at java.base/java.lang.Thread.run(Thread.java:829)
smillst commented 3 weeks ago

Thanks. I was able to reproduce this with the follow class:

package typearginfer;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class Issue6762 {

  void method(ResultSet rs) throws SQLException {
    final IntSet roleIds = Optional.ofNullable(rs.getString("role_ids")).map(
            rids -> Arrays.stream(rids.split(",")).map(Integer::parseInt)
                .collect(Collectors.collectingAndThen(Collectors.toSet(), IntArraySet::new)))
        .orElse(new IntArraySet());
  }

  static class IntArraySet extends IntSet {
    IntArraySet() {}
    IntArraySet(Set<Integer> i) {}
  }

  static class IntSet implements Set<Integer> {

    @Override
    public int size() {
      return 0;
    }

    @Override
    public boolean isEmpty() {
      return false;
    }

    @Override
    public boolean contains(Object o) {
      return false;
    }

    @Override
    public Iterator<Integer> iterator() {
      return null;
    }

    @Override
    public Object[] toArray() {
      return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
      return null;
    }

    @Override
    public boolean add(Integer integer) {
      return false;
    }

    @Override
    public boolean remove(Object o) {
      return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
      return false;
    }

    @Override
    public boolean addAll(Collection<? extends Integer> c) {
      return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
      return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
      return false;
    }

    @Override
    public void clear() {}
  }
}