Skip to content

Reflection annotate more of CoreLib #37418

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

Merged
merged 5 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public static partial class Marshal
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Trimming doesn't affect types eligible for marshalling. Different exception for invalid inputs doesn't matter.")]
public static IntPtr OffsetOf(Type t, string fieldName)
{
if (t is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3779,6 +3779,8 @@ private void CreateInstanceCheckThis()
throw new NotSupportedException(SR.Acc_CreateVoid);
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Implementation detail of Activator that linker intrinsically recognizes")]
internal object? CreateInstanceImpl(
BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
**
===========================================================*/

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

Expand All @@ -20,6 +21,8 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class ValueType
{
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Trimmed fields don't make a difference for equality")]
public override bool Equals(object? obj)
{
if (null == obj)
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;
using System.Globalization;
using System.Runtime.Loader;
Expand Down Expand Up @@ -97,6 +98,8 @@ public static partial class Activator
throw new ArgumentException(SR.Arg_MustBeType, nameof(type));
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Implementation detail of Activator that linker intrinsically recognizes")]
private static ObjectHandle? CreateInstanceInternal(string assemblyString,
string typeName,
bool ignoreCase,
Expand Down
4 changes: 4 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Activator.cs
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.Globalization;
using System.Reflection;
using System.Runtime.Remoting;
Expand Down Expand Up @@ -40,12 +41,15 @@ public static partial class Activator
public static object? CreateInstance(Type type) =>
CreateInstance(type, nonPublic: false);

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName) =>
CreateInstanceFrom(assemblyFile, typeName, false, ConstructorDefault, null, null, null, null);

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, object?[]? activationAttributes) =>
CreateInstanceFrom(assemblyFile, typeName, false, ConstructorDefault, null, null, null, activationAttributes);

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes)
{
Assembly assembly = Assembly.LoadFrom(assemblyFile);
Expand Down
13 changes: 13 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/AppDomain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma warning disable CS0067 // events are declared but not used

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -278,6 +279,7 @@ public void SetThreadPrincipal(IPrincipal principal)
}
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstance(string assemblyName, string typeName)
{
if (assemblyName == null)
Expand All @@ -288,6 +290,7 @@ public void SetThreadPrincipal(IPrincipal principal)
return Activator.CreateInstance(assemblyName, typeName);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
if (assemblyName == null)
Expand All @@ -305,6 +308,7 @@ public void SetThreadPrincipal(IPrincipal principal)
activationAttributes);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes)
{
if (assemblyName == null)
Expand All @@ -315,12 +319,14 @@ public void SetThreadPrincipal(IPrincipal principal)
return Activator.CreateInstance(assemblyName, typeName, activationAttributes);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceAndUnwrap(string assemblyName, string typeName)
{
ObjectHandle? oh = CreateInstance(assemblyName, typeName);
return oh?.Unwrap();
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
ObjectHandle? oh = CreateInstance(assemblyName,
Expand All @@ -334,17 +340,20 @@ public void SetThreadPrincipal(IPrincipal principal)
return oh?.Unwrap();
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, object?[]? activationAttributes)
{
ObjectHandle? oh = CreateInstance(assemblyName, typeName, activationAttributes);
return oh?.Unwrap();
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName)
{
return Activator.CreateInstanceFrom(assemblyFile, typeName);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
return Activator.CreateInstanceFrom(assemblyFile,
Expand All @@ -357,17 +366,20 @@ public void SetThreadPrincipal(IPrincipal principal)
activationAttributes);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, object?[]? activationAttributes)
{
return Activator.CreateInstanceFrom(assemblyFile, typeName, activationAttributes);
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName)
{
ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName);
return oh?.Unwrap();
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
ObjectHandle? oh = CreateInstanceFrom(assemblyFile,
Expand All @@ -381,6 +393,7 @@ public void SetThreadPrincipal(IPrincipal principal)
return oh?.Unwrap();
}

[RequiresUnreferencedCode("Type and its constructor could be removed")]
public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, object?[]? activationAttributes)
{
ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, activationAttributes);
Expand Down
5 changes: 5 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Attribute.cs
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;

namespace System
Expand All @@ -15,6 +16,8 @@ public abstract partial class Attribute
protected Attribute() { }

#if !CORERT
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Unused fields don't make a difference for equality")]
public override bool Equals(object? obj)
{
if (obj == null)
Expand Down Expand Up @@ -47,6 +50,8 @@ public override bool Equals(object? obj)
return true;
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Unused fields don't make a difference for hashcode quality")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we're OK with the hascode value itself changing as a result of trimming, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think so. We can make this invariant if we keep all fields of attributes in linker, but I don't think we care so much.

Whoever cares about these hashcodes is probably already overriding this implementation (this returns the hashcode of the first non-null field and if that field also happens to be unused - that's a pretty bad hashcode).

public override int GetHashCode()
{
Type type = GetType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,8 @@ public static void Prelink(MethodInfo m)
PrelinkCore(m);
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "This only needs to prelink methods that are actually used")]
public static void PrelinkAll(Type c)
{
if (c is null)
Expand All @@ -533,7 +535,9 @@ public static void StructureToPtr<T>([DisallowNull] T structure, IntPtr ptr, boo
/// Creates a new instance of "structuretype" and marshals data from a
/// native memory block to it.
/// </summary>
public static object? PtrToStructure(IntPtr ptr, Type structureType)
public static object? PtrToStructure(IntPtr ptr,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type structureType)
{
if (ptr == IntPtr.Zero)
{
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs
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;
using System.Collections;
using System.Collections.Generic;
Expand Down Expand Up @@ -105,6 +106,8 @@ private Array GetEnumRawConstantValues()
return values;
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Literal fields on enums can never be trimmed")]
// This will return enumValues and enumNames sorted by the values.
private void GetEnumData(out string[] enumNames, out Array enumValues)
{
Expand Down
24 changes: 24 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public ConstructorInfo? TypeInitializer
protected abstract ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetConstructors(BindingFlags.Public) but this is what the body is doing")]
public ConstructorInfo[] GetConstructors() => GetConstructors(BindingFlags.Public | BindingFlags.Instance);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Expand All @@ -161,6 +163,8 @@ public ConstructorInfo? TypeInitializer
public abstract EventInfo? GetEvent(string name, BindingFlags bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetEvents(BindingFlags.Public) but this is what the body is doing")]
public virtual EventInfo[] GetEvents() => GetEvents(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
Expand All @@ -173,16 +177,26 @@ public ConstructorInfo? TypeInitializer
public abstract FieldInfo? GetField(string name, BindingFlags bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetFields(BindingFlags.Public) but this is what the body is doing")]
public FieldInfo[] GetFields() => GetFields(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
public abstract FieldInfo[] GetFields(BindingFlags bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public MemberInfo[] GetMember(string name) => GetMember(name, Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr) => GetMember(name, MemberTypes.All, bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public virtual MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SubclassOverride);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
Expand Down Expand Up @@ -253,6 +267,8 @@ public ConstructorInfo? TypeInitializer
protected virtual MethodInfo? GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException();

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetMethods(BindingFlags.Public) but this is what the body is doing")]
public MethodInfo[] GetMethods() => GetMethods(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
Expand All @@ -265,6 +281,8 @@ public ConstructorInfo? TypeInitializer
public abstract Type? GetNestedType(string name, BindingFlags bindingAttr);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetNestedTypes(BindingFlags.Public) but this is what the body is doing")]
public Type[] GetNestedTypes() => GetNestedTypes(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
Expand All @@ -282,6 +300,8 @@ public ConstructorInfo? TypeInitializer
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetPropertyImpl(BindingFlags.Public) but this is what the body is doing")]
public PropertyInfo? GetProperty(string name, Type? returnType)
{
if (name == null)
Expand Down Expand Up @@ -312,6 +332,8 @@ public ConstructorInfo? TypeInitializer
protected abstract PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "Linker doesn't recongnize GetProperties(BindingFlags.Public) but this is what the body is doing")]
public PropertyInfo[] GetProperties() => GetProperties(Type.DefaultLookup);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
Expand Down Expand Up @@ -392,6 +414,8 @@ protected virtual TypeCode GetTypeCodeImpl()
public virtual bool IsInstanceOfType([NotNullWhen(true)] object? o) => o == null ? false : IsAssignableFrom(o.GetType());
public virtual bool IsEquivalentTo([NotNullWhen(true)] Type? other) => this == other;

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "The single instance field on enum types is never trimmed")]
public virtual Type GetEnumUnderlyingType()
{
if (!IsEnum)
Expand Down