Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ce62431
Add well-known members
DoctorKrolic Jan 11, 2024
ed3da0e
Better null-annotate `TryGetWellKnownTypeMember`
DoctorKrolic Jan 11, 2024
6958b61
Optimize for 2 arguments
DoctorKrolic Jan 11, 2024
ba7663d
Optimize for 3 arguments
DoctorKrolic Jan 11, 2024
9e10fe6
Optimize for 4 arguments
DoctorKrolic Jan 11, 2024
db98d9f
Test concat of 5 chars
DoctorKrolic Jan 12, 2024
bfb7388
Add missing grouping cases for concat of 4
DoctorKrolic Jan 12, 2024
ce042d0
Add missing tests for concat 2 arguments case
DoctorKrolic Jan 12, 2024
05f8250
Extract span-based rewrite into common helper and try to merge with u…
DoctorKrolic Jan 13, 2024
95d901f
Merge branch 'dotnet:main' into concat-string-char-v2
DoctorKrolic Jan 24, 2024
a288d21
Handle missing `object.ToString`
DoctorKrolic Jan 24, 2024
176f3e6
Handle `constantChar.ToString()` case
DoctorKrolic Jan 24, 2024
e1766d3
Fix tests on .NET Framework
DoctorKrolic Jan 24, 2024
e4e26f1
Move assert to avoid nullability warning
DoctorKrolic Jan 24, 2024
2c4bf14
Rename
DoctorKrolic Jan 29, 2024
70656d5
Use array builder
DoctorKrolic Jan 30, 2024
da90a6b
Use block body
DoctorKrolic Jan 30, 2024
f5f7efe
Revert naming
DoctorKrolic Jan 30, 2024
e2ea475
Feedback
DoctorKrolic Jan 30, 2024
404d7fc
Get member from compilation
DoctorKrolic Jan 30, 2024
b6bf346
Improve error location of missing `object.ToString()` for concatenati…
DoctorKrolic Jan 31, 2024
083c380
Don't bother about user-made concat calls and leave them as is
DoctorKrolic Feb 3, 2024
1118dcf
Handle case when `char` doesn't override `object.ToString()`
DoctorKrolic Feb 3, 2024
2b11728
Fix
DoctorKrolic Feb 4, 2024
6c3423e
Track sequence locals
DoctorKrolic Feb 6, 2024
54765fa
Early return
DoctorKrolic Feb 6, 2024
199862e
Still produce span-based concat when `char` doesn't directly override…
DoctorKrolic Feb 6, 2024
91888a3
Throw unreachable exception
DoctorKrolic Feb 6, 2024
50bf4e2
Simplify
DoctorKrolic Feb 6, 2024
0f6302d
Drop
DoctorKrolic Feb 6, 2024
db25bda
Simplify
DoctorKrolic Feb 6, 2024
53c529f
Inline helper back
DoctorKrolic Feb 6, 2024
201fd04
Use pooled hash set
DoctorKrolic Feb 7, 2024
49a865f
Use switch statement
DoctorKrolic Feb 7, 2024
a3a58a6
Use containing type
DoctorKrolic Feb 7, 2024
1d3447c
Assert
DoctorKrolic Feb 7, 2024
3634b2f
Convert to `foreach`
DoctorKrolic Feb 8, 2024
0b048b8
Move into `if`
DoctorKrolic Feb 8, 2024
a384b97
Free pooled object
DoctorKrolic Feb 8, 2024
05a2e3c
Remove assert
DoctorKrolic Feb 8, 2024
71ea57d
Free
DoctorKrolic Feb 8, 2024
0cc529d
Handle ROS constructor ref kinds other than `ref readonly` or `in`
DoctorKrolic Feb 8, 2024
8d3a40b
Support `await` scenarios
DoctorKrolic Feb 12, 2024
04046af
Pass ref kind
DoctorKrolic Feb 12, 2024
323b50a
Feedback
DoctorKrolic Feb 12, 2024
7a54762
Unify handling of constant and not constant chars during string concat
AlekseyTs Feb 13, 2024
0f6c8e4
Fixup
AlekseyTs Feb 13, 2024
c694f10
Reduce amount of scenarios affected by unification
AlekseyTs Feb 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -558,11 +558,11 @@ private static BoundExpression BadExpression(SyntaxNode syntax, TypeSymbol resul
return new BoundBadExpression(syntax, LookupResultKind.NotReferencable, ImmutableArray<Symbol?>.Empty, children, resultType);
}

private bool TryGetWellKnownTypeMember<TSymbol>(SyntaxNode? syntax, WellKnownMember member, out TSymbol symbol, bool isOptional = false, Location? location = null) where TSymbol : Symbol
private bool TryGetWellKnownTypeMember<TSymbol>(SyntaxNode? syntax, WellKnownMember member, [NotNullWhen(true)] out TSymbol? symbol, bool isOptional = false, Location? location = null) where TSymbol : Symbol
{
Debug.Assert((syntax != null) ^ (location != null));

symbol = (TSymbol)Binder.GetWellKnownTypeMember(_compilation, member, _diagnostics, syntax: syntax, isOptional: isOptional, location: location);
symbol = (TSymbol?)Binder.GetWellKnownTypeMember(_compilation, member, _diagnostics, syntax: syntax, isOptional: isOptional, location: location);
return symbol is { };
}

Expand Down Expand Up @@ -617,7 +617,7 @@ public override BoundNode VisitTypeOfOperator(BoundTypeOfOperator node)
var type = this.VisitType(node.Type);

// Emit needs this helper
MethodSymbol getTypeFromHandle;
MethodSymbol? getTypeFromHandle;
if (!TryGetWellKnownTypeMember(node.Syntax, WellKnownMember.System_Type__GetTypeFromHandle, out getTypeFromHandle))
{
return new BoundTypeOfOperator(node.Syntax, sourceType, null, type, hasErrors: true);
Expand All @@ -634,7 +634,7 @@ public override BoundNode VisitRefTypeOperator(BoundRefTypeOperator node)
var type = this.VisitType(node.Type);

// Emit needs this helper
MethodSymbol getTypeFromHandle;
MethodSymbol? getTypeFromHandle;
if (!TryGetWellKnownTypeMember(node.Syntax, WellKnownMember.System_Type__GetTypeFromHandle, out getTypeFromHandle))
{
return new BoundRefTypeOperator(node.Syntax, operand, null, type, hasErrors: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private BoundExpression MakeUtf8Span(BoundExpression node, IReadOnlyList<byte>?
BadExpression(node.Syntax, byteArray, ImmutableArray<BoundExpression>.Empty) :
MakeUnderlyingArrayForUtf8Span(node.Syntax, byteArray, bytes, out length);

if (!TryGetWellKnownTypeMember<MethodSymbol>(node.Syntax, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, out MethodSymbol ctor))
if (!TryGetWellKnownTypeMember<MethodSymbol>(node.Syntax, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, out MethodSymbol? ctor))
{
result = BadExpression(node.Syntax, node.Type, ImmutableArray<BoundExpression>.Empty);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private BoundExpression RewriteWindowsRuntimeEventAssignmentOperator(SyntaxNode
BoundExpression? clearCall = null;
if (kind == EventAssignmentKind.Assignment)
{
MethodSymbol clearMethod;
MethodSymbol? clearMethod;
if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveAllEventHandlers, out clearMethod))
{
clearCall = MakeCall(
Expand Down Expand Up @@ -154,7 +154,7 @@ private BoundExpression RewriteWindowsRuntimeEventAssignmentOperator(SyntaxNode

BoundExpression marshalCall;

MethodSymbol marshalMethod;
MethodSymbol? marshalMethod;
if (TryGetWellKnownTypeMember(syntax, helper, out marshalMethod))
{
marshalMethod = marshalMethod.Construct(eventType);
Expand Down Expand Up @@ -248,7 +248,7 @@ private BoundExpression MakeEventAccess(

BoundExpression getOrCreateCall;

MethodSymbol getOrCreateMethod;
MethodSymbol? getOrCreateMethod;
if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, out getOrCreateMethod))
{
getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);
Expand All @@ -266,7 +266,7 @@ private BoundExpression MakeEventAccess(
getOrCreateCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol?>.Empty, ImmutableArray.Create<BoundExpression>(fieldAccess), ErrorTypeSymbol.UnknownResultType);
}

PropertySymbol invocationListProperty;
PropertySymbol? invocationListProperty;
if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__InvocationList, out invocationListProperty))
{
MethodSymbol invocationListAccessor = invocationListProperty.GetMethod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ private BoundStatement InitializeFixedStatementStringLocal(
BoundExpression notNullCheck = _factory.MakeNullCheck(factory.Syntax, factory.Local(localSymbol), BinaryOperatorKind.NotEqual);
BoundExpression helperCall;

MethodSymbol offsetMethod;
MethodSymbol? offsetMethod;
if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__get_OffsetToStringData, out offsetMethod))
{
helperCall = factory.Call(receiver: null, method: offsetMethod);
Expand Down Expand Up @@ -534,7 +534,7 @@ private BoundStatement InitializeFixedStatementArrayLocal(
}
else
{
MethodSymbol lengthMethod;
MethodSymbol? lengthMethod;
if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Array__get_Length, out lengthMethod))
{
lengthCall = factory.Call(factory.Local(pinnedTemp), lengthMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)
BoundStatement boundLockTempInit = new BoundExpressionStatement(lockSyntax, assignmentToLockTemp);
BoundExpression exitCallExpr;

MethodSymbol exitMethod;
MethodSymbol? exitMethod;
if (TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Exit, out exitMethod))
{
exitCallExpr = BoundCall.Synthesized(
Expand All @@ -75,7 +75,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)

BoundStatement exitCall = new BoundExpressionStatement(lockSyntax, exitCallExpr);

MethodSymbol enterMethod;
MethodSymbol? enterMethod;

if ((TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter2, out enterMethod, isOptional: true) ||
TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter, out enterMethod)) && // If we didn't find the overload introduced in .NET 4.0, then use the older one.
Expand Down Expand Up @@ -153,7 +153,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)

BoundExpression enterCallExpr;

if ((object)enterMethod != null)
if ((object?)enterMethod != null)
{
Debug.Assert(enterMethod.ParameterCount == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ private BoundExpression MakeNewT(SyntaxNode syntax, TypeParameterSymbol typePara
// if struct defines one.
// Since we cannot know if T has a parameterless constructor statically,
// we must call Activator.CreateInstance unconditionally.
MethodSymbol method;
MethodSymbol? method;

if (!this.TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Activator__CreateInstance_T, out method))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private BoundNode VisitStackAllocArrayCreationBase(BoundStackAllocArrayCreationB
stackAllocNode.Syntax, elementType, stackSize, initializerOpt, _compilation.CreatePointerTypeSymbol(elementType));

BoundExpression constructorCall;
if (TryGetWellKnownTypeMember(stackAllocNode.Syntax, WellKnownMember.System_Span_T__ctor_Pointer, out MethodSymbol spanConstructor))
if (TryGetWellKnownTypeMember(stackAllocNode.Syntax, WellKnownMember.System_Span_T__ctor_Pointer, out MethodSymbol? spanConstructor))
{
constructorCall = _factory.New((MethodSymbol)spanConstructor.SymbolAsMember(spanType), stackAllocNode, countTemp);
}
Expand Down
Loading