diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index aa2fe6a31..4f94aadbe 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -5993,11 +5993,51 @@ public static Guid PIID = Vftbl.PIID; bool write_abi_interface(writer& w, TypeDef const& type) { - bool is_generic = distance(type.GenericParam()) > 0; XLANG_ASSERT(get_category(type) == category::interface_type); auto type_name = write_type_name_temp(w, type, "%", typedef_name_type::ABI); + // For exclusive interfaces which aren't overridable interfaces that are implemented by unsealed types, + // we do not need any of the Do_Abi functions or the vtable logic as we will not create CCWs for them. + // But we are still keeping the interface itself for any helper type lookup that may happen for like GUID lookup. + if (!is_generic && + is_exclusive_to(type) && + // check for !authored type + !(settings.component && settings.filter.includes(type))) + { + bool hasOverridableAttribute = false; + auto exclusive_to_type = get_exclusive_to_type(type); + for (auto&& iface : exclusive_to_type.InterfaceImpl()) + { + for_typedef(w, get_type_semantics(iface.Interface()), [&](auto interface_type) + { + if (type == interface_type && is_overridable(iface)) + { + hasOverridableAttribute = true; + } + }); + + if (hasOverridableAttribute) + { + break; + } + } + + if (!hasOverridableAttribute) + { + w.write(R"(% +internal interface % : % +{ +} +)", +bind(type), +type_name, +bind(type, typedef_name_type::CCW, false) +); + return true; + } + } + auto nongenerics_class = w.write_temp("%_Delegates", bind(type, typedef_name_type::ABI, false)); std::vector nongeneric_delegates; @@ -6017,7 +6057,7 @@ internal unsafe interface % : % type_name, bind(type, typedef_name_type::CCW, false), [&](writer& w) { - w.write(distance(type.GenericParam()) > 0 ? "public static Guid PIID = Vftbl.PIID;\n\n" : ""); + w.write(is_generic ? "public static Guid PIID = Vftbl.PIID;\n\n" : ""); }, // Vftbl bind([&](writer& w) @@ -7652,4 +7692,4 @@ bind(invokeMethodSig)); typeNameToDefinitionMap[eventTypeCode] = eventClass; } } -} \ No newline at end of file +} diff --git a/src/cswinrt/helpers.h b/src/cswinrt/helpers.h index e1e2380e5..32eeaed58 100644 --- a/src/cswinrt/helpers.h +++ b/src/cswinrt/helpers.h @@ -39,6 +39,25 @@ namespace cswinrt return get_category(type) == category::interface_type && has_attribute(type, "Windows.Foundation.Metadata"sv, "ExclusiveToAttribute"sv); } + TypeDef get_exclusive_to_type(TypeDef const& type) + { + if (auto exclusive_to_attr = get_attribute(type, "Windows.Foundation.Metadata"sv, "ExclusiveToAttribute"sv)) + { + auto sig = exclusive_to_attr.Value(); + auto const& fixed_args = sig.FixedArgs(); + XLANG_ASSERT(fixed_args.size() == 1); + auto sys_type = std::get(std::get(fixed_args[0].value).value); + return type.get_cache().find_required(sys_type.name); + } + + throw_invalid("Exclusive type not found"); + } + + bool is_overridable(InterfaceImpl const& interfaceImpl) + { + return has_attribute(interfaceImpl, "Windows.Foundation.Metadata"sv, "OverridableAttribute"sv); + } + bool is_projection_internal(TypeDef const& type) { return has_attribute(type, "WinRT.Interop"sv, "ProjectionInternalAttribute"sv);