2
0
Эх сурвалжийг харах

Made type lookup errors 'var' instead of 'Object', less error cascading

Brian Fiete 6 жил өмнө
parent
commit
d48d03c58b

+ 4 - 1
IDEHelper/Compiler/BfCompiler.cpp

@@ -3828,7 +3828,10 @@ void BfCompiler::ProcessAutocompleteTempType()
 			if (BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef))
 			{
 				if (fieldDef->mInitializer == NULL)
-					mPassInstance->Fail("Implicitly-typed fields must be initialized", fieldDef->mFieldDeclaration);
+				{
+					if ((fieldDef->mTypeRef->IsA<BfVarTypeReference>()) || (fieldDef->mTypeRef->IsA<BfLetTypeReference>()))
+						mPassInstance->Fail("Implicitly-typed fields must be initialized", fieldDef->GetRefNode());
+				}
 			}
 		}
 	}

+ 57 - 8
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -3053,6 +3053,9 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
 					fieldInstance->mResolvedType = mModule->ResolveVarFieldType(curCheckType, fieldInstance, field);
 					if (fieldInstance->mResolvedType == NULL)
 						return BfTypedValue();
+
+					if ((fieldInstance->mResolvedType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
+						mModule->Fail("Field type reference failed to resolve", targetSrc);
 				}
 					
 				auto resolvedFieldType = fieldInstance->mResolvedType;
@@ -3332,7 +3335,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
 				{
 					if (retVal.IsAddr())
 						retVal.mKind = BfTypedValueKind_TempAddr;
-				}
+				}				
 
 				return retVal;				
 			}
@@ -5080,7 +5083,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 	}
 
 	auto func = moduleMethodInstance.mFunc;	
-	return CreateCall(methodInstance, func, bypassVirtual, irArgs);	
+	BfTypedValue result = CreateCall(methodInstance, func, bypassVirtual, irArgs);	
+	if ((result.mType != NULL) && (result.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))		
+		mModule->Fail("Method return type reference failed to resolve", targetSrc);
+	return result;
 }
 
 BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, BfTypeInstance* targetType, BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue)
@@ -7718,13 +7724,45 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
 	
 	auto objectType = mModule->mContext->mBfObjectType;
 	mModule->PopulateType(objectType, BfPopulateType_Full);
+		
+	targetValue = mModule->LoadValue(targetValue);
+
+	BfTypeInstance* srcTypeInstance = targetValue.mType->ToTypeInstance();
+	BfTypeInstance* targetTypeInstance = targetType->ToTypeInstance();
+	bool wasGenericParamType = false;
+
+	if ((srcTypeInstance != NULL) && (targetTypeInstance != NULL))
+	{
+		if (mModule->TypeIsSubTypeOf(srcTypeInstance, targetTypeInstance))
+		{
+			// We don't give this warning when we have wasGenericParmType set because that indicates we had a generic type constraint,
+			//  and a type constraint infers that the ACTUAL type used will be equal to or derived from that type and therefore
+			//  it may be a "necessary cast" indeed
+			if ((!wasGenericParamType) && (mModule->mCurMethodState->mMixinState == NULL))
+			{
+				if (srcTypeInstance == targetType)
+					mModule->Warn(BfWarning_BF4203_UnnecessaryDynamicCast, StrFormat("Unnecessary cast, the value is already type '%s'",
+						mModule->TypeToString(srcTypeInstance).c_str()), checkTypeExpr->mIsToken);
+				else
+					mModule->Warn(BfWarning_BF4203_UnnecessaryDynamicCast, StrFormat("Unnecessary cast, '%s' is a subtype of '%s'",
+						mModule->TypeToString(srcTypeInstance).c_str(), mModule->TypeToString(targetType).c_str()), checkTypeExpr->mIsToken);
+			}
+			
+			mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), boolType);
+			return;
+		}
+		else if ((!targetType->IsInterface()) && (srcTypeInstance != mModule->mContext->mBfObjectType) && (!mModule->TypeIsSubTypeOf(targetTypeInstance, srcTypeInstance)))
+		{
+			mModule->Fail(StrFormat("Cannot convert type '%s' to '%s' via any conversion",
+				mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(targetTypeInstance).c_str()), checkTypeExpr->mIsToken);
+		}
+	}
+
 	if (mModule->mCompiler->IsAutocomplete())
 	{
 		mResult = mModule->GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Addr);
 		return;
 	}
