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 22, 2021
1 parent 039cc3d commit 4ab858d
Show file tree
Hide file tree
Showing 11 changed files with 500 additions and 116 deletions.
56 changes: 35 additions & 21 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7889,7 +7889,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 Down Expand Up @@ -7941,6 +7940,8 @@ private BoundExpression BindIndexerOrIndexedPropertyAccess(
memberGroup: candidates,
typeContainingConstructor: null,
delegateTypeBeingInvoked: null);

diagnostics.Add(syntax, useSiteInfo);
}
}

Expand All @@ -7961,6 +7962,7 @@ 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 @@ -8053,9 +8055,8 @@ 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 (!TryFindIndexOrRangeIndexerPattern(syntax, receiverOpt, receiverType, argIsIndex: argIsIndex,
out PropertySymbol? lengthOrCountProperty, out Symbol? patternSymbol, diagnostics))
{
return false;
}
Expand All @@ -8068,9 +8069,6 @@ private bool TryBindIndexOrRangeIndexer(
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 @@ -8099,14 +8097,13 @@ void checkWellKnown(WellKnownMember member)
}

private bool TryFindIndexOrRangeIndexerPattern(
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,9 +8117,10 @@ 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) &&
TryFindIndexOrRangeIndexerPattern(syntax, lookupResult, receiverOpt, receiverType, argIsIndex, out patternSymbol, diagnostics))
{
ReportDiagnosticsIfObsolete(diagnostics, patternSymbol, syntax, hasBaseReceiver: false); // TODO2 factor
CheckImplicitThisCopyInReadOnlyMember(receiverOpt, lengthOrCountProperty.GetMethod, diagnostics);
lookupResult.Free();
return true;
Expand All @@ -8134,15 +8132,16 @@ private bool TryFindIndexOrRangeIndexerPattern(
}

private bool TryFindIndexOrRangeIndexerPattern(
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 +8170,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);

return true;
}
}
Expand All @@ -8181,7 +8183,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 +8219,8 @@ 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);
CheckImplicitThisCopyInReadOnlyMember(receiverOpt, method, diagnostics);
return true;
}
Expand All @@ -8230,18 +8233,26 @@ 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);
ReportDiagnosticsIfObsolete(diagnostics, lengthOrCountProperty.GetMethod, 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 +8274,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
22 changes: 12 additions & 10 deletions src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ private BoundPattern BindSlicePattern(
{
sliceType = inputType;
}
else if (TryPerformPatternIndexerLookup(node, inputType, argIsIndex: false, out indexerAccess, out Symbol? patternSymbol, lengthProperty: out _, diagnostics))
else if (TryBindIndexerForPattern(node, inputType, argIsIndex: false, out indexerAccess, out Symbol? patternSymbol, lengthProperty: out _, diagnostics))
{
if (patternSymbol is MethodSymbol method)
{
Expand Down Expand Up @@ -280,6 +280,8 @@ private BoundListPattern BindListPattern(
bool hasErrors,
BindingDiagnosticBag diagnostics)
{
CheckFeatureAvailability(node, MessageID.IDS_FeatureListPattern, diagnostics);

TypeSymbol elementType;
BoundIndexerAccess? indexerAccess = null;
PropertySymbol? indexerSymbol = null;
Expand All @@ -295,7 +297,7 @@ private BoundListPattern BindListPattern(
elementType = ((ArrayTypeSymbol)inputType).ElementType;
hasErrors |= !TryGetSpecialTypeMember(Compilation, SpecialMember.System_Array__Length, node, diagnostics, out lengthProperty);
}
else if (TryPerformPatternIndexerLookup(node, narrowedType, argIsIndex: true, out indexerAccess, out Symbol? patternSymbol, out lengthProperty, diagnostics))
else if (TryBindIndexerForPattern(node, narrowedType, argIsIndex: true, out indexerAccess, out Symbol? patternSymbol, out lengthProperty, diagnostics))
{
if (patternSymbol is PropertySymbol indexer)
{
Expand Down Expand Up @@ -331,7 +333,7 @@ private BoundListPattern BindListPattern(
variableAccess: variableAccess, inputType: inputType, narrowedType: narrowedType, hasErrors);
}

private bool TryPerformPatternIndexerLookup(
private bool TryBindIndexerForPattern(
SyntaxNode syntax,
TypeSymbol receiverType,
bool argIsIndex,
Expand Down Expand Up @@ -379,14 +381,14 @@ private bool TryPerformPatternIndexerLookup(
switch (boundAccess)
{
case BoundIndexerAccess boundIndexerAccess:
Debug.Assert(!boundIndexerAccess.Indexer.IsStatic);

if (boundIndexerAccess.ResultKind == LookupResultKind.Viable &&
boundIndexerAccess.Indexer.GetMethod is { } getMethod &&
IsAccessible(getMethod, ref useSiteInfo) &&
TryLookupLengthOrCount(receiverType, lookupResult, out lengthProperty, ref useSiteInfo))
TryLookupLengthOrCount(syntax, receiverType, lookupResult, out lengthProperty, bindingDiagnostics) &&
!boundIndexerAccess.Indexer.IsStatic)
{
// PROTOTYPE(list-patterns) Can this be ever true? If so, move to if above
Debug.Assert(!boundIndexerAccess.Indexer.IsStatic);
ReportDiagnosticsIfObsolete(bindingDiagnostics, lengthProperty, syntax, hasBaseReceiver: false);
GetWellKnownTypeMember(argIsIndex ? WellKnownMember.System_Index__ctor : WellKnownMember.System_Range__ctor, bindingDiagnostics, syntax: syntax);
indexerAccess = BindIndexerDefaultArguments(boundIndexerAccess, BindValueKind.RValue, bindingDiagnostics);
found = true;
Expand All @@ -412,8 +414,8 @@ boundIndexerAccess.Indexer.GetMethod is { } getMethod &&
}

// If the argType is missing or the indexer lookup has failed, we will fallback to the implicit indexer support.
found = TryLookupLengthOrCount(receiverType, lookupResult, out lengthProperty, ref useSiteInfo) &&
TryFindIndexOrRangeIndexerPattern(lookupResult, receiverOpt: null, receiverType, argIsIndex, out patternSymbol, diagnostics, ref useSiteInfo);
found = TryLookupLengthOrCount(syntax, receiverType, lookupResult, out lengthProperty, diagnostics) &&
TryFindIndexOrRangeIndexerPattern(syntax, lookupResult, receiverOpt: null, receiverType, argIsIndex, out patternSymbol, diagnostics);

done:
if (found)
Expand Down Expand Up @@ -1458,7 +1460,7 @@ private ImmutableArray<BoundPropertySubpattern> BindPropertyPatternClause(
{
isLengthOrCount = receiverType.IsSZArray()
? ReferenceEquals(memberSymbol, Compilation.GetSpecialTypeMember(SpecialMember.System_Array__Length))
: TryPerformPatternIndexerLookup(node, receiverType, argIsIndex: true, indexerAccess: out _, patternSymbol: out _, lengthProperty: out _, BindingDiagnosticBag.Discarded);
: TryBindIndexerForPattern(node, receiverType, argIsIndex: true, indexerAccess: out _, patternSymbol: out _, lengthProperty: out _, BindingDiagnosticBag.Discarded);
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,10 +2000,13 @@ internal enum ErrorCode
WRN_MethGrpToNonDel = 8974,
ERR_LambdaExplicitReturnTypeVar = 8975,

// PROTOTYPE(list-patterns)
ERR_UnsupportedTypeForListPattern = 9200,
ERR_UnsupportedTypeForSlicePattern,
ERR_MisplacedSlicePattern,
#endregion

#region diagnostics introduced for C# 11.0

ERR_UnsupportedTypeForListPattern = 9000,
ERR_UnsupportedTypeForSlicePattern = 9001,
ERR_MisplacedSlicePattern = 9002,

#endregion

Expand Down
12 changes: 5 additions & 7 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,6 @@ internal enum MessageID
IDS_FeatureInferredDelegateType = MessageBase + 12799,
IDS_FeatureLambdaAttributes = MessageBase + 12800,

// PROTOTYPE(list-patterns) To reduce conflicts with upstream. Should be moved/indexed eventually.
IDS_FeatureListPattern = MessageBase + 12850,

IDS_FeatureWithOnAnonymousTypes = MessageBase + 12801,
IDS_FeatureExtendedPropertyPatterns = MessageBase + 12802,
IDS_FeatureStaticAbstractMembersInInterfaces = MessageBase + 12803,
Expand All @@ -238,7 +235,9 @@ internal enum MessageID
IDS_FeatureFileScopedNamespace = MessageBase + 12809,
IDS_FeatureParameterlessStructConstructors = MessageBase + 12810,
IDS_FeatureStructFieldInitializers = MessageBase + 12811,

IDS_FeatureGenericAttributes = MessageBase + 12812,
IDS_FeatureListPattern = MessageBase + 12813,
}

// Message IDs may refer to strings that need to be localized.
Expand Down Expand Up @@ -345,9 +344,12 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
// Checks are in the LanguageParser unless otherwise noted.
switch (feature)
{
// PREFER reporting diagnostics in binding when diagnostics do not affect the shape of the tree

// C# preview features.
case MessageID.IDS_FeatureStaticAbstractMembersInInterfaces: // semantic check
case MessageID.IDS_FeatureGenericAttributes: // semantic check
case MessageID.IDS_FeatureListPattern: // semantic check
return LanguageVersion.Preview;

// C# 10.0 features.
Expand Down Expand Up @@ -533,10 +535,6 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)

default:
throw ExceptionUtilities.UnexpectedValue(feature);

// PROTOTYPE(list-patterns)
case MessageID.IDS_FeatureListPattern:
return LanguageVersion.Preview;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,14 @@ private void LearnFromAnyNullPatterns(
case BoundITuplePattern _:
case BoundRelationalPattern _:
case BoundSlicePattern _:
case BoundListPattern lp:
break; // nothing to learn
case BoundTypePattern tp:
if (tp.IsExplicitNotNullTest)
{
LearnFromNullTest(inputSlot, inputType, ref this.State, markDependentSlotsNotNull: false);
}
break;
case BoundListPattern lp:
// PROTOTYPE(list-patterns)
break;
case BoundRecursivePattern rp:
{
if (rp.IsExplicitNotNullTest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,7 @@ private PatternSyntax ParseListPattern(bool whenIsKeyword)
SyntaxKind.CloseBracketToken,
static p => p.ParsePattern(Precedence.Conditional));
TryParseSimpleDesignation(out VariableDesignationSyntax designation, whenIsKeyword);
var result = _syntaxFactory.ListPattern(openBracket, list, closeBracket, designation);
return CheckFeatureAvailability(result, MessageID.IDS_FeatureListPattern);
return _syntaxFactory.ListPattern(openBracket, list, closeBracket, designation);
}
}
}
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ public enum SyntaxKind : ushort
AndPattern = 9032,
NotPattern = 9033,

// PROTOTYPE(list-patterns) new patterns added
// new patterns added in C# 11.0
SlicePattern = 9034,
ListPattern = 9035,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13637,11 +13637,16 @@ public void M()
}
";

// PROTOTYPE missing diagnostics (we're checking the Count property but not the accessor)
CreateCompilation(code, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
// (23,13): error CS0619: 'C.Count.get' is obsolete: 'error'
// _ = this[^1]; // 1, 2
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "this[^1]").WithArguments("C.Count.get", "error").WithLocation(23, 13),
// (23,13): error CS0619: 'C.this[int].get' is obsolete: 'error'
// _ = this[^1]; // 1, 2
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "this[^1]").WithArguments("C.this[int].get", "error").WithLocation(23, 13),
// (24,13): error CS0619: 'C.Count.get' is obsolete: 'error'
// _ = this[..]; // 3, 4
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "this[..]").WithArguments("C.Count.get", "error").WithLocation(24, 13),
// (24,13): error CS0619: 'C.Slice(int, int)' is obsolete: 'error'
// _ = this[..]; // 3, 4
Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "this[..]").WithArguments("C.Slice(int, int)", "error").WithLocation(24, 13)
Expand Down
Loading

0 comments on commit 4ab858d

Please sign in to comment.