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

Params parameters are implicitly scoped when their type is a ref struct. #72000

Merged

Conversation

AlekseyTs
Copy link
Contributor

@AlekseyTs AlekseyTs requested a review from a team as a code owner February 7, 2024 21:43
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Feb 7, 2024
@RikkiGibson RikkiGibson self-assigned this Feb 7, 2024
@AlekseyTs
Copy link
Contributor Author

@RikkiGibson, @333fred, @dotnet/roslyn-compiler Please review. It looks like the CI failures are due to some test infrastructure issues.

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done review pass.

// partial void Test3([UnscopedRef] params Span<long> a)
Diagnostic(ErrorCode.ERR_PartialMethodParamsDifference, "Test3").WithLocation(22, 18)
);
}
Copy link
Member

@333fred 333fred Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to modify these mismatch tests, or add more versions. The interesting cases for mismatches are cases where a missed scoped on an overridden method could cause a safety issue. For example, in the below code example, M1 and M2 have a compile error due to mismatched scoped, while M3 does not. All the examples above are of M3, as far as I can tell, so we should have variants that look like M1 and M2 that use params parameters.

class Base
{
    public virtual void M1(scoped Span<string> s, ref Span<string> s2) { }
    public virtual Span<string> M2(scoped Span<string> s) => throw new NotImplementedException();
    public virtual void M3(scoped Span<string> s) { }
}

class Derived : Base
{
    // error CS8987: The 'scoped' modifier of parameter 's' doesn't match overridden or implemented member.
    public override void M1(Span<string> s, ref Span<string> s2) => s2 = s;
    // error CS8987: The 'scoped' modifier of parameter 's' doesn't match overridden or implemented member.
    public override Span<string> M1(Span<string> s) => s;
    // Fine because there's no chance of `s` getting exposed.
    public override void M3(Span<string> s) { }
}
``` #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to modify these mismatch tests

Thanks. I thought I was missing something because I was not getting any mismatch errors even for non-params scenarios.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the tests

Assert.Equal(comp.GetMember<MethodSymbol>("C1.Test2").Parameters.Single().EffectiveScope, comp.GetMember<MethodSymbol>("C2.Test2").Parameters.Single().EffectiveScope);
Assert.NotEqual(comp.GetMember<MethodSymbol>("C1.Test3").Parameters.Single().EffectiveScope, comp.GetMember<MethodSymbol>("C2.Test3").Parameters.Single().EffectiveScope);

comp.VerifyDiagnostics(
Copy link
Member

@333fred 333fred Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem correct. Since params is scoped by default, we should have errors on the overrides for being unscoped. This implies that the following code will compile, which is a ref safety hole:

abstract class C1
{
    public abstract Span<long> Test1(params Span<long> a);
}
class C2 : C1
{
    public override Span<long> Test1(Span<long> a) => a;
}
``` #Resolved

Copy link
Contributor Author

@AlekseyTs AlekseyTs Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem correct.

That might come as a surprise, but the params modifier, or lack there of, is getting inherited during overriding regardless of the modifiers on the overriding method. The parameters are implicitly params and, therefore, they are implicitly scoped. The asserts above actually demonstrate that the scope is identical to the overridden method for Test1 and Test2.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I think this is something to bring up with LDM and consider enforcing scoped or params on overiddes for this scenario.

@AlekseyTs
Copy link
Contributor Author

@333fred For the second review

Assert.Equal(comp.GetMember<MethodSymbol>("C1.Test2").Parameters.Single().EffectiveScope, comp.GetMember<MethodSymbol>("C2.Test2").Parameters.Single().EffectiveScope);
Assert.NotEqual(comp.GetMember<MethodSymbol>("C1.Test3").Parameters.Single().EffectiveScope, comp.GetMember<MethodSymbol>("C2.Test3").Parameters.Single().EffectiveScope);

comp.VerifyDiagnostics(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I think this is something to bring up with LDM and consider enforcing scoped or params on overiddes for this scenario.

@AlekseyTs
Copy link
Contributor Author

/azp run

Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@AlekseyTs AlekseyTs enabled auto-merge (squash) February 9, 2024 19:35
@AlekseyTs AlekseyTs merged commit 6fcac7d into dotnet:features/ParamsCollections Feb 9, 2024
25 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers New Feature - ParamsCollections untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants