Skip to content

Commit eec087b

Browse files
committed
Merge remote-tracking branch 'upstream/main' into merges/main-to-main-vs-deps
2 parents 4cda89e + 1f9bf9a commit eec087b

File tree

271 files changed

+9337
-1985
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

271 files changed

+9337
-1985
lines changed

docs/compilers/CSharp/Compiler Breaking Changes - post DotNet 5.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ record Derived(int I) // The positional member 'Base.I' found corresponding to t
4848
}
4949
```
5050

51-
4. In C# 10, method groups are implicitly convertible to `System.Delegate`, and lambda expressions are implicitly convertible to `System.Delegate` and `System.Linq.Expressions.Expression`.
51+
4. In C# 10, lambda expressions and method groups are implicitly convertible to `System.MulticastDelegate`, or any base classes or interfaces of `System.MulticastDelegate` including `object`, and lambda expressions are implicitly convertible to `System.Linq.Expressions.Expression`.
5252

53-
This is a breaking change to overload resolution if there exists an overload with a `System.Delegate` or `System.Linq.Expressions.Expression` parameter that is applicable and the closest applicable overload with a strongly-typed delegate parameter is in an enclosing namespace.
53+
This is a breaking change to overload resolution if there exists an applicable overload with a parameter of type `System.MulticastDelegate`, or a parameter of a type in the base types or interfaces of `System.MulticastDelegate`, or a parameter of type `System.Linq.Expressions.Expression`, and the closest applicable extension method overload with a strongly-typed delegate parameter is in an enclosing namespace.
5454

5555
```C#
5656
class C

docs/contributing/Compiler Test Plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ __makeref( x )
319319
- Tuple
320320
- Default literal
321321
- Implicit object creation (target-typed new)
322+
- Function type (in type inference comparing function types of lambdas or method groups)
322323

323324
## Types
324325

eng/Version.Details.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
<Sha>7e80445ee82adbf9a8e6ae601ac5e239d982afaa</Sha>
77
<SourceBuild RepoName="xliff-tasks" ManagedOnly="true" />
88
</Dependency>
9-
<Dependency Name="Microsoft.SourceBuild.Intermediate.source-build" Version="0.1.0-alpha.1.21426.1">
9+
<Dependency Name="Microsoft.SourceBuild.Intermediate.source-build" Version="0.1.0-alpha.1.21428.1">
1010
<Uri>https://github.com/dotnet/source-build</Uri>
11-
<Sha>c96e044a8031b92e840142eab84b85a45fa9c4c0</Sha>
11+
<Sha>32d7d9397b3dcf1d0633cbfae18f81812c90d562</Sha>
1212
<SourceBuild RepoName="source-build" ManagedOnly="true" />
1313
</Dependency>
1414
</ProductDependencies>

src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs

Lines changed: 61 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ protected BoundExpression CreateConversion(
9797
return CreateAnonymousFunctionConversion(syntax, source, conversion, isCast: isCast, conversionGroupOpt, destination, diagnostics);
9898
}
9999

