diff --git a/FSharp.sln b/FSharp.sln index 2527bf8b5eb..fdf3b68cdef 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -48,6 +48,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestTP", "tests\service\dat EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{4E4F41D9-86A7-4F5D-B735-1A0744AB68AC}" ProjectSection(SolutionItems) = preProject + docs\builder-caches.md = docs\builder-caches.md + docs\changing-the-ast.md = docs\changing-the-ast.md docs\coding-standards.md = docs\coding-standards.md docs\compiler-startup-performance.md = docs\compiler-startup-performance.md docs\debug-emit.md = docs\debug-emit.md @@ -57,12 +59,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{4E4F41D9-8 docs\index.md = docs\index.md docs\large-inputs-and-stack-overflows.md = docs\large-inputs-and-stack-overflows.md docs\memory-usage.md = docs\memory-usage.md - docs\optimizations.md = docs\optimizations.md + docs\names.md = docs\names.md docs\optimizations-equality.md = docs\optimizations-equality.md + docs\optimizations.md = docs\optimizations.md docs\overview.md = docs\overview.md - docs\builder-caches.md = docs\builder-caches.md - docs\changing-the-ast.md = docs\changing-the-ast.md - docs\names.md = docs\names.md docs\perf-discussions-archive.md = docs\perf-discussions-archive.md docs\project-builds.md = docs\project-builds.md docs\representations.md = docs\representations.md @@ -84,8 +84,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fcs", "fcs", "{B86EBFF1-E03 docs\fcs\symbols.fsx = docs\fcs\symbols.fsx docs\fcs\tokenizer.fsx = docs\fcs\tokenizer.fsx docs\fcs\typedtree.fsx = docs\fcs\typedtree.fsx - docs\fcs\untypedtree.fsx = docs\fcs\untypedtree.fsx docs\fcs\untypedtree-apis.fsx = docs\fcs\untypedtree-apis.fsx + docs\fcs\untypedtree.fsx = docs\fcs\untypedtree.fsx EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsc", "src\fsc\fscProject\fsc.fsproj", "{10D15DBB-EFF0-428C-BA83-41600A93EEC4}" @@ -142,6 +142,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".FSharp.Compiler.Service", docs\release-notes\.FSharp.Compiler.Service\8.0.200.md = docs\release-notes\.FSharp.Compiler.Service\8.0.200.md docs\release-notes\.FSharp.Compiler.Service\8.0.202.md = docs\release-notes\.FSharp.Compiler.Service\8.0.202.md docs\release-notes\.FSharp.Compiler.Service\8.0.300.md = docs\release-notes\.FSharp.Compiler.Service\8.0.300.md + docs\release-notes\.FSharp.Compiler.Service\8.0.400.md = docs\release-notes\.FSharp.Compiler.Service\8.0.400.md + docs\release-notes\.FSharp.Compiler.Service\9.0.100.md = docs\release-notes\.FSharp.Compiler.Service\9.0.100.md + docs\release-notes\.FSharp.Compiler.Service\9.0.200.md = docs\release-notes\.FSharp.Compiler.Service\9.0.200.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".FSharp.Core", ".FSharp.Core", "{23798638-A1E9-4DAE-9C9C-F5D87499ADD6}" @@ -158,8 +161,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Language", ".Language", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".VisualStudio", ".VisualStudio", "{AF70EC5A-8E7C-4FDA-857D-AF08082CFC64}" ProjectSection(SolutionItems) = preProject - docs\release-notes\.VisualStudio\17.9.md = docs\release-notes\.VisualStudio\17.9.md docs\release-notes\.VisualStudio\17.10.md = docs\release-notes\.VisualStudio\17.10.md + docs\release-notes\.VisualStudio\17.9.md = docs\release-notes\.VisualStudio\17.9.md EndProjectSection EndProject Global diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md index 22b160629f3..6fa9786c092 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md @@ -15,6 +15,7 @@ * Fix locals allocating for the special `copyOfStruct` defensive copy ([PR #18025](https://github.com/dotnet/fsharp/pull/18025)) * Fix lowering of computed array expressions when the expression consists of a simple mapping from a `uint64` or `unativeint` array. [PR #18081](https://github.com/dotnet/fsharp/pull/18081) + ### Added * Let `dotnet fsi --help` print a link to the documentation website. ([PR #18006](https://github.com/dotnet/fsharp/pull/18006)) @@ -22,6 +23,7 @@ * Support literal attribute on decimals ([PR #17769](https://github.com/dotnet/fsharp/pull/17769)) * Added type conversions cache, only enabled for compiler runs, guarded by language version preview ([PR #17668](https://github.com/dotnet/fsharp/pull/17668)) * Added project property ParallelCompilation which turns on graph based type checking, parallel ILXGen and parallel optimization. By default on for users of langversion=preview ([PR #17948](https://github.com/dotnet/fsharp/pull/17948)) +* Adding warning when consuming generic method returning T|null for types not supporting nullness (structs,anons,tuples) ([PR #18057](https://github.com/dotnet/fsharp/pull/18057)) ### Changed diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index b52b4b2ad2c..b13e3d01d12 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9728,10 +9728,13 @@ and TcMethodApplicationThen let (CallerNamedArg(id, _)) = List.head attributeAssignedNamedItems errorR(Error(FSComp.SR.tcNamedArgumentDidNotMatch(id.idText), id.idRange)) - // Resolve the "delayed" lookups let exprTy = (tyOfExpr g expr) + for problematicTy in GetDisallowedNullness g exprTy do + let denv = env.DisplayEnv + warning(Error(FSComp.SR.tcDisallowedNullableApplication(methodName,NicePrint.minimalStringOfType denv problematicTy), m)) + PropagateThenTcDelayed cenv overallTy env tpenv mWholeExpr (MakeApplicableExprNoFlex cenv expr) exprTy atomicFlag delayed /// Infer initial type information at the callsite from the syntax of an argument, prior to overload resolution. diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index b42500049d2..f5522147e8c 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1538,6 +1538,7 @@ tcPassingWithoutNullToNonNullQuickAP,"You can remove this |NonNullQuick| pattern tcPassingWithoutNullTononNullFunction,"You can remove this `nonNull` assertion." 3263,tcNullableToStringOverride,"With nullness checking enabled, overrides of .ToString() method must return a non-nullable string. You can handle potential nulls via the built-in string function." 3264,tcDowncastFromNullableToWithoutNull,"Nullness warning: Downcasting from '%s' into '%s' can introduce unexpected null values. Cast to '%s|null' instead or handle the null before downcasting." +3265,tcDisallowedNullableApplication,"Application of method '%s' attempted to create a nullable type ('T | null) for '%s'. Nullness warnings won't be reported correctly for such types." 3268,csNullNotNullConstraintInconsistent,"The constraints 'null' and 'not null' are inconsistent" 3271,tcNullnessCheckingNotEnabled,"The 'nullness checking' language feature is not enabled. This use of a nullness checking construct will be ignored." csTypeHasNullAsTrueValue,"The type '%s' uses 'null' as a representation value but a non-null type is expected" diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index e2c1c0861a9..d383130d0ee 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -9215,6 +9215,57 @@ let reqTyForArgumentNullnessInference g actualTy reqTy = changeWithNullReqTyToVariable g reqTy | _ -> reqTy + +let GetDisallowedNullness (g:TcGlobals) (ty:TType) = + if g.checkNullness then + let rec hasWithNullAnyWhere ty alreadyWrappedInOuterWithNull = + match ty with + | TType_var (tp, n) -> + let withNull = alreadyWrappedInOuterWithNull || n.TryEvaluate() = (ValueSome NullnessInfo.WithNull) + match tp.Solution with + | None -> [] + | Some t -> hasWithNullAnyWhere t withNull + + | TType_app (tcr, tinst, nullnessOrig) -> + let tyArgs = tinst |> List.collect (fun t -> hasWithNullAnyWhere t false) + + match alreadyWrappedInOuterWithNull, tcr.TypeAbbrev with + | true, _ when isStructTyconRef tcr -> ty :: tyArgs + | true, _ when tcr.IsMeasureableReprTycon -> + match tcr.TypeReprInfo with + | TMeasureableRepr realType -> + if hasWithNullAnyWhere realType true |> List.isEmpty then + [] + else [ty] + | _ -> [] + | true, Some tAbbrev -> (hasWithNullAnyWhere tAbbrev true) @ tyArgs + | _ -> tyArgs + + | TType_tuple (_,tupTypes) -> + let inner = tupTypes |> List.collect (fun t -> hasWithNullAnyWhere t false) + if alreadyWrappedInOuterWithNull then ty :: inner else inner + + | TType_anon (anon,tys) -> + let inner = tys |> List.collect (fun t -> hasWithNullAnyWhere t false) + if alreadyWrappedInOuterWithNull then ty :: inner else inner + | TType_fun (d, r, _) -> + (hasWithNullAnyWhere d false) @ (hasWithNullAnyWhere r false) + + | TType_forall _ -> [] + | TType_ucase _ -> [] + | TType_measure m -> + if alreadyWrappedInOuterWithNull then + let measuresInside = + ListMeasureVarOccs m + |> List.choose (fun x -> x.Solution) + |> List.collect (fun x -> hasWithNullAnyWhere x true) + ty :: measuresInside + else [] + + hasWithNullAnyWhere ty false + else + [] + let TypeHasAllowNull (tcref:TyconRef) g m = not tcref.IsStructOrEnumTycon && not (isByrefLikeTyconRef g m tcref) && diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 4eafbf229dc..8b2cf510ac9 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -1815,6 +1815,11 @@ val TypeNullIsTrueValue: TcGlobals -> TType -> bool val TypeNullIsExtraValue: TcGlobals -> range -> TType -> bool +/// A type coming via interop from C# can be holding a nullness combination not supported in F#. +/// Prime example are APIs marked as T|null applied to structs, tuples and anons. +/// Unsupported values can also be nested within generic type arguments, e.g. a List> applied to an anon. +val GetDisallowedNullness: TcGlobals -> TType -> TType list + val TypeHasAllowNull: TyconRef -> TcGlobals -> range -> bool val TypeNullIsExtraValueNew: TcGlobals -> range -> TType -> bool diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index c74702e5ddc..1531db70738 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1337,6 +1337,11 @@ Tento výraz záznamu kopírování a aktualizace mění všechna pole typu záznamu '{0}'. Zvažte použití syntaxe konstrukce záznamu. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. Zkrácená syntaxe lambda je podporována pouze pro atomické výrazy, jako je metoda, vlastnost, pole nebo indexer v implicitní argumentu _. Příklad: let f = _. Length'. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 3e0443ea3ba..232b9023663 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1337,6 +1337,11 @@ Dieser Ausdruck zum Kopieren und Aktualisieren von Datensätzen ändert alle Felder des Datensatztyps "{0}". Erwägen Sie stattdessen die Verwendung der Datensatzerstellungssyntax. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. Die Lambdasyntax der Kurzform wird nur für atomische Ausdrücke wie Methode, Eigenschaft, Feld oder Indexer für das implizite Argument "_" unterstützt. Beispiel: "let f = _. Länge". diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index ecadc24a021..e36ffcc1a4d 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1337,6 +1337,11 @@ Esta expresión de copia y actualización de registros cambia todos los campos de tipo de registro "{0}". Es preferible utilizar la sintaxis de construcción de registros. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. La sintaxis lambda abreviada solo se admite para expresiones atómicas, como el método, la propiedad, el campo o el indexador en el argumento '_' implícito. Por ejemplo: 'let f = _.Length'. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 7a9769e0d22..25e8fc5614e 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1337,6 +1337,11 @@ Cette expression d'enregistrement de copie et de mise à jour modifie tous les champs du type d'enregistrement '{0}'. Envisagez d'utiliser la syntaxe de construction d'enregistrement à la place. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. La syntaxe lambda raccourcie est prise en charge uniquement pour les expressions atomiques, telles que la méthode, la propriété, le champ ou l’indexeur sur l’argument ’_’ implicite. Par exemple : « let f = _. Longueur ». diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 1db94e74c44..c439eed4de1 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1337,6 +1337,11 @@ Questa espressione di record di copia e aggiornamento modifica tutti i campi del tipo di record '{0}'. Provare a usare la sintassi di costruzione dei record. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. La sintassi lambda a sintassi abbreviata è supportata solo per le espressioni atomiche, ad esempio metodo, proprietà, campo o indicizzatore nell'argomento '_' implicito. Ad esempio: 'let f = _. Lunghezza'. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 67b3ad51f9a..06487230d19 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1337,6 +1337,11 @@ この copy-and-update レコード式は、レコードの種類が '{0}' であるすべてのフィールドを変更します。代わりにレコード構築構文を使用することを検討してください。 + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. 短縮ラムダ構文は、暗黙的な '_' 引数のメソッド、プロパティ、フィールド、インデクサーなどのアトミック式でのみサポートされています。例: 'let f = _.Length'。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index d33ad95bff5..2fe10e6fae1 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1337,6 +1337,11 @@ 이 레코드 복사 및 업데이트 식은 '{0}' 레코드 형식의 모든 필드를 변경합니다. 레코드 생성 구문을 대신 사용하는 것이 좋습니다. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. 줄임 람다 구문은 암시적 '_' 인수의 메서드, 속성, 필드 또는 인덱서와 같은 원자성 식에 대해서만 지원됩니다. 예: 'let f = _.Length'. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index a992a59bb23..1f353b7e3ec 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1337,6 +1337,11 @@ To wyrażenie rekordu kopiowania i aktualizacji zmienia wszystkie pola typu rekordu „{0}”. Zamiast tego rozważ użycie składni konstrukcji rekordu. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. Składnia lambda skrótu jest obsługiwana tylko w przypadku wyrażeń niepodzielnych, takich jak metoda, właściwość, pole lub indeksator w dorozumianym argumencie „_”. Na przykład: „let f = _. Length”. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index d547f088b3e..232a3798b4d 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1337,6 +1337,11 @@ Essa expressão de registro copiar e atualizar altera todos os campos do tipo de registro '{0}'. Considere usar a sintaxe de construção de registro em vez disso. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. A sintaxe lambda abreviada só tem suporte para expressões atômicas, como método, propriedade, campo ou indexador no argumento '_' implícito. Por exemplo: 'let f = _. Comprimento'. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 1da17d068ce..2d174a1d325 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1337,6 +1337,11 @@ Это выражение записи копирования и обновления изменяет все поля типа записи "{0}". Вместо этого можно использовать синтаксис конструкции записи. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. Сокращенный синтаксис лямбда-выражений поддерживается только для атомарных выражений, таких как метод, свойство, поле или индексатор подразумеваемого аргумента «_». Например: 'let f = _.Length'. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index fe29aebcff7..6f81b800ddb 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1337,6 +1337,11 @@ Bu kopyalama ve güncelleştirme kayıt ifadesi, '{0}' kayıt türündeki tüm alanları değiştirir. Bunun yerine kayıt oluşturma söz dizimini kullanmayı deneyin. + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. Toplu lambda söz dizimi yalnızca örtülü '_' bağımsız değişkeninde yöntem, özellik, alan veya dizin oluşturucu gibi atomik ifadeler için destekleniyor. Örnek: 'let f = _.Length'. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index c1b2b3d4682..0c0d5e1a2ee 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1337,6 +1337,11 @@ 此复制和更新记录表达式更改记录类型“{0}”的所有字段。请考虑改用记录构造语法。 + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. 仅原子表达式支持速记 lambda 语法,例如隐含的“_”参数上的方法、属性、字段或索引器。例如:“let f = _.Length”。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 7c6c76ff2f7..cfd80e7e706 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1337,6 +1337,11 @@ 此複製和更新記錄運算式將變更記錄類型為 '{0}' 的所有欄位。請考慮改用記錄建構語法。 + + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + Application of method '{0}' attempted to create a nullable type ('T | null) for '{1}'. Nullness warnings won't be reported correctly for such types. + + Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'. 只有不可部分完成運算式才支援速記 Lambda 語法,例如隱含 '_' 引數上的方法、屬性、欄位或索引子。例如: 'let f = _.Length'。 diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index 63b208c42e0..55a76b6f522 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -18,6 +18,73 @@ let typeCheckWithStrictNullness cu = |> typecheck +[] +let ``Report warning when applying anon record to a nullable generic return value`` () = + FSharp """ +open System.Text.Json +type R = { x: int } +type RA = {| x: int |} + +[] +let main _args = + let a = JsonSerializer.Deserialize<{| x: int |}> "null" + let _a = a.x + + let b = JsonSerializer.Deserialize "null" + let _b = b.x + + let c = JsonSerializer.Deserialize "null" + let _c = c.x + 0""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [ Error 3265, Line 8, Col 13, Line 8, Col 60, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for '{| x: int |}'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 11, Col 13, Line 11, Col 50, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for '{| x: int |}'. Nullness warnings won't be reported correctly for such types." + Error 3261, Line 15, Col 14, Line 15, Col 17, "Nullness warning: The types 'R' and 'R | null' do not have compatible nullability."] + +[] +let ``Report warning when generic type instance creates a null-disallowed type`` () = + FSharp """ +open System.Text.Json + +[] +type mykg +type mykgalias = int + +[] // Despite being an abbreviation, this points to a string - does not warn +type string<[] 'Measure> = string|null + +[] +let main _args = + let a = JsonSerializer.Deserialize<{| x: int |}> "null" + let a = JsonSerializer.Deserialize "null" + let a = JsonSerializer.Deserialize "null" + let a = JsonSerializer.Deserialize "null" + let a = JsonSerializer.Deserialize> "null" + let a = JsonSerializer.Deserialize "null" + + // Should be ok from here below + let b = JsonSerializer.Deserialize "null" + let b = JsonSerializer.Deserialize "null" + let b = JsonSerializer.Deserialize>> "null" + let b = JsonSerializer.Deserialize> "null" + + 0""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics + [ Error 3265, Line 13, Col 13, Line 13, Col 60, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for '{| x: int |}'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 14, Col 13, Line 14, Col 51, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for 'System.Int32'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 15, Col 13, Line 15, Col 59, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for '(int * float)'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 16, Col 13, Line 16, Col 67, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for 'struct (int * float)'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 17, Col 13, Line 17, Col 57, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for 'int'. Nullness warnings won't be reported correctly for such types." + Error 3265, Line 18, Col 13, Line 18, Col 57, "Application of method 'Deserialize' attempted to create a nullable type ('T | null) for 'int'. Nullness warnings won't be reported correctly for such types."] + + + [] let ``Does report when null goes to DateTime Parse`` () =