diff --git a/standard/types.md b/standard/types.md index a431c7273..013a2018f 100644 --- a/standard/types.md +++ b/standard/types.md @@ -859,6 +859,8 @@ A compiler is not required to perform any static analysis nor is it required to **The remainder of this subclause is conditionally normative.** +#### 8.9.5.1 Flow analysis + A compiler that generates diagnostic warnings conforms to these rules. Every expression has one of three ***null state***s: @@ -925,10 +927,10 @@ A compiler can update the null state of a variable as part of its analysis. > int length = p.Length; // Warning: p is maybe null > > string s = p; // No warning. p is not null -> +> > if (s != null) > { -> int l2 = s.Length; // No warning. s is not null +> int l2 = s.Length; // No warning. s is not null > } > int l3 = s.Length; // Warning. s is maybe null > } @@ -998,13 +1000,13 @@ A compiler can treat a property ([§15.7](classes.md#157-properties)) as either > { > get > { -> string tmp = _field; -> _field = null; -> return tmp; +> string tmp = _field; +> _field = null; +> return tmp; > } > set > { -> _field = value; +> _field = value; > } > } > @@ -1031,7 +1033,7 @@ A compiler may use any expression that dereferences a variable, property, or eve > public class C > { > private C? child; -> +> > public void M() > { > _ = child.child.child; // Warning. Dereference possible null value @@ -1042,4 +1044,78 @@ A compiler may use any expression that dereferences a variable, property, or eve > > *end example* +#### 8.9.5.2 Type conversions + +For the purpose of determining whether a conversion is *permitted*, a compiler must consider every nullable-annotated type to be equivalent to its unannotated version. A compiler may issue warnings if the annotations of the types are not compatible. + +(examples: `List` to `IEnumerable`, or `List?` to `IEnumerable`, ...) + +A compiler may follow rules for interface variance ([§18.2.3.3](interfaces.md#18233-variance-conversion)), delegate variance ([§20.4](delegates.md#204-delegate-compatibility)), and array covariance ([§1.7.6](arrays.md#176-array-covariance)) in determining whether to issue a warning for type conversions. +(Do we need to list each type here? E.g. tuple types...) + +> +> ```csharp +> #nullable enable +> public class C +> { +> public void M1(IEnumerable p) +> { +> IEnumerable v1 = p; // No warning +> } +> +> public void M2(IEnumerable p) +> { +> IEnumerable v1 = p; // Warning +> IEnumerable v2 = p!; // No warning +> } +> +> public void M3(Action p) +> { +> Action v1 = p; // No warning +> } +> +> public void M4(Action p) +> { +> Action v1 = p; // Warning +> Action v2 = p!; // No warning +> } +> +> public void M5(string[] p) +> { +> string?[] v1 = p; // No warning +> } +> +> public void M6(string?[] p) +> { +> string[] v1 = p; // Warning +> string[] v2 = p!; // No warning +> } +> } +> ``` +> +> *end example* + +A compiler may issue a warning when nullability differs in either direction in types which do not permit a variant conversion. + +> +> ```csharp +> #nullable enable +> public class C +> { +> public void M1(List p) +> { +> List v1 = p; // Warning +> List v1 = p!; // No Warning +> } +> +> public void M2(List p) +> { +> List v1 = p; // Warning +> List v1 = p!; // No Warning +> } +> } +> ``` +> +> *end example* + ***End of conditionally normative text***