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

Erroneous CS0266 on 'byte = byte & byte' #74375

Closed
aehancoc opened this issue Jul 12, 2024 · 4 comments
Closed

Erroneous CS0266 on 'byte = byte & byte' #74375

aehancoc opened this issue Jul 12, 2024 · 4 comments
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead

Comments

@aehancoc
Copy link

aehancoc commented Jul 12, 2024

Version Used:

Steps to Reproduce:

Observe this example.

Diagnostic Id:

CS0266: Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)

Expected Behavior:

Because System.Byte implements System.Numerics.IBitwiseOperators<byte,byte,byte> as seen here, this should compile without issue. This occurs even if using a constant, like byte b = a & (byte)2;.

Interestingly, this works fine in VB.NET (example) and in F# (example).

Actual Behavior:

Compilation error is raised, because for whatever reason the compiler elects to cast some part of this to an int. The easiest workaround (and what the VB.NET/F# examples decompile to) is byte b = (byte)(a & a);, but this feels clunky.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 12, 2024
@aehancoc
Copy link
Author

May be related to #42816

@hez2010
Copy link

hez2010 commented Jul 13, 2024

IBitwiseOperators<byte,byte,byte> are implemented explicitly for byte, those methods are not public: https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Byte.cs,422

If you want to call into IBitwiseOperators<byte,byte,byte>.op_And, you need to go through type parameter:

T And<T>(T l, T r) where T : IBitwiseOperators<T, T, T> => l & r;

byte a = 1, b = 2;
byte c = And(a, b);

Note that exposing those methods public on byte is considered as a breaking change, as existing code expect it to be casted to int.

@aehancoc
Copy link
Author

aehancoc commented Jul 16, 2024

I suppose that makes sense. The default behaviour is just a bit counter-intuitive imo. I'm assuming that it stems from the CIL's internal representation of integers as being at least 32 bits?

I'm not expecting anything to change, given the backwards compatibility requirements, so unless you want to reply then feel free to close this. (That said, I'm curious why the default integer promotion rules wouldn't be adequate if the methods were to be made public, but I'm sure there's plenty of edge cases I'm not considering.)

@CyrusNajmabadi
Copy link
Member

Consider:

Foo(b1 & b2)
void Foo(byte b) { ... }
void Foo(int i) { ... }

This can't change meaning.

@jaredpar jaredpar closed this as not planned Won't fix, can't repro, duplicate, stale Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

No branches or pull requests

4 participants