From 7809f0e2bfd4d4572cb08a9a7693bf8f9b26f5f4 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 26 May 2023 09:47:27 -0700 Subject: [PATCH] Add support for ref returning methods and properties in `With` statement. (#68203) Fixes #68194. --- .../Portable/Binding/Binder_WithBlock.vb | 32 +- .../VisualBasic/Portable/Errors/ErrorFacts.vb | 1 + .../VisualBasic/Portable/Errors/Errors.vb | 4 +- .../LocalRewriter/LocalRewriter_With.vb | 1 + .../Lowering/WithExpressionRewriter.vb | 40 +- .../VisualBasic/Portable/VBResources.resx | 3 + .../Portable/xlf/VBResources.cs.xlf | 5 + .../Portable/xlf/VBResources.de.xlf | 5 + .../Portable/xlf/VBResources.es.xlf | 5 + .../Portable/xlf/VBResources.fr.xlf | 5 + .../Portable/xlf/VBResources.it.xlf | 5 + .../Portable/xlf/VBResources.ja.xlf | 5 + .../Portable/xlf/VBResources.ko.xlf | 5 + .../Portable/xlf/VBResources.pl.xlf | 5 + .../Portable/xlf/VBResources.pt-BR.xlf | 5 + .../Portable/xlf/VBResources.ru.xlf | 5 + .../Portable/xlf/VBResources.tr.xlf | 5 + .../Portable/xlf/VBResources.zh-Hans.xlf | 5 + .../Portable/xlf/VBResources.zh-Hant.xlf | 5 + .../Emit/CodeGen/CodeGenRefReturnTests.vb | 437 ++++++++++++++++++ 20 files changed, 573 insertions(+), 10 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_WithBlock.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_WithBlock.vb index f4b54e074ab7a..7d3e7fa41f7fa 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_WithBlock.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_WithBlock.vb @@ -102,6 +102,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic expressionPlaceholder As BoundValuePlaceholderBase, draftSubstitute As BoundExpression, draftInitializers As ImmutableArray(Of BoundExpression), + capturedLvalueByRefCallOrProperty As BoundExpression, diagnostics As ImmutableBindingDiagnostic(Of AssemblySymbol)) Debug.Assert(originalExpression IsNot Nothing) @@ -112,6 +113,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Me.OriginalExpression = originalExpression Me.ExpressionPlaceholder = expressionPlaceholder Me.DraftSubstitute = draftSubstitute + Me.CapturedLvalueByRefCallOrProperty = capturedLvalueByRefCallOrProperty Me.DraftInitializers = draftInitializers Me.Diagnostics = diagnostics End Sub @@ -140,6 +142,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' Public ReadOnly DraftSubstitute As BoundExpression + Public ReadOnly CapturedLvalueByRefCallOrProperty As BoundExpression + Public ReadOnly Property ExpressionIsAccessedFromNestedLambda As Boolean Get Return Me._exprAccessedFromNestedLambda = ThreeState.True @@ -210,6 +214,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' NOTE: If the expression is not an l-value we should make an r-value of it If Not boundExpression.IsLValue Then boundExpression = Me.MakeRValue(boundExpression, diagnostics) + Else + Dim propertyAccess = TryCast(boundExpression, BoundPropertyAccess) + + If propertyAccess IsNot Nothing Then + WarnOnRecursiveAccess(propertyAccess, PropertyAccessKind.Get, diagnostics) + boundExpression = propertyAccess.SetAccessKind(PropertyAccessKind.Get) + End If End If ' Prepare draft substitute/initializers for expression placeholder; @@ -218,6 +229,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim result As WithExpressionRewriter.Result = (New WithExpressionRewriter(Me._withBlockSyntax.WithStatement)).AnalyzeWithExpression(Me.ContainingMember, boundExpression, doNotUseByRefLocal:=True, + isDraftRewrite:=True, binder:=Me.ContainingBinder, preserveIdentityOfLValues:=True) @@ -234,7 +246,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' so if the following call fails we can just drop the bound node and diagnostics on the floor Interlocked.CompareExchange(Me._withBlockInfo, New WithBlockInfo(boundExpression, placeholder, - result.Expression, result.Initializers, diagnostics.ToReadOnlyAndFree()), + result.Expression, result.Initializers, result.CapturedLvalueByRefCallOrProperty, diagnostics.ToReadOnlyAndFree()), Nothing) End If @@ -302,10 +314,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' See also comment in PrepareBindingOfOmittedLeft(...) diagnostics.AddRange(Me._withBlockInfo.Diagnostics, allowMismatchInDependencyAccumulation:=True) - Return New BoundWithStatement(node, - Me._withBlockInfo.OriginalExpression, - boundBlockBinder.BindBlock(node, node.Statements, diagnostics).MakeCompilerGenerated(), - Me) + Dim result = New BoundWithStatement(node, + Me._withBlockInfo.OriginalExpression, + boundBlockBinder.BindBlock(node, node.Statements, diagnostics).MakeCompilerGenerated(), + Me) + If Me._withBlockInfo.CapturedLvalueByRefCallOrProperty IsNot Nothing Then + Dim containingMethod = TryCast(ContainingMember, MethodSymbol) + + If (containingMethod IsNot Nothing AndAlso (containingMethod.IsIterator OrElse containingMethod.IsAsync)) OrElse + result.Binder.ExpressionIsAccessedFromNestedLambda Then + ReportDiagnostic(diagnostics, Me._withBlockInfo.CapturedLvalueByRefCallOrProperty.Syntax, ERRID.ERR_UnsupportedRefReturningCallInWithStatement) + End If + End If + + Return result End Function #End Region diff --git a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb index b06e4c7c71ce4..bc8058d5ed9da 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb @@ -1362,6 +1362,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERRID.ERR_RequiredMembersInvalid, ERRID.ERR_NewConstraintCannotHaveRequiredMembers, ERRID.ERR_DoNotUseRequiredMember, + ERRID.ERR_UnsupportedRefReturningCallInWithStatement, ERRID.ERR_NextAvailable, ERRID.WRN_UseOfObsoleteSymbol2, ERRID.WRN_InvalidOverrideDueToTupleNames2, diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 660b3233e63a8..688f1f13592f6 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1773,7 +1773,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_NewConstraintCannotHaveRequiredMembers = 37324 ERR_DoNotUseRequiredMember = 37325 - ERR_NextAvailable = 37326 + ERR_UnsupportedRefReturningCallInWithStatement = 37326 + + ERR_NextAvailable = 37327 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 diff --git a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_With.vb b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_With.vb index 2c40e5461d41e..ad83c1afba6e1 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_With.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_With.vb @@ -35,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic (New WithExpressionRewriter(statementSyntax)).AnalyzeWithExpression(Me._currentMethodOrLambda, rewrittenExpression, doNotUseByRefLocal, + isDraftRewrite:=False, Nothing) RestoreUnstructuredExceptionHandlingContext(node, saveState) diff --git a/src/Compilers/VisualBasic/Portable/Lowering/WithExpressionRewriter.vb b/src/Compilers/VisualBasic/Portable/Lowering/WithExpressionRewriter.vb index 6bb695a09d578..7cb6eb808422d 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/WithExpressionRewriter.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/WithExpressionRewriter.vb @@ -17,10 +17,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private ReadOnly _withSyntax As WithStatementSyntax Public Structure Result - Public Sub New(expression As BoundExpression, locals As ImmutableArray(Of LocalSymbol), initializers As ImmutableArray(Of BoundExpression)) + Public Sub New(expression As BoundExpression, locals As ImmutableArray(Of LocalSymbol), initializers As ImmutableArray(Of BoundExpression), capturedLvalueByRefCallOrProperty As BoundExpression) Me.Expression = expression Me.Locals = locals Me.Initializers = initializers + Me.CapturedLvalueByRefCallOrProperty = capturedLvalueByRefCallOrProperty End Sub ''' Expression to be used instead of With statement expression placeholder @@ -31,6 +32,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' Locals initialization expressions Public ReadOnly Initializers As ImmutableArray(Of BoundExpression) + + Public ReadOnly CapturedLvalueByRefCallOrProperty As BoundExpression End Structure Friend Sub New(withSyntax As WithStatementSyntax) @@ -44,15 +47,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public ReadOnly DoNotUseByRefLocal As Boolean Public ReadOnly Binder As Binder Public ReadOnly PreserveIdentityOfLValues As Boolean + Public ReadOnly IsDraftRewrite As Boolean Private _locals As ArrayBuilder(Of LocalSymbol) = Nothing Private _initializers As ArrayBuilder(Of BoundExpression) = Nothing + Public _capturedLvalueByRefCallOrProperty As BoundExpression = Nothing - Public Sub New(containingMember As Symbol, doNotUseByRefLocal As Boolean, binder As Binder, preserveIdentityOfLValues As Boolean) + Public Sub New(containingMember As Symbol, doNotUseByRefLocal As Boolean, binder As Binder, preserveIdentityOfLValues As Boolean, isDraftRewrite As Boolean) Me.ContainingMember = containingMember Me.DoNotUseByRefLocal = doNotUseByRefLocal Me.Binder = binder Me.PreserveIdentityOfLValues = preserveIdentityOfLValues + Me.IsDraftRewrite = isDraftRewrite End Sub Public Sub AddLocal(local As LocalSymbol, initializer As BoundExpression) @@ -73,7 +79,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Function CreateResult(expression As BoundExpression) As Result Return New Result(expression, If(Me._locals Is Nothing, ImmutableArray(Of LocalSymbol).Empty, Me._locals.ToImmutableAndFree()), - If(Me._initializers Is Nothing, ImmutableArray(Of BoundExpression).Empty, Me._initializers.ToImmutableAndFree())) + If(Me._initializers Is Nothing, ImmutableArray(Of BoundExpression).Empty, Me._initializers.ToImmutableAndFree()), + Me._capturedLvalueByRefCallOrProperty) End Function End Class @@ -262,10 +269,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic containingMember As Symbol, value As BoundExpression, doNotUseByRefLocal As Boolean, + isDraftRewrite As Boolean, binder As Binder, Optional preserveIdentityOfLValues As Boolean = False ) As Result - Dim state As New State(containingMember, doNotUseByRefLocal, binder, preserveIdentityOfLValues) + Dim state As New State(containingMember, doNotUseByRefLocal, binder, preserveIdentityOfLValues, isDraftRewrite) Return state.CreateResult(CaptureWithExpression(value, state)) End Function @@ -326,6 +334,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Case BoundKind.FieldAccess expression = CaptureFieldAccess(DirectCast(value, BoundFieldAccess), state) + Case BoundKind.PropertyAccess + If Not state.IsDraftRewrite OrElse Not DirectCast(value, BoundPropertyAccess).PropertySymbol.ReturnsByRef Then + Throw ExceptionUtilities.UnexpectedValue(value.Kind) + End If + + Debug.Assert(state.DoNotUseByRefLocal) + If state._capturedLvalueByRefCallOrProperty Is Nothing Then + state._capturedLvalueByRefCallOrProperty = value + End If + + expression = CaptureInATemp(value, state) ' Capture by value for the purpose of draft rewrite + + Case BoundKind.Call + If Not state.IsDraftRewrite OrElse Not DirectCast(value, BoundCall).Method.ReturnsByRef Then + Throw ExceptionUtilities.UnexpectedValue(value.Kind) + End If + + Debug.Assert(state.DoNotUseByRefLocal) + If state._capturedLvalueByRefCallOrProperty Is Nothing Then + state._capturedLvalueByRefCallOrProperty = value + End If + + expression = CaptureInATemp(value, state) ' Capture by value for the purpose of draft rewrite + Case Else Throw ExceptionUtilities.UnexpectedValue(value.Kind) End Select diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 1ab1410a67155..df15b37941e1d 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5685,4 +5685,7 @@ 'System.Runtime.CompilerServices.RequiredMemberAttribute' is reserved for compiler usage only. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + \ No newline at end of file diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index 78d4f4581e8bb..7a29f5096722b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -107,6 +107,11 @@ {0} vyžaduje funkci kompilátoru {1}, což tato verze kompilátoru Visual Basic nepodporuje. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression výraz argumentu volajícího diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index 2b94448b25db4..feee6da3898bb 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -107,6 +107,11 @@ "{0}" erfordert die Compilerfunktion "{1}", die von dieser Version des Visual Basic Compilers nicht unterstützt wird. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression Aufruferargumentausdruck diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index 2bde3eda0ff26..4ade6e7ff9a21 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -107,6 +107,11 @@ '{0}' requiere la característica del compilador '{1}', que no es compatible con esta versión del compilador de Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression expresión de argumento de autor de llamada diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index 324e70dc7dcf1..86a76b0f9ff55 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -107,6 +107,11 @@ '{0}' nécessite la fonctionnalité de compilateur '{1}', qui n’est pas prise en charge par cette version du compilateur Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression expression d’argument de l’appelant diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index dc4527c57c197..6af1dfc0688d9 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -107,6 +107,11 @@ '{0}' richiede la funzionalità del compilatore '{1}', che non è supportata da questa versione del compilatore Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression espressione passata come argomento del chiamante diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index 5ea74d453c40f..bb417ed37ac05 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -107,6 +107,11 @@ '{0}' にはコンパイラ機能 '{1}' が必要ですが、このバージョンのVisual Basic コンパイラではサポートされていません。 + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression 呼び出し元の引数式 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 0c2fd82f626c1..3e4f00bbe1ff2 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -107,6 +107,11 @@ '{0}'에는 이 버전의 Visual Basic 컴파일러에서 지원하지 않는 컴파일러 기능 '{1}'이(가) 필요합니다. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression 호출자 인수 표현식 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index b991b5393a5f1..f69022e9347b4 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -107,6 +107,11 @@ „{0}” wymaga funkcji kompilatora „{1}”, która nie jest obsługiwana przez tę wersję kompilatora języka Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression wyrażenie argumentu wywołującego diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index 4af0d2bbc9fa0..66cfe9000aa27 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -107,6 +107,11 @@ '{0}' requer o recurso de compilador '{1}', o que não é suportado por esta versão do compilador do Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression expressão do argumento do chamador diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index 090f2a6f470b6..f5878abdb22ac 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -107,6 +107,11 @@ Для "{0}" требуется функция компилятора "{1}", которая не поддерживается в этой версии компилятора Visual Basic. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression выражение аргумента вызывающего diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index d7dd9755dc36f..7a9a49a28e56b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -107,6 +107,11 @@ '{0}', Visual Basic derleyicisinin bu sürümü tarafından desteklenmeyen '{1}' derleyici özelliğini gerektirir. + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression çağıran bağımsız değişken ifadesi diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index 125695b2fbeb5..9a49644116afa 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -107,6 +107,11 @@ '{0}' 需要编译器功能 '{1}',此版本的 Visual Basic 编译器不支持此功能。 + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression 调用方参数表达式 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index 51c0cb2e499a3..6efb5f5f0b29b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -107,6 +107,11 @@ '{0}' 需要編譯器功能 '{1}',此版本的 Visual Basic 編譯器不支援此功能。 + + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + + caller argument expression 呼叫者引數運算式 diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb index 1cc6b9983c769..fe8645255f49f 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenRefReturnTests.vb @@ -2577,6 +2577,443 @@ End Module verifier.VerifyDiagnostics() End Sub + + + Public Sub With_Method_01() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim o = New C(Of Integer)() + o.GetP() += 1 + With o.GetP() + System.Console.Write(.ToString()) + o.GetP() = 2 + System.Console.Write(.ToString()) + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugExe) + Dim verifier = CompileAndVerify(comp2, expectedOutput:="12") + verifier.VerifyIL("M.Main", + ) + verifier.VerifyDiagnostics() + End Sub + + + + Public Sub With_Method_02() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +" +#disable warning BC42356 + +Module M + async Sub Main() + Dim o = New C(Of Integer)() + With o.GetP() + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.GetP() + ~~~~~~~~ +) + End Sub + + + + Public Sub With_Method_03() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + iterator Function Main() As System.Collections.IEnumerable + Dim o = New C(Of Integer)() + With o.GetP() + End With + End Function +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.GetP() + ~~~~~~~~ +) + End Sub + + + + Public Sub With_Method_04() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +" +#disable warning BC42356 + +Module M + Sub Main() + Dim f = async Sub() + Dim o = New C(Of Integer)() + With o.GetP() + End With + End Sub + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.GetP() + ~~~~~~~~ +) + End Sub + + + + Public Sub With_Method_05() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim f = iterator Function() As System.Collections.IEnumerable + Dim o = New C(Of Integer)() + With o.GetP() + End With + End Function + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.GetP() + ~~~~~~~~ +) + End Sub + + + + Public Sub With_Method_06() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T GetP() + { + return ref _p; + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim o = New C(Of Integer)() + With o.GetP() + Dim f = Sub() System.Console.Write(.ToString()) + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugDll) + + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.GetP() + ~~~~~~~~ +) + End Sub + + + + Public Sub With_Property_01() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T P + { + get { return ref _p; } + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim o = New C(Of Integer)() + o.P += 1 + With o.P + System.Console.Write(.ToString()) + o.P = 2 + System.Console.Write(.ToString()) + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugExe) + Dim verifier = CompileAndVerify(comp2, expectedOutput:="12") + verifier.VerifyIL("M.Main", + ) + verifier.VerifyDiagnostics() + End Sub + + + + Public Sub With_Property_02() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T P + { + get { return ref _p; } + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim o = New C(Of Integer)() + With o.P + Dim f = Sub() System.Console.Write(.ToString()) + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugExe) + + comp2.AssertTheseDiagnostics( + +BC37326: A call to a method or property that returns by reference may not be used as 'With' statement expression in an async or iterator method, or if referenced implicitly in a lambda. + With o.P + ~~~ +) + End Sub + + + + Public Sub With_Indexer() + Dim comp1 = CreateCSharpCompilation( +"public class C +{ +#pragma warning disable 0649 + private T _p; + public ref T this[int i] + { + get { return ref _p; } + } +}") + comp1.VerifyDiagnostics() + Dim comp2 = CreateVisualBasicCompilation( + Nothing, +"Module M + Sub Main() + Dim o = New C(Of Integer)() + o(0) += 1 + With o(0) + System.Console.Write(.ToString()) + o(0) = 2 + System.Console.Write(.ToString()) + End With + End Sub +End Module", + referencedCompilations:={comp1}, + compilationOptions:=TestOptions.DebugExe) + Dim verifier = CompileAndVerify(comp2, expectedOutput:="12") + verifier.VerifyIL("M.Main", + ) + verifier.VerifyDiagnostics() + End Sub + End Class End Namespace