Skip to content
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

Interfaces don't forward static members to other interfaces #62855

Closed
Shadowblitz16 opened this issue Jul 21, 2022 · 12 comments
Closed

Interfaces don't forward static members to other interfaces #62855

Shadowblitz16 opened this issue Jul 21, 2022 · 12 comments
Labels
Area-Compilers Resolution-By Design The behavior reported in the issue matches the current design
Milestone

Comments

@Shadowblitz16
Copy link

Shadowblitz16 commented Jul 21, 2022

Description

Interfaces don't forward static members to other interfaces

for example this doesn't work...

public interface ICreatable<out T> where T : ICreatable<T>
{
    static abstract T Create();
}
public interface ICreatable<out T, in TArgs> where T : ICreatable<T, TArgs>
{
    static abstract T Create(TArgs args);
}

public interface IWindow : ICreatable<IWindow, WindowArgs>
{ 
    uint Width  { get; }
    uint Height { get; }
    
}

It complains when I pass IWindow to ICreatable

The interface 'HazelSharp.Common.Windowing.IWindow' cannot be used as type parameter 'T' in the generic interface 'HazelSharp.Common.Patterns.ICreatable<out T,in TArgs>'. The constraint interface 'HazelSharp.Common.Patterns.ICreatable<HazelSharp.Common.Windowing.IWindow,HazelSharp.Common.Windowing.WindowArgs>' or its base interface has static abstract members.

Reproduction Steps

  • Copy the code
  • Paste it in your IDE (I'm using rider)
  • See error

Expected behavior

It would forward the static member to the IWindow interface so that any class or struct that eventually implements IWindow has to implement ICreatable too

Actual behavior

It errors...

The interface 'HazelSharp.Common.Windowing.IWindow' cannot be used as type parameter 'T' in the generic interface 'HazelSharp.Common.Patterns.ICreatable<out T,in TArgs>'. The constraint interface 'HazelSharp.Common.Patterns.ICreatable<HazelSharp.Common.Windowing.IWindow,HazelSharp.Common.Windowing.WindowArgs>' or its base interface has static abstract members.

Regression?

Idk

Known Workarounds

None that I know of.

Configuration

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <LangVersion>11</LangVersion>
        <EnablePreviewFeatures>true</EnablePreviewFeatures>
        <WarningsAsErrors>Nullable</WarningsAsErrors>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="OpenTK" Version="4.7.4" />
    </ItemGroup>

    <ItemGroup>
      <Folder Include="Platform" />
    </ItemGroup>

</Project>

image

Other information

No response

@ghost ghost added the untriaged Issues and PRs which have not yet been triaged by a lead label Jul 21, 2022
@stephentoub stephentoub removed the untriaged Issues and PRs which have not yet been triaged by a lead label Jul 22, 2022
@stephentoub stephentoub transferred this issue from dotnet/runtime Jul 22, 2022
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Jul 22, 2022
@dotnet-issue-labeler
Copy link

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.

@jaredpar jaredpar added Need More Info The issue needs more information to proceed. and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Aug 9, 2022
@jaredpar
Copy link
Member

jaredpar commented Aug 9, 2022

Thanks for taking the time to file this issue. Unfortunately it's hard to determine exactly what the problem is here because the sample is incomplete. Could you provide a complete sample, including WindowArgs, to help us see what the issue is?

@ghost ghost added untriaged Issues and PRs which have not yet been triaged by a lead and removed Need More Info The issue needs more information to proceed. labels Aug 9, 2022
@jaredpar jaredpar added this to the 17.4 milestone Aug 9, 2022
@jaredpar jaredpar added Need More Info The issue needs more information to proceed. and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Aug 9, 2022
@Shadowblitz16
Copy link
Author

Thanks for taking the time to file this issue. Unfortunately it's hard to determine exactly what the problem is here because the sample is incomplete. Could you provide a complete sample, including WindowArgs, to help us see what the issue is?

I don't have the project anymore but WindowArgs was just a non generic readonly record struct to pass in the creation args to the IWindow.

@ghost ghost added untriaged Issues and PRs which have not yet been triaged by a lead and removed Need More Info The issue needs more information to proceed. labels Aug 13, 2022
@jaredpar
Copy link
Member

Updating the repro to the following:

public interface ICreatable<out T> where T : ICreatable<T>
{
    static abstract T Create();
}
public interface ICreatable<out T, in TArgs> where T : ICreatable<T, TArgs>
{
    static abstract T Create(TArgs args);
}

public interface IWindow : ICreatable<IWindow, WindowArgs>
{ 
    uint Width  { get; }
    uint Height { get; }
}

public record struct WindowArgs(int i) {}

Produces a very different error:

error CS8920: The interface 'IWindow' cannot be used as type argument. Static member 'ICreatable<IWindow, WindowArgs>.Create(WindowArgs)' does not have a most specific implementation in the interface.

The error difference is likely cause I'm using the C# 11 compiler vs you using the C# 10 compiler.

At a glance that error seems to make sense in this context but I will let @333fred say for sure.

@333fred
Copy link
Member

333fred commented Aug 15, 2022

This error is as-designed. Interfaces with static abstract members cannot be used as type arguments, as that presents a type safety hole that could cause a static member that does not actually exist to be invoked (causing a runtime exception).

@333fred 333fred closed this as not planned Won't fix, can't repro, duplicate, stale Aug 15, 2022
@333fred 333fred added Resolution-By Design The behavior reported in the issue matches the current design and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Aug 15, 2022
@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Aug 15, 2022

@333fred please reopen this. your failing to understand the issue.
The issue is that unlike instance interface members static interface members don't forward their requirements interfaces that implement them

public interface A
{
   public void Instance();
   public static abstract void Static();
}

public interface B : A //B  implements A so classes that implement B should be requires to implement A also
{
    
}

public class C : B // B should have the interface of A also but static members from A are not carried to B like instance members.
{
    
}

static interface members are not forwarded to other interfaces

@333fred
Copy link
Member

333fred commented Aug 15, 2022

@Shadowblitz16 looking at your example I'm not sure what you are saying. Can you show a us an example of where you expect to be able to use B? And to make sure, have you seen dotnet/csharplang#5955?

@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Aug 15, 2022

@333fred sorry I am trying to be a clear as possible forgive my communication issues, I have autism so its hard for me.

basically the way I see static interface members is that they are just like instance members but are static.
I still don't understand the need for the abstract keyword and why normal static members aren't allowed but that's not the issue.

The issue is for example with instance members if B implements A and C implements B since B implements A, C is required to implement A also regardless if B redefineds A's members.

This doesn't seem to be the case with abstract static interface members.
with them it seems to act differently.

@333fred
Copy link
Member

333fred commented Aug 16, 2022

@Shadowblitz16 there is no difference there with static abstract and regular instance abstract members. Both will require that C satisfy all interfaces, in this case both A and B.

@Shadowblitz16
Copy link
Author

@333fred I just want a static interface where I am not forced to implement it in the next interface or abstract class.

@CyrusNajmabadi
Copy link
Member

@333fred I just want a static interface where I am not forced to implement it in the next interface or abstract class.

But then where will the implementation of that interface member be found?

@333fred
Copy link
Member

333fred commented Aug 17, 2022

@333fred I just want a static interface where I am not forced to implement it in the next interface

You are not forced to implement it in the next interface.

or abstract class.

The feature is not designed to allow this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Resolution-By Design The behavior reported in the issue matches the current design
Projects
None yet
Development

No branches or pull requests

6 participants