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

Span<RefStruct> is permitted through an implicitly-typed variable #25038

Closed
alrz opened this issue Feb 24, 2018 · 9 comments
Closed

Span<RefStruct> is permitted through an implicitly-typed variable #25038

alrz opened this issue Feb 24, 2018 · 9 comments
Assignees

Comments

@alrz
Copy link
Member

alrz commented Feb 24, 2018

Version Used: 37e7192 head of features/compilers

Steps to Reproduce:

ref struct S {}

void M(bool c) {
  // ERROR: The type 'S' may not be used as a type argument
  Span<S> x = c ? stackalloc S[2] : stackalloc S[3]; 

  // OK?
  var y = c ? stackalloc S[2] : stackalloc S[3]; 
}

Expected Behavior: error in both cases

Actual Behavior: error only if S is spelt out

@alrz
Copy link
Member Author

alrz commented Feb 24, 2018

/cc @VSadov

@VSadov
Copy link
Member

VSadov commented Feb 24, 2018

I think the second case is where it is a pointer for compat reasons.

What is the type of y ?

@alrz
Copy link
Member Author

alrz commented Feb 24, 2018

newobj instance void valuetype [System.Memory]System.Span`1<valuetype S>::.ctor(void*, int32)

is actually emitted. See the example in sharplab.

AFAIK stackalloc only returns a pointer when it's directly in a local decl initializer.

@VSadov
Copy link
Member

VSadov commented Feb 24, 2018

A bug then :)

@alrz
Copy link
Member Author

alrz commented Feb 24, 2018

I really wished we hadn't change stackalloc default type based on the context it's being used. as far as I know the motivating example was that in a ternary we didn't want to cast either of operands to Span,

var x = size < 100 ? stackalloc int[size] : (Span<int>)new int[100]; // x is Span

And that stackalloc in local decl initializers already produce a pointer

var x = stackalloc int[size]; // x is pointer

So we changed the default type to Span anywhere except for the above case.

We could address the problem by target typing the whole ternary expression if it fails to cast either of operands to each other.

Span<int> x = size < 100 ? stackalloc int[size] : new int[100]; 

But now it's a breaking change because the above code works with var.

Note that that could be useful in other places too,

IEnumerable<StatemnetSyntax> x = statementSyntax is Block block
    ? block.Statements
    : new [] { statemnetSyntax }; // No cast required,

Would it worth it to open an issue in csharplang or it's too late for this?

@OmarTawfik
Copy link
Contributor

I'd say it is worth taking the breaking change. Will create a PR and see what others might say about this.

@alrz
Copy link
Member Author

alrz commented Feb 28, 2018

@OmarTawfik Do you mean fixing the bug in the OP worth the breaking change or my proposal above? (note: that proposal would make this bug irrelevant because you need to specify the type anyways)

@OmarTawfik
Copy link
Contributor

I meant fixing the original bug. stackalloc T [count] expressions should always check T if it was fit to use in Span<T> construction. That's a compiler bug and should be fixed.

@OmarTawfik
Copy link
Contributor

@alrz closing as my PR was merged. Please tag me if you've other concerns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants