diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index ba7c01071df6a..d9725520211f0 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1964,14 +1964,17 @@ private IOperation CreateBoundDiscardExpressionOperation(BoundDiscardExpression private IOperation CreateFromEndIndexExpressionOperation(BoundFromEndIndexExpression boundIndex) { - return new CSharpLazyFromEndIndexOperation( + return new CSharpLazyUnaryOperation( operationFactory: this, boundIndex.Operand, + UnaryOperatorKind.Hat, isLifted: boundIndex.Type.IsNullableType(), + isChecked: false, + operatorMethod: null, _semanticModel, boundIndex.Syntax, boundIndex.Type, - boundIndex.MethodOpt, + constantValue: default, isImplicit: boundIndex.WasCompilerGenerated); } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs index 51fb5c6f64d92..6a50c59a9c7ed 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs @@ -1805,24 +1805,6 @@ protected override IObjectOrCollectionInitializerOperation CreateInitializer() } } - internal sealed class CSharpLazyFromEndIndexOperation : LazyFromEndIndexOperation - { - private readonly CSharpOperationFactory _operationFactory; - private readonly BoundNode _operand; - - internal CSharpLazyFromEndIndexOperation(CSharpOperationFactory operationFactory, BoundNode operand, bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) - { - _operationFactory = operationFactory; - _operand = operand; - } - - protected override IOperation CreateOperand() - { - return _operationFactory.Create(_operand); - } - } - internal sealed class CSharpLazyRangeOperation : LazyRangeOperation { private readonly CSharpOperationFactory _operationFactory; diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IBinaryOperatorExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IBinaryOperatorExpression.cs index 299b89c4e6903..eb8c28c7cec5b 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IBinaryOperatorExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IBinaryOperatorExpression.cs @@ -7942,7 +7942,7 @@ void M(int arg) Operand: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') RightOperand: - IFromEndIndexOperation (OperationKind.None, Type: System.Index) (Syntax: '^1') + IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index) (Syntax: '^1') Operand: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') "; @@ -8084,7 +8084,7 @@ void M(int? start, int? end) Operand: IParameterReferenceOperation: start (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'start') RightOperand: - IFromEndIndexOperation (IsLifted) (OperationKind.None, Type: System.Index?) (Syntax: '^end') + IUnaryOperation (UnaryOperatorKind.Hat, IsLifted) (OperationKind.Unary, Type: System.Index?) (Syntax: '^end') Operand: IParameterReferenceOperation: end (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'end') "; diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IFromEndIndexOperation_IRangeOperation.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IFromEndIndexOperation_IRangeOperation.cs index c4e16d2743c6d..e0aca6c42ea7d 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IFromEndIndexOperation_IRangeOperation.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IFromEndIndexOperation_IRangeOperation.cs @@ -34,7 +34,7 @@ void M(int arg) IVariableDeclaratorOperation (Symbol: System.Index x) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'x = ^arg') Initializer: IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= ^arg') - IFromEndIndexOperation (OperationKind.None, Type: System.Index) (Syntax: '^arg') + IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index) (Syntax: '^arg') Operand: IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'arg') Initializer: @@ -60,7 +60,7 @@ void M(int arg) Left: ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Index, IsImplicit) (Syntax: 'x = ^arg') Right: - IFromEndIndexOperation (OperationKind.None, Type: System.Index) (Syntax: '^arg') + IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index) (Syntax: '^arg') Operand: IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'arg') diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUnaryOperatorExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUnaryOperatorExpression.cs index 6e7525426f55e..231c19500aedd 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUnaryOperatorExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUnaryOperatorExpression.cs @@ -3629,13 +3629,13 @@ void M(int arg) }").VerifyDiagnostics(); string expectedOperationTree = @" -IFromEndIndexOperation (OperationKind.None, Type: System.Index) (Syntax: '^arg') +IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index) (Syntax: '^arg') Operand: IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'arg') "; - var operation = (IFromEndIndexOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); - Assert.Equal("System.Index..ctor(System.Int32 value, [System.Boolean fromEnd = false])", operation.Symbol.ToTestDisplayString()); + var operation = (IUnaryOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); + Assert.Null(operation.OperatorMethod); } [Fact] @@ -3652,13 +3652,13 @@ void M(int? arg) }").VerifyDiagnostics(); string expectedOperationTree = @" -IFromEndIndexOperation (IsLifted) (OperationKind.None, Type: System.Index?) (Syntax: '^arg') +IUnaryOperation (UnaryOperatorKind.Hat, IsLifted) (OperationKind.Unary, Type: System.Index?) (Syntax: '^arg') Operand: IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'arg') "; - var operation = (IFromEndIndexOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); - Assert.Equal("System.Index..ctor(System.Int32 value, [System.Boolean fromEnd = false])", operation.Symbol.ToTestDisplayString()); + var operation = (IUnaryOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); + Assert.Null(operation.OperatorMethod); } [Fact] @@ -3675,7 +3675,7 @@ void M(byte arg) }").VerifyDiagnostics(); string expectedOperationTree = @" -IFromEndIndexOperation (OperationKind.None, Type: System.Index) (Syntax: '^arg') +IUnaryOperation (UnaryOperatorKind.Hat) (OperationKind.Unary, Type: System.Index) (Syntax: '^arg') Operand: IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'arg') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) @@ -3683,8 +3683,8 @@ void M(byte arg) IParameterReferenceOperation: arg (OperationKind.ParameterReference, Type: System.Byte) (Syntax: 'arg') "; - var operation = (IFromEndIndexOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); - Assert.Equal("System.Index..ctor(System.Int32 value, [System.Boolean fromEnd = false])", operation.Symbol.ToTestDisplayString()); + var operation = (IUnaryOperation)VerifyOperationTreeForTest(compilation, expectedOperationTree); + Assert.Null(operation.OperatorMethod); } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index d0ff8499bf7e5..28994c0343c17 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -51911,7 +51911,7 @@ static void F(object? x) }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (3,16): warning CS8618: Non-nullable field 'F' is uninitialized. + // (3,16): warning CS8618: Non-nullable field 'F' is uninitialized. // internal T F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(3, 16), // (21,27): warning CS8625: Cannot convert null literal to non-nullable reference type. diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 44afb4d5b1b12..e342f3782c538 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -6577,11 +6577,6 @@ public override IOperation VisitDelegateCreation(IDelegateCreationOperation oper operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation)); } - internal override IOperation VisitFromEndIndexOperation(IFromEndIndexOperation operation, int? argument) - { - return new FromEndIndexOperation(operation.IsLifted, semanticModel: null, operation.Syntax, operation.Type, Visit(operation.Operand), operation.Symbol, isImplicit: IsImplicit(operation)); - } - public override IOperation VisitRangeOperation(IRangeOperation operation, int? argument) { if (!(operation.LeftOperand is null)) diff --git a/src/Compilers/Core/Portable/Operations/IIndexOperation.cs b/src/Compilers/Core/Portable/Operations/IIndexOperation.cs deleted file mode 100644 index c6dd0b8c42515..0000000000000 --- a/src/Compilers/Core/Portable/Operations/IIndexOperation.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.CodeAnalysis.Operations -{ - /// - /// Represents a from end index operation. - /// - /// Current Usage: - /// (1) C# from end index expressions - /// - /// - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to change it in the future. - /// - internal interface IFromEndIndexOperation : IOperation - { - /// - /// The operand. - /// - IOperation Operand { get; } - - /// - /// true if this is a 'lifted' from end index operation. When there is an - /// operator that is defined to work on a value type, 'lifted' operators are - /// created to work on the versions of those - /// value types. - /// - bool IsLifted { get; } - - /// - /// Constructor symbol that's called to create this Index value. - /// Can be null if appropriate symbol was not found. - /// - IMethodSymbol Symbol { get; } - } -} diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index 8222fd1b1936e..b96f8ef42239f 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -635,11 +635,6 @@ public override IOperation VisitStaticLocalInitializationSemaphore(IStaticLocalI throw ExceptionUtilities.Unreachable; } - internal override IOperation VisitFromEndIndexOperation(IFromEndIndexOperation operation, object argument) - { - return new FromEndIndexOperation(operation.IsLifted, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, Visit(operation.Operand), operation.Symbol, operation.IsImplicit); - } - public override IOperation VisitRangeOperation(IRangeOperation operation, object argument) { return new RangeOperation(operation.IsLifted, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, Visit(operation.LeftOperand), Visit(operation.RightOperand), operation.Method, operation.IsImplicit); diff --git a/src/Compilers/Core/Portable/Operations/OperationNodes.cs b/src/Compilers/Core/Portable/Operations/OperationNodes.cs index a8fca8beb40d8..539ba6c74adbd 100644 --- a/src/Compilers/Core/Portable/Operations/OperationNodes.cs +++ b/src/Compilers/Core/Portable/Operations/OperationNodes.cs @@ -9491,80 +9491,6 @@ public override IObjectOrCollectionInitializerOperation Initializer } } - internal abstract class BaseFromEndIndexOperation : Operation, IFromEndIndexOperation - { - protected BaseFromEndIndexOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(OperationKind.None, semanticModel, syntax, type, constantValue: default, isImplicit: isImplicit) - { - IsLifted = isLifted; - Symbol = symbol; - } - - public abstract IOperation Operand { get; } - public bool IsLifted { get; } - public IMethodSymbol Symbol { get; } - - public sealed override IEnumerable Children - { - get - { - IOperation operand = Operand; - if (operand != null) - { - yield return operand; - } - } - } - - public override void Accept(OperationVisitor visitor) - { - visitor.VisitFromEndIndexOperation(this); - } - - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitFromEndIndexOperation(this, argument); - } - } - - internal sealed class FromEndIndexOperation : BaseFromEndIndexOperation - { - public FromEndIndexOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IOperation operand, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) - { - Operand = Operation.SetParentOperation(operand, this); - } - - public override IOperation Operand { get; } - } - - internal abstract class LazyFromEndIndexOperation : BaseFromEndIndexOperation - { - private IOperation _operandInterlocked = s_unset; - - public LazyFromEndIndexOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : - base(isLifted, semanticModel, syntax, type, symbol, isImplicit) - { - } - - protected abstract IOperation CreateOperand(); - - public override IOperation Operand - { - get - { - if (_operandInterlocked == s_unset) - { - IOperation operand = CreateOperand(); - SetParentOperation(operand, this); - Interlocked.CompareExchange(ref _operandInterlocked, operand, s_unset); - } - - return _operandInterlocked; - } - } - } - internal abstract class BaseRangeOperation : Operation, IRangeOperation { protected BaseRangeOperation(bool isLifted, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, IMethodSymbol symbol, bool isImplicit) : diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index f130da5cb530f..9651b67c976b1 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -590,11 +590,6 @@ public virtual void VisitStaticLocalInitializationSemaphore(IStaticLocalInitiali DefaultVisit(operation); } - internal virtual void VisitFromEndIndexOperation(IFromEndIndexOperation operation) - { - DefaultVisit(operation); - } - public virtual void VisitRangeOperation(IRangeOperation operation) { DefaultVisit(operation); @@ -1203,11 +1198,6 @@ public virtual TResult VisitStaticLocalInitializationSemaphore(IStaticLocalIniti return DefaultVisit(operation, argument); } - internal virtual TResult VisitFromEndIndexOperation(IFromEndIndexOperation operation, TArgument argument) - { - return DefaultVisit(operation, argument); - } - public virtual TResult VisitRangeOperation(IRangeOperation operation, TArgument argument) { return DefaultVisit(operation, argument); diff --git a/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs b/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs index cff58206902f7..2f0ff4c0d32c4 100644 --- a/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs +++ b/src/Compilers/Core/Portable/Operations/UnaryOperatorKind.cs @@ -41,6 +41,11 @@ public enum UnaryOperatorKind /// Represents the C# 'false' operator and VB 'IsFalse' operator. /// False = 0x6, + + /// + /// Represents the C# '^' operator. + /// + Hat = 0x7, } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 1ab5a0346b6b1..ad95a500a13b1 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -179,6 +179,7 @@ Microsoft.CodeAnalysis.Operations.ISwitchOperation.ExitLabel.get -> Microsoft.Co Microsoft.CodeAnalysis.Operations.ISwitchOperation.Locals.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.Operations.ITryOperation.ExitLabel.get -> Microsoft.CodeAnalysis.ILabelSymbol Microsoft.CodeAnalysis.Operations.IUsingOperation.Locals.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Operations.UnaryOperatorKind.Hat = 7 -> Microsoft.CodeAnalysis.Operations.UnaryOperatorKind Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral = 128 -> Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier = 64 -> Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions Microsoft.CodeAnalysis.SymbolDisplayPartKind.ConstantName = 30 -> Microsoft.CodeAnalysis.SymbolDisplayPartKind diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index edf6358e6821d..de8523aacb7df 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -1884,20 +1884,6 @@ public override void VisitStaticLocalInitializationSemaphore(IStaticLocalInitial LogCommonPropertiesAndNewLine(operation); } - internal override void VisitFromEndIndexOperation(IFromEndIndexOperation operation) - { - LogString(nameof(IFromEndIndexOperation)); - - if (operation.IsLifted) - { - LogString(" (IsLifted)"); - } - - LogCommonPropertiesAndNewLine(operation); - - Visit(operation.Operand, nameof(operation.Operand)); - } - public override void VisitRangeOperation(IRangeOperation operation) { LogString(nameof(IRangeOperation)); diff --git a/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs b/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs index bcde6d12a48c4..987cb0987dfcf 100644 --- a/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs +++ b/src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs @@ -1434,12 +1434,6 @@ public override void VisitStaticLocalInitializationSemaphore(IStaticLocalInitial Assert.True(operation.Local.IsStatic); } - internal override void VisitFromEndIndexOperation(IFromEndIndexOperation operation) - { - Assert.Equal(OperationKind.None, operation.Kind); - Assert.Same(operation.Operand, operation.Children.Single()); - } - public override void VisitRangeOperation(IRangeOperation operation) { Assert.Equal(OperationKind.Range, operation.Kind);