Tunable Static Inference for Generic Universe Types Werner Dietl Michael Ernst & Peter Müller
Generic Universe Types (GUT) Lightweight ownership type system Heap topology Owner-as-Modifier encapsulation discipline
Glimpse of Generic Universe Types class List<Y> { List rep Node<Y> head; ... Node } Node class Node<X> { peer Node<X> next; Node ... } 3
Generic Universe Types (GUT) Lightweight ownership type system Heap topology Owner-as-Modifier encapsulation discipline Large-scale use hampered by annotation effort All fields, parameters, object creations, … need annotations
Manual annotation effort huge rep AnnotatedTypeMirror lhsBase = lhs; AnnotatedTypeMirror lhsBase = lhs; while (lhsBase.getKind() != rhs.getKind() && (lhsBase.getKind() == TypeKind.WILDCARD || lhsBase.getKind() == while (lhsBase.getKind() != rhs.getKind() TypeKind.TYPEVAR)) { && (lhsBase.getKind() == TypeKind.WILDCARD || lhsBase.getKind() == if (lhsBase.getKind() == TypeKind.WILDCARD && rhs.getKind() != TypeKind.TYPEVAR)) { TypeKind.WILDCARD) { if (lhsBase.getKind() == TypeKind.WILDCARD && rhs.getKind() != AnnotatedWildcardType wildcard = (AnnotatedWildcardType)lhsBase; TypeKind.WILDCARD) { if (lhsBase == null || !lhsBase.isAnnotated()) rep AnnotatedWildcardType wildcard = ( rep return true; visited.add(lhsBase.getElement()); } else if (rhs.getKind() == TypeKind.WILDCARD) { AnnotatedWildcardType)lhsBase; if (lhsBase == null || !lhsBase.isAnnotated()) rhs = ((AnnotatedWildcardType)rhs).getExtendsBound(); return true; } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhs.getKind() != visited.add(lhsBase.getElement()); TypeKind.TYPEVAR) { } else if (rhs.getKind() == TypeKind.WILDCARD) { AnnotatedTypeVariable lhsb_atv = (AnnotatedTypeVariable)lhsBase; rhs = (( peer AnnotatedWildcardType)rhs).getExtendsBound(); Set<AnnotationMirror> lAnnos = lhsb_atv.getLowerBoundAnnotations(); if (!lAnnos.isEmpty()) return qualifierHierarchy.isSubtype(rhs.getAnnotations(), lAnnos); } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhs.getKind() != rhs.getAnnotations().contains(qualifierHierarchy.getBottomQualifier()); TypeKind.TYPEVAR) { rep AnnotatedTypeVariable lhsb_atv = ( rep } } AnnotatedTypeVariable)lhsBase; AnnotatedTypeMirror rhsBase = rhs.typeFactory.atypes.asSuper(rhs, rep Set< peer AnnotationMirror> lAnnos = lhsBase); if (!qualifierHierarchy.isSubtype(rhsBase.getAnnotations(), lhsb_atv.getLowerBoundAnnotations(); lhsBase.getAnnotations())) if (!lAnnos.isEmpty()) return false; return qualifierHierarchy.isSubtype(rhs.getAnnotations(), lAnnos); rhs.getAnnotations().contains(qualifierHierarchy.getBottomQualifier()); if (lhs.getKind() == TypeKind.ARRAY && rhsBase.getKind() == } TypeKind.ARRAY) { } rep AnnotatedTypeMirror rhsBase = AnnotatedTypeMirror rhsComponent = ((AnnotatedArrayType)rhsBase).getComponentType(); AnnotatedTypeMirror lhsComponent = rhs.typeFactory.atypes.asSuper(rhs, lhsBase); ((AnnotatedArrayType)lhsBase).getComponentType(); return isSubtypeAsArrayComponent(rhsComponent, lhsComponent); if (lhs.getKind() == TypeKind.ARRAY && rhsBase.getKind() == } else if (lhsBase.getKind() == TypeKind.DECLARED && rhsBase.getKind() TypeKind.ARRAY) { == TypeKind.DECLARED) { peer AnnotatedTypeMirror rhsComponent = (( peer return isSubtypeTypeArguments((AnnotatedDeclaredType)rhsBase, (AnnotatedDeclaredType)lhsBase); AnnotatedArrayType)rhsBase).getComponentType(); } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhsBase.getKind() == peer AnnotatedTypeMirror lhsComponent = (( peer TypeKind.TYPEVAR) { l AnnotatedTypeMirror rhsSuperClass = rhsBase; while (rhsSuperClass.getKind() == TypeKind.TYPEVAR) { AnnotatedArrayType)lhsBase).getComponentType(); rhsSuperClass = ((AnnotatedTypeVariable) return isSubtypeAsArrayComponent(rhsComponent, lhsComponent); rhsSuperClass).getUpperBound(); } else if (lhsBase.getKind() == TypeKind.DECLARED && rhsBase.getKind() } == TypeKind.DECLARED) { rep AnnotatedTypeMirror rhsBase = Set<AnnotationMirror> las = ((AnnotatedTypeVariable) lhsBase).getLowerBoundAnnotations(); Set<AnnotationMirror> ras = ((AnnotatedTypeVariable) rhs.typeFactory.atypes.asSuper(rhs, lhsBase); rhsBase).getUpperBoundAnnotations(); if (!las.isEmpty()) { return qualifierHierarchy.isSubtype(ras, las);
Automated annotation support rep AnnotatedTypeMirror lhsBase = lhs; AnnotatedTypeMirror lhsBase = lhs; while (lhsBase.getKind() != rhs.getKind() && (lhsBase.getKind() == TypeKind.WILDCARD || lhsBase.getKind() == while (lhsBase.getKind() != rhs.getKind() TypeKind.TYPEVAR)) { && (lhsBase.getKind() == TypeKind.WILDCARD || lhsBase.getKind() == if (lhsBase.getKind() == TypeKind.WILDCARD && rhs.getKind() != TypeKind.TYPEVAR)) { TypeKind.WILDCARD) { if (lhsBase.getKind() == TypeKind.WILDCARD && rhs.getKind() != AnnotatedWildcardType wildcard = (AnnotatedWildcardType)lhsBase; TypeKind.WILDCARD) { if (lhsBase == null || !lhsBase.isAnnotated()) rep AnnotatedWildcardType wildcard = ( rep return true; visited.add(lhsBase.getElement()); } else if (rhs.getKind() == TypeKind.WILDCARD) { AnnotatedWildcardType)lhsBase; if (lhsBase == null || !lhsBase.isAnnotated()) rhs = ((AnnotatedWildcardType)rhs).getExtendsBound(); return true; } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhs.getKind() != visited.add(lhsBase.getElement()); TypeKind.TYPEVAR) { } else if (rhs.getKind() == TypeKind.WILDCARD) { AnnotatedTypeVariable lhsb_atv = (AnnotatedTypeVariable)lhsBase; rhs = (( peer AnnotatedWildcardType)rhs).getExtendsBound(); Set<AnnotationMirror> lAnnos = lhsb_atv.getLowerBoundAnnotations(); if (!lAnnos.isEmpty()) return qualifierHierarchy.isSubtype(rhs.getAnnotations(), lAnnos); } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhs.getKind() != rhs.getAnnotations().contains(qualifierHierarchy.getBottomQualifier()); TypeKind.TYPEVAR) { rep AnnotatedTypeVariable lhsb_atv = ( rep } } AnnotatedTypeVariable)lhsBase; AnnotatedTypeMirror rhsBase = rhs.typeFactory.atypes.asSuper(rhs, rep Set< peer AnnotationMirror> lAnnos = lhsBase); if (!qualifierHierarchy.isSubtype(rhsBase.getAnnotations(), lhsb_atv.getLowerBoundAnnotations(); lhsBase.getAnnotations())) if (!lAnnos.isEmpty()) return false; return qualifierHierarchy.isSubtype(rhs.getAnnotations(), lAnnos); rhs.getAnnotations().contains(qualifierHierarchy.getBottomQualifier()); if (lhs.getKind() == TypeKind.ARRAY && rhsBase.getKind() == } TypeKind.ARRAY) { } rep AnnotatedTypeMirror rhsBase = AnnotatedTypeMirror rhsComponent = ((AnnotatedArrayType)rhsBase).getComponentType(); AnnotatedTypeMirror lhsComponent = rhs.typeFactory.atypes.asSuper(rhs, lhsBase); ((AnnotatedArrayType)lhsBase).getComponentType(); return isSubtypeAsArrayComponent(rhsComponent, lhsComponent); if (lhs.getKind() == TypeKind.ARRAY && rhsBase.getKind() == } else if (lhsBase.getKind() == TypeKind.DECLARED && rhsBase.getKind() TypeKind.ARRAY) { == TypeKind.DECLARED) { peer AnnotatedTypeMirror rhsComponent = (( peer return isSubtypeTypeArguments((AnnotatedDeclaredType)rhsBase, (AnnotatedDeclaredType)lhsBase); AnnotatedArrayType)rhsBase).getComponentType(); } else if (lhsBase.getKind() == TypeKind.TYPEVAR && rhsBase.getKind() == peer AnnotatedTypeMirror lhsComponent = (( peer TypeKind.TYPEVAR) { l AnnotatedTypeMirror rhsSuperClass = rhsBase; while (rhsSuperClass.getKind() == TypeKind.TYPEVAR) { AnnotatedArrayType)lhsBase).getComponentType(); rhsSuperClass = ((AnnotatedTypeVariable) return isSubtypeAsArrayComponent(rhsComponent, lhsComponent); rhsSuperClass).getUpperBound(); } else if (lhsBase.getKind() == TypeKind.DECLARED && rhsBase.getKind() } == TypeKind.DECLARED) { rep AnnotatedTypeMirror rhsBase = Set<AnnotationMirror> las = ((AnnotatedTypeVariable) lhsBase).getLowerBoundAnnotations(); Set<AnnotationMirror> ras = ((AnnotatedTypeVariable) rhs.typeFactory.atypes.asSuper(rhs, lhsBase); rhsBase).getUpperBoundAnnotations(); if (!las.isEmpty()) { return qualifierHierarchy.isSubtype(ras, las);
Architecture Max-SAT Solver Solution Generic Universe Types Inference WCNF Formula Constraint AST Constraint Constrs. Solver Variable Generation Interface Introduction Source Code Heuristics Annotations 7
Many solutions exist Problem is different from usual type inference Not interested in only a typable solution We want a good structure 8
Outline Overview Tunable Static Inference for GUT GUT motivation & example Constraint variable introduction Constraint generation Max-SAT encoding Implementation & Evaluation Conclusion 9
Intended Structure User List Appl Node Data Node Data Node Data 10
Object Ownership User Iter List Appl Node Data Node Data Node Data 11
Generic Universe Types (GUT) User rep peer Iter List Appl rep rep any Node Data X peer Node Data X peer Node Data X 12
Generic Universe Types (GUT) User rep peer Iter List Appl rep rep any Node Data X peer Node Data X peer Node Data X 13
Generic Universe Types (GUT) User rep peer Iter List Appl rep rep any Node Data X peer Node Data X peer Node Data X 14
Generic Universe Types (GUT) User rep peer Iter List Appl rep rep any Node Data X peer Node Data X peer Node Data X 15
Recommend
More recommend