未验证 提交 e8f52801 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #41996 from 333fred/binder-annotations

Binder annotations
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -15,15 +16,15 @@ namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class Binder
{
internal ImmutableArray<Symbol> BindCref(CrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
internal ImmutableArray<Symbol> BindCref(CrefSyntax syntax, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
ImmutableArray<Symbol> symbols = BindCrefInternal(syntax, out ambiguityWinner, diagnostics);
Debug.Assert(!symbols.IsDefault, "Prefer empty to null.");
Debug.Assert((symbols.Length > 1) == ((object)ambiguityWinner != null), "ambiguityWinner should be set iff more than one symbol is returned.");
Debug.Assert((symbols.Length > 1) == ((object?)ambiguityWinner != null), "ambiguityWinner should be set iff more than one symbol is returned.");
return symbols;
}
private ImmutableArray<Symbol> BindCrefInternal(CrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindCrefInternal(CrefSyntax syntax, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
switch (syntax.Kind())
{
......@@ -41,7 +42,7 @@ private ImmutableArray<Symbol> BindCrefInternal(CrefSyntax syntax, out Symbol am
}
}
private ImmutableArray<Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
NamespaceOrTypeSymbol result = BindNamespaceOrTypeSymbolInCref(syntax.Type);
......@@ -60,7 +61,7 @@ private ImmutableArray<Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol am
return ImmutableArray.Create<Symbol>(result);
}
private ImmutableArray<Symbol> BindQualifiedCref(QualifiedCrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindQualifiedCref(QualifiedCrefSyntax syntax, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
// NOTE: we won't check whether container is an error type - we'll just let BindMemberCref fail
// and report a blanket diagnostic.
......@@ -98,9 +99,9 @@ private NamespaceOrTypeSymbol BindNamespaceOrTypeSymbolInCref(TypeSyntax syntax)
return namespaceOrTypeSymbol;
}
private ImmutableArray<Symbol> BindMemberCref(MemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindMemberCref(MemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
if ((object)containerOpt != null && containerOpt.Kind == SymbolKind.TypeParameter)
if ((object?)containerOpt != null && containerOpt.Kind == SymbolKind.TypeParameter)
{
// As in normal lookup (see CreateErrorIfLookupOnTypeParameter), you can't dot into a type parameter
// (though you can dot into an expression of type parameter type).
......@@ -141,9 +142,9 @@ private ImmutableArray<Symbol> BindMemberCref(MemberCrefSyntax syntax, Namespace
return result;
}
private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
SimpleNameSyntax nameSyntax = syntax.Name as SimpleNameSyntax;
SimpleNameSyntax? nameSyntax = syntax.Name as SimpleNameSyntax;
int arity;
string memberName;
......@@ -157,7 +158,7 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N
{
// If the name isn't a SimpleNameSyntax, then we must have a type name followed by a parameter list.
// Thus, we're looking for a constructor.
Debug.Assert((object)containerOpt == null);
Debug.Assert((object?)containerOpt == null);
// Could be an error type, but we'll just lookup fail below.
containerOpt = BindNamespaceOrTypeSymbolInCref(syntax.Name);
......@@ -184,13 +185,13 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N
sortedSymbols,
arity,
syntax,
typeArgumentListSyntax: arity == 0 ? null : ((GenericNameSyntax)nameSyntax).TypeArgumentList,
typeArgumentListSyntax: arity == 0 ? null : ((GenericNameSyntax)nameSyntax!).TypeArgumentList,
parameterListSyntax: syntax.Parameters,
ambiguityWinner: out ambiguityWinner,
diagnostics: diagnostics);
}
private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
const int arity = 0;
......@@ -218,17 +219,17 @@ private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syn
// NOTE: not guaranteed to be a method (e.g. class op_Addition)
// NOTE: constructor fallback logic applies
private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
const int arity = 0;
CrefParameterListSyntax parameterListSyntax = syntax.Parameters;
CrefParameterListSyntax? parameterListSyntax = syntax.Parameters;
// NOTE: Prefer binary to unary, unless there is exactly one parameter.
// CONSIDER: we're following dev11 by never using a binary operator name if there's
// exactly one parameter, but doing so would allow us to match single-parameter constructors.
SyntaxKind operatorTokenKind = syntax.OperatorToken.Kind();
string memberName = parameterListSyntax != null && parameterListSyntax.Parameters.Count == 1
string? memberName = parameterListSyntax != null && parameterListSyntax.Parameters.Count == 1
? null
: OperatorFacts.BinaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind);
memberName = memberName ?? OperatorFacts.UnaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind);
......@@ -258,7 +259,7 @@ private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax s
}
// NOTE: not guaranteed to be a method (e.g. class op_Implicit)
private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol containerOpt, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol? containerOpt, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
const int arity = 0;
......@@ -304,15 +305,15 @@ private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperat
/// <remarks>
/// Never returns null.
/// </remarks>
private ImmutableArray<Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol containerOpt, string memberName, int arity, bool hasParameterList, DiagnosticBag diagnostics)
private ImmutableArray<Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol? containerOpt, string memberName, int arity, bool hasParameterList, DiagnosticBag diagnostics)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
HashSet<DiagnosticInfo>? useSiteDiagnostics = null;
var result = ComputeSortedCrefMembers(containerOpt, memberName, arity, hasParameterList, ref useSiteDiagnostics);
diagnostics.Add(syntax, useSiteDiagnostics);
return result;
}
private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol containerOpt, string memberName, int arity, bool hasParameterList, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol? containerOpt, string memberName, int arity, bool hasParameterList, ref HashSet<DiagnosticInfo>? useSiteDiagnostics)
{
// Since we may find symbols without going through the lookup API,
// expose the symbols via an ArrayBuilder.
......@@ -373,12 +374,12 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
// As in the native compiler, we treat this as a fallback case - something that actually has the
// specified name is preferred.
NamedTypeSymbol constructorType = null;
NamedTypeSymbol? constructorType = null;
if (arity == 0) // Member arity
{
NamedTypeSymbol containerType = containerOpt as NamedTypeSymbol;
if ((object)containerType != null)
NamedTypeSymbol? containerType = containerOpt as NamedTypeSymbol;
if ((object?)containerType != null)
{
// Case 1: If the name is qualified by a type with the same name, then we want a
// constructor (unless the type is generic, the cref is on/in the type (but not
......@@ -389,21 +390,21 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
constructorType = containerType;
}
}
else if ((object)containerOpt == null && hasParameterList)
else if ((object?)containerOpt == null && hasParameterList)
{
// Case 2: If the name is not qualified by anything, but we're in the scope
// of a type with the same name (regardless of arity), then we want a constructor,
// as long as there were parens after the member name.
NamedTypeSymbol binderContainingType = this.ContainingType;
if ((object)binderContainingType != null && memberName == binderContainingType.Name)
NamedTypeSymbol? binderContainingType = this.ContainingType;
if ((object?)binderContainingType != null && memberName == binderContainingType.Name)
{
constructorType = binderContainingType;
}
}
}
if ((object)constructorType != null)
if ((object?)constructorType != null)
{
ImmutableArray<MethodSymbol> instanceConstructors = constructorType.InstanceConstructors;
int numInstanceConstructors = instanceConstructors.Length;
......@@ -443,9 +444,9 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol co
ImmutableArray<Symbol> symbols,
int arity,
MemberCrefSyntax memberSyntax,
TypeArgumentListSyntax typeArgumentListSyntax,
BaseCrefParameterListSyntax parameterListSyntax,
out Symbol ambiguityWinner,
TypeArgumentListSyntax? typeArgumentListSyntax,
BaseCrefParameterListSyntax? parameterListSyntax,
out Symbol? ambiguityWinner,
DiagnosticBag diagnostics)
{
Debug.Assert(!symbols.IsEmpty);
......@@ -578,8 +579,8 @@ private static bool IsNestedTypeOfUnconstructedGenericType(NamedTypeSymbol type)
ImmutableArray<Symbol> symbols,
int arity,
MemberCrefSyntax memberSyntax,
TypeArgumentListSyntax typeArgumentListSyntax,
out Symbol ambiguityWinner,
TypeArgumentListSyntax? typeArgumentListSyntax,
out Symbol? ambiguityWinner,
DiagnosticBag diagnostics)
{
// If the syntax indicates arity zero, then we match methods of any arity.
......@@ -679,13 +680,13 @@ private static bool IsNestedTypeOfUnconstructedGenericType(NamedTypeSymbol type)
/// Replace any named type in the symbol list with its instance constructors.
/// Construct all candidates with the implicitly-declared CrefTypeParameterSymbols.
/// </summary>
private void GetCrefOverloadResolutionCandidates(ImmutableArray<Symbol> symbols, int arity, TypeArgumentListSyntax typeArgumentListSyntax, ArrayBuilder<Symbol> candidates)
private void GetCrefOverloadResolutionCandidates(ImmutableArray<Symbol> symbols, int arity, TypeArgumentListSyntax? typeArgumentListSyntax, ArrayBuilder<Symbol> candidates)
{
foreach (Symbol candidate in symbols)
{
Symbol constructedCandidate = ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, candidate);
NamedTypeSymbol constructedCandidateType = constructedCandidate as NamedTypeSymbol;
if ((object)constructedCandidateType == null)
NamedTypeSymbol? constructedCandidateType = constructedCandidate as NamedTypeSymbol;
if ((object?)constructedCandidateType == null)
{
// Construct before overload resolution so the signatures will match.
candidates.Add(constructedCandidate);
......@@ -705,9 +706,9 @@ private void GetCrefOverloadResolutionCandidates(ImmutableArray<Symbol> symbols,
/// Produces a diagnostic for ambiguous matches, but not for unresolved members - WRN_BadXMLRef is
/// handled in BindMemberCref.
/// </remarks>
private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder<Symbol> candidates, ImmutableArray<ParameterSymbol> parameterSymbols, int arity, MemberCrefSyntax memberSyntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder<Symbol> candidates, ImmutableArray<ParameterSymbol> parameterSymbols, int arity, MemberCrefSyntax memberSyntax, out Symbol? ambiguityWinner, DiagnosticBag diagnostics)
{
ArrayBuilder<Symbol> viable = null;
ArrayBuilder<Symbol>? viable = null;
foreach (Symbol candidate in candidates)
{
......@@ -827,10 +828,11 @@ private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder
/// <summary>
/// If the member is generic, construct it with the CrefTypeParameterSymbols that should be in scope.
/// </summary>
private Symbol ConstructWithCrefTypeParameters(int arity, TypeArgumentListSyntax typeArgumentListSyntax, Symbol symbol)
private Symbol ConstructWithCrefTypeParameters(int arity, TypeArgumentListSyntax? typeArgumentListSyntax, Symbol symbol)
{
if (arity > 0)
{
Debug.Assert(typeArgumentListSyntax is object);
SeparatedSyntaxList<TypeSyntax> typeArgumentSyntaxes = typeArgumentListSyntax.Arguments;
var typeArgumentsWithAnnotations = ArrayBuilder<TypeWithAnnotations>.GetInstance(arity);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
......@@ -30,8 +31,8 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
{
var left = node.Left;
var right = node.Right;
DeclarationExpressionSyntax declaration = null;
ExpressionSyntax expression = null;
DeclarationExpressionSyntax? declaration = null;
ExpressionSyntax? expression = null;
var result = BindDeconstruction(node, left, right, diagnostics, ref declaration, ref expression, resultIsUsedOverride);
if (declaration != null)
{
......@@ -88,13 +89,13 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
ExpressionSyntax left,
ExpressionSyntax right,
DiagnosticBag diagnostics,
ref DeclarationExpressionSyntax declaration,
ref ExpressionSyntax expression,
ref DeclarationExpressionSyntax? declaration,
ref ExpressionSyntax? expression,
bool resultIsUsedOverride = false,
BoundDeconstructValuePlaceholder rightPlaceholder = null)
BoundDeconstructValuePlaceholder? rightPlaceholder = null)
{
DeconstructionVariable locals = BindDeconstructionVariables(left, diagnostics, ref declaration, ref expression);
Debug.Assert(locals.HasNestedVariables);
Debug.Assert(locals.NestedVariables is object);
var deconstructionDiagnostics = new DiagnosticBag();
BoundExpression boundRight = rightPlaceholder ?? BindValue(right, deconstructionDiagnostics, BindValueKind.RValue);
......@@ -120,7 +121,7 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
{
uint rightEscape = GetValEscape(boundRHS, this.LocalScopeDepth);
if ((object)boundRHS.Type == null || boundRHS.Type.IsErrorType())
if ((object?)boundRHS.Type == null || boundRHS.Type.IsErrorType())
{
// we could still not infer a type for the RHS
FailRemainingInferencesAndSetValEscape(checkedVariables, diagnostics, rightEscape);
......@@ -154,7 +155,8 @@ internal BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Dia
FailRemainingInferencesAndSetValEscape(checkedVariables, diagnostics, rightEscape);
var lhsTuple = DeconstructionVariablesAsTuple(left, checkedVariables, diagnostics, ignoreDiagnosticsFromTuple: diagnostics.HasAnyErrors() || !resultIsUsed);
TypeSymbol returnType = hasErrors ? CreateErrorType() : lhsTuple.Type;
Debug.Assert(hasErrors || lhsTuple.Type is object);
TypeSymbol returnType = hasErrors ? CreateErrorType() : lhsTuple.Type!;
uint leftEscape = GetBroadestValEscape(lhsTuple, this.LocalScopeDepth);
boundRHS = ValidateEscape(boundRHS, leftEscape, isByRef: false, diagnostics: diagnostics);
......@@ -216,13 +218,13 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
// If we already have diagnostics at this point, it is not worth collecting likely duplicate diagnostics from making the merged type
bool hadErrors = diagnostics.HasAnyErrors();
TypeSymbol mergedTupleType = MakeMergedTupleType(checkedVariables, (BoundTupleLiteral)boundRHS, syntax, Compilation, hadErrors ? null : diagnostics);
if ((object)mergedTupleType != null)
TypeSymbol? mergedTupleType = MakeMergedTupleType(checkedVariables, (BoundTupleLiteral)boundRHS, syntax, Compilation, hadErrors ? null : diagnostics);
if ((object?)mergedTupleType != null)
{
boundRHS = GenerateConversionForAssignment(mergedTupleType, boundRHS, diagnostics);
}
}
else if ((object)boundRHS.Type == null)
else if ((object?)boundRHS.Type == null)
{
Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, boundRHS.Syntax);
}
......@@ -297,7 +299,7 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
var variable = variables[i];
Conversion nestedConversion;
if (variable.HasNestedVariables)
if (variable.NestedVariables is object)
{
var elementSyntax = syntax.Kind() == SyntaxKind.TupleExpression ? ((TupleExpressionSyntax)syntax).Arguments[i] : syntax;
......@@ -307,7 +309,8 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
else
{
var single = variable.Single;
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
Debug.Assert(single is object);
HashSet<DiagnosticInfo>? useSiteDiagnostics = null;
nestedConversion = this.Conversions.ClassifyConversionFromType(tupleOrDeconstructedTypes[i], single.Type, ref useSiteDiagnostics);
diagnostics.Add(single.Syntax, useSiteDiagnostics);
......@@ -334,10 +337,9 @@ private void SetInferredTypes(ArrayBuilder<DeconstructionVariable> variables, Im
for (int i = 0; i < matchCount; i++)
{
var variable = variables[i];
if (!variable.HasNestedVariables)
if (variable.Single is { } pending)
{
var pending = variable.Single;
if ((object)pending.Type != null)
if ((object?)pending.Type != null)
{
continue;
}
......@@ -359,7 +361,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
case BoundKind.DiscardExpression:
{
var pending = (BoundDiscardExpression)expression;
Debug.Assert((object)pending.Type == null);
Debug.Assert((object?)pending.Type == null);
return pending.SetInferredTypeWithAnnotations(TypeWithAnnotations.Create(type));
}
default:
......@@ -378,12 +380,13 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
for (int i = 0; i < count; i++)
{
var variable = variables[i];
if (variable.HasNestedVariables)
if (variable.NestedVariables is object)
{
FailRemainingInferencesAndSetValEscape(variable.NestedVariables, diagnostics, rhsValEscape);
}
else
{
Debug.Assert(variable.Single is object);
switch (variable.Single.Kind)
{
case BoundKind.Local:
......@@ -399,7 +402,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
break;
case BoundKind.DiscardExpression:
var pending = (BoundDiscardExpression)variable.Single;
if ((object)pending.Type == null)
if ((object?)pending.Type == null)
{
Error(diagnostics, ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, pending.Syntax, "_");
variables[i] = new DeconstructionVariable(pending.FailInference(this, diagnostics), pending.Syntax);
......@@ -408,7 +411,7 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
}
// at this point we expect to have a type for every lvalue
Debug.Assert((object)variables[i].Single.Type != null);
Debug.Assert((object?)variables[i].Single!.Type != null);
}
}
}
......@@ -419,8 +422,8 @@ private BoundExpression SetInferredType(BoundExpression expression, TypeSymbol t
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
internal sealed class DeconstructionVariable
{
internal readonly BoundExpression Single;
internal readonly ArrayBuilder<DeconstructionVariable> NestedVariables;
internal readonly BoundExpression? Single;
internal readonly ArrayBuilder<DeconstructionVariable>? NestedVariables;
internal readonly CSharpSyntaxNode Syntax;
internal DeconstructionVariable(BoundExpression variable, SyntaxNode syntax)
......@@ -437,8 +440,6 @@ internal DeconstructionVariable(ArrayBuilder<DeconstructionVariable> variables,
Syntax = (CSharpSyntaxNode)syntax;
}
internal bool HasNestedVariables => NestedVariables != null;
internal static void FreeDeconstructionVariables(ArrayBuilder<DeconstructionVariable> variables)
{
variables.FreeAll(v => v.NestedVariables);
......@@ -450,6 +451,7 @@ private string GetDebuggerDisplay()
{
return Single.GetDebuggerDisplay();
}
Debug.Assert(NestedVariables is object);
return $"Nested variables ({NestedVariables.Count})";
}
}
......@@ -459,29 +461,29 @@ private string GetDebuggerDisplay()
/// For cases where the RHS of a deconstruction-assignment is a tuple literal, the type information from the LHS determines the merged type, since all variables have a type.
/// Returns null if a merged tuple type could not be fabricated.
/// </summary>
private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariable> lhsVariables, BoundTupleLiteral rhsLiteral, CSharpSyntaxNode syntax, CSharpCompilation compilation, DiagnosticBag diagnostics)
private static TypeSymbol? MakeMergedTupleType(ArrayBuilder<DeconstructionVariable> lhsVariables, BoundTupleLiteral rhsLiteral, CSharpSyntaxNode syntax, CSharpCompilation compilation, DiagnosticBag? diagnostics)
{
int leftLength = lhsVariables.Count;
int rightLength = rhsLiteral.Arguments.Length;
var typesWithAnnotationsBuilder = ArrayBuilder<TypeWithAnnotations>.GetInstance(leftLength);
var locationsBuilder = ArrayBuilder<Location>.GetInstance(leftLength);
var locationsBuilder = ArrayBuilder<Location?>.GetInstance(leftLength);
for (int i = 0; i < rightLength; i++)
{
BoundExpression element = rhsLiteral.Arguments[i];
TypeSymbol mergedType = element.Type;
TypeSymbol? mergedType = element.Type;
if (i < leftLength)
{
var variable = lhsVariables[i];
if (variable.HasNestedVariables)
if (variable.NestedVariables is object)
{
if (element.Kind == BoundKind.TupleLiteral)
{
// (variables) on the left and (elements) on the right
mergedType = MakeMergedTupleType(variable.NestedVariables, (BoundTupleLiteral)element, syntax, compilation, diagnostics);
}
else if ((object)mergedType == null)
else if ((object?)mergedType == null && diagnostics is object)
{
// (variables) on the left and null on the right
Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax);
......@@ -489,7 +491,8 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
else
{
if ((object)variable.Single.Type != null)
Debug.Assert(variable.Single is object);
if ((object?)variable.Single.Type != null)
{
// typed-variable on the left
mergedType = variable.Single.Type;
......@@ -498,7 +501,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
else
{
if ((object)mergedType == null)
if ((object?)mergedType == null && diagnostics is object)
{
// a typeless element on the right, matching no variable on the left
Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, element.Syntax);
......@@ -523,7 +526,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
locationOpt: null,
elementTypesWithAnnotations: typesWithAnnotationsBuilder.ToImmutableAndFree(),
elementLocations: locationsBuilder.ToImmutableAndFree(),
elementNames: default(ImmutableArray<string>),
elementNames: default(ImmutableArray<string?>),
compilation: compilation,
diagnostics: diagnostics,
shouldCheckConstraints: true,
......@@ -538,19 +541,20 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
int count = variables.Count;
var valuesBuilder = ArrayBuilder<BoundExpression>.GetInstance(count);
var typesWithAnnotationsBuilder = ArrayBuilder<TypeWithAnnotations>.GetInstance(count);
var locationsBuilder = ArrayBuilder<Location>.GetInstance(count);
var namesBuilder = ArrayBuilder<string>.GetInstance(count);
var locationsBuilder = ArrayBuilder<Location?>.GetInstance(count);
var namesBuilder = ArrayBuilder<string?>.GetInstance(count);
foreach (var variable in variables)
{
BoundExpression value;
if (variable.HasNestedVariables)
if (variable.NestedVariables is object)
{
value = DeconstructionVariablesAsTuple(variable.Syntax, variable.NestedVariables, diagnostics, ignoreDiagnosticsFromTuple);
namesBuilder.Add(null);
}
else
{
Debug.Assert(variable.Single is object);
value = variable.Single;
namesBuilder.Add(ExtractDeconstructResultElementName(value));
}
......@@ -564,7 +568,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
RemoveDuplicateInferredTupleNamesAndFreeIfEmptied(ref namesBuilder, uniqueFieldNames);
uniqueFieldNames.Free();
ImmutableArray<string> tupleNames = namesBuilder is null ? default : namesBuilder.ToImmutableAndFree();
ImmutableArray<string?> tupleNames = namesBuilder is null ? default : namesBuilder.ToImmutableAndFree();
ImmutableArray<bool> inferredPositions = tupleNames.IsDefault ? default : tupleNames.SelectAsArray(n => n != null);
bool disallowInferredNames = this.Compilation.LanguageVersion.DisallowInferredTupleElementNames();
......@@ -581,7 +585,7 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
}
/// <summary>Extract inferred name from a single deconstruction variable.</summary>
private static string ExtractDeconstructResultElementName(BoundExpression expression)
private static string? ExtractDeconstructResultElementName(BoundExpression expression)
{
if (expression.Kind == BoundKind.DiscardExpression)
{
......@@ -607,7 +611,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
{
anyApplicableCandidates = false;
var receiverSyntax = (CSharpSyntaxNode)receiver.Syntax;
if (receiver.Type.IsDynamic())
if (receiver.Type?.IsDynamic() ?? false)
{
Error(diagnostics, ErrorCode.ERR_CannotDeconstructDynamic, rightSyntax);
outPlaceholders = default(ImmutableArray<BoundDeconstructValuePlaceholder>);
......@@ -695,9 +699,9 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
private BoundBadExpression MissingDeconstruct(BoundExpression receiver, SyntaxNode rightSyntax, int numParameters, DiagnosticBag diagnostics,
out ImmutableArray<BoundDeconstructValuePlaceholder> outPlaceholders, BoundExpression childNode)
{
if (!receiver.Type.IsErrorType())
if (receiver.Type?.IsErrorType() == false)
{
Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, rightSyntax, receiver.Type, numParameters);
Error(diagnostics, ErrorCode.ERR_MissingDeconstruct, rightSyntax, receiver.Type!, numParameters);
}
outPlaceholders = default;
......@@ -713,8 +717,8 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres
private DeconstructionVariable BindDeconstructionVariables(
ExpressionSyntax node,
DiagnosticBag diagnostics,
ref DeclarationExpressionSyntax declaration,
ref ExpressionSyntax expression)
ref DeclarationExpressionSyntax? declaration,
ref ExpressionSyntax? expression)
{
switch (node.Kind())
{
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.CSharp.Symbols;
using System.Diagnostics;
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics;
......@@ -18,7 +19,7 @@ internal struct ProcessedFieldInitializers
internal ImmutableArray<BoundInitializer> BoundInitializers { get; set; }
internal BoundStatement LoweredInitializers { get; set; }
internal bool HasErrors { get; set; }
internal ImportChain FirstImportChain { get; set; }
internal ImportChain? FirstImportChain { get; set; }
}
internal static void BindFieldInitializers(
......@@ -29,7 +30,7 @@ internal struct ProcessedFieldInitializers
ref ProcessedFieldInitializers processedInitializers)
{
var diagsForInstanceInitializers = DiagnosticBag.GetInstance();
ImportChain firstImportChain;
ImportChain? firstImportChain;
processedInitializers.BoundInitializers = BindFieldInitializers(compilation, scriptInitializerOpt, fieldInitializers, diagsForInstanceInitializers, out firstImportChain);
processedInitializers.HasErrors = diagsForInstanceInitializers.HasAnyErrors();
processedInitializers.FirstImportChain = firstImportChain;
......@@ -42,7 +43,7 @@ internal struct ProcessedFieldInitializers
SynthesizedInteractiveInitializerMethod scriptInitializerOpt,
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
DiagnosticBag diagnostics,
out ImportChain firstImportChain)
out ImportChain? firstImportChain)
{
if (initializers.IsEmpty)
{
......@@ -71,7 +72,7 @@ internal struct ProcessedFieldInitializers
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
ArrayBuilder<BoundInitializer> boundInitializers,
DiagnosticBag diagnostics,
out ImportChain firstDebugImports)
out ImportChain? firstDebugImports)
{
firstDebugImports = null;
......@@ -80,7 +81,7 @@ internal struct ProcessedFieldInitializers
// All sibling initializers share the same parent node and tree so we can reuse the binder
// factory across siblings. Unfortunately, we cannot reuse the binder itself, because
// individual fields might have their own binders (e.g. because of being declared unsafe).
BinderFactory binderFactory = null;
BinderFactory? binderFactory = null;
foreach (FieldOrPropertyInitializer initializer in siblingInitializers)
{
......@@ -129,7 +130,7 @@ internal struct ProcessedFieldInitializers
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
ArrayBuilder<BoundInitializer> boundInitializers,
DiagnosticBag diagnostics,
out ImportChain firstDebugImports)
out ImportChain? firstDebugImports)
{
firstDebugImports = null;
......@@ -140,9 +141,9 @@ internal struct ProcessedFieldInitializers
// All sibling initializers share the same parent node and tree so we can reuse the binder
// factory across siblings. Unfortunately, we cannot reuse the binder itself, because
// individual fields might have their own binders (e.g. because of being declared unsafe).
BinderFactory binderFactory = null;
BinderFactory? binderFactory = null;
// Label instances must be shared across all global statements.
ScriptLocalScopeBinder.Labels labels = null;
ScriptLocalScopeBinder.Labels? labels = null;
for (int j = 0; j < siblingInitializers.Length; j++)
{
......@@ -169,7 +170,7 @@ internal struct ProcessedFieldInitializers
}
Binder scriptClassBinder = binderFactory.GetBinder(syntax);
Debug.Assert(((NamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);
Debug.Assert(scriptClassBinder.ContainingMemberOrLambda is NamedTypeSymbol { IsScriptClass: true });
if (firstDebugImports == null)
{
......@@ -182,7 +183,7 @@ internal struct ProcessedFieldInitializers
new ScriptLocalScopeBinder(labels, scriptClassBinder));
BoundInitializer boundInitializer;
if ((object)fieldSymbol != null)
if ((object?)fieldSymbol != null)
{
boundInitializer = BindFieldInitializer(
parentBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol),
......@@ -221,7 +222,7 @@ internal struct ProcessedFieldInitializers
// insert an implicit conversion for the submission return type (if needed):
var expression = InitializerRewriter.GetTrailingScriptExpression(statement);
if (expression != null &&
((object)expression.Type == null || !expression.Type.IsVoidType()))
((object?)expression.Type == null || !expression.Type.IsVoidType()))
{
var submissionResultType = scriptInitializer.ResultType;
expression = binder.GenerateConversionForAssignment(submissionResultType, expression, diagnostics);
......@@ -256,7 +257,7 @@ internal struct ProcessedFieldInitializers
var fieldsBeingBound = binder.FieldsBeingBound;
var sourceField = fieldSymbol as SourceMemberFieldSymbolFromDeclarator;
bool isImplicitlyTypedField = (object)sourceField != null && sourceField.FieldTypeInferred(fieldsBeingBound);
bool isImplicitlyTypedField = (object?)sourceField != null && sourceField.FieldTypeInferred(fieldsBeingBound);
// If the type is implicitly typed, the initializer diagnostics have already been reported, so ignore them here:
// CONSIDER (tomat): reusing the bound field initializers for implicitly typed fields.
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
......@@ -47,8 +48,8 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta
// GenerateConversionForAssignment with objectType. However we want to preserve the original expression's
// natural type so that overload resolution may select a specialized implementation of string.Format,
// so we discard the result of that call and only preserve its diagnostics.
BoundExpression alignment = null;
BoundLiteral format = null;
BoundExpression? alignment = null;
BoundLiteral? format = null;
if (interpolation.AlignmentClause != null)
{
alignment = GenerateConversionForAssignment(intType, BindValue(interpolation.AlignmentClause.Value, diagnostics, Binder.BindValueKind.RValue), diagnostics);
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
......@@ -75,7 +76,7 @@ internal partial class Binder
hasSignature = anon.ParameterList != null;
if (hasSignature)
{
parameterSyntaxList = anon.ParameterList.Parameters;
parameterSyntaxList = anon.ParameterList!.Parameters;
}
isAsync = (anon.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword);
break;
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -33,7 +34,7 @@ private static Location GetLocation(Symbol symbol)
bool allowShadowingNames,
DiagnosticBag diagnostics)
{
PooledHashSet<string> tpNames = null;
PooledHashSet<string>? tpNames = null;
if (!typeParameters.IsDefaultOrEmpty)
{
tpNames = PooledHashSet<string>.GetInstance();
......@@ -56,7 +57,7 @@ private static Location GetLocation(Symbol symbol)
}
}
PooledHashSet<string> pNames = null;
PooledHashSet<string>? pNames = null;
if (!parameters.IsDefaultOrEmpty)
{
pNames = PooledHashSet<string>.GetInstance();
......@@ -93,7 +94,7 @@ private static Location GetLocation(Symbol symbol)
/// <remarks>
/// Don't call this one directly - call one of the helpers.
/// </remarks>
private bool ValidateNameConflictsInScope(Symbol symbol, Location location, string name, DiagnosticBag diagnostics)
private bool ValidateNameConflictsInScope(Symbol? symbol, Location location, string name, DiagnosticBag diagnostics)
{
if (string.IsNullOrEmpty(name))
{
......@@ -102,7 +103,7 @@ private bool ValidateNameConflictsInScope(Symbol symbol, Location location, stri
bool allowShadowing = Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNameShadowingInNestedFunctions);
for (Binder binder = this; binder != null; binder = binder.Next)
for (Binder? binder = this; binder != null; binder = binder.Next)
{
// no local scopes enclose members
if (binder is InContainerBinder)
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -53,7 +54,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, DiagnosticBag dia
// from T x in e
// is translated into
// from x in ( e ) . Cast < T > ( )
BoundExpression cast = null;
BoundExpression? cast = null;
if (fromClause.Type != null)
{
var typeRestriction = BindTypeArgument(fromClause.Type, diagnostics);
......@@ -63,7 +64,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, DiagnosticBag dia
state.fromExpression = MakeQueryClause(fromClause, state.fromExpression, x, castInvocation: cast);
BoundExpression result = BindQueryInternal1(state, diagnostics);
for (QueryContinuationSyntax continuation = node.Body.Continuation; continuation != null; continuation = continuation.Body.Continuation)
for (QueryContinuationSyntax? continuation = node.Body.Continuation; continuation != null; continuation = continuation.Body.Continuation)
{
// A query expression with a continuation
// from ... into x ...
......@@ -129,7 +130,7 @@ private BoundExpression BindQueryInternal2(QueryTranslationState state, Diagnost
// ignore missing or malformed Select method
DiagnosticBag discarded = DiagnosticBag.GetInstance();
var unoptimized = FinalTranslation(state, discarded);
BoundExpression? unoptimized = FinalTranslation(state, discarded);
discarded.Free();
if (unoptimized.HasAnyErrors && !result.HasAnyErrors) unoptimized = null;
......@@ -186,7 +187,7 @@ private BoundExpression FinalTranslation(QueryTranslationState state, Diagnostic
// k and v appear reversed in the invocation, so we reorder their evaluation
result = ReverseLastTwoParameterOrder(result);
BoundExpression unoptimizedForm = null;
BoundExpression? unoptimizedForm = null;
if (vId != null && vId.Identifier.ValueText == x.Name)
{
// The optimized form. We store the unoptimized form for analysis
......@@ -284,7 +285,7 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Diag
inExpression = BadExpression(join.InExpression, inExpression);
}
BoundExpression castInvocation = null;
BoundExpression? castInvocation = null;
if (join.Type != null)
{
// A join clause that explicitly specifies a range variable type
......@@ -474,7 +475,7 @@ private void ReduceFrom(FromClauseSyntax from, QueryTranslationState state, Diag
diagnostics);
// Adjust the second-to-last parameter to be a query clause (if it was an extension method, an extra parameter was added)
BoundExpression castInvocation = (from.Type != null) ? ExtractCastInvocation(invocation) : null;
BoundExpression? castInvocation = (from.Type != null) ? ExtractCastInvocation(invocation) : null;
var arguments = invocation.Arguments;
invocation = invocation.Update(
......@@ -512,12 +513,12 @@ private void ReduceFrom(FromClauseSyntax from, QueryTranslationState state, Diag
ImmutableArray.Create(collectionSelectorLambda, resultSelectorLambda),
diagnostics);
BoundExpression castInvocation = (from.Type != null) ? ExtractCastInvocation(invocation) : null;
BoundExpression? castInvocation = (from.Type != null) ? ExtractCastInvocation(invocation) : null;
state.fromExpression = MakeQueryClause(from, invocation, x2, invocation, castInvocation);
}
}
private static BoundExpression ExtractCastInvocation(BoundCall invocation)
private static BoundExpression? ExtractCastInvocation(BoundCall invocation)
{
int index = invocation.InvokedAsExtensionMethod ? 1 : 0;
var c1 = invocation.Arguments[index] as BoundConversion;
......@@ -569,8 +570,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
{
var xExpression = new BoundParameter(let, lambdaSymbol.Parameters[0]) { WasCompilerGenerated = true };
lambdaBodyBinder = lambdaBodyBinder.GetBinder(let.Expression);
Debug.Assert(lambdaBodyBinder != null);
lambdaBodyBinder = lambdaBodyBinder.GetRequiredBinder(let.Expression);
var yExpression = lambdaBodyBinder.BindRValueWithoutTargetType(let.Expression, d);
SourceLocation errorLocation = new SourceLocation(let.SyntaxTree, new TextSpan(let.Identifier.SpanStart, let.Expression.Span.End - let.Identifier.SpanStart));
......@@ -579,9 +579,9 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Display);
yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray<Symbol>.Empty, ImmutableArray.Create(yExpression), CreateErrorType());
}
else if (!yExpression.HasAnyErrors && yExpression.Type.IsVoidType())
else if (!yExpression.HasAnyErrors && yExpression.Type!.IsVoidType())
{
Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Type);
Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Type!);
yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray<Symbol>.Empty, ImmutableArray.Create(yExpression), yExpression.Type);
}
......@@ -615,10 +615,10 @@ private BoundBlock CreateLambdaBlockForQueryClause(ExpressionSyntax expression,
private BoundQueryClause MakeQueryClause(
CSharpSyntaxNode syntax,
BoundExpression expression,
RangeVariableSymbol definedSymbol = null,
BoundExpression queryInvocation = null,
BoundExpression castInvocation = null,
BoundExpression unoptimizedForm = null)
RangeVariableSymbol? definedSymbol = null,
BoundExpression? queryInvocation = null,
BoundExpression? castInvocation = null,
BoundExpression? unoptimizedForm = null)
{
if (unoptimizedForm != null && unoptimizedForm.HasAnyErrors && !expression.HasAnyErrors) unoptimizedForm = null;
return new BoundQueryClause(
......@@ -636,7 +636,7 @@ private BoundExpression MakePair(CSharpSyntaxNode node, string field1Name, Bound
{
// we will generate a diagnostic elsewhere
field2Name = state.TransparentRangeVariableName();
field2Value = new BoundBadExpression(field2Value.Syntax, LookupResultKind.Empty, ImmutableArray<Symbol>.Empty, ImmutableArray.Create(field2Value), field2Value.Type, true);
field2Value = new BoundBadExpression(field2Value.Syntax, LookupResultKind.Empty, ImmutableArray<Symbol?>.Empty, ImmutableArray.Create(field2Value), field2Value.Type, true);
}
AnonymousTypeDescriptor typeDescriptor = new AnonymousTypeDescriptor(
......@@ -668,7 +668,7 @@ private UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArra
{
return MakeQueryUnboundLambda(expression, new QueryUnboundLambdaState(this, qvm, parameters, (LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, DiagnosticBag diagnostics) =>
{
lambdaBodyBinder = lambdaBodyBinder.GetBinder(expression);
lambdaBodyBinder = lambdaBodyBinder.GetRequiredBinder(expression);
Debug.Assert(lambdaSymbol != null);
BoundExpression boundExpression = lambdaBodyBinder.BindValue(expression, diagnostics, BindValueKind.RValue);
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(expression, boundExpression, diagnostics);
......@@ -679,8 +679,7 @@ private UnboundLambda MakeQueryUnboundLambdaWithCast(RangeVariableMap qvm, Range
{
return MakeQueryUnboundLambda(expression, new QueryUnboundLambdaState(this, qvm, ImmutableArray.Create(parameter), (LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, DiagnosticBag diagnostics) =>
{
lambdaBodyBinder = lambdaBodyBinder.GetBinder(expression);
Debug.Assert(lambdaBodyBinder != null);
lambdaBodyBinder = lambdaBodyBinder.GetRequiredBinder(expression);
BoundExpression boundExpression = lambdaBodyBinder.BindValue(expression, diagnostics, BindValueKind.RValue);
// We transform the expression from "expr" to "expr.Cast<castTypeOpt>()".
......@@ -723,7 +722,8 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
// clean up the receiver
var ultimateReceiver = receiver;
while (ultimateReceiver.Kind == BoundKind.QueryClause) ultimateReceiver = ((BoundQueryClause)ultimateReceiver).Value;
if ((object)ultimateReceiver.Type == null)
Debug.Assert(receiver.Type is object || ultimateReceiver.Type is null);
if ((object?)ultimateReceiver.Type == null)
{
if (ultimateReceiver.HasAnyErrors || node.HasErrors)
{
......@@ -749,7 +749,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
else if (ultimateReceiver.Kind == BoundKind.MethodGroup)
{
var methodGroup = (BoundMethodGroup)ultimateReceiver;
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
HashSet<DiagnosticInfo>? useSiteDiagnostics = null;
var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, isMethodGroupConversion: false, useSiteDiagnostics: ref useSiteDiagnostics);
diagnostics.Add(node, useSiteDiagnostics);
diagnostics.AddRange(resolution.Diagnostics);
......@@ -767,7 +767,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
receiver = new BoundBadExpression(receiver.Syntax, LookupResultKind.NotAValue, ImmutableArray<Symbol>.Empty, ImmutableArray.Create(receiver), CreateErrorType());
}
else if (receiver.Type.IsVoidType())
else if (receiver.Type!.IsVoidType())
{
if (!receiver.HasAnyErrors && !node.HasErrors)
{
......
......@@ -1576,7 +1576,7 @@
<AbstractNode Name="BoundTupleExpression" Base="BoundExpression">
<Field Name="Arguments" Type="ImmutableArray&lt;BoundExpression&gt;"/>
<Field Name="ArgumentNamesOpt" Type="ImmutableArray&lt;string&gt;" Null="allow"/>
<Field Name="ArgumentNamesOpt" Type="ImmutableArray&lt;string?&gt;" Null="allow"/>
<!-- Which argument names were inferred (as opposed to explicitly provided)? -->
<Field Name="InferredNamesOpt" Type="ImmutableArray&lt;bool&gt;" Null="allow"/>
......
......@@ -5542,7 +5542,7 @@ public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableA
internal abstract partial class BoundTupleExpression : BoundExpression
{
protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string?> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(kind, syntax, type, hasErrors)
{
......@@ -5556,14 +5556,14 @@ protected BoundTupleExpression(BoundKind kind, SyntaxNode syntax, ImmutableArray
public ImmutableArray<BoundExpression> Arguments { get; }
public ImmutableArray<string> ArgumentNamesOpt { get; }
public ImmutableArray<string?> ArgumentNamesOpt { get; }
public ImmutableArray<bool> InferredNamesOpt { get; }
}
internal sealed partial class BoundTupleLiteral : BoundTupleExpression
{
public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string?> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(BoundKind.TupleLiteral, syntax, arguments, argumentNamesOpt, inferredNamesOpt, type, hasErrors || arguments.HasErrors())
{
......@@ -5576,7 +5576,7 @@ public BoundTupleLiteral(SyntaxNode syntax, ImmutableArray<BoundExpression> argu
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitTupleLiteral(this);
public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, ImmutableArray<string?> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
{
if (arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || inferredNamesOpt != this.InferredNamesOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{
......@@ -5590,7 +5590,7 @@ public BoundTupleLiteral Update(ImmutableArray<BoundExpression> arguments, Immut
internal sealed partial class BoundConvertedTupleLiteral : BoundTupleExpression
{
public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string?> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type, bool hasErrors = false)
: base(BoundKind.ConvertedTupleLiteral, syntax, arguments, argumentNamesOpt, inferredNamesOpt, type, hasErrors || sourceTuple.HasErrors() || arguments.HasErrors())
{
......@@ -5607,7 +5607,7 @@ public BoundConvertedTupleLiteral(SyntaxNode syntax, BoundTupleLiteral? sourceTu
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitConvertedTupleLiteral(this);
public BoundConvertedTupleLiteral Update(BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
public BoundConvertedTupleLiteral Update(BoundTupleLiteral? sourceTuple, bool wasTargetTyped, ImmutableArray<BoundExpression> arguments, ImmutableArray<string?> argumentNamesOpt, ImmutableArray<bool> inferredNamesOpt, TypeSymbol? type)
{
if (sourceTuple != this.SourceTuple || wasTargetTyped != this.WasTargetTyped || arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || inferredNamesOpt != this.InferredNamesOpt || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{
......
......@@ -129,7 +129,7 @@ private BoundExpression RewriteDeconstruction(BoundTupleExpression left, Convers
for (int i = 0; i < leftTargets.Count; i++)
{
BoundExpression resultPart;
if (leftTargets[i].HasNestedVariables)
if (leftTargets[i].NestedVariables is object)
{
resultPart = ApplyDeconstructionConversion(leftTargets[i].NestedVariables, rightParts[i],
underlyingConversions[i], temps, effects, isUsed, inInit);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册