100+
if (conversion.Kind == ConversionKind.FunctionType)
101+
{
102+
return CreateFunctionTypeConversion(syntax, source, conversion, isCast: isCast, conversionGroupOpt, destination, diagnostics);
103+
}
104+
100105
if (conversion.IsStackAlloc)
101106
{
102107
return CreateStackAllocConversion(syntax, source, conversion, isCast, conversionGroupOpt, destination, diagnostics);
@@ -546,69 +551,68 @@ private BoundExpression CreateUserDefinedConversion(
546551
return finalConversion;
547552
}
548553

549-
private BoundExpression CreateAnonymousFunctionConversion(SyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, BindingDiagnosticBag diagnostics)
554+
private BoundExpression CreateFunctionTypeConversion(SyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, BindingDiagnosticBag diagnostics)
550555
{
551-
// We have a successful anonymous function conversion; rather than producing a node
552-
// which is a conversion on top of an unbound lambda, replace it with the bound
553-
// lambda.
556+
Debug.Assert(conversion.Kind == ConversionKind.FunctionType);
557+
Debug.Assert(source.Kind is BoundKind.MethodGroup or BoundKind.UnboundLambda);
558+
Debug.Assert(syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType));
554559

555-
// UNDONE: Figure out what to do about the error case, where a lambda
556-
// UNDONE: is converted to a delegate that does not match. What to surface then?
560+
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
561+
var delegateType = source.GetInferredDelegateType(ref useSiteInfo);
562+
Debug.Assert(delegateType is { });
557563

558-
var unboundLambda = (UnboundLambda)source;
559-
if ((destination.SpecialType == SpecialType.System_Delegate || destination.IsNonGenericExpressionType()) &&
560-
syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType))
564+
if (source.Kind == BoundKind.UnboundLambda &&
565+
destination.IsNonGenericExpressionType())
561566
{
562-
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
563-
var delegateType = unboundLambda.InferDelegateType(ref useSiteInfo);
564-
BoundLambda boundLambda;
565-
if (delegateType is { })
566-
{
567-
bool isExpressionTree = destination.IsNonGenericExpressionType();
568-
if (isExpressionTree)
569-
{
570-
delegateType = Compilation.GetWellKnownType(WellKnownType.System_Linq_Expressions_Expression_T).Construct(delegateType);
571-
delegateType.AddUseSiteInfo(ref useSiteInfo);
572-
}
573-
boundLambda = unboundLambda.Bind(delegateType, isExpressionTree);
574-
}
575-
else
576-
{
577-
diagnostics.Add(ErrorCode.ERR_CannotInferDelegateType, syntax.GetLocation());
578-
delegateType = CreateErrorType();
579-
boundLambda = unboundLambda.BindForErrorRecovery();
580-
}
581-
diagnostics.AddRange(boundLambda.Diagnostics);
582-
var expr = createAnonymousFunctionConversion(syntax, source, boundLambda, conversion, isCast, conversionGroup, delegateType);
583-
conversion = Conversions.ClassifyConversionFromExpression(expr, destination, ref useSiteInfo);
584-
diagnostics.Add(syntax, useSiteInfo);
585-
return CreateConversion(syntax, expr, conversion, isCast, conversionGroup, destination, diagnostics);
567+
delegateType = Compilation.GetWellKnownType(WellKnownType.System_Linq_Expressions_Expression_T).Construct(delegateType);
568+
delegateType.AddUseSiteInfo(ref useSiteInfo);
569+
}
570+
571+
conversion = Conversions.ClassifyConversionFromExpression(source, delegateType, ref useSiteInfo);
572+
BoundExpression expr;
573+
if (!conversion.Exists)
574+
{
575+
GenerateImplicitConversionError(diagnostics, syntax, conversion, source, delegateType);
576+
expr = new BoundConversion(syntax, source, conversion, @checked: false, explicitCastInCode: isCast, conversionGroup, constantValueOpt: ConstantValue.NotAvailable, type: delegateType, hasErrors: true) { WasCompilerGenerated = source.WasCompilerGenerated };
586577
}
587578
else
588579
{
589-
#if DEBUG
590-
// Test inferring a delegate type for all callers.
591-
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
592-
_ = unboundLambda.InferDelegateType(ref discardedUseSiteInfo);
593-
#endif
594-
var boundLambda = unboundLambda.Bind((NamedTypeSymbol)destination, isExpressionTree: destination.IsGenericOrNonGenericExpressionType(out _));
595-
diagnostics.AddRange(boundLambda.Diagnostics);
596-
return createAnonymousFunctionConversion(syntax, source, boundLambda, conversion, isCast, conversionGroup, destination);
580+
expr = CreateConversion(syntax, source, conversion, isCast, conversionGroup, delegateType, diagnostics);
597581
}
598582

599-
static BoundConversion createAnonymousFunctionConversion(SyntaxNode syntax, BoundExpression source, BoundLambda boundLambda, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination)
583+
conversion = Conversions.ClassifyConversionFromExpression(expr, destination, ref useSiteInfo);
584+
if (!conversion.Exists)
600585
{
601-
return new BoundConversion(
602-
syntax,
603-
boundLambda,
604-
conversion,
605-
@checked: false,
606-
explicitCastInCode: isCast,
607-
conversionGroup,
608-
constantValueOpt: ConstantValue.NotAvailable,
609-
type: destination)
610-
{ WasCompilerGenerated = source.WasCompilerGenerated };
586+
GenerateImplicitConversionError(diagnostics, syntax, conversion, source, destination);
611587
}
588+
589+
diagnostics.Add(syntax, useSiteInfo);
590+
return CreateConversion(syntax, expr, conversion, isCast, conversionGroup, destination, diagnostics);
591+
}
592+
593+
private BoundExpression CreateAnonymousFunctionConversion(SyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, BindingDiagnosticBag diagnostics)
594+
{
595+
// We have a successful anonymous function conversion; rather than producing a node
596+
// which is a conversion on top of an unbound lambda, replace it with the bound
597+
// lambda.
598+
599+
// UNDONE: Figure out what to do about the error case, where a lambda
600+
// UNDONE: is converted to a delegate that does not match. What to surface then?
601+
602+
var unboundLambda = (UnboundLambda)source;
603+
604+
var boundLambda = unboundLambda.Bind((NamedTypeSymbol)destination, isExpressionTree: destination.IsGenericOrNonGenericExpressionType(out _));
605+
diagnostics.AddRange(boundLambda.Diagnostics);
606+
return new BoundConversion(
607+
syntax,
608+
boundLambda,
609+
conversion,
610+
@checked: false,
611+
explicitCastInCode: isCast,
612+
conversionGroup,
613+
constantValueOpt: ConstantValue.NotAvailable,
614+
type: destination)
615+
{ WasCompilerGenerated = source.WasCompilerGenerated };
612616
}
613617

