diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 8e3ec28f..e1cf8450 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -4947,7 +4947,7 @@ namespace IDE.ui { if (mHoverResolveTask == null) { - if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning)) + if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning) && (gApp.mSettings.mEditorSettings.mHiliteCursorReferences)) { ResolveParams resolveParams = new .(); resolveParams.mOverrideCursorPos = (int32)textIdx; diff --git a/IDEHelper/Backend/BeCOFFObject.cpp b/IDEHelper/Backend/BeCOFFObject.cpp index 54896ff8..8c9026b3 100644 --- a/IDEHelper/Backend/BeCOFFObject.cpp +++ b/IDEHelper/Backend/BeCOFFObject.cpp @@ -1986,6 +1986,12 @@ void BeCOFFObject::Generate(BeModule* module) { auto globalVar = module->mGlobalVariables[globalVarIdx]; + if ((globalVar->mRefCount == 0) && (globalVar->mInitializer == NULL)) + { + globalVarSyms.push_back(NULL); + continue; + } + BeMCSymbol* sym = mSymbols.Alloc(); sym->mType = globalVar->mType; sym->mName = globalVar->mName; @@ -2001,6 +2007,10 @@ void BeCOFFObject::Generate(BeModule* module) for (int globalVarIdx = 0; globalVarIdx < (int)module->mGlobalVariables.size(); globalVarIdx++) { auto globalVar = module->mGlobalVariables[globalVarIdx]; + + if ((globalVar->mRefCount == 0) && (globalVar->mInitializer == NULL)) + continue; + auto sym = globalVarSyms[globalVarIdx]; if (globalVar->mInitializer != NULL) diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 76938100..67967e0f 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -710,6 +710,7 @@ void BeIRCodeGen::Read(BeValue*& beValue) } else beValue = GetBeValue(streamId); + beValue->mRefCount++; BE_MEM_END("ParamType_Const_GlobalVar"); return; } diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index bd01820e..2b7a57c8 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -291,7 +291,7 @@ void BfStructuralVisitor::Visit(BfDelegateTypeRef* typeRef) Visit(typeRef->ToBase()); } -void BfStructuralVisitor::Visit(BfDeclTypeRef* declTypeRef) +void BfStructuralVisitor::Visit(BfExprModTypeRef* declTypeRef) { Visit(declTypeRef->ToBase()); } @@ -1307,6 +1307,8 @@ const char* Beefy::BfTokenToString(BfToken token) return "checked"; case BfToken_Class: return "class"; + case BfToken_Comptype: + return "comptype"; case BfToken_Concrete: return "concrete"; case BfToken_Const: diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index fd5cc823..93fe73c1 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -122,6 +122,7 @@ enum BfToken : uint8 BfToken_Catch, BfToken_Checked, BfToken_Class, + BfToken_Comptype, BfToken_Concrete, BfToken_Const, BfToken_Continue, @@ -308,7 +309,7 @@ class BfLetTypeReference; class BfGenericInstanceTypeRef; class BfTupleTypeRef; class BfDelegateTypeRef; -class BfDeclTypeRef; +class BfExprModTypeRef; class BfCommentNode; class BfIfStatement; class BfParenthesizedExpression; @@ -473,8 +474,8 @@ public: virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef); - virtual void Visit(BfDelegateTypeRef* typeRef); - virtual void Visit(BfDeclTypeRef* declTypeRef); + virtual void Visit(BfDelegateTypeRef* typeRef); + virtual void Visit(BfExprModTypeRef* declTypeRef); virtual void Visit(BfPointerTypeRef* typeRef); virtual void Visit(BfNullableTypeRef* typeRef); virtual void Visit(BfVariableDeclaration* varDecl); @@ -2543,16 +2544,16 @@ public: BfAstNode* mCloseParen; }; BF_AST_DECL(BfDelegateTypeRef, BfTypeReference); -class BfDeclTypeRef : public BfTypeReference +class BfExprModTypeRef : public BfTypeReference { public: - BF_AST_TYPE(BfDeclTypeRef, BfTypeReference); + BF_AST_TYPE(BfExprModTypeRef, BfTypeReference); BfTokenNode* mToken; BfTokenNode* mOpenParen; BfExpression* mTarget; BfTokenNode* mCloseParen; -}; BF_AST_DECL(BfDeclTypeRef, BfTypeReference); +}; BF_AST_DECL(BfExprModTypeRef, BfTypeReference); enum BfGenericParamKind { diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index fe29f6c4..aadc5ae0 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -1708,6 +1708,8 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken // Statics, inner types auto checkType = targetValue.mType; + if (checkType->IsConcreteInterfaceType()) + checkType = checkType->GetUnderlyingType(); if (checkType->IsGenericParam()) { diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 0810f8bc..573e6be9 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -7296,7 +7296,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) if ((mCEMachine != NULL) && (!mIsResolveOnly) && (mCEMachine->mRevisionExecuteTime > 0)) { - mPassInstance->OutputLine(StrFormat(":med Const evaluation time: %0.2fs", mCEMachine->mRevisionExecuteTime / 1000.0f)); + mPassInstance->OutputLine(StrFormat(":med Comptime execution time: %0.2fs", mCEMachine->mRevisionExecuteTime / 1000.0f)); } BpLeave(); diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 04d6936b..0c76c570 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -103,7 +103,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo wantIgnoreWrites = true; } - SetAndRestoreValue ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites); + SetAndRestoreValue prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites); auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock(); @@ -139,7 +139,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo { if ((flags & BfConstResolveFlag_RemapFromStringId) != 0) { - ignoreWrites.Restore(); + prevIgnoreWrites.Restore(); mModule->mBfIRBuilder->PopulateType(mResult.mType); return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType); } @@ -203,7 +203,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo { auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue); if ((constant->mConstType == BfConstType_GlobalVar) && ((mBfEvalExprFlags & BfConstResolveFlag_AllowGlobalVariable) != 0)) - isConst = false; + isConst = false; } if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0)) @@ -232,6 +232,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo }*/ mModule->FixIntUnknown(mResult); + mModule->FixValueActualization(mResult); return mResult; } diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index fc64eee1..ab8a8fa6 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -44,6 +44,7 @@ BfContext::BfContext(BfCompiler* compiler) : mMappedObjectRevision = 0; mDeleting = false; mLockModules = false; + mAllowLockYield = true; mCurTypeState = NULL; mCurConstraintState = NULL; @@ -255,9 +256,15 @@ void BfContext::EnsureHotMangledVirtualMethodNames() } } +void BfContext::CheckLockYield() +{ + if (mAllowLockYield) + mSystem->CheckLockYield(); +} + bool BfContext::IsCancellingAndYield() { - mSystem->CheckLockYield(); + CheckLockYield(); return mCompiler->mCanceling; } diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index cdcb1c97..e210cb0c 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -309,6 +309,8 @@ public: BfType* mLeftType; BfType* mRightType; BfConstraintState* mPrevState; + BfMethodInstance* mMethodInstance; + BfTypeVector* mMethodGenericArgsOverride; public: BfConstraintState() @@ -316,6 +318,8 @@ public: mGenericParamInstance = NULL; mLeftType = NULL; mRightType = NULL; + mMethodInstance = NULL; + mMethodGenericArgsOverride = NULL; mPrevState = NULL; } @@ -343,6 +347,7 @@ public: BfSystem* mSystem; BfCompiler* mCompiler; + bool mAllowLockYield; bool mLockModules; BfModule* mScratchModule; BfModule* mUnreifiedModule; @@ -433,6 +438,7 @@ public: void ReportMemory(MemReporter* memReporter); void ProcessMethod(BfMethodInstance* methodInstance); int GetStringLiteralId(const StringImpl& str); + void CheckLockYield(); bool IsCancellingAndYield(); void QueueFinishModule(BfModule * module); void CancelWorkItems(); diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 8378ed16..bd0da9e9 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -414,7 +414,7 @@ void BfElementVisitor::Visit(BfTupleTypeRef* typeRef) VisitChild(typeRef->mCloseParen); } -void BfElementVisitor::Visit(BfDeclTypeRef* typeRef) +void BfElementVisitor::Visit(BfExprModTypeRef* typeRef) { Visit(typeRef->ToBase()); diff --git a/IDEHelper/Compiler/BfElementVisitor.h b/IDEHelper/Compiler/BfElementVisitor.h index 4d3d91a7..a72f3cd7 100644 --- a/IDEHelper/Compiler/BfElementVisitor.h +++ b/IDEHelper/Compiler/BfElementVisitor.h @@ -61,7 +61,7 @@ public: virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef); - virtual void Visit(BfDeclTypeRef* typeRef); + virtual void Visit(BfExprModTypeRef* typeRef); virtual void Visit(BfDelegateTypeRef* typeRef); virtual void Visit(BfPointerTypeRef* typeRef); virtual void Visit(BfNullableTypeRef* typeRef); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 09a9ce34..b9062b9a 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -588,54 +588,41 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc return true; } +bool BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx) +{ + auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx]; + if (srcGenericArg == NULL) + return false; + + int startInferCount = mInferredCount; + + auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx]; + for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints) + { + if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance())) + { + InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue()); + auto typeInstance = srcGenericArg->ToTypeInstance(); + if (typeInstance != NULL) + { + for (auto ifaceEntry : typeInstance->mInterfaces) + InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue()); + } + } + } + + return mInferredCount != startInferCount; +} + void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance) { // Attempt to infer from other generic args for (int srcGenericIdx = 0; srcGenericIdx < (int)mCheckMethodGenericArguments->size(); srcGenericIdx++) { - auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx]; - if (srcGenericArg == NULL) - continue; - - auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx]; - for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints) - { - if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance())) - { - InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue()); - auto typeInstance = srcGenericArg->ToTypeInstance(); - if (typeInstance != NULL) - { - for (auto ifaceEntry : typeInstance->mInterfaces) - InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue()); - } - } - } + InferGenericArguments(methodInstance, srcGenericIdx); } } -// void BfGenericInferContext::PropogateInference(BfType* resolvedType, BfType* unresovledType) -// { -// if (!unresovledType->IsUnspecializedTypeVariation()) -// return; -// -// auto resolvedTypeInstance = resolvedType->ToTypeInstance(); -// auto unresolvedTypeInstance = unresovledType->ToTypeInstance(); -// -// if ((resolvedTypeInstance == NULL) || (unresolvedTypeInstance == NULL)) -// return; -// if (resolvedTypeInstance->mTypeDef != unresolvedTypeInstance->mTypeDef) -// return; -// -// if (unres) -// -// if (resolvedType->IsGenericTypeInstance()) -// { -// -// -// } -// } - int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs) { if ((lhs->IsRef()) && (rhs->IsRef())) @@ -1440,10 +1427,10 @@ bool BfMethodMatcher::WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInst return true; } -bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs) +bool BfMethodMatcher::InferFromGenericConstraints(BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs) { - if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0) - return false; +// if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0) +// return false; if (!genericParamInst->mExternType->IsGenericParam()) return false; @@ -1490,6 +1477,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi if (checkOpConstraint.mBinaryOp != BfBinaryOp_None) { + if ((leftType == NULL) || (rightType == NULL)) + continue; + BfExprEvaluator exprEvaluator(mModule); BfTypedValue leftValue(mModule->mBfIRBuilder->GetFakeVal(), leftType); @@ -1507,6 +1497,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi } else { + if (rightType == NULL) + continue; + BfTypedValue rightValue(mModule->mBfIRBuilder->GetFakeVal(), rightType); StringT<128> failedOpName; @@ -1537,6 +1530,28 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi } } + if ((checkArgType == NULL) && ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_ComptypeExpr) != 0)) + { + for (auto comptypeConstraint : genericParamInst->mComptypeConstraint) + { + BfConstraintState constraintSet; + constraintSet.mPrevState = mModule->mContext->mCurConstraintState; + constraintSet.mGenericParamInstance = genericParamInst; + constraintSet.mMethodInstance = methodInstance; + constraintSet.mMethodGenericArgsOverride = methodGenericArgs; + + SetAndRestoreValue prevConstraintSet(mModule->mContext->mCurConstraintState, &constraintSet); + if (!mModule->CheckConstraintState(NULL)) + return false; + + SetAndRestoreValue prevMethodInstance(mModule->mCurMethodInstance, methodInstance); + SetAndRestoreValue prevTypeInstance(mModule->mCurTypeInstance, methodInstance->GetOwner()); + SetAndRestoreValue prevIgnoreErrors(mModule->mIgnoreErrors, true); + + checkArgType = mModule->ResolveTypeRef(comptypeConstraint); + } + } + if (checkArgType == NULL) return false; if (checkArgType->IsVar()) @@ -1857,23 +1872,55 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst } paramIdx++; - } - } - - // - for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++) - { - auto& genericArg = mCheckMethodGenericArguments[genericArgIdx]; - if (genericArg == NULL) - { - auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx]; - InferFromGenericConstraints(genericParam, &mCheckMethodGenericArguments); - if (genericArg != NULL) - continue; - if (!allowEmptyGenericSet.Contains(genericArgIdx)) - goto NoMatch; } } + +// while (true) +// { +// +// } + + // + + bool failed = false; + bool inferredAllGenericArguments = false; + for (int pass = 0; true; pass++) + { + bool madeProgress = false; + bool hasUninferred = false; + failed = false; + + for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++) + { + auto& genericArg = mCheckMethodGenericArguments[genericArgIdx]; + if (genericArg == NULL) + { + auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx]; + InferFromGenericConstraints(methodInstance, genericParam, &mCheckMethodGenericArguments); + if (genericArg != NULL) + { + if (inferredAllGenericArguments) + genericInferContext.InferGenericArguments(methodInstance, genericArgIdx); + madeProgress = true; + } + hasUninferred = true; + if (!allowEmptyGenericSet.Contains(genericArgIdx)) + failed = true; + } + } + + if (!hasUninferred) + break; + if (inferredAllGenericArguments) + { + if (!madeProgress) + break; + } + genericInferContext.InferGenericArguments(methodInstance); + inferredAllGenericArguments = true; + } + if (failed) + goto NoMatch; } if (checkMethod->mMethodType == BfMethodType_Extension) @@ -2538,7 +2585,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori if ((mModule->mCompiler->IsAutocomplete()) || (mModule->mContext->mResolvingVarField)) return; - if (mModule->mBfIRBuilder->mIgnoreWrites) + if ((mModule->mBfIRBuilder->mIgnoreWrites) && (!mBestMethodDef->mIsConcrete)) return; if (mBestMethodTypeInstance->IsInterface()) @@ -5169,6 +5216,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* auto _GetDefaultReturnValue = [&]() { + if (methodInstance->mVirtualTableIdx == -1) + { + if (methodInstance->GetOwner()->IsInterface()) + { + // We're attempting to directly invoke a non-virtual interface method, if we're return an interface then + // it is a concrete interface + if (returnType->IsInterface()) + returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance()); + } + } + if ((returnType->IsVar()) && (mExpectingType != NULL)) returnType = mExpectingType; if (returnType->IsRef()) @@ -5241,19 +5299,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* if (wantQuickEval) { // In an autocomplete pass we may have stale method references that need to be resolved - // in the full classify pass, and in the full classify pass while just refreshing internals, we - // may have NULL funcs temporarily. We simply skip generating the method call here. - if (methodInstance->mVirtualTableIdx == -1) - { - if (methodInstance->GetOwner()->IsInterface()) - { - // We're attempting to directly invoke a non-virtual interface method, if we're return an interface then - // it is a concrete interface - if (returnType->IsInterface()) - returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance()); - } - } - + // in the full classify pass, and in the full classify pass while just refreshing internals, we + // may have NULL funcs temporarily. We simply skip generating the method call here. if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) { if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) @@ -5348,6 +5395,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* } else { + if (returnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) + { + if (mExpectingType->IsUndefSizedArray()) + { + if (returnType->GetUnderlyingType() == mExpectingType->GetUnderlyingType()) + return mModule->GetDefaultTypedValue(mExpectingType, true, BfDefaultValueKind_Undef); + } + } + return mModule->GetDefaultTypedValue(returnType, true, BfDefaultValueKind_Undef); } @@ -6148,7 +6204,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (!mModule->mCompiler->mIsResolveOnly) sCallIdx++; int callIdx = sCallIdx; - if (callIdx == 1177) + if (callIdx == 0x000020F9) { NOP; } @@ -7594,8 +7650,7 @@ bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfR { mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc); success = false; - } - + } return success; } @@ -7618,9 +7673,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp BF_ASSERT(!mFunctionBindResult->mOrigTarget); mFunctionBindResult->mOrigTarget = origTarget; } - + if (target) { + if (target.mType->IsConcreteInterfaceType()) + target.mType = target.mType->GetUnderlyingType(); + // Turn T* into a T, if we can if ((target.mType->IsPointer()) && (target.mType->GetUnderlyingType()->IsGenericParam())) { @@ -9790,7 +9848,6 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr) } mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); - mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType); } @@ -15580,6 +15637,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m } } } + else if (expectingType->IsVar()) + { + // Silently allow + gaveUnqualifiedDotError = true; + } else { gaveUnqualifiedDotError = true; diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 8401d157..1b1f8b6e 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -142,6 +142,7 @@ public: { return (int)mCheckMethodGenericArguments->size() - mInferredCount; } + bool InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx); void InferGenericArguments(BfMethodInstance* methodInstance); }; @@ -212,7 +213,7 @@ public: public: BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType = NULL, BfResolveArgFlags flags = BfResolveArgFlag_None); - bool InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs); + bool InferFromGenericConstraints(BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs); void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute, BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute, bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 37f6d256..fcbc5c67 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3962,7 +3962,7 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance* BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfFieldDef* field) { - bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact(field->mFieldDeclaration->mTypeRef) != NULL; + bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact(field->mFieldDeclaration->mTypeRef) != NULL; auto fieldType = fieldInstance->GetResolvedType(); if ((field->mIsConst) && (!isDeclType)) @@ -7280,9 +7280,16 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar else { bool checkEquality = false; - - if (constraintType->IsPrimitiveType()) + + if (constraintType->IsVar()) { + // From a `comptype` generic undef resolution. Ignore. + genericParamInstance->mGenericParamFlags |= BfGenericParamFlag_ComptypeExpr; + genericParamInstance->mComptypeConstraint.Add(constraintTypeRef); + continue; + } + else if (constraintType->IsPrimitiveType()) + { if (isUnspecialized) { Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef); @@ -7336,7 +7343,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar { auto constraintTypeInst = constraintType->ToTypeInstance(); if (genericParamInstance->mTypeConstraint != NULL) - { + { if ((constraintTypeInst != NULL) && (TypeIsSubTypeOf(constraintTypeInst, genericParamInstance->mTypeConstraint->ToTypeInstance(), false))) { // Allow more specific type @@ -8079,6 +8086,8 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, if ((flags & BfEvalExprFlags_AllowIntUnknown) == 0) FixIntUnknown(typedVal); + if (!mBfIRBuilder->mIgnoreWrites) + FixValueActualization(typedVal); exprEvaluator.CheckResultForReading(typedVal); if ((wantTypeRef == NULL) || (!wantTypeRef->IsRef())) @@ -8098,7 +8107,7 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, if (!allowRef) typedVal = RemoveRef(typedVal); } - } + } if ((!typedVal.mType->IsComposite()) && (!typedVal.mType->IsGenericParam())) // Load non-structs by default { @@ -8115,7 +8124,7 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, if (outOrigType != NULL) *outOrigType = typedVal.mType; - if ((flags & BfEvalExprFlags_NoCast) == 0) + if (((flags & BfEvalExprFlags_NoCast) == 0) && (!wantTypeRef->IsVar())) { BfCastFlags castFlags = ((flags & BfEvalExprFlags_ExplicitCast) != 0) ? BfCastFlags_Explicit : BfCastFlags_None; if ((flags & BfEvalExprFlags_FieldInitializer) != 0) @@ -8125,9 +8134,6 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, return typedVal; } - //WTF- why did we have this? - /*if ((flags & BfEvalExprFlags_ExplicitCast) == 0) - typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);*/ if (exprEvaluator.mIsVolatileReference) typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference); } @@ -13252,9 +13258,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM // if ((flags & BfGetMethodInstanceFlag_NoReference) != 0) // addToWorkList = false; - - declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList); - + + declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList); + if (processNow) { SetAndRestoreValue prevMethodState(mCurMethodState, NULL); @@ -13805,6 +13811,16 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli isByAddr = true; } + if (diValue.IsConst()) + { + auto constant = mBfIRBuilder->GetConstant(diValue); + if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData)) + { + // Ignore for now + return; + } + } + auto diType = mBfIRBuilder->DbgGetType(localVarDef->mResolvedType); bool didConstToMem = false; @@ -13882,7 +13898,7 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli if (isByAddr) localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertDeclare(diValue, diVariable, declareBefore); else if (diValue) - { + { localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(diValue, diVariable); } else if (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU) // DWARF chokes on this: @@ -17390,7 +17406,7 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx) } delete deferredLocalMethod; - mSystem->CheckLockYield(); + mContext->CheckLockYield(); } } @@ -17455,7 +17471,7 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx) } } - mSystem->CheckLockYield(); + mContext->CheckLockYield(); } } @@ -21169,7 +21185,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool // We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here // to effectively make mIgnoreWrites method-scoped SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized || mCurTypeInstance->mResolvingVarField); - SetAndRestoreValue prevIsCapturingMethodMatchInfo; + SetAndRestoreValue prevIsCapturingMethodMatchInfo; + SetAndRestoreValue prevAllowLockYield(mContext->mAllowLockYield, false); SetAndRestoreValue prevMethodState(mCurMethodState, NULL); if (mCompiler->IsAutocomplete()) prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false); @@ -21314,28 +21331,18 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool else { auto externConstraintDef = genericParam->GetExternConstraintDef(); - -// if (unspecializedTypeInstance == NULL) -// unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance); -// -// // Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg -// { -// SetAndRestoreValue prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance); -// genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); -// } - genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); auto autoComplete = mCompiler->GetAutoComplete(); -if (autoComplete != NULL) -autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false); + if (autoComplete != NULL) + autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false); -if (genericParam->mExternType != NULL) -{ - // -} -else -genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); + if (genericParam->mExternType != NULL) + { + // + } + else + genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); } ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized); @@ -21486,7 +21493,8 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric); - if (((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) && (methodDef->mReturnTypeRef->IsA())) + if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod)) + && (methodDef->mReturnTypeRef->IsA())) resolvedReturnType = GetPrimitiveType(BfTypeCode_Var); else resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 6ff53a32..e9f01017 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1762,6 +1762,7 @@ public: BfType* FixIntUnknown(BfType* type); void FixIntUnknown(BfTypedValue& typedVal, BfType* matchType = NULL); void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs); + void FixValueActualization(BfTypedValue& typedVal); bool TypeEquals(BfTypedValue& val, BfType* type); BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index e6aec8c3..67bac363 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3515,7 +3515,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy fieldInstance->mIsEnumPayloadCase = true; } } - else if ((field->mTypeRef != NULL) && ((field->mTypeRef->IsExact()) || (field->mTypeRef->IsExact()) || (field->mTypeRef->IsExact()))) + else if ((field->mTypeRef != NULL) && ((field->mTypeRef->IsExact()) || (field->mTypeRef->IsExact()) || (field->mTypeRef->IsExact()))) { resolvedFieldType = GetPrimitiveType(BfTypeCode_Var); @@ -5153,7 +5153,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField)) { disableYield.Release(); - mSystem->CheckLockYield(); + mContext->CheckLockYield(); disableYield.Acquire(); } } @@ -6258,6 +6258,21 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs) FixIntUnknown(rhs); } +void BfModule::FixValueActualization(BfTypedValue& typedVal) +{ + if (!typedVal.mValue.IsConst()) + return; + if (mBfIRBuilder->mIgnoreWrites) + return; + auto constant = mBfIRBuilder->GetConstant(typedVal.mValue); + if (constant->mConstType == BfConstType_TypeOf) + { + auto constTypeOf = (BfTypeOf_Const*)constant; + AddDependency(constTypeOf->mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); + typedVal.mValue = CreateTypeDataRef(constTypeOf->mType); + } +} + BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode) { BfTypeInstance* typeInst = NULL; @@ -7858,7 +7873,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy { baseNode = qualifiedNameNode->mRight; } - else if (auto declTypeRef = BfNodeDynCast(baseNode)) + else if (auto declTypeRef = BfNodeDynCast(baseNode)) { baseNode = NULL; break; @@ -8868,6 +8883,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula return GetGenericParamType(BfGenericParamKind_Method, genericParamIdx); else { + if ((mContext->mCurConstraintState != NULL) && (mContext->mCurConstraintState->mMethodInstance == checkMethodInstance) && + (mContext->mCurConstraintState->mMethodGenericArgsOverride != NULL)) + { + return ResolveTypeResult(typeRef, (*mContext->mCurConstraintState->mMethodGenericArgsOverride)[genericParamIdx], populateType, resolveFlags); + } + SetAndRestoreValue prevSymbolRefKind; if (mCompiler->mResolvePassData != NULL) // Don't add these typeRefs, they are indirect prevSymbolRefKind.Init(mCompiler->mResolvePassData->mGetSymbolReferenceKind, BfGetSymbolReferenceKind_None); @@ -9334,10 +9355,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula lookupCtx.mRootTypeDef = typeDef; lookupCtx.mModule = this; BfResolvedTypeSet::Entry* resolvedEntry = NULL; - auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry); - + auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry); + if (resolvedEntry == NULL) - { + { + if (lookupCtx.mHadVar) + return ResolveTypeResult(typeRef, GetPrimitiveType(BfTypeCode_Var), populateType, resolveFlags); return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); } @@ -9620,7 +9643,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula for (auto genericArgRef : genericArguments) { auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue)); - if (genericArg == NULL) + if ((genericArg == NULL) || (genericArg->IsVar())) { mContext->mResolvedTypes.RemoveEntry(resolvedEntry); return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index 6497471f..4575fb10 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -2889,6 +2889,10 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate) if (SrcPtrHasToken("class")) mToken = BfToken_Class; break; + case TOKEN_HASH('c', 'o', 'm', 'p'): + if ((!mCompatMode) && (SrcPtrHasToken("comptype"))) + mToken = BfToken_Comptype; + break; case TOKEN_HASH('c', 'o', 'n', 'c'): if ((!mCompatMode) && (SrcPtrHasToken("concrete"))) mToken = BfToken_Concrete; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index d1898633..ccc6a701 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -270,7 +270,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int* { // Tuple start } - else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) + else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) { // Decltype start } @@ -777,7 +777,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int* checkIdx = funcEndNode; continue; } - else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) + else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) { int endNodeIdx = checkIdx + 1; @@ -2231,7 +2231,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat } } } - else if (tokenNode->GetToken() == BfToken_Decltype) + else if ((tokenNode->GetToken() == BfToken_Comptype) || (tokenNode->GetToken() == BfToken_Decltype)) { auto typeRef = CreateTypeRef(tokenNode, CreateTypeRefFlags_EarlyExit); if (typeRef != NULL) @@ -4755,9 +4755,9 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0) return delegateTypeRef; } - else if (token == BfToken_Decltype) + else if ((token == BfToken_Comptype) || (token == BfToken_Decltype)) { - auto declTypeRef = mAlloc->Alloc(); + auto declTypeRef = mAlloc->Alloc(); ReplaceNode(tokenNode, declTypeRef); declTypeRef->mToken = tokenNode; tokenNode = ExpectTokenAfter(declTypeRef, BfToken_LParen); @@ -5064,6 +5064,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF (token == BfToken_LParen) || (token == BfToken_Delegate) || (token == BfToken_Function) || + (token == BfToken_Comptype) || (token == BfToken_Decltype) || ((token == BfToken_Star) && (mAllowTypeWildcard)))) doAddType = true; @@ -6521,6 +6522,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth, BfAstNode* defe (token == BfToken_AllocType) || (token == BfToken_RetType) || (token == BfToken_Nullable) || + (token == BfToken_Comptype) || (token == BfToken_Decltype) || (token == BfToken_LParen)) { diff --git a/IDEHelper/Compiler/BfResolvePass.cpp b/IDEHelper/Compiler/BfResolvePass.cpp index 4502e3eb..8431a180 100644 --- a/IDEHelper/Compiler/BfResolvePass.cpp +++ b/IDEHelper/Compiler/BfResolvePass.cpp @@ -126,7 +126,7 @@ BfAstNode* BfResolvePassData::FindBaseNode(BfAstNode* node) { baseNode = qualifiedNameNode->mRight; } - else if (auto declTypeRef = BfNodeDynCast(baseNode)) + else if (auto declTypeRef = BfNodeDynCast(baseNode)) { baseNode = NULL; break; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index b01758ad..81ad6511 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3408,12 +3408,12 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } return hashVal; - } - else if (auto declTypeRef = BfNodeDynCastExact(typeRef)) + } + else if (auto exprModTypeRef = BfNodeDynCastExact(typeRef)) { if (ctx->mResolvedType == NULL) { - if (declTypeRef->mTarget != NULL) + if (exprModTypeRef->mTarget != NULL) { BfTypedValue result; // @@ -3427,9 +3427,34 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash SetAndRestoreValue ignoreWrites(ctx->mModule->mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue allowUninitReads(ctx->mModule->mCurMethodState->mAllowUinitReads, true); - result = ctx->mModule->CreateValueFromExpression(declTypeRef->mTarget); + if (exprModTypeRef->mToken->mToken == BfToken_Comptype) + result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget, ctx->mModule->ResolveTypeDef(ctx->mModule->mCompiler->mTypeTypeDef), BfEvalExprFlags_Comptime); + else + result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget); } - ctx->mResolvedType = result.mType; + + if ((result) && (exprModTypeRef->mToken->mToken == BfToken_Comptype)) + { + auto constant = ctx->mModule->mBfIRBuilder->GetConstant(result.mValue); + if (constant != NULL) + { + if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData)) + { + auto typeOf = (BfTypeOf_Const*)constant; + ctx->mResolvedType = typeOf->mType; + } + else if (constant->mConstType == BfConstType_Undef) + { + ctx->mHadVar = true; + ctx->mResolvedType = ctx->mModule->GetPrimitiveType(BfTypeCode_Var); + } + } + + if (ctx->mResolvedType == NULL) + ctx->mModule->Fail("Constant System.Type value required", exprModTypeRef->mTarget); + } + else + ctx->mResolvedType = result.mType; } } @@ -3875,7 +3900,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* } } - if (auto declTypeRef = BfNodeDynCastExact(rhs)) + if (auto declTypeRef = BfNodeDynCastExact(rhs)) { BF_ASSERT(ctx->mResolvedType != NULL); return lhs == ctx->mResolvedType; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 4c7a87c7..fb18a6c6 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1104,6 +1104,7 @@ public: BfType* mExternType; Array mInterfaceConstraints; Array mOperatorConstraints; + Array mComptypeConstraint; BfType* mTypeConstraint; int mRefCount; @@ -2428,7 +2429,7 @@ public: { BfHashFlag_None = 0, BfHashFlag_AllowRef = 1, - BfHashFlag_AllowGenericParamConstValue = 2 + BfHashFlag_AllowGenericParamConstValue = 2 }; class LookupContext @@ -2440,6 +2441,7 @@ public: BfTypeInstance* mRootOuterTypeInstance; BfType* mResolvedType; BfResolveTypeRefFlags mResolveFlags; + bool mHadVar; bool mFailed; public: @@ -2451,6 +2453,7 @@ public: mModule = NULL; mResolvedType = NULL; mFailed = false; + mHadVar = false; mResolveFlags = BfResolveTypeRefFlag_None; } @@ -2488,10 +2491,10 @@ public: int tryCount = 0; ctx->mFailed = false; int hashVal = Hash(findType, ctx, BfHashFlag_AllowRef); - if (ctx->mFailed) + if ((ctx->mFailed) || (ctx->mHadVar)) { return false; - } + } int bucket = (hashVal & 0x7FFFFFFF) % mHashSize; auto checkEntry = mHashHeads[bucket]; while (checkEntry != NULL) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index a367d117..01bec0e4 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3420,8 +3420,8 @@ void BfModule::VisitCodeBlock(BfBlock* block) } else child->Accept(this); - - mSystem->CheckLockYield(); + + mContext->CheckLockYield(); ++itr; } @@ -3437,7 +3437,7 @@ void BfModule::VisitCodeBlock(BfBlock* block) //?? auto moduleMethodInstance = GetLocalMethodInstance(localMethod, BfTypeVector(), NULL, true); } - mSystem->CheckLockYield(); + mContext->CheckLockYield(); } while ((int)mCurMethodState->mLocalMethods.size() > startLocalMethod) @@ -4967,7 +4967,11 @@ void BfModule::Visit(BfReturnStatement* returnStmt) BfType* expectingReturnType = retType; if ((expectingReturnType != NULL) && (expectingReturnType->IsVar())) - expectingReturnType = NULL; + { + NOP; + // expectingReturnType = NULL; + } + BfType* origType; BfExprEvaluator exprEvaluator(this); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 9ddcd141..8c51ce91 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -637,7 +637,8 @@ enum BfGenericParamFlags : uint16 BfGenericParamFlag_Equals = 0x400, BfGenericParamFlag_Equals_Op = 0x800, BfGenericParamFlag_Equals_Type = 0x1000, - BfGenericParamFlag_Equals_IFace = 0x2000 + BfGenericParamFlag_Equals_IFace = 0x2000, + BfGenericParamFlag_ComptypeExpr = 0x4000 }; class BfConstraintDef diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 0d52829e..ed809425 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -3480,6 +3480,19 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType return BfIRValue(); } + if (typeInst->IsInstanceOf(ceModule->mCompiler->mTypeTypeDef)) + { + addr_ce addr = *(addr_ce*)(instData); + int typeId = GetTypeIdFromType(addr); + if (typeId <= 0) + { + Fail("Unable to locate return type type"); + return BfIRValue(); + } + + return module->CreateTypeDataRef(module->mContext->mTypes[typeId]); + } + if (typeInst->IsObjectOrInterface()) { Fail(StrFormat("Reference type '%s' return value not allowed", module->TypeToString(typeInst).c_str())); @@ -3846,7 +3859,12 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns memStart = &mMemory[0]; addr_ce retInstAddr = retAddr; - if ((returnType->IsObject()) || (returnType->IsPointer())) + + if (returnType->IsInstanceOf(mCeMachine->mCompiler->mTypeTypeDef)) + { + // Allow + } + else if ((returnType->IsObject()) || (returnType->IsPointer())) { // Or pointer? retInstAddr = *(addr_ce*)(memStart + retAddr); diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index ef56a86e..a67f1c4b 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -955,7 +955,7 @@ DbgType* DbgExprEvaluator::ResolveTypeRef(BfTypeReference* typeRef) } } - if (auto declTypeRef = BfNodeDynCastExact(typeRef)) + if (auto declTypeRef = BfNodeDynCastExact(typeRef)) { mResult = DbgTypedValue(); VisitChild(declTypeRef->mTarget); diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 7a8f4569..49c93b6d 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Reflection; +using System.Collections; namespace Tests { @@ -73,6 +74,40 @@ namespace Tests } + struct DoublingEnumerator : IEnumerator + where TElem : operator TElem + TElem + where TEnum : concrete, IEnumerator + { + TEnum mEnum; + + public this(TEnum e) + { + mEnum = e; + } + + public Result GetNext() mut + { + switch (mEnum.GetNext()) + { + case .Ok(let val): return .Ok(val + val); + case .Err: return .Err; + } + } + } + + static Type GetConcreteEnumerator() where TCollection : IEnumerable + { + TCollection col = ?; + return col.GetEnumerator().GetType(); + } + + public static DoublingEnumerator())> GetDoublingEnumerator(this TCollection it) + where TCollection: concrete, IEnumerable + where TElem : operator TElem + TElem + { + return .(it.GetEnumerator()); + } + [Test] public static void TestBasics() { @@ -88,6 +123,14 @@ namespace Tests MethodA(34, 45); Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45"); + + List fList = scope .() { 1, 2, 3 }; + var e = fList.GetDoublingEnumerator(); + Test.Assert(e.GetNext().Value == 2); + Test.Assert(e.GetNext().Value == 4); + Test.Assert(e.GetNext().Value == 6); + + //Test.Assert(fList.DoubleVals() == 12); } } }