diff --git a/standard/types.md b/standard/types.md index a431c7273..b8fa23d9c 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.** +#### §flow-analysis 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,125 @@ A compiler may use any expression that dereferences a variable, property, or eve > > *end example* +#### §type-conversions Type conversions + +A compiler that generates diagnostic warnings conforms to these rules. + +> *Note:* Differences in top-level or nested nullability annotations in types do not affect whether conversion between the types is permitted, since there is no semantic difference between a non-nullable reference type and its corresponding nullable type ([§8.9.1](types.md#891-general)). + +A compiler may issue a warning when nullability annotations differ between two types, either top-level or nested, when the conversion is narrowing. + +> *Example*: Types differing in top-level annotations +> +> +> ```csharp +> #nullable enable +> public class C +> { +> public void M1(string p) +> { +> _ = (string?)p; // No warning, widening +> } +> +> public void M2(string? p) +> { +> _ = (string)p; // Warning, narrowing +> _ = (string)p!; // No warning, suppressed +> } +> } +> ``` +> +> *end example* + + + +> *Example*: Types differing in nested nullability annotations +> +> +> ```csharp +> #nullable enable +> public class C +> { +> public void M1((string, string) p) +> { +> _ = ((string?, string?))p; // No warning, widening +> } +> +> public void M2((string?, string?) p) +> { +> _ = ((string, string))p; // Warning, narrowing +> _ = ((string, string))p!; // No warning, suppressed +> } +> } +> ``` +> +> *end example* + +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 (§17.6) in determining whether to issue a warning for type conversions. + +> +> ```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 v2 = p!; // No warning +> } +> +> public void M2(List p) +> { +> List v1 = p; // Warning +> List v2 = p!; // No warning +> } +> } +> ``` +> +> *end example* + ***End of conditionally normative text***