Skip to content

Commit

Permalink
Augment several "bool IsXx" APIs with [NotNullWhen(true)] (#1372)
Browse files Browse the repository at this point in the history
If these methods return true, we know the argument passed in wasn't null.  Annotating it as such can help reduce warnings in callers.
  • Loading branch information
stephentoub committed Jan 8, 2020
1 parent 7c24ebc commit 25ea6c4
Show file tree
Hide file tree
Showing 22 changed files with 60 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
**
===========================================================*/

using System.Diagnostics.CodeAnalysis;
using CultureInfo = System.Globalization.CultureInfo;

namespace System.Reflection.Emit
{
public sealed class EnumBuilder : TypeInfo
{
public override bool IsAssignableFrom(TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using System.Globalization;

namespace System.Reflection.Emit
{
public sealed class GenericTypeParameterBuilder : TypeInfo
{
public override bool IsAssignableFrom(System.Reflection.TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
Expand Down Expand Up @@ -176,7 +177,7 @@ public override Type MakeArrayType(int rank)

protected override bool IsValueTypeImpl() { return false; }

public override bool IsAssignableFrom(Type? c) { throw new NotSupportedException(); }
public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) { throw new NotSupportedException(); }

public override bool IsSubclassOf(Type c) { throw new NotSupportedException(); }
#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using CultureInfo = System.Globalization.CultureInfo;

namespace System.Reflection.Emit
Expand All @@ -16,7 +17,7 @@ internal enum TypeKind
// This is a kind of Type object that will represent the compound expression of a parameter type or field type.
internal sealed class SymbolType : TypeInfo
{
public override bool IsAssignableFrom(TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using CultureInfo = System.Globalization.CultureInfo;
Expand All @@ -12,7 +13,7 @@ namespace System.Reflection.Emit
{
public sealed class TypeBuilder : TypeInfo
{
public override bool IsAssignableFrom(TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
Expand Down Expand Up @@ -915,7 +916,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
return m_bakedRuntimeType.GetMembers(bindingAttr);
}

public override bool IsAssignableFrom(Type? c)
public override bool IsAssignableFrom([NotNullWhen(true)] Type? c)
{
if (IsTypeEqual(c, this))
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
using System.Collections;
using System.Globalization;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace System.Reflection.Emit
{
internal sealed class TypeBuilderInstantiation : TypeInfo
{
public override bool IsAssignableFrom(System.Reflection.TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null) return false;
return IsAssignableFrom(typeInfo.AsType());
Expand Down Expand Up @@ -208,7 +209,7 @@ public override bool ContainsGenericParameters
public override MethodBase? DeclaringMethod => null;
public override Type GetGenericTypeDefinition() { return m_type; }
public override Type MakeGenericType(params Type[] inst) { throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericTypeDefinition, this)); }
public override bool IsAssignableFrom(Type? c) { throw new NotSupportedException(); }
public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) { throw new NotSupportedException(); }

public override bool IsSubclassOf(Type c)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -35,7 +36,7 @@ internal RuntimeType GetTypeChecked()
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool IsInstanceOfType(RuntimeType type, object? o);
internal static extern bool IsInstanceOfType(RuntimeType type, [NotNullWhen(true)] object? o);

internal static Type GetTypeHelper(Type typeStart, Type[]? genericArgs, IntPtr pModifiers, int cModifiers)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Internal.Runtime.CompilerServices;
using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
using MdToken = System.Reflection.MetadataToken;
using Internal.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;

namespace System
{
Expand Down Expand Up @@ -3082,7 +3082,7 @@ public override bool IsSubclassOf(Type type)

#if FEATURE_TYPEEQUIVALENCE
// Reflexive, symmetric, transitive.
public override bool IsEquivalentTo(Type? other)
public override bool IsEquivalentTo([NotNullWhen(true)] Type? other)
{
if (!(other is RuntimeType otherRtType))
{
Expand Down
6 changes: 3 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/Convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace System
{
Expand Down Expand Up @@ -163,7 +163,7 @@ public static TypeCode GetTypeCode(object? value)

// Returns true if the given object is a database null. This operation
// corresponds to "value.GetTypeCode() == TypeCode.DBNull".
public static bool IsDBNull(object? value)
public static bool IsDBNull([NotNullWhen(true)] object? value)
{
if (value == System.DBNull.Value) return true;
return value is IConvertible convertible ? convertible.GetTypeCode() == TypeCode.DBNull : false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;

Expand Down Expand Up @@ -103,7 +104,7 @@ public static string GetTempFileName()
return Encoding.UTF8.GetString(name, 0, name.Length - 1); // trim off the trailing '\0'
}

public static bool IsPathRooted(string? path)
public static bool IsPathRooted([NotNullWhen(true)] string? path)
{
if (path == null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#nullable enable
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;

#if MS_IO_REDIST
Expand Down Expand Up @@ -187,7 +188,7 @@ public static string GetTempFileName()

// Tests if the given path contains a root. A path is considered rooted
// if it starts with a backslash ("\") or a valid drive letter and a colon (":").
public static bool IsPathRooted(string? path)
public static bool IsPathRooted([NotNullWhen(true)] string? path)
{
return path != null && IsPathRooted(path.AsSpan());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;

namespace System.Reflection
Expand Down Expand Up @@ -80,7 +81,7 @@ public sealed override Type MakeArrayType(int rank)
public sealed override Type BaseType => throw new NotSupportedException(SR.NotSupported_SignatureType);

public sealed override Type[] GetInterfaces() => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsAssignableFrom(Type? c) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsAssignableFrom([NotNullWhen(true)] Type? c) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override int MetadataToken => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => throw new NotSupportedException(SR.NotSupported_SignatureType);

Expand Down Expand Up @@ -129,8 +130,8 @@ public sealed override Type MakeArrayType(int rank)
public sealed override InterfaceMapping GetInterfaceMap(Type interfaceType) => throw new NotSupportedException(SR.NotSupported_SignatureType);
protected sealed override bool IsContextfulImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsEnum => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsEquivalentTo(Type? other) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsInstanceOfType(object? o) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsEquivalentTo([NotNullWhen(true)] Type? other) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsInstanceOfType([NotNullWhen(true)] object? o) => throw new NotSupportedException(SR.NotSupported_SignatureType);
protected sealed override bool IsMarshalByRefImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsSecurityCritical => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override bool IsSecuritySafeCritical => throw new NotSupportedException(SR.NotSupported_SignatureType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
//
// This class wraps a Type object and delegates all methods to that Type.

using System.Diagnostics.CodeAnalysis;
using CultureInfo = System.Globalization.CultureInfo;

namespace System.Reflection
{
public class TypeDelegator : TypeInfo
{
public override bool IsAssignableFrom(TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace System.Reflection
{
Expand Down Expand Up @@ -50,7 +51,7 @@ public virtual IEnumerable<System.Reflection.TypeInfo> DeclaredNestedTypes
public virtual IEnumerable<Type> ImplementedInterfaces => GetInterfaces();

// a re-implementation of ISAF from Type, skipping the use of UnderlyingType
public virtual bool IsAssignableFrom(TypeInfo? typeInfo)
public virtual bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;

Expand Down Expand Up @@ -293,17 +294,17 @@ protected override bool IsValueTypeImpl()

protected override bool IsCOMObjectImpl() => RuntimeTypeHandle.IsComObject(this, false);

public override bool IsInstanceOfType(object? o) => RuntimeTypeHandle.IsInstanceOfType(this, o);
public override bool IsInstanceOfType([NotNullWhen(true)] object? o) => RuntimeTypeHandle.IsInstanceOfType(this, o);

public override bool IsAssignableFrom(TypeInfo? typeInfo)
public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
{
if (typeInfo == null)
return false;

return IsAssignableFrom(typeInfo.AsType());
}

public override bool IsAssignableFrom(Type? c)
public override bool IsAssignableFrom([NotNullWhen(true)] Type? c)
{
if (c is null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace System
Expand Down Expand Up @@ -330,7 +331,7 @@ public virtual bool IsSubclassOf(Type c)
return false;
}

public virtual bool IsAssignableFrom(Type? c)
public virtual bool IsAssignableFrom([NotNullWhen(true)] Type? c)
{
if (c == null)
return false;
Expand Down
9 changes: 5 additions & 4 deletions src/libraries/System.Private.CoreLib/src/System/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Threading;
using System.Reflection;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;

namespace System
{
Expand Down Expand Up @@ -314,8 +315,8 @@ protected virtual TypeCode GetTypeCodeImpl()

public virtual InterfaceMapping GetInterfaceMap(Type interfaceType) => throw new NotSupportedException(SR.NotSupported_SubclassOverride);

public virtual bool IsInstanceOfType(object? o) => o == null ? false : IsAssignableFrom(o.GetType());
public virtual bool IsEquivalentTo(Type? other) => this == other;
public virtual bool IsInstanceOfType([NotNullWhen(true)] object? o) => o == null ? false : IsAssignableFrom(o.GetType());
public virtual bool IsEquivalentTo([NotNullWhen(true)] Type? other) => this == other;

public virtual Type GetEnumUnderlyingType()
{
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.Private.Uri/src/System/UriExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ public bool IsWellFormedOriginalString()
return Syntax.InternalIsWellFormedOriginalString(this);
}

public static bool IsWellFormedUriString(string? uriString, UriKind uriKind)
public static bool IsWellFormedUriString([NotNullWhen(true)] string? uriString, UriKind uriKind)
{
Uri? result;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public sealed partial class GenericTypeParameterBuilder : System.Type
protected override bool HasElementTypeImpl() { throw null; }
public override object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder? binder, object? target, object?[]? args, System.Reflection.ParameterModifier[]? modifiers, System.Globalization.CultureInfo? culture, string[]? namedParameters) { throw null; }
protected override bool IsArrayImpl() { throw null; }
public override bool IsAssignableFrom(System.Type? c) { throw null; }
public override bool IsAssignableFrom([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? c) { throw null; }
protected override bool IsByRefImpl() { throw null; }
protected override bool IsCOMObjectImpl() { throw null; }
public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
Expand Down Expand Up @@ -449,7 +449,7 @@ public sealed partial class TypeBuilder : System.Type
protected override bool HasElementTypeImpl() { throw null; }
public override object? InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder? binder, object? target, object?[]? args, System.Reflection.ParameterModifier[]? modifiers, System.Globalization.CultureInfo? culture, string[]? namedParameters) { throw null; }
protected override bool IsArrayImpl() { throw null; }
public override bool IsAssignableFrom(System.Type? c) { throw null; }
public override bool IsAssignableFrom([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? c) { throw null; }
protected override bool IsByRefImpl() { throw null; }
protected override bool IsCOMObjectImpl() { throw null; }
public bool IsCreated() { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static partial class TypeExtensions
public static System.Reflection.PropertyInfo? GetProperty(this System.Type type, string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
public static System.Reflection.PropertyInfo? GetProperty(this System.Type type, string name, System.Type? returnType) { throw null; }
public static System.Reflection.PropertyInfo? GetProperty(this System.Type type, string name, System.Type? returnType, System.Type[] types) { throw null; }
public static bool IsAssignableFrom(this System.Type type, System.Type? c) { throw null; }
public static bool IsInstanceOfType(this System.Type type, object? o) { throw null; }
public static bool IsAssignableFrom(this System.Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? c) { throw null; }
public static bool IsInstanceOfType(this System.Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? o) { throw null; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,13 @@ public static PropertyInfo[] GetProperties(Type type, BindingFlags bindingAttr)
return type.GetProperty(name, returnType, types);
}

public static bool IsAssignableFrom(Type type, Type? c)
public static bool IsAssignableFrom(Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] Type? c)
{
Requires.NotNull(type, nameof(type));
return type.IsAssignableFrom(c);
}

public static bool IsInstanceOfType(Type type, object? o)
public static bool IsInstanceOfType(Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? o)
{
Requires.NotNull(type, nameof(type));
return type.IsInstanceOfType(o);
Expand Down

0 comments on commit 25ea6c4

Please sign in to comment.