From 92d3ab6ca97f4b646b22ff9725a9a4fce74160a7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 4 Aug 2020 10:30:25 -0700 Subject: [PATCH] Fixed error messages for methods with extern constraints in variations --- IDE/Tests/CompileFail001/src/Generics.bf | 25 ++++++++++++++++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 17 ++++++++++--- IDEHelper/Compiler/BfModule.cpp | 32 ++++++++++++++++++------ 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/IDE/Tests/CompileFail001/src/Generics.bf b/IDE/Tests/CompileFail001/src/Generics.bf index e9b88957..6527df3d 100644 --- a/IDE/Tests/CompileFail001/src/Generics.bf +++ b/IDE/Tests/CompileFail001/src/Generics.bf @@ -1,9 +1,24 @@ +#pragma warning disable 168 + using System; +namespace System +{ + extension Array1 + { + public static bool operator==(Self lhs, Self rhs) where T : IOpEquals + { + return true; + } + } +} + namespace IDETest { class Generics { + + public void Method1(T val) where T : Array { @@ -13,5 +28,15 @@ namespace IDETest { Method1(val2); //FAIL 'T', declared to be 'T2' } + + public void Method3(ref TFoo[] val) + { + bool eq = val == val; //FAIL Generic argument 'T', declared to be 'TFoo' for 'TFoo[].operator==(TFoo[] lhs, TFoo[] rhs)', must implement 'System.IOpEquals' + } + + public void Method4() + { + + } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 2cf0eb22..46ac24d1 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -196,6 +196,12 @@ void BfMethodMatcher::Init(/*SizedArrayImpl& arguments, */BfSized for (BfTypeReference* genericArg : *methodGenericArguments) { auto genericArgType = mModule->ResolveTypeRef(genericArg); + if (genericArgType->IsGenericParam()) + { + auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)genericArgType); + if ((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Var) != 0) + mHasVarArguments = true; + } mExplicitMethodGenericArguments.push_back(genericArgType); } mHadExplicitGenericArguments = true; @@ -13023,7 +13029,12 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, { checkMethodGenericArgs = &methodMatcher.mBestMethodGenericArguments; genericArg = genericParams->mExternType; - genericArg = mModule->ResolveGenericType(genericArg, NULL, checkMethodGenericArgs); + + auto owner = methodInstance.mMethodInstance->GetOwner(); + BfTypeVector* typeGenericArguments = NULL; + if (owner->mGenericTypeInfo != NULL) + typeGenericArguments = &owner->mGenericTypeInfo->mTypeGenericArguments; + genericArg = mModule->ResolveGenericType(genericArg, typeGenericArguments, checkMethodGenericArgs); } if (genericArg->IsVar()) @@ -13039,8 +13050,8 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, // Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized BfError* error = NULL; - if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams, checkMethodGenericArgs, - failed ? NULL : &error)) + if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams, NULL, + failed ? NULL : &error)) { if (methodInstance.mMethodInstance->IsSpecializedGenericMethod()) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 624ea161..a4adbcec 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6878,8 +6878,7 @@ String BfModule::GenericParamSourceToString(const BfGenericParamSource & generic { if (genericParamSource.mMethodInstance != NULL) { - auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance); - SetAndRestoreValue prevMethodInst(mCurMethodInstance, methodInst); + auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance); return MethodToString(methodInst); } else @@ -9598,6 +9597,8 @@ String BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags type = ResolveGenericType(type, NULL, methodGenericArgs); if ((type == NULL) || (!type->IsUnspecializedTypeVariation())) typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames; + if (allowResolveGenericParamNames) + typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames; String methodName; if ((methodNameFlags & BfMethodNameFlag_OmitTypeName) == 0) @@ -11289,13 +11290,15 @@ bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstan else if (methodA->mMethodDef->mName != methodB->mMethodDef->mName) return false; if (methodA->mMethodDef->mCheckedKind != methodB->mMethodDef->mCheckedKind) - return false; + return false; + if ((methodA->mMethodDef->mMethodType == BfMethodType_Mixin) != (methodB->mMethodDef->mMethodType == BfMethodType_Mixin)) + return false; if (methodA->mMethodDef->mMethodType == BfMethodType_Ctor) { if (methodA->mMethodDef->mIsStatic != methodB->mMethodDef->mIsStatic) return false; - } + } if (methodA->mMethodDef->mMethodType == BfMethodType_Operator) { @@ -15501,7 +15504,8 @@ void BfModule::EmitTupleToStringBody() if (fieldValue.mType->IsObjectOrInterface()) { - BF_ASSERT(!fieldValue.IsAddr()); + fieldValue = LoadValue(fieldValue); + BF_ASSERT(!fieldValue.IsAddr()); SizedArray args; args.Add(mBfIRBuilder->CreateBitCast(fieldValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType))); auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]); @@ -19838,9 +19842,16 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool BfAutoComplete* bfAutocomplete = NULL; if (mCompiler->mResolvePassData != NULL) bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete; - + + if ((methodDeclaration != NULL) && (methodDeclaration->ToString().Contains("//TEST"))) + { + NOP; + } + if (methodInstance->mMethodInfoEx != NULL) { + BfTypeInstance* unspecializedTypeInstance = NULL; + for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++) { auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx]; @@ -19850,8 +19861,15 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool } else { + if (unspecializedTypeInstance == NULL) + unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance); + auto externConstraintDef = genericParam->GetExternConstraintDef(); - genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); + // 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); + } auto autoComplete = mCompiler->GetAutoComplete(); if (autoComplete != NULL)