-
Notifications
You must be signed in to change notification settings - Fork 1k
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
[Proposal]: params in
parameters
#8301
Comments
I don't think there is anything fundamentally wrong but there are a few parts that we'd need to think through. Let's change up the example a bit to use a C.M([1, 2, 3]);
public static class C
{
public static void M(in MyLargeRefStruct list) {}
}
[CollectionBuilder(typeof(MyLargeRefStruct), "Create")]
public ref struct MyLargeRefStruct
{
public IEnumerator<int> GetEnumerator() => throw null!;
public static MyLargeRefStruct Create(ReadOnlySpan<int> span) => throw null!;
} Today the params collections feature has the following line:
The underlying motivation of this was to make // Okay
MyLargeRefStruct M1(params in MyLargeRefStruct s) => s;
// Error: can't escape value `s` to calling method
MyLargeRefStruct M2(params MyLargeRefStruct s) => s; The behavior in
That gives me a little pause in doing |
If |
That would not make much sense as one should not pass rvalues to |
I think the main drawback is if the ReadOnlySpan<int> M(params in ReadOnlySpan<int> span) => span; // ok
// user code
var span1 = M([1, 2, 3]);
M([4, 5, 6]);
Console.Write(span1[0]); // needs to be '1' |
Presumably, |
// Works
Span<char> M(scoped ref Span<char> s) => s; To prevent the value, and the // Error
Span<char> M(ref scoped Span<char> s) => s; |
Our ref lifetimes model is currently held back by the fact that every lifetime can be related to every other lifetime. For any two lifetimes, they are either the same or one is known to be bigger and the other smaller. But in order to do ref scoped, I think we want the ability to say that the referent's lifetime is not known to be either bigger or smaller than any other ref scoped referent. They are different lifetimes which have no known relation to any existing returnable or ref scoped lifetimes. (They would be defined as bigger than local scopes though so that locals can refer to them.) That way you aren't struggling with, well, the ref is not returnable, unless you smuggle it out through a second ref scoped parameter. |
Sounds like we need lifetimes ala Rust ;) Span['b]<char> M<'a, 'b>(scoped ref Span['a]<char> s)
where 'b : 'a =>
s; |
@colejohnson66 if you haven't read the proposal for At the same time it's also likely the limit of what we can achieve in C# without going to explicit lifetimes. |
params in parameters
Summary
It should be possible for
params
parameters to also bein
.Motivation
I can have an
in
parameter and initialize it with a collection expression:And I can have a
params
parameter and initialize it with a list of arguments (dropping the brackets of the collection expression):but it's currently an error to have both
in
andparams
:I'm not aware of any reason why these shouldn't be allowed in conjunction. And with the introduction of collection expressions and their synergy with params, it's strange that one way of representing the same situation works and the other doesn't. For cases where a large struct is used and is thus desirable to be passed by reference, and where that struct is initializable with a collection expression, it'd be nice to be able to also allow someone to choose to use the params syntax.
The actual documentation for CS1611 refers to
ref
andout
:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/params-arrays#method-declaration-rules
and it makes sense that
ref
andout
can't be used with params. But that same reasoning doesn't apply toin
. Maybe it just inherited the behavior and we never thought to fix it?Detailed design
TBD
Drawbacks
TBD
Alternatives
TBD
Unresolved questions
TBD
Design meetings
The text was updated successfully, but these errors were encountered: