Skip to content

Commit

Permalink
Address some PROTOTYPE markers
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv committed Oct 25, 2021
1 parent 3fc766e commit 025f398
Show file tree
Hide file tree
Showing 25 changed files with 976 additions and 312 deletions.
38 changes: 19 additions & 19 deletions src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -398,16 +398,16 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
case BoundKind.IndexerAccess:
return CheckPropertyValueKind(node, expr, valueKind, checkingReceiver, diagnostics);

case BoundKind.IndexOrRangePatternIndexerAccess:
var patternIndexer = ((BoundIndexOrRangePatternIndexerAccess)expr);
if (patternIndexer.PatternSymbol.Kind == SymbolKind.Property)
case BoundKind.IndexOrRangeIndexerFallbackAccess:
var fallbackIndexer = (BoundIndexOrRangeIndexerFallbackAccess)expr;
if (fallbackIndexer.PatternSymbol.Kind == SymbolKind.Property)
{
// If this is an Index indexer, PatternSymbol should be a property, pointing to the
// pattern indexer. If it's a Range access, it will be a method, pointing to a Slice method
// fallback indexer. If it's a Range access, it will be a method, pointing to a Slice method
// and it's handled below as part of invocations.
return CheckPropertyValueKind(node, expr, valueKind, checkingReceiver, diagnostics);
}
Debug.Assert(patternIndexer.PatternSymbol.Kind == SymbolKind.Method);
Debug.Assert(fallbackIndexer.PatternSymbol.Kind == SymbolKind.Method);
break;

case BoundKind.EventAccess:
Expand Down Expand Up @@ -589,9 +589,9 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
checkingReceiver,
diagnostics);

case BoundKind.IndexOrRangePatternIndexerAccess:
var patternIndexer = (BoundIndexOrRangePatternIndexerAccess)expr;
// If we got here this should be a pattern indexer taking a Range,
case BoundKind.IndexOrRangeIndexerFallbackAccess:
var patternIndexer = (BoundIndexOrRangeIndexerFallbackAccess)expr;
// If we got here this should be a fallback indexer taking a Range,
// meaning that the pattern symbol must be a method (either Slice or Substring)
return CheckMethodReturnValueKind(
(MethodSymbol)patternIndexer.PatternSymbol,
Expand Down Expand Up @@ -2347,12 +2347,12 @@ internal static bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint
diagnostics,
isRefEscape: true);

case BoundKind.IndexOrRangePatternIndexerAccess:
var patternIndexer = (BoundIndexOrRangePatternIndexerAccess)expr;
case BoundKind.IndexOrRangeIndexerFallbackAccess:
var fallbackIndexer = (BoundIndexOrRangeIndexerFallbackAccess)expr;
RefKind refKind;
ImmutableArray<ParameterSymbol> parameters;

switch (patternIndexer.PatternSymbol)
switch (fallbackIndexer.PatternSymbol)
{
case PropertySymbol p:
refKind = p.RefKind;
Expand All @@ -2372,11 +2372,11 @@ internal static bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint
}

return CheckInvocationEscape(
patternIndexer.Syntax,
patternIndexer.PatternSymbol,
patternIndexer.Receiver,
fallbackIndexer.Syntax,
fallbackIndexer.PatternSymbol,
fallbackIndexer.Receiver,
parameters,
ImmutableArray.Create<BoundExpression>(patternIndexer.Argument),
ImmutableArray.Create<BoundExpression>(fallbackIndexer.Argument),
default,
default,
checkingReceiver,
Expand Down Expand Up @@ -2618,8 +2618,8 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin
scopeOfTheContainingExpression,
isRefEscape: false);

case BoundKind.IndexOrRangePatternIndexerAccess:
var patternIndexer = (BoundIndexOrRangePatternIndexerAccess)expr;
case BoundKind.IndexOrRangeIndexerFallbackAccess:
var patternIndexer = (BoundIndexOrRangeIndexerFallbackAccess)expr;
var parameters = patternIndexer.PatternSymbol switch
{
PropertySymbol p => p.Parameters,
Expand Down Expand Up @@ -3040,8 +3040,8 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint
diagnostics,
isRefEscape: false);

case BoundKind.IndexOrRangePatternIndexerAccess:
var patternIndexer = (BoundIndexOrRangePatternIndexerAccess)expr;
case BoundKind.IndexOrRangeIndexerFallbackAccess:
var patternIndexer = (BoundIndexOrRangeIndexerFallbackAccess)expr;
var patternSymbol = patternIndexer.PatternSymbol;
var parameters = patternSymbol switch
{
Expand Down
95 changes: 60 additions & 35 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7736,29 +7736,30 @@ private BoundExpression BindIndexerAccess(ExpressionSyntax node, BoundExpression
LookupOptions lookupOptions = expr.Kind == BoundKind.BaseReference ? LookupOptions.UseBaseReferenceAccessibility : LookupOptions.Default;
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
this.LookupMembersWithFallback(lookupResult, expr.Type, WellKnownMemberNames.Indexer, arity: 0, useSiteInfo: ref useSiteInfo, options: lookupOptions);
diagnostics.Add(node, useSiteInfo);

// Store, rather than return, so that we can release resources.
BoundExpression indexerAccessExpression;

if (!lookupResult.IsMultiViable)
{
if (TryBindIndexOrRangeIndexer(
if (TryBindIndexOrRangeIndexerFallback(
node,
expr,
analyzedArguments,
diagnostics,
out var patternIndexerAccess))
out var indexerFallbackAccess))
{
indexerAccessExpression = patternIndexerAccess;
indexerAccessExpression = indexerFallbackAccess;
}
else
{
diagnostics.Add(node, useSiteInfo);
indexerAccessExpression = BadIndexerExpression(node, expr, analyzedArguments, lookupResult.Error, diagnostics);
}
}
else
{
diagnostics.Add(node, useSiteInfo);
ArrayBuilder<PropertySymbol> indexerGroup = ArrayBuilder<PropertySymbol>.GetInstance();
foreach (Symbol symbol in lookupResult.Symbols)
{
Expand Down Expand Up @@ -7889,7 +7890,6 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
bool allowRefOmittedArguments = receiverOpt.IsExpressionOfComImportType();
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
this.OverloadResolution.PropertyOverloadResolution(propertyGroup, receiverOpt, analyzedArguments, overloadResolutionResult, allowRefOmittedArguments, ref useSiteInfo);
diagnostics.Add(syntax, useSiteInfo);
BoundExpression propertyAccess;

if (analyzedArguments.HasDynamicArgument && overloadResolutionResult.HasAnyApplicableMember)
Expand All @@ -7914,14 +7914,14 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(

if (!analyzedArguments.HasErrors)
{
if (TryBindIndexOrRangeIndexer(
if (TryBindIndexOrRangeIndexerFallback(
syntax,
receiverOpt,
analyzedArguments,
diagnostics,
out var patternIndexerAccess))
out var indexerFallbackAccess))
{
return patternIndexerAccess;
return indexerFallbackAccess;
}
else
{
Expand All @@ -7941,6 +7941,8 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
memberGroup: candidates,
typeContainingConstructor: null,
delegateTypeBeingInvoked: null);

diagnostics.Add(syntax, useSiteInfo);
}
}

Expand All @@ -7961,6 +7963,8 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
}
else
{
diagnostics.Add(syntax, useSiteInfo);

MemberResolutionResult<PropertySymbol> resolutionResult = overloadResolutionResult.ValidResult;
PropertySymbol property = resolutionResult.Member;
RefKind? receiverRefKind = receiverOpt?.GetRefKind();
Expand Down Expand Up @@ -8020,14 +8024,14 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
}

#nullable enable
private bool TryBindIndexOrRangeIndexer(
private bool TryBindIndexOrRangeIndexerFallback(
SyntaxNode syntax,
BoundExpression? receiverOpt,
AnalyzedArguments arguments,
BindingDiagnosticBag diagnostics,
[NotNullWhen(true)] out BoundIndexOrRangePatternIndexerAccess? patternIndexerAccess)
[NotNullWhen(true)] out BoundIndexOrRangeIndexerFallbackAccess? indexerFallbackAccess)
{
patternIndexerAccess = null;
indexerFallbackAccess = null;

// Verify a few things up-front, namely that we have a single argument
// to this indexer that has an Index or Range type and that there is
Expand All @@ -8053,24 +8057,20 @@ private bool TryBindIndexOrRangeIndexer(
}

bool argIsIndex = argIsIndexNotRange.Value();
var useSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
if (!TryFindIndexOrRangeIndexerPattern(receiverOpt, receiverType, argIsIndex: argIsIndex,
out PropertySymbol? lengthOrCountProperty, out Symbol? patternSymbol, diagnostics, ref useSiteInfo))
if (!TryFindIndexOrRangeIndexerFallback(syntax, receiverOpt, receiverType, argIsIndex: argIsIndex,
out PropertySymbol? lengthOrCountProperty, out Symbol? patternSymbol, diagnostics))
{
return false;
}

patternIndexerAccess = new BoundIndexOrRangePatternIndexerAccess(
indexerFallbackAccess = new BoundIndexOrRangeIndexerFallbackAccess(
syntax,
receiverOpt,
lengthOrCountProperty,
patternSymbol,
BindToNaturalType(argument, diagnostics),
patternSymbol.GetTypeOrReturnType().Type);

ReportDiagnosticsIfObsolete(diagnostics, patternSymbol, syntax, hasBaseReceiver: false);
ReportDiagnosticsIfObsolete(diagnostics, lengthOrCountProperty, syntax, hasBaseReceiver: false);

if (!argIsIndex)
{
checkWellKnown(WellKnownMember.System_Range__get_Start);
Expand Down Expand Up @@ -8098,15 +8098,17 @@ void checkWellKnown(WellKnownMember member)
}
}

private bool TryFindIndexOrRangeIndexerPattern(
/// <summary>
/// Finds pattern-based fallback indexer and Length/Count property.
/// </summary>
private bool TryFindIndexOrRangeIndexerFallback(
SyntaxNode syntax,
BoundExpression? receiverOpt,
TypeSymbol receiverType,
bool argIsIndex,
[NotNullWhen(true)] out PropertySymbol? lengthOrCountProperty,
[NotNullWhen(true)] out Symbol? patternSymbol,
// PROTOTYPE(list-patterns) We should take either of these and adjust the caller.
BindingDiagnosticBag diagnostics,
ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
BindingDiagnosticBag diagnostics)
{
// SPEC:

Expand All @@ -8120,10 +8122,12 @@ private bool TryFindIndexOrRangeIndexerPattern(

var lookupResult = LookupResult.GetInstance();

if (TryLookupLengthOrCount(receiverType, lookupResult, out lengthOrCountProperty, ref useSiteInfo) &&
TryFindIndexOrRangeIndexerPattern(lookupResult, receiverOpt, receiverType, argIsIndex, out patternSymbol, diagnostics, ref useSiteInfo))
if (TryLookupLengthOrCount(syntax, receiverType, lookupResult, out lengthOrCountProperty, diagnostics) &&
TryFindIndexOrRangeIndexerFallback(syntax, lookupResult, receiverOpt, receiverType, argIsIndex, out patternSymbol, diagnostics))
{
CheckImplicitThisCopyInReadOnlyMember(receiverOpt, lengthOrCountProperty.GetMethod, diagnostics);
var lengthAccess = new BoundPropertyAccess(syntax, receiverOpt, lengthOrCountProperty, LookupResultKind.Viable, lengthOrCountProperty.Type);
CheckPropertyValueKind(syntax, lengthAccess, BindValueKind.RValue, checkingReceiver: false, diagnostics);

lookupResult.Free();
return true;
}
Expand All @@ -8133,16 +8137,22 @@ private bool TryFindIndexOrRangeIndexerPattern(
return false;
}

private bool TryFindIndexOrRangeIndexerPattern(
/// <summary>
/// Finds pattern-based fallback indexer:
/// - for Index indexer, this will find `this[int]`.
/// - for Range indexer, this will find `Slice(int, int)` or `string.Substring(int, int)`.
/// </summary>
private bool TryFindIndexOrRangeIndexerFallback(
SyntaxNode syntax,
LookupResult lookupResult,
BoundExpression? receiverOpt,
TypeSymbol receiverType,
bool argIsIndex,
[NotNullWhen(true)] out Symbol? patternSymbol,
// PROTOTYPE(list-patterns) We should take either of these and adjust the caller.
BindingDiagnosticBag diagnostics,
ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
BindingDiagnosticBag diagnostics)
{
var useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);

Debug.Assert(lookupResult.IsClear);
if (argIsIndex)
{
Expand Down Expand Up @@ -8171,6 +8181,9 @@ candidate is PropertySymbol property &&
{
// note: implicit copy check on the indexer accessor happens in CheckPropertyValueKind
patternSymbol = property;
property.AddUseSiteInfo(ref useSiteInfo);
diagnostics.Add(syntax, useSiteInfo);
ReportDiagnosticsIfObsolete(diagnostics, property, syntax, hasBaseReceiver: false);
return true;
}
}
Expand All @@ -8181,7 +8194,6 @@ candidate is PropertySymbol property &&
Debug.Assert(!argIsIndex);
// Look for Substring
var substring = (MethodSymbol)Compilation.GetSpecialTypeMember(SpecialMember.System_String__Substring);
// PROTOTYPE(list-patterns) Consider reporting a missing member for string.Substring
if (substring is object)
{
patternSymbol = substring;
Expand Down Expand Up @@ -8218,6 +8230,9 @@ method.OriginalDefinition is var original &&
original.Parameters[1] is { Type: { SpecialType: SpecialType.System_Int32 }, RefKind: RefKind.None })
{
patternSymbol = method;
method.AddUseSiteInfo(ref useSiteInfo);
diagnostics.Add(syntax, useSiteInfo);
ReportDiagnosticsIfObsolete(diagnostics, method, syntax, hasBaseReceiver: false);
CheckImplicitThisCopyInReadOnlyMember(receiverOpt, method, diagnostics);
return true;
}
Expand All @@ -8230,18 +8245,25 @@ method.OriginalDefinition is var original &&
}

private bool TryLookupLengthOrCount(
SyntaxNode syntax,
TypeSymbol receiverType,
LookupResult lookupResult,
[NotNullWhen(true)] out PropertySymbol? lengthOrCountProperty,
ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
BindingDiagnosticBag diagnostics)
{
Debug.Assert(lookupResult.IsClear);
// PROTOTYPE(list-patterns) Assert about whether diagnostics and dependencies are being accumulated.
return tryLookupLengthOrCount(WellKnownMemberNames.LengthPropertyName, out lengthOrCountProperty, ref useSiteInfo) ||
tryLookupLengthOrCount(WellKnownMemberNames.CountPropertyName, out lengthOrCountProperty, ref useSiteInfo);
if (tryLookupLengthOrCount(WellKnownMemberNames.LengthPropertyName, out lengthOrCountProperty, diagnostics) ||
tryLookupLengthOrCount(WellKnownMemberNames.CountPropertyName, out lengthOrCountProperty, diagnostics))
{
ReportDiagnosticsIfObsolete(diagnostics, lengthOrCountProperty, syntax, hasBaseReceiver: false);
return true;
}

bool tryLookupLengthOrCount(string propertyName, out PropertySymbol? valid, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
return false;

bool tryLookupLengthOrCount(string propertyName, [NotNullWhen(true)] out PropertySymbol? valid, BindingDiagnosticBag diagnostics)
{
var useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
LookupMembersInType(
lookupResult,
receiverType,
Expand All @@ -8263,8 +8285,11 @@ lookupResult.Symbols[0] is PropertySymbol property &&
{
lookupResult.Clear();
valid = property;
property.AddUseSiteInfo(ref useSiteInfo);
diagnostics.Add(syntax, useSiteInfo);
return true;
}

lookupResult.Clear();
valid = null;
return false;
Expand Down
Loading

0 comments on commit 025f398

Please sign in to comment.