Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/org/checkerframework/specimin/Slicer.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ public static SliceResult slice(

slicer.buildSlice();

// Every use site has now been seen, so a placeholder return type that no use site put a
// member on can be recognized as saying nothing and replaced by the bound it stands for.
// This must run before supertype relationships are expanded into alternates, so that the
// placeholders it removes are not first turned into alternates of other types.
unsolvedSymbolGenerator
.collapseMemberlessPlaceholderReturnTypes()
.forEach(slicer.generatedSymbolSlice::remove);

unsolvedSymbolGenerator.generateAllAlternatesBasedOnSuperTypeRelationships();

Set<Node> dependentSlice = new HashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ public class FullyQualifiedNameGenerator {
/** Whether to check generated symbols when getting expression types. */
private boolean shouldCheckGeneratedSymbols = true;

/** Whether an expression's surrounding context may supply its type. */
private boolean shouldUseSurroundingContextType = true;

/**
* Create a new instance. Needs a map of type FQNs to compilation units for symbol resolution.
*
Expand Down Expand Up @@ -144,6 +147,30 @@ public boolean getShouldCheckGeneratedSymbols() {
return shouldCheckGeneratedSymbols;
}

/**
* Sets whether an expression's surrounding context may supply its type. Default is true; ensure
* that this is set back to true after your operation is done if you set it to false.
*
* <p>A context type is an upper bound on the expression's type, not the type itself: JLS 5.2 asks
* only that the expression be assignable to it. Set this to false to ask what the expression's
* type is on its own, so that the bound can be recorded as a bound instead of being mistaken for
* the answer.
*
* @param shouldUseSurroundingContextType Whether surrounding context may supply expression types
*/
public void setShouldUseSurroundingContextType(boolean shouldUseSurroundingContextType) {
this.shouldUseSurroundingContextType = shouldUseSurroundingContextType;
}

/**
* Returns whether an expression's surrounding context may supply its type.
*
* @return Whether this FullyQualifiedNameGenerator consults surrounding context
*/
public boolean getShouldUseSurroundingContextType() {
return shouldUseSurroundingContextType;
}

/**
* When evaluating an expression, there is only one possible type. However, the location of an
* expression could vary, depending on the parent classes/interfaces of the class which holds the
Expand Down Expand Up @@ -635,7 +662,7 @@ else if (expr.isCastExpr()) {
}

// Handle the cases where the type of the expression can be inferred from surrounding context
if (expr.hasParentNode()) {
if (shouldUseSurroundingContextType && expr.hasParentNode()) {
@Nullable Set<FullyQualifiedNameSet> fromLHS = getFQNsFromSurroundingContextType(expr);
if (fromLHS != null) {
return fromLHS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,30 @@ public boolean doesImplement(MemberType interfaceType) {
return getSuperTypeRelationship(interfaceType) == SuperTypeRelationship.IMPLEMENTS;
}

/**
* Returns this type's single supertype, if it has exactly one. Useful to decide whether this type
* can be replaced by its supertype everywhere.
*
* @return the sole supertype of this type, or null if it does not have exactly one
*/
public @Nullable MemberType getSoleSuperType() {
if (superTypeRelationships.size() != 1) {
return null;
}

Set<MemberType> onlySet = superTypeRelationships.keySet().iterator().next();
return onlySet.size() == 1 ? onlySet.iterator().next() : null;
}

/**
* Returns the number of distinct supertype constraints recorded for this type.
*
* @return how many separate supertypes this type has been required to have
*/
public int getSuperTypeCount() {
return superTypeRelationships.size();
}

/**
* Checks to see if the given superType is in any mutually exclusive set key of the
* superTypeRelationships map.
Expand Down
Loading
Loading