-	
-	targetValue = mModule->LoadValue(targetValue);
 
 	auto irb = mModule->mBfIRBuilder;
 	auto prevBB = mModule->mBfIRBuilder->GetInsertBlock();
@@ -7835,6 +7873,9 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
 	auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
 	if (targetValue.mType->IsValueTypeOrValueTypePtr())
 	{
+		mModule->Warn(0, StrFormat("Type '%s' is not applicable for dynamic casting",
+			mModule->TypeToString(targetValue.mType).c_str()), dynCastExpr->mAsToken);
+
 		auto typeInstance = targetValue.mType->ToTypeInstance();
 		if (targetValue.mType->IsWrappableType())
 			typeInstance = mModule->GetWrappedStructType(targetValue.mType);
@@ -7955,7 +7996,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
 	else if ((!targetType->IsInterface()) && (!mModule->TypeIsSubTypeOf(targetTypeInstance, srcTypeInstance)))
 	{
 		mModule->Fail(StrFormat("Cannot convert type '%s' to '%s' via any conversion", 
-			mModule->TypeToString(targetTypeInstance).c_str(), mModule->TypeToString(targetValue.mType).c_str()), dynCastExpr->mAsToken);
+			mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(targetTypeInstance).c_str()), dynCastExpr->mAsToken);
 	}
 
 	if (autoComplete != NULL)	
@@ -12514,9 +12555,13 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 		}
 		else if (auto expr = BfNodeDynCast<BfExpression>(memberRefExpression->mTarget))
 		{
+			BfType* expectingTargetType = NULL;
+			if (memberRefExpression->mDotToken->mToken == BfToken_DotDot)
+				expectingTargetType = mExpectingType;
+
 			bool handled = false;
 			if (auto subMemberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(expr))
-			{
+			{								
 				String findName;
 				if (subMemberRefExpr->mMemberName != NULL)
                 	findName = subMemberRefExpr->mMemberName->ToString();
@@ -12570,7 +12615,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 			if (!handled)
 			{
 				SetAndRestoreValue<BfAttributeState*> prevAttributeState(mModule->mAttributeState, &attributeState);
-				auto flags = BfEvalExprFlags_PropogateNullConditional;
+				auto flags = (BfEvalExprFlags)(BfEvalExprFlags_PropogateNullConditional | BfEvalExprFlags_NoCast);
 				if (mFunctionBindResult != NULL)
 				{
 					if (auto paranExpr = BfNodeDynCast<BfParenthesizedExpression>(expr))
@@ -12582,7 +12627,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 					
 				}
 				if (expr != NULL)
-					mResult = mModule->CreateValueFromExpression(expr, NULL, flags);
+					mResult = mModule->CreateValueFromExpression(expr, expectingTargetType, flags);
 			}
 		}
 
@@ -13253,7 +13298,11 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
 			else
 				mResult = CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
 			if (mResult.mType != NULL)
+			{
+				if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
+					mModule->Fail("Property type reference failed to resolve", mPropSrc);
 				BF_ASSERT(!mResult.mType->IsRef());
+			}
 		}
 		mPropDef = NULL;
 		mPropDefBypassVirtual = false;

+ 28 - 11
IDEHelper/Compiler/BfModule.cpp

@@ -2462,6 +2462,12 @@ void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementTyp
 	}
 }
 
