New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow using SupportedOSPlatformAttribute
on interfaces
#47599
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
c.c. @terrajobst - it looks like we missed the lack of |
Cc @jeffhandley |
This came up in the API review for the attributes during 5.0; we decided at that time to intentionally exclude interfaces. We concluded that there's nothing about an interface that is truly platform-specific, but instead it's the implementations of the interface that would be platform-specific. It sounds like you have a scenario that might disprove that assertion. Is it correct that no classes actually implement /cc @buyaa-n |
Agreed. I understand that, from a .net perspective, its neither platform specific nor does it need availability attributes. But ObjC protocols are not quite interfaces but they are the closest match there is in .net.
Yes, but Protocols are used for different things. When they ends with name suffixes like Other protocols are not meant to be user-created. In such cases you consume them thru the interface. Most of the time you can guess the availability thru the property/method that expose the interface. But since ObjC is weakly-typed some API support more than one protocol type for a single API (generally the version information is the key to provide the correct one). Finally there's the assembly bloating issue. Our logic is to annotate types (classes, interfaces, struct and enums) so that members inherit this information (and do not each require additional attributes). Only the difference (a newer or obsoleted/deprecated member) requires extra annotations. |
What @jeffhandley said. We disabled it on interfaces to communicate/shape the intent. However, I've got no problem with relaxing that if that's useful for iOS. |
Me either. @buyaa-n -- will the Platform Compatibility Analyzer will work with interfaces as implemented, or will changes be required in the analyzer to handle platform attributes on them? |
I don't think there is any change required, but interface attributes would only work for the interface references, not for derived types inherited from that interface
The attributes are not inherited, runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs Line 63 in 1b1ff80
|
Are we sure there is significant bloat? Attribute blobs are interned and shared between applications. |
right :-( this differs even more from our current attributes and tooling...
It made a difference in our current attributes, but those are also using string messages. I'm doing more measurements using the new, message-less, attributes...
applications ? you mean it exists once in metadata and each type/member can reference the same entry (when identical) right ? |
Yes. The attribute applications point to an entry in the blob table that contains the data passed to it. So long the values are the same between applications even strings should be fine because you only pay for them once. |
This moves our current/legacy attributes to the ones added in dotnet 5 [1]. Short Forms (only in bindings) | Old | New | |---------------------------------------|-------------------------------------| | [iOS (7,0)] | [SupportedOSPlatform ("ios7.0")] | | [NoIOS] | [UnsupportedOSPlatform ("ios")] | Long Forms | Old | New | |---------------------------------------|-------------------------------------| | [Introduced (PlatformName.iOS, 7,0)] | [SupportedOSPlatform ("ios7.0")] | | [Obsoleted (PlatformName.iOS, 12,1)] | [Obsolete (...)] | | [Deprecated (PlatformName.iOS, 14,3)] | [UnsupportedOSPlatform ("ios14.3")] | | [Unavailable (PlatformName.iOS)] | [UnsupportedOSPlatform ("ios")] | Other changes * `[SupportedOSPlatform]` and `[UnsupportedOSPlatform]` are not allowed on `interface` [2] which means they cannot be used for protocols. This is currently handled by inlining the existing attributes on all members. * `[ObsoletedInOSPlatform]` was removed in net5 RC. This PR is now mapping the existing attributes to `[Obsolote]`, however multiple ones cannot be added so they need to be platform specific. Still Missing * [ ] Generator deduplication of type/members attributes for interfaces (due to [2]) * [ ] Manual bindings * [ ] Introspection tests updates References * [1] xamarin#10170 * [2] dotnet/runtime#47599 * [3] dotnet/runtime#47601
I think we have different definition of application :-) An early check seems to add about 40kb to the assembly (not everything is updated). Considering the 1000s of bindings that's likely just metadata entries pointing to the same (limited set of) data and not real duplication. |
I have tested by adding [SupportedOSPlatform("linux")]
[SupportedOSPlatform("windows")]
[UnsupportedOSPlatform("windows10.0")]
public interface IWindowsOnly
{
void Derived1();
void Derived2();
}
public class Child : IWindowsOnly
{
public void Derived1() { }
[UnsupportedOSPlatform("linux")]
public void Derived2() { }
public void NonDerived() { }
}
public class Test
{
void Callsite()
{
IWindowsOnly test = new Child();
test.Derived1(); // 'IWindowsOnly.Derived1()' is only supported on 'linux', 'windows' 10.0 and before.
test.Derived2(); // 'IWindowsOnly.Derived2()' is only supported on 'linux', 'windows' 10.0 and before.
var child = new Child();
child.Derived1(); // no warning
child.Derived2(); // 'Child.Derived2()' is unsupported on 'linux'. (only warn for the attribute within Child)
child.NonDerived(); // no warning
}
} |
Thanks, @buyaa-n. I assume no changes were necessary in the analyzer itself to achieve that result; let me know if that is not correct. @spouliot, would this behavior of the analyzer match your expectations? @terrajobst, do you have concerns about misleading users (to think attributes are inherited) here, or do you think we (can) cover this well enough in documentation that no form of based types/interfaces is recognized? |
That is correct |
namespace System.Runtime.Versioning
{
[AttributeUsage(Assembly | Class | Constructor | Enum | Event | Field | Method | Module |
Interface /* new */ |
Property | Struct, AllowMultiple=true, Inherited=false)]
public partial class SupportedOSPlatformAttribute
{
}
[AttributeUsage(Assembly | Class | Constructor | Enum | Event | Field | Method | Module |
Interface /* new */ |
Property | Struct, AllowMultiple=true, Inherited=false)]
public partial class UnsupportedOSPlatformAttribute
{
}
} |
That is probably what we should do instead of: Consider flag platform specific constructor called implicitly in derived types |
Background and Motivation
This is a slight addition to the existing
[SupportedOSPlatform]
attribute type.For Xamarin (iOS, tvOS, macOS and Catalyst) we expose Objective-C protocols as .net interfaces. However the current implementation of
SupportedOSPlatformAttribute
[1] does not let us annotate interfaces.Apple does include versioning information for their protocols and the current version of Xamarin SDK do support this feature (with our own attributes).
The lack of support for annotating interface is blocking the completion of xamarin/xamarin-macios#10170
[1] https://docs.microsoft.com/en-us/dotnet/api/system.runtime.versioning.supportedosplatformattribute?view=net-5.0
Proposed API
Add
AttributeTargets.Interface
toSupportedOSPlatformAttribute
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Module | + System.AttributeTargets.Interface | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] public sealed class SupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute
Usage Examples
This is how an existing generated interface for a protocol looks like:
And we would like to be able to do this for .net6
Alternative Designs
Annotating only interface members is possible but:
Risks
The existing analyzers might need to consider interfaces (if they do not scan them already).
The text was updated successfully, but these errors were encountered: