Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing nullability warnings around unconstrained type parameters #29981

Closed
AlekseyTs opened this issue Sep 17, 2018 · 3 comments
Closed

Missing nullability warnings around unconstrained type parameters #29981

AlekseyTs opened this issue Sep 17, 2018 · 3 comments

Comments

@AlekseyTs
Copy link
Contributor

        // PROTOTYPE(NullableReferenceTypes): Should report CS8600 for `T1 t = (T1)NullableObject();`
        // and `T3 t = (T3)NullableObject();`. (See VisitConversion which skips reporting because the
        // `object?` has an Unboxing conversion. Should report warning on unconverted operand
        // when Unboxing.)
        [Fact]
        public void UnconstrainedTypeParameter_MayBeNonNullable()
        {
            var source =
@"class C1<T1>
{
    static object? NullableObject() => null;
    static T1 F1() => default; // warn: return type T1 may be non-null
    static T1 F2() => default(T1); // warn: return type T1 may be non-null
    static void F4()
    {
        T1 t1 = (T1)NullableObject(); // warn: T1 may be non-null
    }
}
class C2<T2> where T2 : class
{
    static object? NullableObject() => null;
    static T2 F1() => default; // warn: return type T2 may be non-null
    static T2 F2() => default(T2); // warn: return type T2 may be non-null
    static void F4()
    {
        T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null
    }
}
class C3<T3> where T3 : new()
{
    static object? NullableObject() => null;
    static T3 F1() => default; // warn: return type T3 may be non-null
    static T3 F2() => default(T3); // warn: return type T3 may be non-null
    static T3 F3() => new T3();
    static void F4()
    {
        T3 t = (T3)NullableObject(); // warn: T3 may be non-null
    }
}
class C4<T4> where T4 : I
{
    static object? NullableObject() => null;
    static T4 F1() => default; // warn: return type T4 may be non-null
    static T4 F2() => default(T4); // warn: return type T4 may be non-null
    static void F4()
    {
        T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null
    }
}
class C5<T5> where T5 : A
{
    static object? NullableObject() => null;
    static T5 F1() => default; // warn: return type T5 may be non-null
    static T5 F2() => default(T5); // warn: return type T5 may be non-null
    static void F4()
    {
        T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null
    }
}
interface I
{
}
class A
{
}";
            var comp = CreateCompilation(new[] { source, NonNullTypesTrue, NonNullTypesAttributesDefinition });
            // PROTOTYPE(NullableReferenceTypes): missing warnings
            comp.VerifyDiagnostics(
                // (45,23): warning CS8603: Possible null reference return.
                //     static T5 F1() => default; // warn: return type T5 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(45, 23),
                // (35,23): warning CS8603: Possible null reference return.
                //     static T4 F1() => default; // warn: return type T4 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(35, 23),
                // (35,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T4 F1() => default; // warn: return type T4 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(35, 23),
                // (24,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T3 F1() => default; // warn: return type T3 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(24, 23),
                // (14,23): warning CS8603: Possible null reference return.
                //     static T2 F1() => default; // warn: return type T2 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(14, 23),
                // (4,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T1 F1() => default; // warn: return type T1 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(4, 23),
                // (46,23): warning CS8603: Possible null reference return.
                //     static T5 F2() => default(T5); // warn: return type T5 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T5)").WithLocation(46, 23),
                // (25,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T3 F2() => default(T3); // warn: return type T3 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T3)").WithLocation(25, 23),
                // (36,23): warning CS8603: Possible null reference return.
                //     static T4 F2() => default(T4); // warn: return type T4 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T4)").WithLocation(36, 23),
                // (36,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T4 F2() => default(T4); // warn: return type T4 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T4)").WithLocation(36, 23),
                // (5,23): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
                //     static T1 F2() => default(T1); // warn: return type T1 may be non-null
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T1)").WithLocation(5, 23),
                // (15,23): warning CS8603: Possible null reference return.
                //     static T2 F2() => default(T2); // warn: return type T2 may be non-null
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T2)").WithLocation(15, 23),
                // (49,17): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T5)NullableObject()").WithLocation(49, 17),
                // (49,17): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T5)NullableObject()").WithLocation(49, 17),
                // (18,17): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T2)NullableObject()").WithLocation(18, 17),
                // (18,17): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T2)NullableObject()").WithLocation(18, 17)
            );
        }
@AlekseyTs
Copy link
Contributor Author

Another scenario:

        [Fact]
        public void UnconstrainedTypeParameter_Return_03()
        {
            var source =
@"class C
{
    static T F01<T>(T t) => t;
    static T F02<T>(T t) where T : class => t;
    static T F03<T>(T t) where T : struct => t;
    static T F04<T>(T t) where T : new() => t;
    static T F05<T, U>(U u) where U : T => u;
    static T F06<T, U>(U u) where U : class, T => u;
    static T F07<T, U>(U u) where U : struct, T => u;
    static T F08<T, U>(U u) where U : T, new() => u;
    static T F09<T>(T t) => (T)t;
    static T F10<T>(T t) where T : class => (T)t;
    static T F11<T>(T t) where T : struct => (T)t;
    static T F12<T>(T t) where T : new() => (T)t;
    static T F13<T, U>(U u) where U : T => (T)u;
    static T F14<T, U>(U u) where U : class, T => (T)u;
    static T F15<T, U>(U u) where U : struct, T => (T)u;
    static T F16<T, U>(U u) where U : T, new() => (T)u;
    static U F17<T, U>(T t) where U : T => (U)t;
    static U F18<T, U>(T t) where U : class, T => (U)t;
    static U F19<T, U>(T t) where U : struct, T => (U)t;
    static U F20<T, U>(T t) where U : T, new() => (U)t;
    static U F21<T, U>(T t) => (U)(object)t;
}";
            var comp = CreateCompilation(new[] { source, NonNullTypesTrue, NonNullTypesAttributesDefinition });

            // PROTOTYPE(NullableReferenceTypes): There should be a warning for F17

            comp.VerifyDiagnostics(
                // (20,51): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //     static U F18<T, U>(T t) where U : class, T => (U)t;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)t").WithLocation(20, 51),
                // (20,51): warning CS8603: Possible null reference return.
                //     static U F18<T, U>(T t) where U : class, T => (U)t;
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)t").WithLocation(20, 51),
                // (23,35): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //     static U F21<T, U>(T t) => (U)(object)t;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(23, 35)
            );
        }

@AlekseyTs
Copy link
Contributor Author

More tests are affected, comments refer to this issue.

@jcouv jcouv added this to the 16.0 milestone Sep 20, 2018
AlekseyTs added a commit that referenced this issue Nov 9, 2018
…in TypeSymbolWithAnnotations. (#30913)

Remove NonNullTypes context and other unnecessary information stored in TypeSymbolWithAnnotations.

Fixes #30845.

Explicitly handle nullability analysis for unconstraint type parameters.

Related to #29981, #29993
@gafter gafter modified the milestones: 16.0, 16.1 Jan 30, 2019
@gafter gafter self-assigned this Feb 15, 2019
@gafter
Copy link
Member

gafter commented Mar 5, 2019

All of these scenarios are implemented and tested in #33648

@gafter gafter closed this as completed Mar 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants