Skip to content
Draft
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
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,11 @@ internal static BoundExpression GetUnderlyingCollectionExpressionElement(BoundCo
Debug.Assert(call.Method.Name == "Add");
return call.Arguments[call.InvokedAsExtensionMethod ? 1 : 0];
case BoundBadExpression badExpression:
if (badExpression.ChildBoundNodes is [BoundObjectOrCollectionValuePlaceholder, var child])
{
return child;
}

Debug.Assert(false); // Add test if we hit this assert.
return badExpression;
default:
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,12 @@ private BoundExpression MakeDeconstructInvocationExpression(
return MissingDeconstruct(receiver, rightSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result);
}

if (result.Kind == BoundKind.BadExpression)
{
outPlaceholders = default;
return result;
}

// Verify all the parameters (except "this" for extension methods) are out parameters.
// This prevents, for example, an unused params parameter after the out parameters.
var deconstructMethod = ((BoundCall)result).Method;
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6852,7 +6852,7 @@ private BoundObjectCreationExpression BindClassCreationExpressionContinued(
return creation;
}

private BoundExpression CreateBadClassCreationExpression(
private BoundBadExpression CreateBadClassCreationExpression(
SyntaxNode node,
SyntaxNode typeNode,
NamedTypeSymbol type,
Expand Down Expand Up @@ -10263,7 +10263,7 @@ private bool TryBindIndexOrRangeImplicitIndexer(
}

Debug.Assert(lengthOrCountAccess is BoundPropertyAccess);
Debug.Assert(indexerOrSliceAccess is BoundIndexerAccess or BoundCall);
Debug.Assert(indexerOrSliceAccess is BoundIndexerAccess or BoundCall or BoundBadExpression);
Debug.Assert(indexerOrSliceAccess.Type is not null);

implicitIndexerAccess = new BoundImplicitIndexerAccess(
Expand Down
89 changes: 72 additions & 17 deletions src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@
}
break;
case BoundKind.FunctionPointerInvocation:
case BoundKind.BadExpression:
break;
default:
throw ExceptionUtilities.UnexpectedValue(expression.Kind);
Expand All @@ -1118,7 +1119,7 @@
/// <param name="diagnostics">Diagnostics.</param>
/// <param name="queryClause">The syntax for the query clause generating this invocation expression, if any.</param>
/// <returns>BoundCall or error expression representing the invocation.</returns>
private BoundCall BindInvocationExpressionContinued(
private BoundExpression BindInvocationExpressionContinued(
SyntaxNode node,
SyntaxNode expression,
string methodName,
Expand Down Expand Up @@ -1972,18 +1973,17 @@
return null;
}

private BoundCall CreateBadCall(
private BoundExpression CreateBadCall(
SyntaxNode node,
string name,

Check failure on line 1978 in src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs#L1978

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs(1978,20): error IDE0060: (NETCORE_ENGINEERING_TELEMETRY=Build) Remove unused parameter 'name' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060)

Check failure on line 1978 in src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs

View check run for this annotation

Azure Pipelines / roslyn-CI

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs#L1978

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs(1978,20): error IDE0060: (NETCORE_ENGINEERING_TELEMETRY=Build) Remove unused parameter 'name' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060)
BoundExpression receiver,
ImmutableArray<MethodSymbol> methods,
LookupResultKind resultKind,
ImmutableArray<TypeWithAnnotations> typeArgumentsWithAnnotations,
AnalyzedArguments analyzedArguments,
bool invokedAsExtensionMethod,

Check failure on line 1984 in src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs#L1984

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs(1984,18): error IDE0060: (NETCORE_ENGINEERING_TELEMETRY=Build) Remove unused parameter 'invokedAsExtensionMethod' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060)
bool isDelegate)

Check failure on line 1985 in src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs

View check run for this annotation

Azure Pipelines / roslyn-CI (Correctness Correctness_Analyzers)

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs#L1985

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs(1985,18): error IDE0060: (NETCORE_ENGINEERING_TELEMETRY=Build) Remove unused parameter 'isDelegate' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060)

Check failure on line 1985 in src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs

View check run for this annotation

Azure Pipelines / roslyn-CI

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs#L1985

src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs(1985,18): error IDE0060: (NETCORE_ENGINEERING_TELEMETRY=Build) Remove unused parameter 'isDelegate' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060)
{
MethodSymbol method;
ImmutableArray<BoundExpression> args;
if (!typeArgumentsWithAnnotations.IsDefaultOrEmpty)
{
Expand All @@ -2010,24 +2010,83 @@
methods = constructedMethods.ToImmutableAndFree();
}

TypeSymbol resultType;

if (methods.Length == 1 && !IsUnboundGeneric(methods[0]))
{
method = methods[0];
resultType = methods[0].ReturnType;
}
else
{
var returnType = GetCommonTypeOrReturnType(methods) ?? new ExtendedErrorTypeSymbol(this.Compilation, string.Empty, arity: 0, errorInfo: null);
var methodContainer = (object)receiver != null && (object)receiver.Type != null
? receiver.Type
: this.ContainingType;
method = new ErrorMethodSymbol(methodContainer, returnType, name);
resultType = GetCommonTypeOrReturnType(methods) ?? new ExtendedErrorTypeSymbol(this.Compilation, string.Empty, arity: 0, errorInfo: null);
}

args = BuildArgumentsForErrorRecovery(analyzedArguments, methods);
var argNames = analyzedArguments.GetNames();
var argRefKinds = analyzedArguments.RefKinds.ToImmutableOrNull();
receiver = BindToTypeForErrorRecovery(receiver);
return BoundCall.ErrorCall(node, receiver, method, args, argNames, argRefKinds, isDelegate, invokedAsExtensionMethod: invokedAsExtensionMethod, originalMethods: methods, resultKind: resultKind, binder: this);
return ErrorCall(node, receiver, args, argRefKinds, methods, resultKind, resultType, binder: this);
}

