Skip to content

Commit

Permalink
Merge pull request #43758 from rdulmina/master
Browse files Browse the repository at this point in the history
Reset `unknownTypeRefs` after silent type checking
  • Loading branch information
rdulmina authored Feb 10, 2025
2 parents c44e140 + 9333af5 commit 5f26a7b
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ private void defineConstructs(BLangPackage pkgNode, SymbolEnv pkgEnv) {
}
}
}
typeResolver.clearUnknowTypeRefs();
typeResolver.clearUnknownTypeRefs();
}

private void defineDependentFields(List<BLangNode> typeDefNodes, SymbolEnv pkgEnv) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ public class TypeChecker extends SimpleBLangNodeAnalyzer<TypeChecker.AnalyzerDat
private final Types types;
private final Unifier unifier;
protected final QueryTypeChecker queryTypeChecker;
private final TypeResolver typeResolver;

static {
LIST_LENGTH_MODIFIER_FUNCTIONS.add(FUNCTION_NAME_PUSH);
Expand Down Expand Up @@ -324,6 +325,7 @@ public TypeChecker(CompilerContext context) {
this.missingNodesHelper = BLangMissingNodesHelper.getInstance(context);
this.unifier = new Unifier();
this.queryTypeChecker = QueryTypeChecker.getInstance(context);
this.typeResolver = TypeResolver.getInstance(context);
}

public TypeChecker(CompilerContext context, CompilerContext.Key<TypeChecker> key) {
Expand All @@ -343,6 +345,7 @@ public TypeChecker(CompilerContext context, CompilerContext.Key<TypeChecker> key
this.missingNodesHelper = BLangMissingNodesHelper.getInstance(context);
this.unifier = new Unifier();
this.queryTypeChecker = null;
this.typeResolver = TypeResolver.getInstance(context);
}

private BType checkExpr(BLangExpression expr, SymbolEnv env, AnalyzerData data) {
Expand Down Expand Up @@ -600,14 +603,13 @@ private BType silentIntTypeCheck(BLangLiteral literalExpr, Object literalValue,
AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

BType exprCompatibleType = getIntegerLiteralType(nodeCloner.cloneNode(literalExpr), literalValue, expType,
data);
data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);

if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
Expand Down Expand Up @@ -1224,7 +1226,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr, AnalyzerData d

boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int errorCount = this.dlog.errorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

List<BType> matchingTypes = new ArrayList<>();
Expand All @@ -1246,7 +1248,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr, AnalyzerData d
}

data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
this.dlog.setErrorCount(errorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -1803,7 +1805,7 @@ private BType checkListConstructorCompatibility(BType referredType, BType origin
int tag = referredType.tag;
if (tag == TypeTags.UNION) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
int errorCount = this.dlog.errorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
data.commonAnalyzerData.nonErrorLoggingCheck = true;
this.dlog.mute();

Expand Down Expand Up @@ -1832,7 +1834,7 @@ private BType checkListConstructorCompatibility(BType referredType, BType origin
}

data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
this.dlog.setErrorCount(errorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -2545,7 +2547,7 @@ public BType checkMappingConstructorCompatibility(BType bType, BLangRecordLitera
if (tag == TypeTags.UNION) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int errorCount = this.dlog.errorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

List<BType> compatibleTypes = new ArrayList<>();
Expand Down Expand Up @@ -2574,7 +2576,7 @@ public BType checkMappingConstructorCompatibility(BType bType, BLangRecordLitera
}

data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
dlog.setErrorCount(errorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -3928,13 +3930,13 @@ private void validateErrorConstructorPositionalArgs(BLangErrorConstructorExpr er
protected BType checkExprSilent(BLangExpression expr, BType expType, AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int errorCount = this.dlog.errorCount();
this.dlog.mute();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();

BType type = checkExpr(expr, expType, data);

data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
dlog.setErrorCount(errorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -5469,15 +5471,14 @@ public boolean isOptionalFloatOrDecimal(BType expectedType) {
private BType checkAndGetType(BLangExpression expr, SymbolEnv env, BLangBinaryExpr binaryExpr, AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

expr.cloneAttempt++;
BType exprCompatibleType = checkExpr(nodeCloner.cloneNode(expr), env, binaryExpr.expectedType, data);
data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
int errorCount = this.dlog.errorCount();
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -5731,26 +5732,26 @@ public boolean silentCompatibleFiniteMembersInUnionTypeCheck(BLangUnaryExpr unar
AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

BType compatibleTypeOfUnaryExpression;
for (BType type : expectedType.getMemberTypes()) {
compatibleTypeOfUnaryExpression = checkExpr(nodeCloner.cloneNode(unaryExpr), Types.getImpliedType(type),
data);
if (Types.getImpliedType(compatibleTypeOfUnaryExpression).tag == TypeTags.FINITE) {
unmuteDlog(data, prevNonErrorLoggingCheck, prevErrorCount);
unmuteDlog(data, prevNonErrorLoggingCheck, previousGlobalState);
return true;
}
}
unmuteDlog(data, prevNonErrorLoggingCheck, prevErrorCount);
unmuteDlog(data, prevNonErrorLoggingCheck, previousGlobalState);
return false;
}

private void unmuteDlog(AnalyzerData data, boolean prevNonErrorLoggingCheck, int prevErrorCount) {
private void unmuteDlog(AnalyzerData data, boolean prevNonErrorLoggingCheck,
GlobalStateSnapshot previousGlobalState) {
data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand All @@ -5759,13 +5760,12 @@ private void unmuteDlog(AnalyzerData data, boolean prevNonErrorLoggingCheck, int
public BType silentTypeCheckExpr(BLangExpression expr, BType referredType, AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

BType exprCompatibleType = checkExpr(nodeCloner.cloneNode(expr), referredType, data);

unmuteDlog(data, prevNonErrorLoggingCheck, prevErrorCount);
unmuteDlog(data, prevNonErrorLoggingCheck, previousGlobalState);
return exprCompatibleType;
}

Expand Down Expand Up @@ -5823,14 +5823,13 @@ public void visit(BLangTypeConversionExpr conversionExpr, AnalyzerData data) {

boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

BType exprCompatibleType = checkExpr(nodeCloner.cloneNode(expr), targetType, data);
data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
int errorCount = this.dlog.errorCount();
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);

if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
Expand Down Expand Up @@ -6609,9 +6608,8 @@ private BType getCandidateLaxType(BLangNode expr, BType rhsType) {
private BType getCandidateType(BLangCheckedExpr checkedExpr, BType checkExprCandidateType, AnalyzerData data) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
this.dlog.mute();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();

checkedExpr.expr.cloneAttempt++;
BLangExpression clone = nodeCloner.cloneNode(checkedExpr.expr);
Expand All @@ -6622,7 +6620,7 @@ private BType getCandidateType(BLangCheckedExpr checkedExpr, BType checkExprCand
rhsType = checkExpr(clone, checkExprCandidateType, data);
}
data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);
if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
}
Expand Down Expand Up @@ -8243,15 +8241,14 @@ private List<BLangExpression> concatSimilarKindXMLNodes(List<BLangExpression> ex
for (BLangExpression expr : exprs) {
boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck;
data.commonAnalyzerData.nonErrorLoggingCheck = true;
int prevErrorCount = this.dlog.errorCount();
this.dlog.resetErrorCount();
GlobalStateSnapshot previousGlobalState = getGlobalStateSnapshotAndResetGlobalState();
this.dlog.mute();

BType exprType = checkExpr(nodeCloner.cloneNode(expr), xmlElementEnv, symTable.xmlType, data);

data.commonAnalyzerData.nonErrorLoggingCheck = prevNonErrorLoggingCheck;
int errorCount = this.dlog.errorCount();
this.dlog.setErrorCount(prevErrorCount);
restoreGlobalState(previousGlobalState);

if (!prevNonErrorLoggingCheck) {
this.dlog.unmute();
Expand Down Expand Up @@ -9918,6 +9915,23 @@ String recordsToString(Set<BRecordType> recordTypeSet) {
}
}

public GlobalStateSnapshot getGlobalStateSnapshotAndResetGlobalState() {
// Preserve global state
GlobalStateSnapshot globalStateSnapshot = new GlobalStateSnapshot(typeResolver.getUnknownTypeRefs(),
this.dlog.errorCount());

// Reset global state
typeResolver.setUnknownTypeRefs(new HashSet<>());
this.dlog.resetErrorCount();

return globalStateSnapshot;
}

public void restoreGlobalState(GlobalStateSnapshot globalStateSnapshot) {
typeResolver.setUnknownTypeRefs(globalStateSnapshot.unknownTypeRefs);
this.dlog.setErrorCount(globalStateSnapshot.errorCount);
}

/**
* @since 2.0.0
*/
Expand All @@ -9933,4 +9947,13 @@ public static class AnalyzerData {
QueryTypeChecker.AnalyzerData queryData = new QueryTypeChecker.AnalyzerData();
Set<String> queryVariables;
}

/**
* This record is used to hold a snapshot of the global fields of multiple class objects.
* @param unknownTypeRefs current unknownTypeRefs set
* @param errorCount current errorCount
* @since 2201.12.0
*/
public record GlobalStateSnapshot(HashSet<TypeResolver.LocationData> unknownTypeRefs, int errorCount) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public class TypeResolver {
private final HashSet<BLangClassDefinition> resolvedClassDef = new HashSet<>();
private final Map<String, BLangNode> modTable = new LinkedHashMap<>();
private final Map<String, BLangConstantValue> constantMap = new HashMap<>();
private final HashSet<LocationData> unknownTypeRefs;
private HashSet<LocationData> unknownTypeRefs;
private SymbolEnv pkgEnv;
private int currentDepth;
private Deque<BType> resolvingTypes;
Expand All @@ -188,7 +188,7 @@ public TypeResolver(CompilerContext context) {
this.unknownTypeRefs = new HashSet<>();
}

public void clearUnknowTypeRefs() {
public void clearUnknownTypeRefs() {
unknownTypeRefs.clear();
}

Expand All @@ -211,6 +211,14 @@ public static TypeResolver getInstance(CompilerContext context) {
return typeResolver;
}

public HashSet<LocationData> getUnknownTypeRefs() {
return unknownTypeRefs;
}

public void setUnknownTypeRefs(HashSet<LocationData> unknownTypeRefs) {
this.unknownTypeRefs = unknownTypeRefs;
}

public void defineBTypes(List<BLangNode> moduleDefs, SymbolEnv pkgEnv) {
this.pkgEnv = pkgEnv;
typePrecedence = 0;
Expand Down Expand Up @@ -2133,7 +2141,7 @@ private static class ResolverData {
*
* @since 2201.7.0
*/
private static class LocationData {
protected static class LocationData {
private final String name;
private final int row;
private final int column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ public void testSemanticsNegative() {
"'function () returns (int)', found 'function () returns (MyTuple)'", 37, 33);
BAssertUtil.validateError(compileResult, index++, "incompatible types: expected 'Foo', found 'string'", 43, 13);

BAssertUtil.validateError(compileResult, index++, "unknown type 'I'", 48, 19);
BAssertUtil.validateError(compileResult, index++, "unknown type 'I'", 52, 35);
BAssertUtil.validateError(compileResult, index++, "unknown type 'J'", 54, 17);
BAssertUtil.validateError(compileResult, index++, "unknown type 'J'", 56, 22);
BAssertUtil.validateError(compileResult, index++, "unknown type 'J'", 58, 23);

Assert.assertEquals(compileResult.getErrorCount(), index);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ type Foo boolean|null;
function testNullFiniteType() {
Foo _ = "null"; // error
}

class H {};

H res = check new I();

int[] a = [1, 2, 3, 4, 5];

int[] b = from var i in a select <I> i;

float result = <J>1 + 2.0;

int result2 = true? <J>1 : 2;

var result3 = <H> new J();

0 comments on commit 5f26a7b

Please sign in to comment.