From b66f235eeb9afa86b9d844d80b81689fe45a9cc5 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Fri, 12 Jun 2020 15:54:24 -0700 Subject: [PATCH 1/8] Check partial method return type compatibility --- .../CSharp/Portable/CSharpResources.resx | 12 + .../CSharp/Portable/Errors/ErrorCode.cs | 8 + .../CSharp/Portable/Errors/ErrorFacts.cs | 2 + .../Generated/ErrorFacts.Generated.cs | 1 + ...berContainerSymbol_ImplementationChecks.cs | 8 +- .../Source/SourceOrdinaryMethodSymbol.cs | 30 +- .../Portable/xlf/CSharpResources.cs.xlf | 20 ++ .../Portable/xlf/CSharpResources.de.xlf | 20 ++ .../Portable/xlf/CSharpResources.es.xlf | 20 ++ .../Portable/xlf/CSharpResources.fr.xlf | 20 ++ .../Portable/xlf/CSharpResources.it.xlf | 20 ++ .../Portable/xlf/CSharpResources.ja.xlf | 20 ++ .../Portable/xlf/CSharpResources.ko.xlf | 20 ++ .../Portable/xlf/CSharpResources.pl.xlf | 20 ++ .../Portable/xlf/CSharpResources.pt-BR.xlf | 20 ++ .../Portable/xlf/CSharpResources.ru.xlf | 20 ++ .../Portable/xlf/CSharpResources.tr.xlf | 20 ++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 20 ++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 20 ++ .../Symbols/ExtendedPartialMethodsTests.cs | 265 ++++++++++++++++++ .../Test/Syntax/Diagnostics/DiagnosticTest.cs | 1 + 21 files changed, 581 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index e7a17e886a9d6..8ccda7f711717 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5386,6 +5386,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Nullability of reference types in type of parameter doesn't match partial method declaration. + + Nullability of reference types in return type doesn't match partial method declaration. + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in type of '{0}' doesn't match implicitly implemented member '{1}'. @@ -6169,6 +6175,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Both partial method declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers. + + Both partial method declarations must have the same return type. + + + Both partial method declarations must return by reference or neither may return by reference. + top-level statements diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 0b17327a6883b..bd1d03c7656d2 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1818,6 +1818,14 @@ internal enum ErrorCode ERR_CannotConvertAddressOfToDelegate = 8811, ERR_AddressOfToNonFunctionPointer = 8812, + // Codes 8813, 8814, 8815, 8816 used by features/module-initializers + + ERR_PartialMethodReturnTypeDifference = 8817, + ERR_PartialMethodRefReturnDifference = 8818, + WRN_NullabilityMismatchInReturnTypeOnPartial = 8819, + + // Codes 8820, 8821 used by features/static-lambdas + ERR_BadRecordDeclaration = 8850, ERR_DuplicateRecordConstructor = 8851, ERR_AssignmentInitOnly = 8852, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 62a3f056edf5d..33835c27e7f77 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -49,6 +49,7 @@ static ErrorFacts() nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride)); nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride)); + nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial)); nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride)); nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial)); nullableWarnings.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation)); @@ -399,6 +400,7 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_NullReferenceArgument: case ErrorCode.WRN_NullabilityMismatchInTypeOnOverride: case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride: + case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial: case ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride: case ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial: case ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation: diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 800d04ded67d3..e1e99a88b77eb 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -243,6 +243,7 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_GeneratorFailedDuringGeneration: case ErrorCode.WRN_GivenExpressionAlwaysMatchesPattern: case ErrorCode.WRN_IsPatternAlways: + case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs index 776b064cd3b71..b678e77abf170 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs @@ -1072,11 +1072,11 @@ static void checkValidNullableMethodOverride( checkParameters ? ReportBadParameter : null, overridingMemberLocation); } + } - static bool IsOrContainsErrorType(TypeSymbol typeSymbol) - { - return (object)typeSymbol.VisitType((currentTypeSymbol, unused1, unused2) => currentTypeSymbol.IsErrorType(), (object)null) != null; - } + internal static bool IsOrContainsErrorType(TypeSymbol typeSymbol) + { + return (object)typeSymbol.VisitType((currentTypeSymbol, unused1, unused2) => currentTypeSymbol.IsErrorType(), (object)null) != null; } static readonly ReportMismatchInReturnType ReportBadReturn = diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 30b1695a4bd3f..db4599d102e9d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -1149,6 +1149,25 @@ private static void PartialMethodChecks(SourceOrdinaryMethodSymbol definition, S { Debug.Assert(!ReferenceEquals(definition, implementation)); + MethodSymbol constructedDefinition = definition; + if (implementation.IsGenericMethod) + { + constructedDefinition = definition.Construct(implementation.TypeArgumentsWithAnnotations); + } + + bool returnTypesEqual = constructedDefinition.ReturnTypeWithAnnotations.Equals(implementation.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions); + if (!returnTypesEqual + && !SourceMemberContainerTypeSymbol.IsOrContainsErrorType(implementation.ReturnType) + && !SourceMemberContainerTypeSymbol.IsOrContainsErrorType(definition.ReturnType)) + { + diagnostics.Add(ErrorCode.ERR_PartialMethodReturnTypeDifference, implementation.Locations[0]); + } + + if (definition.RefKind != implementation.RefKind) + { + diagnostics.Add(ErrorCode.ERR_PartialMethodRefReturnDifference, implementation.Locations[0]); + } + if (definition.IsStatic != implementation.IsStatic) { diagnostics.Add(ErrorCode.ERR_PartialMethodStaticDifference, implementation.Locations[0]); @@ -1195,12 +1214,19 @@ private static void PartialMethodChecks(SourceOrdinaryMethodSymbol definition, S definition.ConstructIfGeneric(implementation.TypeArgumentsWithAnnotations), implementation, diagnostics, - reportMismatchInReturnType: null, + (diagnostics, implementedMethod, implementingMethod, topLevel, returnTypesEqual) => + { + if (returnTypesEqual) + { + // report only if this is an unsafe *nullability* difference + diagnostics.Add(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, implementingMethod.Locations[0]); + } + }, (diagnostics, implementedMethod, implementingMethod, implementingParameter, blameAttributes, arg) => { diagnostics.Add(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, implementingMethod.Locations[0], new FormattedSymbol(implementingParameter, SymbolDisplayFormat.ShortFormat)); }, - extraArgument: (object)null); + extraArgument: returnTypesEqual); } private static void PartialMethodConstraintsChecks(SourceOrdinaryMethodSymbol definition, SourceOrdinaryMethodSymbol implementation, DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 4acdd55a0ad14..787ffb9bf4756 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -557,6 +557,16 @@ Obě deklarace částečné metody musí mít modifikátor readonly, nebo nesmí mít modifikátor readonly žádná z nich. + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Typ odkazu s možnou hodnotou null ve vráceném typu neodpovídá přepsanému členu. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Typ odkazu s možnou hodnotou null v typu neodpovídá implementovanému členu {0}. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 2574672f0af24..7880337c3623f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -557,6 +557,16 @@ Entweder beide oder keine der partiellen Methodendeklarationen müssen als "readonly" festgelegt werden. + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Die NULL-Zulässigkeit von Verweistypen im Rückgabetyp entspricht nicht dem außer Kraft gesetzten Member. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Die NULL-Zulässigkeit von Verweistypen im Typ entspricht nicht dem implementierten Member "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 3ad8f16f0441a..001cba6f9718e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -557,6 +557,16 @@ Ambas declaraciones de métodos parciales deben ser de solo lectura o ninguna de ellas puede ser de solo lectura + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ La nulabilidad de los tipos de referencia en el tipo de valor devuelto no coincide con el miembro reemplazado + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. La nulabilidad de los tipos de referencia del tipo no coincide con el miembro implementado "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index c7a880a9f9679..a998cfbc5a913 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -557,6 +557,16 @@ Soit les deux déclarations de méthodes partielles sont readonly, soit aucune ne l'est + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ La nullabilité des types référence dans le type de retour ne correspond pas au membre substitué. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. La nullabilité des types référence dans le type ne correspond pas au membre implémenté '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 1baae7bfbc6c8..16b15669e0c4d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -557,6 +557,16 @@ Nessuna o entrambe le dichiarazioni di metodi parziali devono essere di tipo readonly + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Il supporto dei valori Null dei tipi riferimento nel tipo restituito non corrisponde al membro di cui è stato eseguito l'override. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Il supporto dei valori Null dei tipi riferimento nel tipo non corrisponde al membro implementato '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 83d58c4008f8c..be15a7a30ca06 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -557,6 +557,16 @@ 部分メソッド宣言は、両方とも readonly であるか、両方とも readonly でないかのいずれかである必要があります + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ 戻り値の型における参照型の Null 許容性が、オーバーライドされるメンバーと一致しません。 + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. 型における参照型の Null 許容性が、実装されるメンバー '{0}' と一致しません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 9cf38b3f9a3e3..a6ce90fa04e86 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -557,6 +557,16 @@ 두 부분 메서드(Partial method) 선언 모두 readonly이거나 readonly가 아니어야 합니다. + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ 반환 형식에 있는 참조 형식 Null 허용 여부가 재정의된 멤버와 일치하지 않습니다. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. 형식에 있는 참조 형식 Null 허용 여부가 구현된 멤버 '{0}'과(와) 일치하지 않습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1b27bc474a1f2..fd0974c20fd97 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -557,6 +557,16 @@ Obie metody częściowe muszą być zadeklarowane jako readonly lub żadna nie może być zadeklarowana jako readonly + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Obsługa wartości null dla typów referencyjnych w typie zwracanym jest niezgodna z przesłoniętą składową. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Obsługa wartości null dla typów referencyjnych w typie jest niezgodna z implementowaną składową „{0}”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 588ccea98fe04..ecda31b5c9512 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -557,6 +557,16 @@ As duas declarações de métodos parciais precisam ser readonly ou nenhuma deve ser readonly + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2147,6 +2157,16 @@ A anulabilidade de tipos de referência em tipo de retorno não corresponde ao membro substituído. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. A anulabilidade de tipos de referência em tipo não corresponde ao membro implementado '{0}'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index f7618d3be4ff9..a4b812a3907ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -557,6 +557,16 @@ Либо оба объявления разделяемого метода должны иметь модификатор readonly, либо ни одно из них не должно иметь модификатор readonly. + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Допустимость значения NULL для ссылочных типов в возвращаемом типе не совпадает с переопределенным членом. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Допустимость значения NULL для ссылочных типов в типе не совпадает с реализованным членом "{0}". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index de972dc0acb12..0ea6d94ae9836 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -557,6 +557,16 @@ İki kısmi yöntem bildiriminin de saltokunur olması ya da hiçbirinin saltokunur olmaması gerekir + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ Dönüş türündeki başvuru türlerinin boş değer atanabilirliği, geçersiz kılınan üye ile eşleşmiyor. + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. Türdeki başvuru türlerinin boş değer atanabilirliği, uygulanan '{0}' üyesi ile eşleşmiyor. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 16050c1532eac..06586b2c1ad74 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -557,6 +557,16 @@ 两个分部方法声明必须都是只读声明,或者两者都不能是只读声明 + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ 返回类型中引用类型的为 Null 性与重写成员不匹配。 + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. 类型中引用类型的为 Null 性与实现的成员“{0}”不匹配。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index c9ce42ddfbf0d..08595853e2dbe 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -557,6 +557,16 @@ 兩個部份方法宣告必須都為唯讀,或者都不為唯讀 + + Both partial method declarations must return by reference or neither may return by reference. + Both partial method declarations must return by reference or neither may return by reference. + + + + Both partial method declarations must have the same return type. + Both partial method declarations must have the same return type. + + Partial method '{0}' must have an implementation part because it has accessibility modifiers. Partial method '{0}' must have an implementation part because it has accessibility modifiers. @@ -2149,6 +2159,16 @@ 傳回型別中參考型別的可 Null 性與覆寫的成員不符合。 + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + + + Nullability of reference types in return type doesn't match partial method declaration. + Nullability of reference types in return type doesn't match partial method declaration. + + Nullability of reference types in type doesn't match implemented member '{0}'. 型別中參考型別的可 Null 性與實作的成員 '{0}' 不符合。 diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index f64f10564af2d..eb18ca21e1d5a 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2638,5 +2638,270 @@ static void verifyArray(TypeSymbol type) Assert.Equal(3, array.Sizes[1]); } } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_01() + { + var source = @" +partial class C +{ + public partial int M(); + public partial long M() => 42; // 1 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,25): error CS8817: Both partial method declarations must have the same return type. + // public partial long M() => 42; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M").WithLocation(5, 25)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_02() + { + var source = @" +partial class C +{ + public partial long M(); + public partial int M() => 42; // 1 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,24): error CS8817: Both partial method declarations must have the same return type. + // public partial int M() => 42; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M").WithLocation(5, 24)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_03() + { + var source = @" +using System.Collections.Generic; +#nullable enable + +partial class C +{ + public partial string? M1(); + public partial string M1() => ""hello""; + + public partial IEnumerable M2(); + public partial IEnumerable M2() => null!; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_04() + { + var source = @" +using System.Collections.Generic; +#nullable enable + +partial class C +{ + public partial string M1(); + public partial string? M1() => null; // 1 + + public partial IEnumerable M2(); + public partial IEnumerable M2() => null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (8,28): error CS8818: Nullability of reference types in return type doesn't match partial method declaration. + // public partial string? M1() => null; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M1").WithLocation(8, 28), + // (11,41): error CS8818: Nullability of reference types in return type doesn't match partial method declaration. + // public partial IEnumerable M2() => null!; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M2").WithLocation(11, 41)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_05() + { + var source = @" +using System.Collections.Generic; + +class Base { } +class Derived : Base { } + +partial class C +{ + public partial Base M1(); + public partial Derived M1() => new Derived(); // 1 + + public partial IEnumerable M2(); + public partial IEnumerable M2() => null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (10,28): error CS8817: Both partial method declarations must have the same return type. + // public partial Derived M1() => new Derived(); // 1 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M1").WithLocation(10, 28), + // (13,41): error CS8817: Both partial method declarations must have the same return type. + // public partial IEnumerable M2() => null!; // 2 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M2").WithLocation(13, 41)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_06() + { + var source = @" +using System.Collections.Generic; + +class Base { } +class Derived : Base { } + +partial class C +{ + public partial Derived M1(); + public partial Base M1() => new Base(); // 1 + + public partial IEnumerable M2(); + public partial IEnumerable M2() => null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (10,25): error CS8817: Both partial method declarations must have the same return type. + // public partial Base M1() => new Base(); // 1 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M1").WithLocation(10, 25), + // (13,38): error CS8817: Both partial method declarations must have the same return type. + // public partial IEnumerable M2() => null!; // 2 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M2").WithLocation(13, 38)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_07() + { + var source = @" +using System.Collections.Generic; + +partial class C +{ + public partial U M1(); + public partial V M1() => default; + + public partial IEnumerable M2(); + public partial IEnumerable M2() => default; + + public partial U M3(); + public partial V M3() => default; + + public partial IEnumerable M4(); + public partial IEnumerable M4() => default; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_08() + { + var source = @" +using System.Collections.Generic; + +partial class C +{ + public partial int M1(); + public partial ERROR M1() => throw null!; // 1 + + public partial IEnumerable M2(); + public partial IEnumerable M2() => throw null!; // 2 + + public partial int M3(); + public partial IEnumerable M3() => throw null!; // 3 + + public partial ERROR M4(); // 4 + public partial int M4() => throw null!; + + public partial IEnumerable M5(); // 5 + public partial IEnumerable M5() => throw null!; + + public partial IEnumerable M6(); // 6 + public partial int M6() => throw null!; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (7,20): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial ERROR M1() => throw null!; // 1 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(7, 20), + // (10,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M2() => throw null!; // 2 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(10, 32), + // (13,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M3() => throw null!; // 3 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(13, 32), + // (15,20): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial ERROR M4(); // 4 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(15, 20), + // (18,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M5(); // 5 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(18, 32), + // (21,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M6(); // 6 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(21, 32)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_09() + { + var source = @" +partial class C +{ + public partial ref int M1(); + public partial int M1() => throw null!; // 1 + + public partial int M2(); + public partial ref int M2() => throw null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,24): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // public partial int M1() => throw null!; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M1").WithLocation(5, 24), + // (8,28): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // public partial ref int M2() => throw null!; // 2 + Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M2").WithLocation(8, 28)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_10() + { + var source = @" +partial class C +{ + public partial U M1(); + public partial U M1() where U : struct => throw null!; // 1 + + public partial U M2() where U : struct; + public partial U M2() => throw null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,22): error CS0761: Partial method declarations of 'C.M1()' have inconsistent constraints for type parameter 'U' + // public partial U M1() where U : struct => throw null!; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodInconsistentConstraints, "M1").WithArguments("C.M1()", "U").WithLocation(5, 22), + // (8,22): error CS0761: Partial method declarations of 'C.M2()' have inconsistent constraints for type parameter 'U' + // public partial U M2() => throw null!; // 2 + Diagnostic(ErrorCode.ERR_PartialMethodInconsistentConstraints, "M2").WithArguments("C.M2()", "U").WithLocation(8, 22)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_11() + { + var source = @" +partial class C +{ + public partial T M1(); + public partial T M2(); +} + +partial class C +{ + public partial T M1() => throw null!; + public partial T M2() => throw null!; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 267e6dcff21e1..453b8219d47d8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -274,6 +274,7 @@ public void WarningLevel_2() case ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment: case ErrorCode.WRN_NullabilityMismatchInTypeOnOverride: case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride: + case ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial: case ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride: case ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial: case ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation: From e51378503a30ad5e13c9fa2002e8e3af23c4275b Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 16 Jun 2020 12:10:07 -0700 Subject: [PATCH 2/8] Add a pair of tuple tests --- .../Symbols/ExtendedPartialMethodsTests.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index 3f5e2eb3ca4a0..da83463d02d84 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2903,5 +2903,37 @@ partial class C var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics(); } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_12() + { + var source = @" +partial class C +{ + public partial (int x, int y) M1(); + public partial (int x1, int y1) M1() => default; // 1 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (4,35): error CS8142: Both partial method declarations, 'C.M1()' and 'C.M1()', must use the same tuple element names. + // public partial (int x, int y) M1(); + Diagnostic(ErrorCode.ERR_PartialMethodInconsistentTupleNames, "M1").WithArguments("C.M1()", "C.M1()").WithLocation(4, 35)); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_13() + { + var source = @" +partial class C +{ + public partial (int x, long y) M1(); + public partial (long x, int y) M1() => default; // 1 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,36): error CS8817: Both partial method declarations must have the same return type. + // public partial (long x, int y) M1() => default; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M1").WithLocation(5, 36)); + } } } From 608ed59974207951e111cb8e5d75c1ffb43352fe Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 16 Jun 2020 12:29:45 -0700 Subject: [PATCH 3/8] More tests --- .../Symbols/ExtendedPartialMethodsTests.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index da83463d02d84..dfc6367ccc239 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2935,5 +2935,61 @@ partial class C // public partial (long x, int y) M1() => default; // 1 Diagnostic(ErrorCode.ERR_PartialMethodReturnTypeDifference, "M1").WithLocation(5, 36)); } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_14() + { + var source = @" +partial class C +{ + public partial object M1(); + public partial dynamic M1() => null; + + public partial dynamic M2(); + public partial object M2() => null; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_15() + { + var source = @" +using System; + +partial class C +{ + public partial IntPtr M1(); + public partial nint M1() => 0; + + public partial nint M2(); + public partial IntPtr M2() => default; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_16() + { + var source = @" +partial class C +{ + public partial ref int M1(); + public partial ref readonly int M1() => throw null!; // 1 + + public partial ref readonly int M2(); + public partial ref int M2() => throw null!; // 2 +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (5,37): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // public partial ref readonly int M1() => throw null!; // 1 + Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M1").WithLocation(5, 37), + // (8,28): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // public partial ref int M2() => throw null!; // 2 + Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M2").WithLocation(8, 28)); + } } } From a98d022b6fd1c971ff6f596a3a302712efe8fcc9 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 16 Jun 2020 14:10:24 -0700 Subject: [PATCH 4/8] Add test from feedback --- .../Symbols/ExtendedPartialMethodsTests.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index dfc6367ccc239..135200d0a5b47 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2991,5 +2991,38 @@ partial class C // public partial ref int M2() => throw null!; // 2 Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M2").WithLocation(8, 28)); } + + [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] + public void DifferentReturnTypes_17() + { + var source = @" +partial class C +{ +#nullable enable + public partial string M1(); + public partial string? M1() => null; // 1 + + public partial string? M2(); + public partial string M2() => ""hello""; + +#nullable disable + public partial string M3(); + public partial string? M3() => null; // 2 + + public partial string? M4(); // 3 + public partial string M4() => ""hello""; +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); + comp.VerifyDiagnostics( + // (6,28): warning CS8819: Nullability of reference types in return type doesn't match partial method declaration. + // public partial string? M1() => null; // 1 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M1").WithLocation(6, 28), + // (13,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M3() => null; // 2 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 26), + // (15,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M4(); // 3 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 26)); + } } } From 3aea65a9be80491208ebba85cdaef5726561648d Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 18 Jun 2020 14:01:40 -0700 Subject: [PATCH 5/8] Add additional test from feedback --- .../Symbols/ExtendedPartialMethodsTests.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index 135200d0a5b47..bbfdb8b5890f0 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -3011,6 +3011,26 @@ partial class C public partial string? M4(); // 3 public partial string M4() => ""hello""; + +#nullable enable + public partial string M5(); + public partial string M6() => null!; + public partial string M7(); + public partial string M8() => null!; + public partial string? M9(); + public partial string? M10() => null; + public partial string? M11(); + public partial string? M12() => null; + +#nullable disable + public partial string M5() => null; + public partial string M6(); + public partial string? M7() => null; // 4 + public partial string? M8(); // 5 + public partial string M9() => null; + public partial string M10(); + public partial string? M11() => null; // 6 + public partial string? M12(); // 7 }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics( @@ -3022,7 +3042,19 @@ partial class C Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 26), // (15,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // public partial string? M4(); // 3 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 26)); + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 26), + // (31,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M7() => null; // 4 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(31, 26), + // (32,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M8(); // 5 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(32, 26), + // (35,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M11() => null; // 6 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(35, 26), + // (36,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. + // public partial string? M12(); // 7 + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(36, 26)); } } } From 3015415358fa435a846f63ec108ce7bb013cfa44 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 18 Jun 2020 15:00:11 -0700 Subject: [PATCH 6/8] Address feedback --- .../Symbols/Source/SourceOrdinaryMethodSymbol.cs | 9 ++------- .../Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index db4599d102e9d..befe03e53cebf 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -1149,12 +1149,7 @@ private static void PartialMethodChecks(SourceOrdinaryMethodSymbol definition, S { Debug.Assert(!ReferenceEquals(definition, implementation)); - MethodSymbol constructedDefinition = definition; - if (implementation.IsGenericMethod) - { - constructedDefinition = definition.Construct(implementation.TypeArgumentsWithAnnotations); - } - + MethodSymbol constructedDefinition = definition.ConstructIfGeneric(implementation.TypeArgumentsWithAnnotations); bool returnTypesEqual = constructedDefinition.ReturnTypeWithAnnotations.Equals(implementation.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions); if (!returnTypesEqual && !SourceMemberContainerTypeSymbol.IsOrContainsErrorType(implementation.ReturnType) @@ -1211,7 +1206,7 @@ private static void PartialMethodChecks(SourceOrdinaryMethodSymbol definition, S SourceMemberContainerTypeSymbol.CheckValidNullableMethodOverride( implementation.DeclaringCompilation, - definition.ConstructIfGeneric(implementation.TypeArgumentsWithAnnotations), + constructedDefinition, implementation, diagnostics, (diagnostics, implementedMethod, implementingMethod, topLevel, returnTypesEqual) => diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index bbfdb8b5890f0..961e313493adb 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2707,10 +2707,10 @@ partial class C }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics( - // (8,28): error CS8818: Nullability of reference types in return type doesn't match partial method declaration. + // (8,28): warning CS8819: Nullability of reference types in return type doesn't match partial method declaration. // public partial string? M1() => null; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M1").WithLocation(8, 28), - // (11,41): error CS8818: Nullability of reference types in return type doesn't match partial method declaration. + // (11,41): warning CS8819: Nullability of reference types in return type doesn't match partial method declaration. // public partial IEnumerable M2() => null!; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M2").WithLocation(11, 41)); } From debcedf849c0993be98028a23334dd92394764d7 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 18 Jun 2020 15:18:38 -0700 Subject: [PATCH 7/8] More error type tests --- .../Symbols/ExtendedPartialMethodsTests.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index 961e313493adb..9eeaa1b42a90c 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2818,6 +2818,12 @@ partial class C public partial IEnumerable M6(); // 6 public partial int M6() => throw null!; + + public partial ERROR M7(); // 7 + public partial ERROR M7() => throw null!; // 8 + + public partial IEnumerable M8(); // 9 + public partial IEnumerable M8() => throw null!; // 10 }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics( @@ -2838,7 +2844,19 @@ partial class C Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(18, 32), // (21,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) // public partial IEnumerable M6(); // 6 - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(21, 32)); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(21, 32), + // (24,20): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial ERROR M7(); // 7 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(24, 20), + // (25,20): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial ERROR M7() => throw null!; // 8 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(25, 20), + // (27,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M8(); // 9 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(27, 32), + // (28,32): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public partial IEnumerable M8() => throw null!; // 10 + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(28, 32)); } [Fact, WorkItem(44930, "https://github.com/dotnet/roslyn/issues/44930")] From 7be99fd7f2e9fdbe8a5ef126bdd262aa74c398a6 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 18 Jun 2020 16:36:37 -0700 Subject: [PATCH 8/8] Update diagnostic message --- src/Compilers/CSharp/Portable/CSharpResources.resx | 2 +- src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf | 4 ++-- src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf | 4 ++-- .../Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs | 8 ++++---- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 37c21fad15e85..88d5f37b8bc43 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6182,7 +6182,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Both partial method declarations must have the same return type. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. top-level statements diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index f9980636b3b42..9e36e1b9da0d2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 7e05d1991ff9b..14a8af4b9768f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 1257eb5c4f657..8da0206f76d0a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 970fbb2c73e71..8e2f9e4cebe59 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index d30ab9b39ad85..352ca0ffbae88 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 31d8ebbc69f9c..9b63f30098df4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index faa26d357e498..f02e62fe46953 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 68c12fa55b50c..2c6f5f476b493 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 465e0980d02e6..ec2b1e348e96c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index bf88846c84475..1ff4f08d6a951 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 57e3f7a82f443..fa292989f39a6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index bbf55ffe3ed8c..d83e8b991ba65 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index c0c037e4f9141..331589fdbae50 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -573,8 +573,8 @@ - Both partial method declarations must return by reference or neither may return by reference. - Both partial method declarations must return by reference or neither may return by reference. + Partial method declarations must have matching ref return values. + Partial method declarations must have matching ref return values. diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs index 9eeaa1b42a90c..77b764111db1b 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtendedPartialMethodsTests.cs @@ -2873,10 +2873,10 @@ partial class C }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics( - // (5,24): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // (5,24): error CS8818: Partial method declarations must have matching ref return values. // public partial int M1() => throw null!; // 1 Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M1").WithLocation(5, 24), - // (8,28): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // (8,28): error CS8818: Partial method declarations must have matching ref return values. // public partial ref int M2() => throw null!; // 2 Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M2").WithLocation(8, 28)); } @@ -3002,10 +3002,10 @@ partial class C }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithExtendedPartialMethods); comp.VerifyDiagnostics( - // (5,37): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // (5,37): error CS8818: Partial method declarations must have matching ref return values. // public partial ref readonly int M1() => throw null!; // 1 Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M1").WithLocation(5, 37), - // (8,28): error CS8818: Both partial method declarations must return by reference or neither may return by reference. + // (8,28): error CS8818: Partial method declarations must have matching ref return values. // public partial ref int M2() => throw null!; // 2 Diagnostic(ErrorCode.ERR_PartialMethodRefReturnDifference, "M2").WithLocation(8, 28)); }