private static BoundBadExpression ErrorCall(
SyntaxNode node,
BoundExpression receiverOpt,
ImmutableArray<BoundExpression> arguments,
ImmutableArray<RefKind> argumentRefKindsOpt,
ImmutableArray<MethodSymbol> originalMethods,
LookupResultKind resultKind,
TypeSymbol resultType,
Binder binder)
{
if (!originalMethods.IsEmpty)
resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);

var childBoundNodes = arguments.SelectAsArray((e, binder) => binder.BindToTypeForErrorRecovery(e), binder);

if (receiverOpt is not null)
{
childBoundNodes = childBoundNodes.Insert(0, binder.BindToTypeForErrorRecovery(receiverOpt));

RefKind receiverRefKind = RefKind.None;

if (originalMethods is [MethodSymbol singleCandidate])
{
if (singleCandidate.TryGetThisParameter(out var thisParameter)
&& thisParameter is object
&& !thisParameter.Type.TypeIsImmutable())
{
receiverRefKind = thisParameter.RefKind;
//if (thisRefKind.IsWritableReference())
//{
// WriteArgument(receiverOpt, thisRefKind, method);
//}
}

}
else if (!originalMethods.Any(m => m.MethodKind == MethodKind.Constructor && !m.ContainingType.IsStructType()))
{
receiverRefKind = RefKind.Ref;
}

if (!argumentRefKindsOpt.IsDefault)
{
argumentRefKindsOpt = argumentRefKindsOpt.Insert(0, receiverRefKind);
}
else if (receiverRefKind != RefKind.None)
{
var builder = ArrayBuilder<RefKind>.GetInstance(childBoundNodes.Length, RefKind.None);
builder[0] = receiverRefKind;
argumentRefKindsOpt = builder.ToImmutableAndFree();
}
}

return new BoundBadExpression(
syntax: node,
resultKind: resultKind,
symbols: originalMethods.Cast<MethodSymbol, Symbol>(),
childBoundNodes: childBoundNodes,
argumentRefKindsOpt: argumentRefKindsOpt,
type: resultType,
hasErrors: true);
}

private static bool IsUnboundGeneric(MethodSymbol method)
Expand Down Expand Up @@ -2251,22 +2310,18 @@
return BuildArgumentsForErrorRecovery(analyzedArguments, Enumerable.Empty<ImmutableArray<ParameterSymbol>>());
}

private BoundCall CreateBadCall(
private BoundExpression CreateBadCall(
SyntaxNode node,
BoundExpression expr,
LookupResultKind resultKind,
AnalyzedArguments analyzedArguments)
{
TypeSymbol returnType = new ExtendedErrorTypeSymbol(this.Compilation, string.Empty, arity: 0, errorInfo: null);
var methodContainer = expr.Type ?? this.ContainingType;
MethodSymbol method = new ErrorMethodSymbol(methodContainer, returnType, string.Empty);

var args = BuildArgumentsForErrorRecovery(analyzedArguments);
var argNames = analyzedArguments.GetNames();
var argRefKinds = analyzedArguments.RefKinds.ToImmutableOrNull();
var originalMethods = (expr.Kind == BoundKind.MethodGroup) ? ((BoundMethodGroup)expr).Methods : ImmutableArray<MethodSymbol>.Empty;

return BoundCall.ErrorCall(node, expr, method, args, argNames, argRefKinds, isDelegateCall: false, invokedAsExtensionMethod: false, originalMethods: originalMethods, resultKind: resultKind, binder: this);
return ErrorCall(node, expr, args, argRefKinds, originalMethods, resultKind: resultKind, returnType, binder: this);
}

private static TypeSymbol GetCommonTypeOrReturnType<TMember>(ImmutableArray<TMember> members)
Expand Down
Loading
Loading