Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 8 additions & 9 deletions src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ internal MethodInfo ReplaceWithExtensionImplementation(out bool wasError)
var setMethod = replace(SetMethod);
Symbol symbol = ReferenceEquals(Symbol, Method) && method is not null ? method : Symbol;

Debug.Assert(SetMethod?.IsExtensionBlockMember() != true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Debug.Assert(SetMethod?.IsExtensionBlockMember() != true);

It is not obvious why this condition was correct for properties and isn't for indexers. Is it still worth asserting for properties?

wasError = (Method is not null && method is null) || (SetMethod is not null && setMethod is null);

return new MethodInfo(symbol, method, setMethod);
Expand Down Expand Up @@ -634,10 +633,11 @@ private BoundIndexerAccess BindIndexerDefaultArgumentsAndParamsCollection(BoundI
{
var coreValueKind = valueKind & ValueKindSignificantBitsMask;
AccessorKind accessorKind = GetIndexerAccessorKind(indexerAccess, valueKind);
var useSetAccessor = coreValueKind == BindValueKind.Assignable && indexerAccess.Indexer.RefKind != RefKind.Ref;
PropertySymbol indexer = indexerAccess.Indexer;
var useSetAccessor = coreValueKind == BindValueKind.Assignable && indexer.RefKind != RefKind.Ref;
var accessorForDefaultArguments = useSetAccessor
? indexerAccess.Indexer.GetOwnOrInheritedSetMethod()
: indexerAccess.Indexer.GetOwnOrInheritedGetMethod();
? indexer.GetOwnOrInheritedSetMethod()
: indexer.GetOwnOrInheritedGetMethod();
if (accessorForDefaultArguments is not null)
{
var argumentsBuilder = ArrayBuilder<BoundExpression>.GetInstance(accessorForDefaultArguments.ParameterCount);
Expand All @@ -664,7 +664,7 @@ private BoundIndexerAccess BindIndexerDefaultArgumentsAndParamsCollection(BoundI
}

BitVector defaultArguments = default;
Debug.Assert(parameters.Length == indexerAccess.Indexer.Parameters.Length);
Debug.Assert(parameters.Length == indexer.Parameters.Length);

ImmutableArray<string?> argumentNamesOpt = indexerAccess.ArgumentNamesOpt;

Expand All @@ -690,9 +690,8 @@ private BoundIndexerAccess BindIndexerDefaultArgumentsAndParamsCollection(BoundI
}
}

// Tracked by https://github.com/dotnet/roslyn/issues/78829 : caller info on extension parameter of an extension indexer will need the receiver/argument to be passed
Debug.Assert(!indexerAccess.Indexer.IsExtensionBlockMember());
BindDefaultArguments(indexerAccess.Syntax, parameters, extensionReceiver: null, argumentsBuilder, refKindsBuilderOpt, namesBuilder, ref argsToParams, out defaultArguments, indexerAccess.Expanded, enableCallerInfo: true, diagnostics: diagnostics);
BoundExpression? extensionReceiver = indexer.IsExtensionBlockMember() ? indexerAccess.ReceiverOpt : null;
BindDefaultArguments(indexerAccess.Syntax, parameters, extensionReceiver, argumentsBuilder, refKindsBuilderOpt, namesBuilder, ref argsToParams, out defaultArguments, indexerAccess.Expanded, enableCallerInfo: true, diagnostics: diagnostics);

if (namesBuilder is object)
{
Expand All @@ -704,7 +703,7 @@ private BoundIndexerAccess BindIndexerDefaultArgumentsAndParamsCollection(BoundI
indexerAccess = indexerAccess.Update(
indexerAccess.ReceiverOpt,
indexerAccess.InitialBindingReceiverIsSubjectToCloning,
indexerAccess.Indexer,
indexer,
argumentsBuilder.ToImmutableAndFree(),
argumentNamesOpt,
refKindsBuilderOpt?.ToImmutableOrNull() ?? default,
Expand Down
8 changes: 8 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,14 @@ internal static void ReportDiagnosticsIfDisallowedExtension(BindingDiagnosticBag
}
}

internal static void ReportDiagnosticsIfDisallowedExtensionIndexer(BindingDiagnosticBag diagnostics, PropertySymbol property, SyntaxNode syntax)
{
if (property.IsExtensionBlockMember())
Copy link
Contributor

@AlekseyTs AlekseyTs Dec 10, 2025

Choose a reason for hiding this comment

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

property

How do we know that this is an indexer? #Pending

{
MessageID.IDS_FeatureExtensionIndexers.CheckFeatureAvailability(diagnostics, syntax);
Copy link
Contributor

@AlekseyTs AlekseyTs Dec 11, 2025

Choose a reason for hiding this comment

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

MessageID.IDS_FeatureExtensionIndexers.CheckFeatureAvailability(diagnostics, syntax);

Consider skipping the check if the indexer is declared in the same module. We already complained on the declaration #Pending

}
}

internal static void ReportDiagnosticsIfUnmanagedCallersOnly(BindingDiagnosticBag diagnostics, MethodSymbol symbol, SyntaxNodeOrToken syntax, bool isDelegateConversion)
{
var unmanagedCallersOnlyAttributeData = symbol.GetUnmanagedCallersOnlyAttributeData(forceComplete: false);
Expand Down
4 changes: 3 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ private ImmutableArray<Symbol> BindExtensionMemberCref(ExtensionMemberCrefSyntax
memberName = GetOperatorMethodName(operatorSyntax);
parameters = operatorSyntax.Parameters;
}
// PROTOTYPE handle IndexerMemberCrefSyntax and check for LangVersion

if (memberName == null)
{
Expand Down Expand Up @@ -326,7 +327,8 @@ ImmutableArray<Symbol> computeSortedAndFilteredCrefExtensionMembers(NamespaceOrT

foreach (var candidate in candidates)
{
if (!SourceMemberContainerTypeSymbol.IsAllowedExtensionMember(candidate))
// PROTOTYPE we should find all the members supported in latest LangVer, but report if they require a new LangVer than current
if (!SourceMemberContainerTypeSymbol.IsAllowedExtensionMember(candidate, LanguageVersion.Preview))
{
continue;
}
Expand Down
Loading
Loading