diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index da2053e8b56ea..b98aea751c268 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -2306,21 +2306,29 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no var boundArgument = BindExpression(argument, diagnostics); bool syntaxIsOk = CheckSyntaxForNameofArgument(argument, out string name, boundArgument.HasAnyErrors ? BindingDiagnosticBag.Discarded : diagnostics); - if (!boundArgument.HasAnyErrors && syntaxIsOk && boundArgument.Kind == BoundKind.MethodGroup) + if (boundArgument is BoundMethodGroup methodGroup) { - var methodGroup = (BoundMethodGroup)boundArgument; - if (!methodGroup.TypeArgumentsOpt.IsDefaultOrEmpty) + if (!boundArgument.HasAnyErrors && syntaxIsOk) { - // method group with type parameters not allowed - diagnostics.Add(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, argument.Location); + if (!methodGroup.TypeArgumentsOpt.IsDefaultOrEmpty) + { + // method group with type parameters not allowed + diagnostics.Add(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, argument.Location); + } + else + { + EnsureNameofExpressionSymbols(methodGroup, diagnostics); + } } - else + } + else if (boundArgument is BoundPropertyAccess propertyAccess) + { + if (propertyAccess.PropertySymbol.GetIsNewExtensionMember()) { - EnsureNameofExpressionSymbols(methodGroup, diagnostics); + diagnostics.Add(ErrorCode.ERR_NameofExtensionMember, boundArgument.Syntax); } } - - if (boundArgument is BoundNamespaceExpression nsExpr) + else if (boundArgument is BoundNamespaceExpression nsExpr) { diagnostics.AddAssembliesUsedByNamespaceReference(nsExpr.NamespaceSymbol); } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index ced190df61062..36430bd52f61c 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -1806,7 +1806,7 @@ If such a class is used as a base class and if the deriving class defines a dest Invalid value for named attribute argument '{0}' - The DllImport attribute must be specified on a method marked 'static' and 'extern' + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member Cannot emit update; {0} '{1}' is missing. @@ -8188,4 +8188,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ An extension member syntax is disallowed in nested position within an extension member syntax + + Extension members are not allowed as an argument to 'nameof'. + diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs index 5ec5fde9c5af4..9d811e630d82d 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/MethodSymbolAdapter.cs @@ -395,7 +395,7 @@ bool Cci.IMethodDefinition.IsExternal { CheckDefinitionInvariant(); - return AdaptedMethodSymbol.IsExternal; + return !AdaptedMethodSymbol.ContainingType.IsExtension && AdaptedMethodSymbol.IsExternal; } } @@ -422,7 +422,7 @@ bool Cci.IMethodDefinition.IsPlatformInvoke get { CheckDefinitionInvariant(); - return AdaptedMethodSymbol.GetDllImportData() != null; + return !AdaptedMethodSymbol.ContainingType.IsExtension && AdaptedMethodSymbol.GetDllImportData() != null; } } #nullable disable @@ -431,14 +431,14 @@ Cci.IPlatformInvokeInformation Cci.IMethodDefinition.PlatformInvokeData get { CheckDefinitionInvariant(); - return AdaptedMethodSymbol.GetDllImportData(); + return AdaptedMethodSymbol.ContainingType.IsExtension ? null : AdaptedMethodSymbol.GetDllImportData(); } } System.Reflection.MethodImplAttributes Cci.IMethodDefinition.GetImplementationAttributes(EmitContext context) { CheckDefinitionInvariant(); - return AdaptedMethodSymbol.ImplementationAttributes; + return AdaptedMethodSymbol.ContainingType.IsExtension ? default : AdaptedMethodSymbol.ImplementationAttributes; } bool Cci.IMethodDefinition.IsRuntimeSpecial diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 3db0d158c3a63..6256a7a53ee51 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2409,6 +2409,7 @@ internal enum ErrorCode ERR_PPShebangInProjectBasedProgram = 9314, ERR_TooManyUserStrings_RestartRequired = 9315, + ERR_NameofExtensionMember = 9316, // Note: you will need to do the following after adding errors: // 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 3b7d348d06638..1b3764f4060a0 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2522,6 +2522,7 @@ or ErrorCode.ERR_CloseUnimplementedInterfaceMemberOperatorMismatch or ErrorCode.ERR_OperatorMismatchOnOverride or ErrorCode.ERR_BadCompoundAssignmentOpArgs or ErrorCode.ERR_PPShebangInProjectBasedProgram + or ErrorCode.ERR_NameofExtensionMember => false, }; #pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. diff --git a/src/Compilers/CSharp/Portable/Symbols/Extensions/SourceExtensionImplementationMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Extensions/SourceExtensionImplementationMethodSymbol.cs index 9d3f3cfeea36e..eac69089d8eaf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Extensions/SourceExtensionImplementationMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Extensions/SourceExtensionImplementationMethodSymbol.cs @@ -22,8 +22,6 @@ public SourceExtensionImplementationMethodSymbol(MethodSymbol sourceMethod) { Debug.Assert(sourceMethod.GetIsNewExtensionMember()); Debug.Assert(sourceMethod.IsStatic || sourceMethod.ContainingType.ExtensionParameter is not null); - Debug.Assert(!sourceMethod.IsExtern); - Debug.Assert(!sourceMethod.IsExternal); // Tracked by https://github.com/dotnet/roslyn/issues/78963 : Are we creating type parameters with the right emit behavior? Attributes, etc. // Also, they should be IsImplicitlyDeclared @@ -59,9 +57,9 @@ internal override int ParameterCount internal sealed override bool IsAccessCheckedOnOverride => false; - public sealed override bool IsExtern => false; - public sealed override DllImportData? GetDllImportData() => null; - internal sealed override bool IsExternal => false; + public sealed override bool IsExtern => _originalMethod.IsExtern; + public sealed override DllImportData? GetDllImportData() => _originalMethod.GetDllImportData(); + internal sealed override bool IsExternal => _originalMethod.IsExternal; internal sealed override bool IsDeclaredReadOnly => false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs index 20fc635fb65f2..bf23f468b8512 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs @@ -825,7 +825,7 @@ private void DecodeDllImportAttribute(ref DecodeWellKnownAttributeArgumentsPřístup k vloženému poli nemůže mít specifikátor pojmenovaného argumentu. + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Omezení new() nejde používat s omezením unmanaged. @@ -7918,8 +7923,8 @@ Pokud se taková třída používá jako základní třída a pokud odvozující - The DllImport attribute must be specified on a method marked 'static' and 'extern' - Pro metodu s deklarací static a extern musí být zadaný atribut DllImport. + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + Pro metodu s deklarací static a extern musí být zadaný atribut DllImport. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 687feee638dbd..dafceae24f839 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1557,6 +1557,11 @@ Ein Inlinearrayzugriff verfügt möglicherweise nicht über einen benannten Argumentspezifizierer. + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Die new()-Einschränkung kann nicht mit der unmanaged-Einschränkung verwendet werden. @@ -7918,8 +7923,8 @@ Wenn solch eine Klasse als Basisklasse verwendet wird und die ableitende Klasse - The DllImport attribute must be specified on a method marked 'static' and 'extern' - Das DllImport-Attribut muss für eine Methode angegeben werden, die als "static" und "extern" markiert ist. + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + Das DllImport-Attribut muss für eine Methode angegeben werden, die als "static" und "extern" markiert ist. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 20ee0d17e8855..e8f31c03b3a7a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1557,6 +1557,11 @@ Un acceso de matriz insertado no puede tener un especificador de argumento con nombre + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La restricción "new()" no se puede utilizar con la restricción "unmanaged" @@ -7918,8 +7923,8 @@ Si se utiliza una clase de este tipo como clase base y si la clase derivada defi - The DllImport attribute must be specified on a method marked 'static' and 'extern' - El atributo DllImport se debe especificar en un método marcado como 'static' y 'extern' + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + El atributo DllImport se debe especificar en un método marcado como 'static' y 'extern' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 120060b6aa3f5..8730934fb2f02 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1557,6 +1557,11 @@ Un accès au tableau en ligne peut ne pas avoir de spécificateur d'argument nommé + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La contrainte 'new()' ne peut pas être utilisée avec la contrainte 'unmanaged' @@ -7918,8 +7923,8 @@ Si une telle classe est utilisée en tant que classe de base et si la classe dé - The DllImport attribute must be specified on a method marked 'static' and 'extern' - L'attribut DllImport doit être spécifié sur une méthode marquée 'static' et 'extern' + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + L'attribut DllImport doit être spécifié sur une méthode marquée 'static' et 'extern' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 44e10a1c36ea6..fa0bc1cc05bb6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1557,6 +1557,11 @@ Un accesso a matrice inline non può includere un identificatore di argomento denominato + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Non è possibile usare il vincolo 'new()' con il vincolo 'unmanaged' @@ -7918,8 +7923,8 @@ Se si usa tale classe come classe base e se la classe di derivazione definisce u - The DllImport attribute must be specified on a method marked 'static' and 'extern' - L'attributo DllImport deve essere specificato in un metodo contrassegnato come 'static' ed 'extern' + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + L'attributo DllImport deve essere specificato in un metodo contrassegnato come 'static' ed 'extern' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index a24d8c00b293a..68c09fb67fc72 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1557,6 +1557,11 @@ インライン配列のアクセスには名前付き引数の指定子を指定できません + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 制約は 'unmanaged' 制約と一緒には使用できません @@ -7918,8 +7923,8 @@ If such a class is used as a base class and if the deriving class defines a dest - The DllImport attribute must be specified on a method marked 'static' and 'extern' - static または extern に指定されているメソッドでは、DllImport 属性を指定する必要があります + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + static または extern に指定されているメソッドでは、DllImport 属性を指定する必要があります diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 85abbd7b43313..92c6d4f138507 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1557,6 +1557,11 @@ 인라인 배열 액세스에는 명명된 인수 지정자가 없을 수 있습니다. + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 제약 조건은 'unmanaged' 제약 조건과 함께 사용할 수 없습니다. @@ -7918,8 +7923,8 @@ If such a class is used as a base class and if the deriving class defines a dest - The DllImport attribute must be specified on a method marked 'static' and 'extern' - DllImport 특성은 'static' 및 'extern'으로 표시된 메서드에만 지정할 수 있습니다. + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + DllImport 특성은 'static' 및 'extern'으로 표시된 메서드에만 지정할 수 있습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 7808486f9b304..4c50962e4ffb3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1557,6 +1557,11 @@ Dostęp do tablicy śródwierszowej nie może mieć specyfikatora argumentu nazwanego + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ograniczenie „new()” nie może być używane z ograniczeniem „unmanaged” @@ -7918,8 +7923,8 @@ Jeśli taka klasa zostanie użyta jako klasa bazowa i klasa pochodna definiuje d - The DllImport attribute must be specified on a method marked 'static' and 'extern' - Dla metody oznaczonej przy użyciu słów kluczowych „static” i „extern” musi zostać określony atrybut DllImport + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + Dla metody oznaczonej przy użyciu słów kluczowych „static” i „extern” musi zostać określony atrybut DllImport diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 3d7f1b33a89f9..7014681057279 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1557,6 +1557,11 @@ Um acesso à matriz não pode ter um especificador de argumento nomeado + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint A restrição 'new()' não pode ser usada com a restrição 'unmanaged' @@ -7918,8 +7923,8 @@ Se tal classe for usada como uma classe base e se a classe derivada definir um d - The DllImport attribute must be specified on a method marked 'static' and 'extern' - O atributo DllImport deve ser especificado em um método marcado como 'static' e 'extern' + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + O atributo DllImport deve ser especificado em um método marcado como 'static' e 'extern' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 3bdbf01e5b6f0..11c500fd0e071 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1557,6 +1557,11 @@ Доступ к встроенному массиву может не иметь спецификатора именованного аргумента. + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ограничение "new()" невозможно использовать вместе с ограничением "unmanaged" @@ -7919,8 +7924,8 @@ If such a class is used as a base class and if the deriving class defines a dest - The DllImport attribute must be specified on a method marked 'static' and 'extern' - Атрибут DllImport должен быть указан для метода, который помечен как "static" и "extern". + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + Атрибут DllImport должен быть указан для метода, который помечен как "static" и "extern". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 94b142d48f3c6..6bbdc94a710cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1557,6 +1557,11 @@ Satır içi dizi erişiminin adlandırılmış bağımsız değişken belirticisi olamaz + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint 'new()' kısıtlaması, 'unmanaged' kısıtlamasıyla kullanılamaz @@ -7918,8 +7923,8 @@ Bu sınıf temel sınıf olarak kullanılırsa ve türetilen sınıf bir yıkıc - The DllImport attribute must be specified on a method marked 'static' and 'extern' - DllImport özniteliği 'static' ve 'extern' olarak işaretlenmiş bir yöntem üzerinde belirtilmelidir + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + DllImport özniteliği 'static' ve 'extern' olarak işaretlenmiş bir yöntem üzerinde belirtilmelidir diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 5517f41b81002..77250accba7d2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1557,6 +1557,11 @@ 内联数组访问可能没有命名参数说明符 + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint "new()" 约束不能与 "unmanaged" 约束一起使用 @@ -7918,8 +7923,8 @@ If such a class is used as a base class and if the deriving class defines a dest - The DllImport attribute must be specified on a method marked 'static' and 'extern' - 必须在标记为 "static" 和 "extern" 的方法上指定 DllImport 特性 + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + 必须在标记为 "static" 和 "extern" 的方法上指定 DllImport 特性 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 44853d257d6f1..96cf004e0afe3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1557,6 +1557,11 @@ 內嵌陣列存取不能有具名引數指定名稱 + + Extension members are not allowed as an argument to 'nameof'. + Extension members are not allowed as an argument to 'nameof'. + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 條件約束不能和 'unmanaged' 條件約束一起使用 @@ -7918,8 +7923,8 @@ If such a class is used as a base class and if the deriving class defines a dest - The DllImport attribute must be specified on a method marked 'static' and 'extern' - DllImport 屬性必須指定在標記為 'static' 和 'extern' 的方法上 + The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + DllImport 屬性必須指定在標記為 'static' 和 'extern' 的方法上 diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_WellKnownAttributes.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_WellKnownAttributes.cs index cb4ef10c97def..17f2158ff006d 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_WellKnownAttributes.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_WellKnownAttributes.cs @@ -3614,13 +3614,13 @@ public class C2 { } // (13,9): error CS0501: 'C.F2(int, string)' must declare a body because it is not marked abstract, extern, or partial // int F2(int bufSize, string buf); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "F2").WithArguments("C.F2(int, string)").WithLocation(13, 9), - // (6,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (6,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("D.DLL")] Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(6, 6), // (9,6): error CS0592: Attribute 'DllImport' is not valid on this declaration type. It is only valid on 'method' declarations. // [DllImport("D.DLL")] Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DllImport").WithArguments("DllImport", "method").WithLocation(9, 6), - // (12,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (12,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("D.DLL")] Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(12, 6), // (15,6): error CS0592: Attribute 'DllImport' is not valid on this declaration type. It is only valid on 'method' declarations. diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 97c8c8f5b4169..1967880b77586 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -24190,7 +24190,10 @@ static class E } """; var comp = CreateCompilation(src); - CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (1,29): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // System.Console.Write(nameof(C.Property)); + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "C.Property").WithLocation(1, 29)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -24228,7 +24231,7 @@ static class E } [Fact] - public void Nameof_Instance_Property() + public void Nameof_Instance_Property_01() { var src = """ C c = null; @@ -24245,7 +24248,10 @@ static class E } """; var comp = CreateCompilation(src); - CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (2,29): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // System.Console.Write(nameof(c.Property)); + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "c.Property").WithLocation(2, 29)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -24253,6 +24259,31 @@ static class E Assert.Equal("System.String E.<>E__0.Property { get; }", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); } + [Fact] + public void Nameof_Instance_Property_02() + { + var src = """ +C c = null; +System.Console.Write(nameof(c.Property.Property)); // 1 +System.Console.Write(nameof(c.Property.ToString)); + +class C { } + +static class E +{ + extension(C c) + { + public C Property => throw null; + } +} +"""; + var comp = CreateCompilation(src); + comp.VerifyEmitDiagnostics( + // (2,29): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // System.Console.Write(nameof(c.Property.Property)); // 1 + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "c.Property.Property").WithLocation(2, 29)); + } + [Fact(Skip = "Assertion in NullableWalker.AsMemberOfType")] // Tracked by https://github.com/dotnet/roslyn/issues/78828 : Nullability analysis of properties public void Nameof_Instance_Property_Generic_01() { @@ -24297,7 +24328,10 @@ static class E } """; var comp = CreateCompilation(src); - CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (1,29): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // System.Console.Write(nameof(C.Property)); + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "C.Property").WithLocation(1, 29)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -24351,7 +24385,10 @@ static class E } """; var comp = CreateCompilation(src); - CompileAndVerify(comp, expectedOutput: "Property").VerifyDiagnostics(); + comp.VerifyEmitDiagnostics( + // (1,29): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // System.Console.Write(nameof(I.Property)); + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "I.Property").WithLocation(1, 29)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -36635,7 +36672,7 @@ required void M() { } } [Fact] - public void Validation_Modifiers_Extern() + public void Extern_01() { string source = """ static class E @@ -36644,155 +36681,1123 @@ static class E { extern void M() { } extern int P { get => 0; set { } } - extern int this[int j] { get => 0; } } } """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,21): error CS0106: The modifier 'extern' is not valid for this item + // (5,21): error CS0179: 'E.extension(int).M()' cannot be extern and declare a body // extern void M() { } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M").WithArguments("extern").WithLocation(5, 21), - // (6,20): error CS0106: The modifier 'extern' is not valid for this item + Diagnostic(ErrorCode.ERR_ExternHasBody, "M").WithArguments("E.extension(int).M()").WithLocation(5, 21), + // (6,24): error CS0179: 'E.extension(int).P.get' cannot be extern and declare a body // extern int P { get => 0; set { } } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P").WithArguments("extern").WithLocation(6, 20), - // (7,20): error CS0106: The modifier 'extern' is not valid for this item - // extern int this[int j] { get => 0; } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("extern").WithLocation(7, 20), - // (7,20): error CS9282: This member is not allowed in an extension block - // extern int this[int j] { get => 0; } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 20)); + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("E.extension(int).P.get").WithLocation(6, 24), + // (6,34): error CS0179: 'E.extension(int).P.set' cannot be extern and declare a body + // extern int P { get => 0; set { } } + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("E.extension(int).P.set").WithLocation(6, 34)); } [Fact] - public void Validation_Modifiers_Unsafe() + public void Extern_02() { - string source = """ + var source = """ +using System.Runtime.InteropServices; static class E { - extension(int i) + extension(int) { - unsafe int* M() => throw null; - unsafe int* P { get => throw null; set { } } - unsafe int* this[int j] { get => throw null; } + [DllImport("something.dll")] + static extern void M(); + + static extern int P + { + [DllImport("something.dll")] + get; + [DllImport("something.dll")] + set; + } } } """; - var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugDll); - comp.VerifyEmitDiagnostics( - // (7,21): error CS9282: This member is not allowed in an extension block - // unsafe int* this[int j] { get => throw null; } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 21)); + var verifier = CompileAndVerify(source).VerifyDiagnostics(); + // Note: skeleton methods have "throw" bodies and lack pinvokeimpl/preservesig. Implementation methods have pinvokeimpl/preservesig and no body. + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 '' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig static + void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname static + int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname static + void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property int32 P() + { + .get int32 E/'<>E__0'::get_P() + .set void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static pinvokeimpl("something.dll" winapi) + void M () cil managed preservesig + { + } // end of method E::M + .method private hidebysig static pinvokeimpl("something.dll" winapi) + int32 get_P () cil managed preservesig + { + } // end of method E::get_P + .method private hidebysig static pinvokeimpl("something.dll" winapi) + void set_P ( + int32 'value' + ) cil managed preservesig + { + } // end of method E::set_P +} // end of class E +"""); } [Fact] - public void Validation_Modifiers_Protected() + public void Extern_03() { - string source = """ + var source = """ +using System.Runtime.InteropServices; static class E { extension(int i) { - protected void M() { } - protected int P { get => 0; set { } } - public int P2 { protected get => 0; set { } } - public int P3 { get => 0; protected set { } } - protected int this[int j] { get => throw null; } - public int this[int j, int k] { protected get => throw null; set { } } + [DllImport("something.dll")] + extern void M(); + + extern int P + { + [DllImport("something.dll")] + get; + [DllImport("something.dll")] + set; + } } } """; var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (5,24): error CS9302: 'E.extension(int).M()': new protected member declared in an extension block - // protected void M() { } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "M").WithArguments("E.extension(int).M()").WithLocation(5, 24), - // (6,23): error CS9302: 'E.extension(int).P': new protected member declared in an extension block - // protected int P { get => 0; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "P").WithArguments("E.extension(int).P").WithLocation(6, 23), - // (7,35): error CS9302: 'E.extension(int).P2.get': new protected member declared in an extension block - // public int P2 { protected get => 0; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).P2.get").WithLocation(7, 35), - // (8,45): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block - // public int P3 { get => 0; protected set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 45), - // (9,23): error CS9282: This member is not allowed in an extension block - // protected int this[int j] { get => throw null; } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 23), - // (9,23): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block - // protected int this[int j] { get => throw null; } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 23), - // (10,20): error CS9282: This member is not allowed in an extension block - // public int this[int j, int k] { protected get => throw null; set { } } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), - // (10,51): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block - // public int this[int j, int k] { protected get => throw null; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).this[int, int].get").WithLocation(10, 51)); - } - - [Fact] - public void Validation_Modifiers_ProtectedInternal() + var verifier = CompileAndVerify(source).VerifyDiagnostics(); + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object { - string source = """ + // Methods + .method private hidebysig specialname static + void '$' ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig + instance void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname + instance int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname + instance void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property instance int32 P() + { + .get instance int32 E/'<>E__0'::get_P() + .set instance void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static pinvokeimpl("something.dll" winapi) + void M ( + int32 i + ) cil managed preservesig + { + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + } // end of method E::M + .method private hidebysig static pinvokeimpl("something.dll" winapi) + int32 get_P ( + int32 i + ) cil managed preservesig + { + } // end of method E::get_P + .method private hidebysig static pinvokeimpl("something.dll" winapi) + void set_P ( + int32 i, + int32 'value' + ) cil managed preservesig + { + } // end of method E::set_P +} // end of class E +"""); + + source = """ +using System.Runtime.InteropServices; static class E { - extension(int i) - { - protected internal void M() { } - protected internal int P { get => 0; set { } } - public int P2 { protected internal get => 0; set { } } - public int P3 { get => 0; protected internal set { } } - protected internal int this[int j] { get => throw null; } - public int this[int j, int k] { protected internal get => throw null; set { } } - } + [DllImport("something.dll")] + static extern void M(this int i); } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (5,33): error CS9302: 'E.extension(int).M()': new protected member declared in an extension block - // protected internal void M() { } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "M").WithArguments("E.extension(int).M()").WithLocation(5, 33), - // (6,32): error CS9302: 'E.extension(int).P': new protected member declared in an extension block - // protected internal int P { get => 0; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "P").WithArguments("E.extension(int).P").WithLocation(6, 32), - // (7,44): error CS9302: 'E.extension(int).P2.get': new protected member declared in an extension block - // public int P2 { protected internal get => 0; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).P2.get").WithLocation(7, 44), - // (8,54): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block - // public int P3 { get => 0; protected internal set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 54), - // (9,32): error CS9282: This member is not allowed in an extension block - // protected internal int this[int j] { get => throw null; } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 32), - // (9,32): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block - // protected internal int this[int j] { get => throw null; } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 32), - // (10,20): error CS9282: This member is not allowed in an extension block - // public int this[int j, int k] { protected internal get => throw null; set { } } - Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), - // (10,60): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block - // public int this[int j, int k] { protected internal get => throw null; set { } } - Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).this[int, int].get").WithLocation(10, 60)); + comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics(); } [Fact] - public void Validation_Modifiers_PrivateProtected() + public void Extern_04() { - string source = """ + var source = """ +using System.Runtime.InteropServices; static class E { - extension(int i) + extension(int) { - private protected void M() { } - private protected int P { get => 0; set { } } - public int P2 { private protected get => 0; set { } } - public int P3 { get => 0; private protected set { } } - private protected int this[int j] { get => throw null; } - public int this[int j, int k] { private protected get => throw null; set { } } + [DllImport("something.dll", EntryPoint = "Method1")] + static extern void M(); + + static extern int P + { + [DllImport("something.dll", EntryPoint = "Method2")] + get; + [DllImport("something.dll", EntryPoint = "Method3")] + set; + } } } """; - var comp = CreateCompilation(source); + var verifier = CompileAndVerify(source).VerifyDiagnostics(); + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 '' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig static + void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname static + int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname static + void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property int32 P() + { + .get int32 E/'<>E__0'::get_P() + .set void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static pinvokeimpl("something.dll" as "Method1" winapi) + void M () cil managed preservesig + { + } // end of method E::M + .method private hidebysig static pinvokeimpl("something.dll" as "Method2" winapi) + int32 get_P () cil managed preservesig + { + } // end of method E::get_P + .method private hidebysig static pinvokeimpl("something.dll" as "Method3" winapi) + void set_P ( + int32 'value' + ) cil managed preservesig + { + } // end of method E::set_P +} // end of class E +"""); + } + + [Fact] + public void Extern_05() + { + var source = """ +static class E +{ + extension(int i) + { + extern void M(); + extern int P { get; set; } + } +} +"""; + var verifier = CompileAndVerify(source, verify: Verification.FailsPEVerify with { PEVerifyMessage = """ + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Type load failed. + """ }); + + verifier.VerifyDiagnostics( + // (5,21): warning CS0626: Method, operator, or accessor 'E.extension(int).M()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern void M(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("E.extension(int).M()").WithLocation(5, 21), + // (6,24): warning CS0626: Method, operator, or accessor 'E.extension(int).P.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P { get; set; } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("E.extension(int).P.get").WithLocation(6, 24), + // (6,29): warning CS0626: Method, operator, or accessor 'E.extension(int).P.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P { get; set; } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("E.extension(int).P.set").WithLocation(6, 29)); + + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig + instance void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname + instance int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname + instance void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property instance int32 P() + { + .get instance int32 E/'<>E__0'::get_P() + .set instance void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static + void M ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + } // end of method E::M + .method private hidebysig static + int32 get_P ( + int32 i + ) cil managed + { + } // end of method E::get_P + .method private hidebysig static + void set_P ( + int32 i, + int32 'value' + ) cil managed + { + } // end of method E::set_P +} // end of class E +"""); + + source = """ +class C +{ + extern void M(); +} +"""; + verifier = CompileAndVerify(source, verify: Verification.FailsPEVerify with { PEVerifyMessage = """ + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Type load failed. + """ }); + + verifier.VerifyDiagnostics( + // (3,17): warning CS0626: Method, operator, or accessor 'C.M()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern void M(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("C.M()").WithLocation(3, 17)); + + VerifyTypeIL(verifier, "C", """ +.class private auto ansi beforefieldinit C + extends [netstandard]System.Object +{ + // Methods + .method private hidebysig + instance void M () cil managed + { + } // end of method C::M + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2067 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [netstandard]System.Object::.ctor() + IL_0006: ret + } // end of method C::.ctor +} // end of class C +"""); + } + + [Fact] + public void Extern_06() + { + var source = """ +static class E +{ + extension(int i) + { + static extern void M(); + static extern int P { get; set; } + } +} +"""; + var verifier = CompileAndVerify(source, verify: Verification.FailsPEVerify with { PEVerifyMessage = """ + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Error: Method marked Abstract, Runtime, InternalCall or Imported must have zero RVA, and vice versa. + Type load failed. + """ }); + + verifier.VerifyDiagnostics( + // (5,28): warning CS0626: Method, operator, or accessor 'E.extension(int).M()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern void M(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("E.extension(int).M()").WithLocation(5, 28), + // (6,31): warning CS0626: Method, operator, or accessor 'E.extension(int).P.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int P { get; set; } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("E.extension(int).P.get").WithLocation(6, 31), + // (6,36): warning CS0626: Method, operator, or accessor 'E.extension(int).P.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int P { get; set; } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("E.extension(int).P.set").WithLocation(6, 36)); + + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig static + void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname static + int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname static + void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property int32 P() + { + .get int32 E/'<>E__0'::get_P() + .set void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static + void M () cil managed + { + } // end of method E::M + .method private hidebysig static + int32 get_P () cil managed + { + } // end of method E::get_P + .method private hidebysig static + void set_P ( + int32 'value' + ) cil managed + { + } // end of method E::set_P +} // end of class E +"""); + } + + [Fact] + public void Extern_07() + { + var source = """ +static class E +{ + extension(int i) + { + extern int this[int j] { get => 0; } + } +} +"""; + CreateCompilation(source).VerifyEmitDiagnostics( + // (5,20): error CS9282: This member is not allowed in an extension block + // extern int this[int j] { get => 0; } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(5, 20), + // (5,34): error CS0179: 'E.extension(int).this[int].get' cannot be extern and declare a body + // extern int this[int j] { get => 0; } + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("E.extension(int).this[int].get").WithLocation(5, 34)); + } + + [Fact] + public void Extern_08() + { + var source = """ +static class E +{ + extension(int i) + { + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + static extern void M(); + + static extern int P + { + [method: System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + get; + + [method: System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + set; + } + } +} +"""; + var comp = CreateCompilation(source); + + // Note: skeleton methods have "throw" bodies and lack internalcall. Implementation methods have internalcall and no body. + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig static + void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname static + int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname static + void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property int32 P() + { + .get int32 E/'<>E__0'::get_P() + .set void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static + void M () cil managed internalcall + { + } // end of method E::M + .method private hidebysig static + int32 get_P () cil managed internalcall + { + } // end of method E::get_P + .method private hidebysig static + void set_P ( + int32 'value' + ) cil managed internalcall + { + } // end of method E::set_P +} // end of class E +"""); + } + + [Fact] + public void Extern_09() + { + var source = """ +static class E +{ + extension(int i) + { + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + extern void M(); + + extern int P + { + [method: System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + get; + + [method: System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + set; + } + } +} +"""; + var comp = CreateCompilation(source); + + var verifier = CompileAndVerify(comp).VerifyDiagnostics(); + VerifyTypeIL(verifier, "E", """ +.class private auto ansi abstract sealed beforefieldinit E + extends [netstandard]System.Object +{ + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + // Nested Types + .class nested public auto ansi sealed specialname beforefieldinit '<>E__0' + extends [netstandard]System.Object + { + // Methods + .method private hidebysig specialname static + void '$' ( + int32 i + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2067 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method '<>E__0'::'$' + .method private hidebysig + instance void M () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::M + .method private hidebysig specialname + instance int32 get_P () cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::get_P + .method private hidebysig specialname + instance void set_P ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2069 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } // end of method '<>E__0'::set_P + // Properties + .property instance int32 P() + { + .get instance int32 E/'<>E__0'::get_P() + .set instance void E/'<>E__0'::set_P(int32) + } + } // end of class <>E__0 + // Methods + .method private hidebysig static + void M ( + int32 i + ) cil managed internalcall + { + .custom instance void [netstandard]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( + 01 00 00 00 + ) + } // end of method E::M + .method private hidebysig static + int32 get_P ( + int32 i + ) cil managed internalcall + { + } // end of method E::get_P + .method private hidebysig static + void set_P ( + int32 i, + int32 'value' + ) cil managed internalcall + { + } // end of method E::set_P +} // end of class E +"""); + } + + [Fact] + public void Extern_10() + { + var source = """ +using System.Runtime.InteropServices; +static class E +{ + extension(int i) + { + [DllImport("something.dll")] + void M() { } + + int P + { + [DllImport("something.dll")] + get => 0; + [DllImport("something.dll")] + set { } + } + } +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(6, 10), + // (11,14): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(11, 14), + // (13,14): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(13, 14)); + } + + [Fact] + public void Extern_11() + { + var source = """ +using System.Runtime.InteropServices; +static class E +{ + extension(int i) + { + [DllImport("something.dll")] + extern void M() { } + + extern int P + { + [DllImport("something.dll")] + get => 0; + [DllImport("something.dll")] + set { } + } + } +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (7,21): error CS0179: 'E.extension(int).M()' cannot be extern and declare a body + // extern void M() { } + Diagnostic(ErrorCode.ERR_ExternHasBody, "M").WithArguments("E.extension(int).M()").WithLocation(7, 21), + // (12,13): error CS0179: 'E.extension(int).P.get' cannot be extern and declare a body + // get => 0; + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("E.extension(int).P.get").WithLocation(12, 13), + // (14,13): error CS0179: 'E.extension(int).P.set' cannot be extern and declare a body + // set { } + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("E.extension(int).P.set").WithLocation(14, 13)); + } + + [Fact] + public void Extern_12() + { + var source = """ +using System.Runtime.InteropServices; +static class E +{ + extension(int) + { + int P + { + [DllImport("something.dll")] + extern get; // 1 + [DllImport("something.dll")] + extern set; // 2 + } + } +} + +static class C +{ + static int P + { + [DllImport("something.dll")] + extern get; // 3 + [DllImport("something.dll")] + extern set; // 4 + } +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,13): error CS9282: This member is not allowed in an extension block + // int P + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "P").WithLocation(6, 13), + // (6,13): error CS9303: 'P': cannot declare instance members in an extension block with an unnamed receiver parameter + // int P + Diagnostic(ErrorCode.ERR_InstanceMemberWithUnnamedExtensionsParameter, "P").WithArguments("P").WithLocation(6, 13), + // (8,14): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(8, 14), + // (9,20): error CS0106: The modifier 'extern' is not valid for this item + // extern get; // 1 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("extern").WithLocation(9, 20), + // (10,14): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(10, 14), + // (11,20): error CS0106: The modifier 'extern' is not valid for this item + // extern set; // 2 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("extern").WithLocation(11, 20), + // (20,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(20, 10), + // (21,16): error CS0106: The modifier 'extern' is not valid for this item + // extern get; // 3 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("extern").WithLocation(21, 16), + // (22,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member + // [DllImport("something.dll")] + Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(22, 10), + // (23,16): error CS0106: The modifier 'extern' is not valid for this item + // extern set; // 4 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("extern").WithLocation(23, 16)); + } + + [Fact] + public void Validation_Modifiers_Unsafe() + { + string source = """ +static class E +{ + extension(int i) + { + unsafe int* M() => throw null; + unsafe int* P { get => throw null; set { } } + unsafe int* this[int j] { get => throw null; } + } +} +"""; + var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugDll); + comp.VerifyEmitDiagnostics( + // (7,21): error CS9282: This member is not allowed in an extension block + // unsafe int* this[int j] { get => throw null; } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(7, 21)); + } + + [Fact] + public void Validation_Modifiers_Protected() + { + string source = """ +static class E +{ + extension(int i) + { + protected void M() { } + protected int P { get => 0; set { } } + public int P2 { protected get => 0; set { } } + public int P3 { get => 0; protected set { } } + protected int this[int j] { get => throw null; } + public int this[int j, int k] { protected get => throw null; set { } } + } +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (5,24): error CS9302: 'E.extension(int).M()': new protected member declared in an extension block + // protected void M() { } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "M").WithArguments("E.extension(int).M()").WithLocation(5, 24), + // (6,23): error CS9302: 'E.extension(int).P': new protected member declared in an extension block + // protected int P { get => 0; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "P").WithArguments("E.extension(int).P").WithLocation(6, 23), + // (7,35): error CS9302: 'E.extension(int).P2.get': new protected member declared in an extension block + // public int P2 { protected get => 0; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).P2.get").WithLocation(7, 35), + // (8,45): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block + // public int P3 { get => 0; protected set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 45), + // (9,23): error CS9282: This member is not allowed in an extension block + // protected int this[int j] { get => throw null; } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 23), + // (9,23): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block + // protected int this[int j] { get => throw null; } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 23), + // (10,20): error CS9282: This member is not allowed in an extension block + // public int this[int j, int k] { protected get => throw null; set { } } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), + // (10,51): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block + // public int this[int j, int k] { protected get => throw null; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).this[int, int].get").WithLocation(10, 51)); + } + + [Fact] + public void Validation_Modifiers_ProtectedInternal() + { + string source = """ +static class E +{ + extension(int i) + { + protected internal void M() { } + protected internal int P { get => 0; set { } } + public int P2 { protected internal get => 0; set { } } + public int P3 { get => 0; protected internal set { } } + protected internal int this[int j] { get => throw null; } + public int this[int j, int k] { protected internal get => throw null; set { } } + } +} +"""; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (5,33): error CS9302: 'E.extension(int).M()': new protected member declared in an extension block + // protected internal void M() { } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "M").WithArguments("E.extension(int).M()").WithLocation(5, 33), + // (6,32): error CS9302: 'E.extension(int).P': new protected member declared in an extension block + // protected internal int P { get => 0; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "P").WithArguments("E.extension(int).P").WithLocation(6, 32), + // (7,44): error CS9302: 'E.extension(int).P2.get': new protected member declared in an extension block + // public int P2 { protected internal get => 0; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).P2.get").WithLocation(7, 44), + // (8,54): error CS9302: 'E.extension(int).P3.set': new protected member declared in an extension block + // public int P3 { get => 0; protected internal set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "set").WithArguments("E.extension(int).P3.set").WithLocation(8, 54), + // (9,32): error CS9282: This member is not allowed in an extension block + // protected internal int this[int j] { get => throw null; } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(9, 32), + // (9,32): error CS9302: 'E.extension(int).this[int]': new protected member declared in an extension block + // protected internal int this[int j] { get => throw null; } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "this").WithArguments("E.extension(int).this[int]").WithLocation(9, 32), + // (10,20): error CS9282: This member is not allowed in an extension block + // public int this[int j, int k] { protected internal get => throw null; set { } } + Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "this").WithLocation(10, 20), + // (10,60): error CS9302: 'E.extension(int).this[int, int].get': new protected member declared in an extension block + // public int this[int j, int k] { protected internal get => throw null; set { } } + Diagnostic(ErrorCode.ERR_ProtectedInExtension, "get").WithArguments("E.extension(int).this[int, int].get").WithLocation(10, 60)); + } + + [Fact] + public void Validation_Modifiers_PrivateProtected() + { + string source = """ +static class E +{ + extension(int i) + { + private protected void M() { } + private protected int P { get => 0; set { } } + public int P2 { private protected get => 0; set { } } + public int P3 { get => 0; private protected set { } } + private protected int this[int j] { get => throw null; } + public int this[int j, int k] { private protected get => throw null; set { } } + } +} +"""; + var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( // (5,32): error CS9302: 'E.extension(int).M()': new protected member declared in an extension block // private protected void M() { } @@ -39834,7 +40839,6 @@ class C public object? P => null; } """; - // Tracked by https://github.com/dotnet/roslyn/issues/78968 : should disallow usage of extension members in nameof comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); comp.VerifyEmitDiagnostics( // (5,5): warning CS8602: Dereference of a possibly null reference. @@ -39877,7 +40881,10 @@ static class E Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o.P").WithLocation(7, 5), // (13,73): error CS8082: Sub-expression cannot be used in an argument to nameof. // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(new object().P))] - Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "new object()").WithLocation(13, 73)); + Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "new object()").WithLocation(13, 73), + // (13,73): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(new object().P))] + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "new object().P").WithLocation(13, 73)); src = """ class E @@ -39935,7 +40942,10 @@ static class E } """; comp = CreateCompilation(src, targetFramework: TargetFramework.Net90); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (7,73): error CS9316: Extension members are not allowed as an argument to 'nameof'. + // [System.Diagnostics.CodeAnalysis.MemberNotNullWhen(true, nameof(object.P))] + Diagnostic(ErrorCode.ERR_NameofExtensionMember, "object.P").WithLocation(7, 73)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs index 3bd43cf601365..f9ea859cb858d 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs @@ -584,7 +584,7 @@ public void AnonymousType_01() var person = new { Name = "John", Age = 30 }; person.M(); person.M2(); -_ = person.P; +_ = person.Property; public static class E { @@ -597,12 +597,32 @@ public static class E public static void M2(this T t) { System.Console.Write("method2 "); } } """; - // Tracked by https://github.com/dotnet/roslyn/issues/78968 : should work var comp = CreateCompilation(src); - comp.VerifyEmitDiagnostics( - // (4,12): error CS1061: '' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type '' could be found (are you missing a using directive or an assembly reference?) - // _ = person.P; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("", "P").WithLocation(4, 12)); + CompileAndVerify(comp, expectedOutput: "method method2 property").VerifyDiagnostics(); + } + + [Fact] + public void AnonymousType_02() + { + // instance members come first + var src = """ +System.Action a = () => { System.Console.Write("method "); }; +var person = new { DoStuff = a, Property = 42 }; + +person.DoStuff(); +System.Console.Write(person.Property); + +public static class E +{ + extension(T t) + { + public void DoStuff() => throw null; + public int Property => throw null; + } +} +"""; + var comp = CreateCompilation(src); + CompileAndVerify(comp, expectedOutput: "method 42").VerifyDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index 54d7002e47a40..0f114d167ec52 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -4147,7 +4147,7 @@ internal class DynamicSecurityMethodAttribute : Attribute { } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.RegularPreview); comp.VerifyDiagnostics( - // (8,22): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (8,22): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // Action a1 = [DllImport("MyModule.dll")] static () => { }; Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(8, 22)); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 3f571adf122cc..7706b5b47a3a3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -1117,19 +1117,19 @@ static void local5() { } "; var comp = CreateCompilation(text, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (10,10): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (10,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("a")] extern void local1(); // 1, 2 Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(10, 10), // (10,38): error CS8112: Local function 'local1()' must either have a body or be marked 'static extern'. // [DllImport("a")] extern void local1(); // 1, 2 Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "local1").WithArguments("local1()").WithLocation(10, 38), - // (11,10): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (11,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("a")] extern void local2() { } // 3, 4 Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(11, 10), // (11,38): error CS0179: 'local2()' cannot be extern and declare a body // [DllImport("a")] extern void local2() { } // 3, 4 Diagnostic(ErrorCode.ERR_ExternHasBody, "local2").WithArguments("local2()").WithLocation(11, 38), - // (12,10): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (12,10): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("a")] extern int local3() => 0; // 5, 6 Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport").WithLocation(12, 10), // (12,37): error CS0179: 'local3()' cannot be extern and declare a body diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs index 2bb1c84896e73..2b6444eb74a8f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs @@ -3055,7 +3055,7 @@ public static void Goo() } "; CreateCompilation(source).VerifyDiagnostics( - // (12,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (12,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [DllImport("goo")] Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport"), // (20,19): error CS1503: Argument 1: cannot convert from 'short' to 'sbyte' diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 2d14058a57436..8fb2036d19f9c 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -11298,9 +11298,9 @@ static void Bar() { } // CS0601 } "; CreateCompilation(text, options: TestOptions.ReleaseDll).VerifyDiagnostics( - // (6,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (6,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport"), - // (9,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (9,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport")); } @@ -14052,7 +14052,7 @@ public static int Main() // (27,34): error CS0507: 'C.PartI()': cannot change access modifiers when overriding 'protected' inherited member 'Base.PartI()' // sealed override partial void PartI(); Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "PartI").WithArguments("C.PartI()", "protected", "Base.PartI()").WithLocation(27, 34), - // (28,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern' + // (28,6): error CS0601: The DllImport attribute must be specified on a method marked 'extern' that is either 'static' or an extension member // [System.Runtime.InteropServices.DllImport("none")] Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "System.Runtime.InteropServices.DllImport").WithLocation(28, 6)); }