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

Address feedback from previous pattern matching ReadOnlySpan<char> change #59451

Merged
merged 6 commits into from
Feb 17, 2022

Conversation

cston
Copy link
Member

@cston cston commented Feb 10, 2022

Addresses comments marked pending in #44388.

Proposal: pattern-match-span-of-char-on-string.md
Test plan: #59191

@cston cston marked this pull request as ready for review February 11, 2022 06:07
@cston cston requested a review from a team as a code owner February 11, 2022 06:07
@RikkiGibson RikkiGibson self-assigned this Feb 11, 2022
@jcouv jcouv self-assigned this Feb 11, 2022
static void Main()
{
var s = new ReadOnlySpan<char>(new char[0]);
_ = s is ""str"";
Copy link
Contributor

@RikkiGibson RikkiGibson Feb 14, 2022

Choose a reason for hiding this comment

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

I'm fine with this scenario not working, but curious if there was a specific reason we can't compile this when 'Length' is missing? Seems like we only actually need to call MemoryExtensions.SequenceEqual? #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, it looks like we're using Span<char>.Length or ReadOnlySpan<char>.Length for lowering switch arms that use "" (in CodeGenerator.EmitStringSwitchJumpTable()), but not for lowering is "".

That said, I think I'd rather ensure Length exists for both scenarios.

// (5,57): error CS0037: Cannot convert null to 'ReadOnlySpan<char>' because it is a non-nullable value type
CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, references: new[] { Net50.SystemMemory }, parseOptions: TestOptions.RegularPreview)
.VerifyEmitDiagnostics(
// (5,57): error CS0150: A constant value is expected
Copy link
Contributor

@RikkiGibson RikkiGibson Feb 14, 2022

Choose a reason for hiding this comment

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

It feels like the previous diagnostic was easier to understand. #ByDesign

Copy link
Member Author

@cston cston Feb 15, 2022

Choose a reason for hiding this comment

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

It feels like the previous diagnostic was easier to understand.

Agreed. To be clear though, the diagnostic changed because the ReadOnlySpan<T> type declaration in NetCoreApp has different conversion operators than the TestSources declaration we were using previously.

I'll leave this as is.

IL_0005: call ""System.ReadOnlySpan<char> string.op_Implicit(string)""
IL_000a: stloc.0
IL_000b: ldloca.s V_0
IL_000d: call ""int System.ReadOnlySpan<char>.Length.get""
Copy link
Member

@jcouv jcouv Feb 15, 2022

Choose a reason for hiding this comment

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

The spec doesn't mention any usage of Length.
What is the purpose? MemoryExtensions.SequenceEqual already compares lengths before comparing bits. #ByDesign

Copy link
Member Author

@cston cston Feb 15, 2022

Choose a reason for hiding this comment

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

This aligns with the behavior for switch with a string value (see sharplab.io).

Let me know if you'd prefer to use SequenceEqual() in all cases.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, that makes sense. Thanks.
nit: The spec should probably mention our usage of those two Length properties.

@@ -149,7 +149,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
LabelSymbol start = F.GenerateLabel("start");


// This method should be kept consistent with SynthesizedStringSwitchHashMethod.ConstructStringHash
// This method should be kept consistent with SynthesizedStringSwitchHashMethod.ComputeStringHash
Copy link
Member

@jcouv jcouv Feb 15, 2022

Choose a reason for hiding this comment

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

nit: extra empty line above #Resolved

@jcouv
Copy link
Member

jcouv commented Feb 15, 2022

internal sealed partial class SynthesizedSpanSwitchHashMethod : SynthesizedGlobalMethodSymbol

Is this spec'ed? Consider adding xml doc on this type.


In reply to: 1039970680


Refers to: src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.Lowered.cs:129 in 27f2ff8. [](commit_id = 27f2ff8, deletion_comment = False)

IL_0014: ldloc.0
IL_0015: ldstr ""string 1""
IL_001a: call ""System.ReadOnlySpan<char> System.MemoryExtensions.AsSpan(string)""
IL_001f: call ""bool System.MemoryExtensions.SequenceEqual<char>(System.ReadOnlySpan<char>, System.ReadOnlySpan<char>)""
Copy link
Member

@jcouv jcouv Feb 15, 2022

Choose a reason for hiding this comment

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

nit: Might it be worthwhile to produce a private implementation help that would do AsSpan and SequenceEqual, so that we don't repeat it in every arm? #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

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

Will leave as is since that would only shrink each call site by one method call.

Copy link
Member

Choose a reason for hiding this comment

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

Don't we expect multiple call sites though?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this would shrink each call site by one method call. It's not clear how that might affect perf though, particularly with respect to inlining. As we discussed offline, let's leave this calling pattern as is and address any specific perf issues as issues are identified.

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

Done with review pass (iteration 4)

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks (iteration 6)

@cston
Copy link
Member Author

cston commented Feb 16, 2022

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 4 pipeline(s).

@cston cston merged commit 8da7001 into dotnet:features/patterns-span-char Feb 17, 2022
@cston cston deleted the 44388-comments branch February 17, 2022 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants