| 19814 | } |
| 19815 | |
| 19816 | BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* methodDef) |
| 19817 | { |
| 19818 | if (mPropDefBypassVirtual) |
| 19819 | { |
| 19820 | if (mPropTarget.mType->IsInterface()) |
| 19821 | { |
| 19822 | auto curTypeInst = mPropTarget.mType->ToTypeInstance(); |
| 19823 | if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, curTypeInst)) |
| 19824 | { |
| 19825 | if (methodDef->mBody != NULL) |
| 19826 | { |
| 19827 | // This is an explicit call to a default static interface method. We pull the methodDef into our own concrete type. |
| 19828 | mPropTarget = mModule->GetThis(); |
| 19829 | return mModule->GetMethodInstance(mModule->mCurTypeInstance, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_ForeignMethodDef, curTypeInst); |
| 19830 | } |
| 19831 | } |
| 19832 | else |
| 19833 | { |
| 19834 | mModule->Fail("Property is not implemented by this type", mPropSrc); |
| 19835 | return BfModuleMethodInstance(); |
| 19836 | } |
| 19837 | } |
| 19838 | else |
| 19839 | { |
| 19840 | auto propTypeInst = mPropTarget.mType->ToTypeInstance(); |
| 19841 | mModule->PopulateType(propTypeInst, BfPopulateType_DataAndMethods); |
| 19842 | auto rawMethodInstance = mModule->GetRawMethodInstance(propTypeInst, methodDef); |
| 19843 | |
| 19844 | if (rawMethodInstance->mVirtualTableIdx == -1) |
| 19845 | { |
| 19846 | if (!mModule->mCompiler->mIsResolveOnly) |
| 19847 | { |
| 19848 | // ResolveOnly does not force methods to slot |
| 19849 | BF_ASSERT(rawMethodInstance->mVirtualTableIdx != -1); |
| 19850 | mModule->Fail(StrFormat("Failed to devirtualize %s", mModule->MethodToString(rawMethodInstance).c_str())); |
| 19851 | } |
| 19852 | } |
| 19853 | else |
| 19854 | { |
| 19855 | auto useTypeInst = mOrigPropTarget.mType->ToTypeInstance(); |
| 19856 | auto virtualMethod = (BfMethodInstance*)useTypeInst->mVirtualMethodTable[rawMethodInstance->mVirtualTableIdx].mImplementingMethod; |
| 19857 | return mModule->ReferenceExternalMethodInstance(virtualMethod); |
| 19858 | } |
| 19859 | } |
| 19860 | } |
| 19861 | |
| 19862 | if ((mOrigPropTarget) && (mOrigPropTarget.mType != mPropTarget.mType) && |
| 19863 | ((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface()))) |
| 19864 | { |
| 19865 | auto checkType = mOrigPropTarget.mType; |
| 19866 | |
| 19867 | if ((checkType->IsNullable()) && (!mPropTarget.mType->IsNullable())) |
| 19868 | checkType = checkType->GetUnderlyingType(); |
| 19869 | if (checkType->IsPointer()) |
| 19870 | checkType = ((BfPointerType*)checkType)->mElementType; |
| 19871 | if (checkType->IsWrappableType()) |
| 19872 | checkType = mModule->GetWrappedStructType(checkType); |
| 19873 | if ((checkType != NULL) && (checkType->IsTypeInstance())) |
nothing calls this directly
no test coverage detected