614618
private BoundExpression CreateMethodGroupConversion(SyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, BindingDiagnosticBag diagnostics)
@@ -627,29 +631,7 @@ private BoundExpression CreateMethodGroupConversion(SyntaxNode syntax, BoundExpr
627631
hasErrors = true;
628632
}
629633

630-
if (destination.SpecialType == SpecialType.System_Delegate &&
631-
syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType))
632-
{
633-
// https://github.com/dotnet/roslyn/issues/52869: Avoid calculating the delegate type multiple times during conversion.
634-
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
635-
var delegateType = GetMethodGroupDelegateType(group, ref useSiteInfo);
636-
var expr = createMethodGroupConversion(syntax, group, conversion, isCast, conversionGroup, delegateType!, hasErrors);
637-
conversion = Conversions.ClassifyConversionFromExpression(expr, destination, ref useSiteInfo);
638-
diagnostics.Add(syntax, useSiteInfo);
639-
return CreateConversion(syntax, expr, conversion, isCast, conversionGroup, destination, diagnostics);
640-
}
641-
642-
#if DEBUG
643-
// Test inferring a delegate type for all callers.
644-
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
645-
_ = GetMethodGroupDelegateType(group, ref discardedUseSiteInfo);
646-
#endif
647-
return createMethodGroupConversion(syntax, group, conversion, isCast, conversionGroup, destination, hasErrors);
648-
649-
static BoundConversion createMethodGroupConversion(SyntaxNode syntax, BoundMethodGroup group, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, bool hasErrors)
650-
{
651-
return new BoundConversion(syntax, group, conversion, @checked: false, explicitCastInCode: isCast, conversionGroup, constantValueOpt: ConstantValue.NotAvailable, type: destination, hasErrors: hasErrors) { WasCompilerGenerated = group.WasCompilerGenerated };
652-
}
634+
return new BoundConversion(syntax, group, conversion, @checked: false, explicitCastInCode: isCast, conversionGroup, constantValueOpt: ConstantValue.NotAvailable, type: destination, hasErrors: hasErrors) { WasCompilerGenerated = group.WasCompilerGenerated };
653635
}
654636

655637
private BoundExpression CreateStackAllocConversion(SyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, ConversionGroup? conversionGroup, TypeSymbol destination, BindingDiagnosticBag diagnostics)
@@ -814,6 +796,7 @@ private BoundMethodGroup FixMethodGroupWithTypeOrValue(BoundMethodGroup group, C
814796
group.LookupSymbolOpt,
815797
group.LookupError,
816798
group.Flags,
799+
group.FunctionType,
817800
receiverOpt, //only change
818801
group.ResultKind);
819802
}
@@ -1226,13 +1209,13 @@ private bool MethodGroupConversionHasErrors(
12261209
TypeSymbol delegateOrFuncPtrType,
12271210
BindingDiagnosticBag diagnostics)
12281211
{
1229-
Debug.Assert(delegateOrFuncPtrType.SpecialType == SpecialType.System_Delegate || delegateOrFuncPtrType.TypeKind == TypeKind.Delegate || delegateOrFuncPtrType.TypeKind == TypeKind.FunctionPointer);
1230-
1212+
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
1213+
Debug.Assert(Conversions.IsAssignableFromMulticastDelegate(delegateOrFuncPtrType, ref discardedUseSiteInfo) || delegateOrFuncPtrType.TypeKind == TypeKind.Delegate || delegateOrFuncPtrType.TypeKind == TypeKind.FunctionPointer);
12311214
Debug.Assert(conversion.Method is object);
12321215
MethodSymbol selectedMethod = conversion.Method;
12331216

12341217
var location = syntax.Location;
1235-
if (delegateOrFuncPtrType.SpecialType != SpecialType.System_Delegate)
1218+
if (!Conversions.IsAssignableFromMulticastDelegate(delegateOrFuncPtrType, ref discardedUseSiteInfo))
12361219
{
12371220
if (!MethodIsCompatibleWithDelegateOrFunctionPointer(receiverOpt, isExtensionMethod, selectedMethod, delegateOrFuncPtrType, location, diagnostics) ||
12381221
MemberGroupFinalValidation(receiverOpt, selectedMethod, syntax, diagnostics, isExtensionMethod))

0 commit comments

Comments
 (0)