+void BfModule::SetHadVarUsage()
+{
+	mHadVarUsage = true;
+	mHadBuildError = true;
+}
+
 BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent)
 {	
 	BP_ZONE("BfModule::Fail");
@@ -3340,6 +3346,8 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
 
 	bool staticOnly = (field->mIsStatic) && (!isDeclType);
 	
+	if (!fieldInstance->mIsInferredType)
+		return fieldType;
 	if (!fieldType->IsVar())
 		return fieldType;	
 	
@@ -3353,7 +3361,8 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
 	if ((!field->mIsStatic) && (typeDef->mIsStatic))
 	{
 		AssertErrorState();
-		return mContext->mBfObjectType;
+		SetHadVarUsage();
+		return GetPrimitiveType(BfTypeCode_Var);
 	}
 	
 	bool hadInferenceCycle = false;
@@ -3372,7 +3381,8 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
 				fieldModule->Fail(StrFormat("Field '%s.%s' creates a type inference cycle", TypeToString(fieldOwner).c_str(), fieldDef->mName.c_str()), fieldDef->mTypeRef, true);				
 			}
 			
-			return mContext->mBfObjectType;
+			SetHadVarUsage();
+			return GetPrimitiveType(BfTypeCode_Var);
 		}
 	}
 	mContext->mFieldResolveReentrys.push_back(fieldInstance);
@@ -3383,8 +3393,10 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
 	
 	if ((field->mInitializer == NULL) && (!isDeclType))
 	{
-		Fail("Implicitly-typed fields must be initialized", field->mFieldDeclaration);
-		return mContext->mBfObjectType;
+		if ((field->mTypeRef->IsA<BfVarTypeReference>()) || (field->mTypeRef->IsA<BfLetTypeReference>()))
+			Fail("Implicitly-typed fields must be initialized", field->GetRefNode());
+		SetHadVarUsage();
+		return GetPrimitiveType(BfTypeCode_Var);
 	}
 
 	BfType* resolvedType = NULL;
@@ -3421,7 +3433,7 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
 	}
 
 	if (resolvedType == NULL)
-		return mContext->mBfObjectType;
+		return GetPrimitiveType(BfTypeCode_Var);
 				
 	fieldInstance->SetResolvedType(resolvedType);
 
@@ -11839,7 +11851,7 @@ void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
 {
 	if (localVar->mResolvedType->IsVar())
 	{
-		BF_ASSERT((mCurMethodInstance->mIsUnspecialized) || (mCurMethodState->mClosureState != NULL));
+		BF_ASSERT((mCurMethodInstance->mIsUnspecialized) || (mCurMethodState->mClosureState != NULL) || (mHadVarUsage));
 	}
 
 	localVar->mLocalVarIdx = (int)mCurMethodState->mLocals.size();
@@ -12008,7 +12020,7 @@ void BfModule::CreateDIRetVal()
 
 	if ((mCurMethodState->mRetVal) || (mCurMethodState->mRetValAddr))
 	{
-		BF_ASSERT(!mBfIRBuilder->mIgnoreWrites);
+		BF_ASSERT((!mBfIRBuilder->mIgnoreWrites) || (mHadVarUsage));
 
 		BfType* dbgType = mCurMethodInstance->mReturnType;
 		BfIRValue dbgValue = mCurMethodState->mRetVal.mValue;
@@ -13150,12 +13162,17 @@ void BfModule::CreateStaticCtor()
 				// For extensions, only handle these fields in the appropriate extension
 				if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
 					continue;
-				
+								
 				UpdateSrcPos(fieldDef->mInitializer);				
 				
 				auto fieldInst = &mCurTypeInstance->mFieldInstances[fieldDef->mIdx];					
 				if (!fieldInst->mFieldIncluded)
 					continue;
+				if (fieldInst->mResolvedType->IsVar())
+				{
+					BF_ASSERT(mHadVarUsage);
+					continue;
+				}
 				auto assignValue = GetFieldInitializerValue(fieldInst);
 				if (assignValue)
 				{
@@ -18665,11 +18682,11 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 		if ((resolvedReturnType != NULL) && (resolvedReturnType->IsVar()) && (methodDef->mMethodType != BfMethodType_Mixin))
 		{
 			Fail("Cannot declare var return types", methodDef->mReturnTypeRef);
-			resolvedReturnType = mContext->mBfObjectType;
+			resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
 		}
 		
 		if (resolvedReturnType == NULL)
-			resolvedReturnType = mContext->mBfObjectType; // Fake an object
+			resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
 	}
 	else
 	{
@@ -18807,7 +18824,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 		}
 		if (resolvedParamType == NULL)
 		{
-			resolvedParamType = mContext->mBfObjectType; // Fake an object				
+			resolvedParamType = GetPrimitiveType(BfTypeCode_Var);
 			unresolvedParamType = resolvedParamType;
 			if (mCurTypeInstance->IsBoxed())
 			{

+ 3 - 1
IDEHelper/Compiler/BfModule.h

@@ -1340,8 +1340,9 @@ public:
 	bool mWroteToLib;
 	bool mHadBuildError;
 	bool mHadBuildWarning;
+	bool mHadVarUsage;
 	bool mIgnoreErrors;
-	bool mIgnoreWarnings;
+	bool mIgnoreWarnings;	
 	bool mSetIllegalSrcPosition;
 	bool mHadIgnoredError;
 	bool mReportErrors; // Still puts system in error state when set to false
@@ -1362,6 +1363,7 @@ public:
 	void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
 	bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType);
 	void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
+	void SetHadVarUsage();
 	BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
 	BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);	
 	BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);

+ 6 - 4
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -2265,6 +2265,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 				resolveEntry.mTypeArrayIdx = (int)llvmFieldTypes.size();
 				deferredVarResolves.push_back(resolveEntry);
 
+				fieldInstance->mIsInferredType = true;
 				// For 'let', make read-only
 			}
 			else
