Browse Source

Added comptype

Brian Fiete 4 years ago
parent
commit
4890303508

+ 1 - 1
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;

+ 10 - 0
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)

+ 1 - 0
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;
 		}		

+ 3 - 1
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:

+ 7 - 6
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
 {	

+ 2 - 0
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())
 			{

+ 1 - 1
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();	

+ 4 - 3
IDEHelper/Compiler/BfConstResolver.cpp

@@ -103,7 +103,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
 		wantIgnoreWrites = true;
 	}
 
-	SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites);
+	SetAndRestoreValue<bool> 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;
 }

+ 8 - 1
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;
 }
 

+ 6 - 0
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();

+ 1 - 1
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());
 

+ 1 - 1
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);

+ 132 - 70
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -588,53 +588,40 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
 	return true;
 }
 
-void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance)
+bool BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx)
 {
-	// 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& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx];
+	if (srcGenericArg == NULL)
+		return false;
 
-		auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
-		for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
+	int startInferCount = mInferredCount;
+
+	auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
+	for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
+	{
+		if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
 		{
-			if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
+			InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
+			auto typeInstance = srcGenericArg->ToTypeInstance();
+			if (typeInstance != NULL)
 			{
-				InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
-				auto typeInstance = srcGenericArg->ToTypeInstance();
-				if (typeInstance != NULL)
-				{
-					for (auto ifaceEntry : typeInstance->mInterfaces)
-						InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
-				}
+				for (auto ifaceEntry : typeInstance->mInterfaces)
+					InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
 			}
 		}
 	}
+
+	return mInferredCount != startInferCount;
 }
 
-// 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())
-// 	{
-// 		
-// 
-// 	}
-// }
+void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance)
+{
+	// Attempt to infer from other generic args
+	for (int srcGenericIdx = 0; srcGenericIdx < (int)mCheckMethodGenericArguments->size(); srcGenericIdx++)
+	{
+		InferGenericArguments(methodInstance, srcGenericIdx);
+	}
+}
 
 int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs)
 {
@@ -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<BfConstraintState*> prevConstraintSet(mModule->mContext->mCurConstraintState, &constraintSet);
+			if (!mModule->CheckConstraintState(NULL))
+				return false;
+
+			SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mModule->mCurMethodInstance, methodInstance);
+			SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mModule->mCurTypeInstance, methodInstance->GetOwner());
+			SetAndRestoreValue<bool> 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++;
-			}			
+			}
 		}
 
+// 		while (true)
+// 		{
+// 
+// 		}
+
 		//
-		for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
+
+		bool failed = false;
+		bool inferredAllGenericArguments = false;
+		for (int pass = 0; true; pass++)
 		{
-			auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
-			if (genericArg == NULL)
+			bool madeProgress = false;
+			bool hasUninferred = false;
+			failed = false;
+
+			for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
 			{
-				auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
-				InferFromGenericConstraints(genericParam, &mCheckMethodGenericArguments);
-				if (genericArg != NULL)
-					continue;
-				if (!allowEmptyGenericSet.Contains(genericArgIdx))
-					goto NoMatch;
+				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;

+ 2 - 1
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);

+ 43 - 35
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<BfDeclTypeRef>(field->mFieldDeclaration->mTypeRef) != NULL;
+	bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact<BfExprModTypeRef>(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<BfMethodState*> 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<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized || mCurTypeInstance->mResolvingVarField);
-	SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
+	SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;	
+	SetAndRestoreValue<bool> prevAllowLockYield(mContext->mAllowLockYield, false);
 	SetAndRestoreValue<BfMethodState*> 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<BfTypeInstance*> 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<BfVarTypeReference>()))
+		if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
+			&& (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
 			resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);		
 		else
 			resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags);		

+ 1 - 0
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);

+ 30 - 7
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<BfVarTypeReference>()) || (field->mTypeRef->IsExact<BfLetTypeReference>()) || (field->mTypeRef->IsExact<BfDeclTypeRef>())))
+				else if ((field->mTypeRef != NULL) && ((field->mTypeRef->IsExact<BfVarTypeReference>()) || (field->mTypeRef->IsExact<BfLetTypeReference>()) || (field->mTypeRef->IsExact<BfExprModTypeRef>())))
 				{
 					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<BfDeclTypeRef>(baseNode))
+								else if (auto declTypeRef = BfNodeDynCast<BfExprModTypeRef>(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<BfGetSymbolReferenceKind> 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);

+ 4 - 0
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;

+ 7 - 5
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<BfDeclTypeRef>();
+					auto declTypeRef = mAlloc->Alloc<BfExprModTypeRef>();
 					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))
 		{

+ 1 - 1
IDEHelper/Compiler/BfResolvePass.cpp

@@ -126,7 +126,7 @@ BfAstNode* BfResolvePassData::FindBaseNode(BfAstNode* node)
 		{
 			baseNode = qualifiedNameNode->mRight;
 		}
-		else if (auto declTypeRef = BfNodeDynCast<BfDeclTypeRef>(baseNode))
+		else if (auto declTypeRef = BfNodeDynCast<BfExprModTypeRef>(baseNode))
 		{
 			baseNode = NULL;
 			break;

+ 31 - 6
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -3408,12 +3408,12 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 		}
 
 		return hashVal;
-	}
-	else if (auto declTypeRef = BfNodeDynCastExact<BfDeclTypeRef>(typeRef))
+	}	
+	else if (auto exprModTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(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<bool> ignoreWrites(ctx->mModule->mBfIRBuilder->mIgnoreWrites, true);
 					SetAndRestoreValue<bool> 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<BfDeclTypeRef>(rhs))
+	if (auto declTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(rhs))
 	{
 		BF_ASSERT(ctx->mResolvedType != NULL);
 		return lhs == ctx->mResolvedType;

+ 6 - 3
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -1104,6 +1104,7 @@ public:
 	BfType* mExternType;
 	Array<BfTypeInstance*> mInterfaceConstraints;
 	Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
+	Array<BfTypeReference*> 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)

+ 8 - 4
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);

+ 2 - 1
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

+ 19 - 1
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);

+ 1 - 1
IDEHelper/DbgExprEvaluator.cpp

@@ -955,7 +955,7 @@ DbgType* DbgExprEvaluator::ResolveTypeRef(BfTypeReference* typeRef)
 		}
 	}
 	
-	if (auto declTypeRef = BfNodeDynCastExact<BfDeclTypeRef>(typeRef))
+	if (auto declTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(typeRef))
 	{
 		mResult = DbgTypedValue();
 		VisitChild(declTypeRef->mTarget);

+ 43 - 0
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<TElem, TEnum> : IEnumerator<TElem>
+			where TElem : operator TElem + TElem
+			where TEnum : concrete, IEnumerator<TElem>
+		{
+			TEnum mEnum;
+
+			public this(TEnum e)
+			{
+				mEnum = e;
+			}
+
+			public Result<TElem> GetNext() mut
+			{
+				switch (mEnum.GetNext())
+				{
+				case .Ok(let val): return .Ok(val + val);
+				case .Err: return .Err;
+				}
+			}
+		}
+
+		static Type GetConcreteEnumerator<TCollection, TElem>() where TCollection : IEnumerable<TElem>
+		{
+			TCollection col = ?;
+			return col.GetEnumerator().GetType();
+		}
+
+		public static DoublingEnumerator<TElem, comptype(GetConcreteEnumerator<TCollection, TElem>())> GetDoublingEnumerator<TCollection, TElem>(this TCollection it)
+		    where TCollection: concrete, IEnumerable<TElem>
+		    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<float> 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);
 		}
 	}
 }