diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 84d9ba6f..5d971e9e 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -427,7 +427,10 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is } } - auto type = mModule->ResolveTypeRef(typeRef); + BfResolveTypeRefFlags resolveTypeRefFlags = BfResolveTypeRefFlag_AllowUnboundGeneric; + if (mResolveType == BfResolveType_VerifyTypeName) + resolveTypeRefFlags = (BfResolveTypeRefFlags)(resolveTypeRefFlags | BfResolveTypeRefFlag_ForceUnboundGeneric); + BfType* type = mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, resolveTypeRefFlags); if (type != NULL) { *isStatic = true; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 63306422..a5df0f4e 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -9211,6 +9211,7 @@ BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, cha resolvePassData.mResolveType = BfResolveType_Autocomplete; parser.mParserFlags = (BfParserFlag)(parser.mParserFlags | ParserFlag_Autocomplete); resolvePassData.mAutoComplete = new BfAutoComplete(); + resolvePassData.mAutoComplete->mResolveType = BfResolveType_VerifyTypeName; resolvePassData.mAutoComplete->mSystem = bfCompiler->mSystem; resolvePassData.mAutoComplete->mCompiler = bfCompiler; resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index fb47baac..f918cef2 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -10969,17 +10969,13 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr) } BfType* type; - if (auto genericTypeRef = BfNodeDynCast(typeOfExpr->mTypeRef)) - { - type = mModule->ResolveTypeRefAllowUnboundGenerics(typeOfExpr->mTypeRef, BfPopulateType_Identity); - } - else if ((typeOfExpr->mTypeRef != NULL) && (typeOfExpr->mTypeRef->IsA())) + if ((typeOfExpr->mTypeRef != NULL) && (typeOfExpr->mTypeRef->IsA())) { type = mModule->GetPrimitiveType(BfTypeCode_Var); } else { - type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGlobalsSelf); + type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGlobalsSelf | BfResolveTypeRefFlag_AllowUnboundGeneric)); } if (type == NULL) diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index c0169cad..9adf97c3 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -1877,6 +1877,7 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn auto _CheckType = [&](BfType* type) { StringImpl typeName = TypeToString(type); + for (int optionIdx = 0; optionIdx < (int)mContext->mSystem->mTypeOptions.size(); optionIdx++) { auto& typeOptions = mContext->mSystem->mTypeOptions[optionIdx]; @@ -5684,9 +5685,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if (((typeInstance->mAlwaysIncludeFlags & BfAlwaysIncludeFlag_AssumeInstantiated) != 0) && (methodDef->IsDefaultCtor())) implRequired = true; - - if ((typeOptionsIncludeAll) && (ApplyTypeOptionMethodFilters(true, methodDef, typeOptions))) - + if ((typeOptionsIncludeAll || typeOptionsIncludeFiltered) && (ApplyTypeOptionMethodFilters(typeOptionsIncludeAll, methodDef, typeOptions))) implRequired = true; @@ -9511,49 +9510,93 @@ bool BfModule::ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef) { if (qualifiedTypeRef->mLeft == NULL) return false; - - StringT<128> leftNameStr; - - BfType* leftType = NULL; - BfAtomComposite leftComposite; - - qualifiedTypeRef->mLeft->ToString(leftNameStr); - if (!mSystem->ParseAtomComposite(leftNameStr, leftComposite)) - return false; - + if (auto wildcardTypeRef = BfNodeDynCast(qualifiedTypeRef->mRight)) { + StringT<128> leftNameStr; + + BfType* leftType = NULL; + BfAtomComposite leftComposite; + + qualifiedTypeRef->mLeft->ToString(leftNameStr); + if (!mSystem->ParseAtomComposite(leftNameStr, leftComposite)) + return false; + if (mSystem->ContainsNamespace(leftComposite, NULL)) return true; return ValidateTypeWildcard(qualifiedTypeRef->mLeft, false); - } + } + } + + if (!BfNodeIsA(typeRef)) + { + if (auto elementedTypeRef = BfNodeDynCast(typeRef)) + { + return ValidateTypeWildcard(elementedTypeRef->mElementType, false); + } } - if (auto genericTypeRef = BfNodeDynCast(typeRef)) + BfAstNode* origTypeRef = typeRef; + + String name; + String nameEx; + int genericCount = 0; + std::function _ToString = [&](BfAstNode* typeRef, bool isLast) { - StringT<128> nameStr; - genericTypeRef->mElementType->ToString(nameStr); - - auto typeDef = mSystem->FindTypeDef(nameStr, (int)genericTypeRef->mGenericArguments.size(), NULL); - if (typeDef == NULL) - return false; - - if (typeDef->mGenericParamDefs.size() != genericTypeRef->GetGenericArgCount()) - return false; - - for (auto genericArgTypeRef : genericTypeRef->mGenericArguments) + if (auto qualifiedTypeRef = BfNodeDynCast(typeRef)) { - if ((genericTypeRef != NULL) && (!ValidateTypeWildcard(genericArgTypeRef, false))) - return false; + _ToString(qualifiedTypeRef->mLeft, false); + name.Append("."); + nameEx.Append("."); + _ToString(qualifiedTypeRef->mRight, typeRef == origTypeRef); + return true; + } + + if (auto genericTypeRef = BfNodeDynCast(typeRef)) + { + _ToString(genericTypeRef->mElementType, false); + genericCount += genericTypeRef->mCommas.mSize + 1; + for (auto genericArg : genericTypeRef->mGenericArguments) + if (!ValidateTypeWildcard(genericArg, false)) + return false; + } + else + { + typeRef->ToString(name); + typeRef->ToString(nameEx); + } + + if (genericCount > 0) + { + if (!isLast) + name += StrFormat("`%d", genericCount); + nameEx += StrFormat("`%d", genericCount); } return true; - } + }; - if (auto elementedTypeRef = BfNodeDynCast(typeRef)) + if (!_ToString(typeRef, true)) + return false; + + BfAtomComposite composite; + if (!mSystem->ParseAtomComposite(name, composite)) + return false; + + BfAtomComposite compositeEx; + if (!mSystem->ParseAtomComposite(nameEx, compositeEx)) + return false; + + auto itr = mSystem->mTypeDefs.TryGet(composite); + while (itr != mSystem->mTypeDefs.end()) { - return ValidateTypeWildcard(elementedTypeRef->mElementType, false); + auto typeDef = *itr; + if (typeDef->mFullName != composite) + break; + if (typeDef->mFullNameEx == compositeEx) + return true; + ++itr; } return false; @@ -10482,8 +10525,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } BfResolvedTypeSet::LookupContext lookupCtx; - lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError | - BfResolveTypeRefFlag_DisallowComptime | BfResolveTypeRefFlag_AllowInferredSizedArray | BfResolveTypeRefFlag_Attribute)); + lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & + (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError | BfResolveTypeRefFlag_DisallowComptime | + BfResolveTypeRefFlag_AllowInferredSizedArray | BfResolveTypeRefFlag_Attribute | BfResolveTypeRefFlag_AllowUnboundGeneric | + BfResolveTypeRefFlag_ForceUnboundGeneric)); lookupCtx.mRootTypeRef = typeRef; lookupCtx.mRootTypeDef = typeDef; lookupCtx.mModule = this; @@ -10909,6 +10954,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx); int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx); BF_ASSERT(refHash == typeHash); + BF_ASSERT(refHash == resolvedEntry->mHash); } if (!BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx)) { diff --git a/IDEHelper/Compiler/BfResolvePass.h b/IDEHelper/Compiler/BfResolvePass.h index 383a9db9..ad1eaa18 100644 --- a/IDEHelper/Compiler/BfResolvePass.h +++ b/IDEHelper/Compiler/BfResolvePass.h @@ -22,6 +22,7 @@ enum BfResolveType BfResolveType_GetTypeDefList, BfResolveType_GetTypeDefInto, BfResolveType_GetResultString, + BfResolveType_VerifyTypeName }; class BfLocalVariable; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index f39074ec..a44c3c0a 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3144,8 +3144,42 @@ void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupCon if (auto genericTypeRef = BfNodeDynCast(typeRef)) { - for (auto genericArg : genericTypeRef->mGenericArguments) - hashVal = HASH_MIX(hashVal, Hash(genericArg, ctx, BfHashFlag_AllowGenericParamConstValue, hashSeed + 1)); + for (int genericIdx = 0; genericIdx < BF_MAX(genericTypeRef->mGenericArguments.mSize, genericTypeRef->mCommas.mSize + 1); genericIdx++) + { + BfAstNode* genericArgTypeRef = NULL; + if (genericIdx < genericTypeRef->mGenericArguments.mSize) + genericArgTypeRef = genericTypeRef->mGenericArguments[genericIdx]; + + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_AllowUnboundGeneric) != 0) + { + if (BfNodeIsExact(genericArgTypeRef)) + genericArgTypeRef = NULL; + } + + int argHashVal = 0; + if (genericArgTypeRef != NULL) + { + argHashVal = Hash(genericArgTypeRef, ctx, BfHashFlag_AllowGenericParamConstValue, hashSeed + 1); + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_ForceUnboundGeneric) != 0) + genericArgTypeRef = NULL; + } + + if (genericArgTypeRef == NULL) + { + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_AllowUnboundGeneric) != 0) + { + argHashVal = (((int)BfGenericParamKind_Type + 0xB00) << 8) ^ (genericIdx + 1); + argHashVal = HASH_MIX(argHashVal, hashSeed + 1); + } + else + { + ctx->mFailed = true; + return; + } + } + + hashVal = HASH_MIX(hashVal, argHashVal); + } } } @@ -3767,6 +3801,11 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa ctx->mFailed = true; return 0; } + else if (auto wildcardTypeRef = BfNodeDynCastExact(typeRef)) + { + ctx->mFailed = true; + return 0; + } else { BF_FATAL("Not handled"); @@ -4033,13 +4072,45 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfType if (auto genericTypeRef = BfNodeDynCastExact(rhs)) { - if (genericTypeRef->mGenericArguments.size() > lhsTypeGenericArguments->size() + genericParamOffset) + int rhsGenericArgCount = BF_MAX(genericTypeRef->mGenericArguments.mSize, genericTypeRef->mCommas.mSize + 1); + + if (genericTypeRef->mGenericArguments.size() > rhsGenericArgCount + genericParamOffset) return false; - for (auto genericArg : genericTypeRef->mGenericArguments) + for (int genericIdx = 0; genericIdx < BF_MAX(genericTypeRef->mGenericArguments.mSize, genericTypeRef->mCommas.mSize + 1); genericIdx++) { - if (!Equals((*lhsTypeGenericArguments)[genericParamOffset++], genericArg, ctx)) - return false; + BfType* lhsArgType = (*lhsTypeGenericArguments)[genericParamOffset++]; + + BfAstNode* genericArgTypeRef = NULL; + if (genericIdx < genericTypeRef->mGenericArguments.mSize) + genericArgTypeRef = genericTypeRef->mGenericArguments[genericIdx]; + + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_ForceUnboundGeneric) != 0) + { + genericArgTypeRef = NULL; + } + else if ((ctx->mResolveFlags & BfResolveTypeRefFlag_AllowUnboundGeneric) != 0) + { + if (BfNodeIsExact(genericArgTypeRef)) + genericArgTypeRef = NULL; + } + + if (genericArgTypeRef == NULL) + { + if (lhsArgType->IsGenericParam()) + { + auto lhsGenericArgType = (BfGenericParamType*)lhsArgType; + if ((lhsGenericArgType->mGenericParamKind != BfGenericParamKind_Type) || (lhsGenericArgType->mGenericParamIdx != genericIdx)) + return false; + } + else + return false; + } + else + { + if (!Equals(lhsArgType, genericArgTypeRef, ctx)) + return false; + } } } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index f11da2bf..58c72a63 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -38,7 +38,9 @@ enum BfResolveTypeRefFlags BfResolveTypeRefFlag_AllowGlobalContainer = 0x4000, BfResolveTypeRefFlag_AllowInferredSizedArray = 0x8000, BfResolveTypeRefFlag_AllowGlobalsSelf = 0x10000, - BfResolveTypeRefFlag_AllowImplicitConstExpr = 0x20000 + BfResolveTypeRefFlag_AllowImplicitConstExpr = 0x20000, + BfResolveTypeRefFlag_AllowUnboundGeneric = 0x40000, + BfResolveTypeRefFlag_ForceUnboundGeneric = 0x80000 }; enum BfTypeNameFlags : uint16 diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index afd464d9..89c37973 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -2781,11 +2781,6 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) { BfLogSys(this, "InjectNewRevision from %p (decl:%p) into %p (decl:%p)\n", typeDef->mNextRevision, typeDef->mNextRevision->mTypeDeclaration, typeDef, typeDef->mTypeDeclaration); - if (typeDef->mName->ToString() == "Zonk") - { - NOP; - } - bool setDeclaringType = !typeDef->mIsCombinedPartial; auto nextTypeDef = typeDef->mNextRevision;