@@ -2273,10 +2274,11 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 				resolvedFieldType = ResolveTypeRef(field->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam);
 				if (resolvedFieldType == NULL)
 				{
-					// Failed, just put in placeholder 'Object'
+					// Failed, just put in placeholder 'var'
 					AssertErrorState();
-					resolvedFieldType = mContext->mBfObjectType;
-				}
+					resolvedFieldType = GetPrimitiveType(BfTypeCode_Var);
+					SetHadVarUsage();
+				}									
 			}
 
 			if (resolvedFieldType->IsMethodRef())
@@ -8659,7 +8661,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 	// * <-> Var 
 	if ((typedVal.mType->IsVar()) || (toType->IsVar()))
 	{
-		BF_ASSERT((mCurMethodInstance->mIsUnspecialized) || (mCurMethodState->mClosureState != NULL));
+		BF_ASSERT((mCurMethodInstance->mIsUnspecialized) || (mCurMethodState->mClosureState != NULL) || (mHadVarUsage));
 		return GetDefaultValue(toType);
 	}
 

+ 4 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -1088,6 +1088,7 @@ public:
 	bool mFieldIncluded;
 	bool mIsEnumPayloadCase;
 	bool mIsThreadLocal;
+	bool mIsInferredType;
 	int mLastRevisionReferenced;
 
 public:
@@ -1109,7 +1110,8 @@ public:
 		mFieldIncluded = copyFrom.mFieldIncluded;		
 		mIsEnumPayloadCase = copyFrom.mIsEnumPayloadCase;
 		mIsThreadLocal = copyFrom.mIsThreadLocal;
-		mLastRevisionReferenced = copyFrom.mLastRevisionReferenced;
+		mIsInferredType = copyFrom.mIsInferredType;
+		mLastRevisionReferenced = copyFrom.mLastRevisionReferenced;		
 	}
 
 	BfFieldInstance()
@@ -1126,6 +1128,7 @@ public:
 		mDataSize = 0;
 		mFieldIncluded = true;
 		mIsThreadLocal = false;
+		mIsInferredType = false;
 		mLastRevisionReferenced = -1;
 	}		
 

+ 5 - 2
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -1383,8 +1383,11 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 				}				
 			}
 		}
-		if (!initValue)
-			initValue = GetDefaultTypedValue(mContext->mBfObjectType);
+		if (!initValue)			
+		{
+			initValue = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Var));
+			SetHadVarUsage();
+		}
 		if (initValue.mType->IsNull())
 		{
 			Fail("Implicitly-typed variables cannot be initialized to 'null'", varDecl->mInitializer);