Skip to content
Merged
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
4 changes: 2 additions & 2 deletions docs/features/ExpressionVariables.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ containing expression variables (out variable declarations and declaration patte
initializers, property initializers, ctor-initializers, and query clauses.

See https://github.com/dotnet/csharplang/issues/32 and
https://github.com/dotnet/csharplang/blob/main/proposals/csharp-7.3/expression-variables-in-initializers.md
https://github.com/dotnet/csharplang/blob/main/proposals/expression-variables-in-initializers.md
for more information.

Current state of the feature:

[X] Permit in field initializers
[X] Permit in property initializers
[ ] Permit in ctor-initializers
[X] Permit in query clauses
[X] Permit in query clauses
2 changes: 1 addition & 1 deletion dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"isRoot": true,
"tools": {
"dotnet-format": {
"version": "6.0.240501",
"version": "6.0.231801",
"commands": [
"dotnet-format"
]
Expand Down
3 changes: 1 addition & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
<RoslynDiagnosticsNugetPackageVersion>3.3.3-beta1.21105.3</RoslynDiagnosticsNugetPackageVersion>
<MicrosoftCodeAnalysisNetAnalyzersVersion>6.0.0-rc1.21366.2</MicrosoftCodeAnalysisNetAnalyzersVersion>
<MicrosoftCodeAnalysisTestingVersion>1.1.0-beta1.21322.2</MicrosoftCodeAnalysisTestingVersion>
<!-- CodeStyleAnalyzerVersion should we updated together with version of dotnet-format in dotnet-tools.json -->
<CodeStyleAnalyzerVersion>4.0.0-3.final</CodeStyleAnalyzerVersion>
<CodeStyleAnalyzerVersion>3.10.0</CodeStyleAnalyzerVersion>
<VisualStudioEditorPackagesVersion>16.10.230</VisualStudioEditorPackagesVersion>
<VisualStudioEditorNewPackagesVersion>17.0.278-preview</VisualStudioEditorNewPackagesVersion>
<ILAsmPackageVersion>5.0.0-alpha1.19409.1</ILAsmPackageVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ bool tryBindAsHandlerType([NotNullWhen(true)] out BoundInterpolatedString? resul
{
result = null;

if (InExpressionTree || !ValidateInterpolatedStringParts(unconvertedInterpolatedString))
if (InExpressionTree || unconvertedInterpolatedString.Parts.ContainsAwaitExpression())
{
return false;
}
Expand All @@ -204,12 +204,8 @@ bool tryBindAsHandlerType([NotNullWhen(true)] out BoundInterpolatedString? resul
}
}

private static bool ValidateInterpolatedStringParts(BoundUnconvertedInterpolatedString unconvertedInterpolatedString)
=> !unconvertedInterpolatedString.Parts.ContainsAwaitExpression()
&& unconvertedInterpolatedString.Parts.All(p => p is not BoundStringInsert { Value.Type.TypeKind: TypeKind.Dynamic });

private static bool AllInterpolatedStringPartsAreStrings(ImmutableArray<BoundExpression> parts)
=> parts.All(p => p is BoundLiteral or BoundStringInsert { Value.Type.SpecialType: SpecialType.System_String, Alignment: null, Format: null });
=> parts.All(p => p is BoundLiteral or BoundStringInsert { Value: { Type: { SpecialType: SpecialType.System_String } }, Alignment: null, Format: null });

private bool TryBindUnconvertedBinaryOperatorToDefaultInterpolatedStringHandler(BoundBinaryOperator binaryOperator, BindingDiagnosticBag diagnostics, [NotNullWhen(true)] out BoundBinaryOperator? convertedBinaryOperator)
{
Expand Down Expand Up @@ -244,7 +240,7 @@ private bool TryBindUnconvertedBinaryOperatorToDefaultInterpolatedStringHandler(
isConstant = isConstant && current.Right.ConstantValue is not null;
var rightInterpolatedString = (BoundUnconvertedInterpolatedString)current.Right;

if (!ValidateInterpolatedStringParts(rightInterpolatedString))
if (rightInterpolatedString.Parts.ContainsAwaitExpression())
{
// Exception to case 3. Delegate to standard binding.
stack.Free();
Expand All @@ -263,7 +259,7 @@ private bool TryBindUnconvertedBinaryOperatorToDefaultInterpolatedStringHandler(
case BoundUnconvertedInterpolatedString interpolatedString:
isConstant = isConstant && interpolatedString.ConstantValue is not null;

if (!ValidateInterpolatedStringParts(interpolatedString))
if (interpolatedString.Parts.ContainsAwaitExpression())
{
// Exception to case 3. Delegate to standard binding.
stack.Free();
Expand Down
9 changes: 0 additions & 9 deletions src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1878,15 +1878,6 @@ internal void GenerateAnonymousFunctionConversionError(BindingDiagnosticBag diag
return;
}

if (reason == LambdaConversionResult.CannotInferDelegateType)
{
Debug.Assert(targetType.SpecialType == SpecialType.System_Delegate || targetType.IsNonGenericExpressionType());
Error(diagnostics, ErrorCode.ERR_CannotInferDelegateType, syntax);
var lambda = anonymousFunction.BindForErrorRecovery();
diagnostics.AddRange(lambda.Diagnostics);
return;
}

// At this point we know that we have either a delegate type or an expression type for the target.

// The target type is a valid delegate or expression tree type. Is there something wrong with the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand Down Expand Up @@ -1393,8 +1394,7 @@ private static LambdaConversionResult IsAnonymousFunctionCompatibleWithExpressio

if (delegateType is null)
{
Debug.Assert(IsFeatureInferredDelegateTypeEnabled(anonymousFunction));
return GetInferredDelegateTypeResult(anonymousFunction);
return LambdaConversionResult.Success;
}

return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, delegateType, isTargetExpressionTree: true);
Expand All @@ -1409,7 +1409,7 @@ public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(Unbou
{
if (IsFeatureInferredDelegateTypeEnabled(anonymousFunction))
{
return GetInferredDelegateTypeResult(anonymousFunction);
return LambdaConversionResult.Success;
}
}
else if (type.IsDelegateType())
Expand All @@ -1432,14 +1432,6 @@ internal static bool IsFeatureInferredDelegateTypeEnabled(BoundExpression expr)
return expr.Syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType);
}

private static LambdaConversionResult GetInferredDelegateTypeResult(UnboundLambda anonymousFunction)
{
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
return anonymousFunction.InferDelegateType(ref discardedUseSiteInfo) is null ?
LambdaConversionResult.CannotInferDelegateType :
LambdaConversionResult.Success;
}

private static bool HasAnonymousFunctionConversion(BoundExpression source, TypeSymbol destination)
{
Debug.Assert(source != null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ internal enum LambdaConversionResult
StaticTypeInImplicitlyTypedLambda,
ExpressionTreeMustHaveDelegateTypeArgument,
ExpressionTreeFromAnonymousMethod,
CannotInferDelegateType,
BindingFailed
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3650,7 +3650,7 @@ private void AddSynthesizedRecordMembersIfNecessary(MembersAndInitializersBuilde
memberNames.Free();

// Synthesizing non-readonly properties in struct would require changing readonly logic for PrintMembers method synthesis
Debug.Assert(isRecordClass || !members.Any(m => m is PropertySymbol { GetMethod.IsEffectivelyReadOnly: false }));
Debug.Assert(isRecordClass || !members.Any(m => m is PropertySymbol { GetMethod.IsEffectivelyReadOnly : false }));

// We put synthesized record members first so that errors about conflicts show up on user-defined members rather than all
// going to the record declaration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ internal override void GenerateMethodBodyStatements(SyntheticBoundNodeFactory F,

internal static bool IsCopyConstructor(Symbol member)
{
if (member is MethodSymbol { ContainingType.IsRecordStruct: false, MethodKind: MethodKind.Constructor } method)
if (member is MethodSymbol { ContainingType: { IsRecordStruct: false }, MethodKind: MethodKind.Constructor } method)
{
return HasCopyConstructorSignature(method);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#nullable disable

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand Down Expand Up @@ -280,8 +279,8 @@ public override bool IsTriviaWithEndOfLine()
}

// Use conditional weak table so we always return same identity for structured trivia
private static readonly ConditionalWeakTable<SyntaxNode, Dictionary<CodeAnalysis.SyntaxTrivia, WeakReference<SyntaxNode>>> s_structuresTable
= new ConditionalWeakTable<SyntaxNode, Dictionary<CodeAnalysis.SyntaxTrivia, WeakReference<SyntaxNode>>>();
private static readonly ConditionalWeakTable<SyntaxNode, Dictionary<CodeAnalysis.SyntaxTrivia, SyntaxNode>> s_structuresTable
= new ConditionalWeakTable<SyntaxNode, Dictionary<CodeAnalysis.SyntaxTrivia, SyntaxNode>>();

/// <summary>
/// Gets the syntax node represented the structure of this trivia, if any. The HasStructure property can be used to
Expand Down Expand Up @@ -309,15 +308,10 @@ public override SyntaxNode GetStructure(Microsoft.CodeAnalysis.SyntaxTrivia triv
var structsInParent = s_structuresTable.GetOrCreateValue(parent);
lock (structsInParent)
{
if (!structsInParent.TryGetValue(trivia, out var weakStructure))
if (!structsInParent.TryGetValue(trivia, out structure))
{
structure = CSharp.Syntax.StructuredTriviaSyntax.Create(trivia);
structsInParent.Add(trivia, new WeakReference<SyntaxNode>(structure));
}
else if (!weakStructure.TryGetTarget(out structure))
{
structure = CSharp.Syntax.StructuredTriviaSyntax.Create(trivia);
weakStructure.SetTarget(structure);
structsInParent.Add(trivia, structure);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1682,9 +1682,12 @@ static void Main()

comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview);
comp.VerifyDiagnostics(
// (6,30): error CS0019: Operator '==' cannot be applied to operands of type '<null>' and 'lambda expression'
// (6,65): error CS8917: The delegate type could not be inferred.
// System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; }));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "(null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })").WithArguments("==", "<null>", "lambda expression").WithLocation(6, 30));
Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(6, 65),
// (6,65): error CS8917: The delegate type could not be inferred.
// System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; }));
Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(6, 65));
verify(comp, inferDelegate: true);

static void verify(CSharpCompilation comp, bool inferDelegate)
Expand All @@ -1711,7 +1714,7 @@ static void verify(CSharpCompilation comp, bool inferDelegate)
// ... its first lambda ...
var firstLambda = tuple2.Arguments[1].Expression;
Assert.Null(model.GetTypeInfo(firstLambda).Type);
verifyType("System.Delegate", model.GetTypeInfo(firstLambda).ConvertedType, inferDelegate: false); // cannot infer delegate type for x => x
verifyType("System.Delegate", model.GetTypeInfo(firstLambda).ConvertedType, inferDelegate);

// ... its method group ...
var methodGroup = tuple2.Arguments[2].Expression;
Expand Down
Loading