Skip to content

Commit

Permalink
Enable trimming in .NET 6 targets (#1906)
Browse files Browse the repository at this point in the history
  • Loading branch information
idg10 committed Mar 30, 2023
1 parent 44a28a8 commit e7c8125
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Rx.NET/Source/Directory.build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>$(DefineConstants);HAS_WINRT;NO_NULLABLE_ATTRIBUTES</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith('net6.0')) or $(TargetFramework.StartsWith('net7.0'))">
<DefineConstants>$(DefineConstants);HAS_TRIMMABILITY_ATTRIBUTES</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith('net6.0-windows')) or $(TargetFramework.StartsWith('net7.0-windows'))">
<DefineConstants>$(DefineConstants);HAS_WINRT;HAS_WINFORMS;HAS_WPF;HAS_DISPATCHER;DESKTOPCLR;WINDOWS;CSWINRT</DefineConstants>
</PropertyGroup>
Expand Down
5 changes: 4 additions & 1 deletion Rx.NET/Source/src/System.Reactive/Internal/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace System.Reactive
{
// We can't make those based on the Strings_Core.resx file, because the ObsoleteAttribute needs a compile-time constant.
// We can't make those based on the Strings_Core.resx file, because attributes need a compile-time constant.

internal static class Constants_Core
{
Expand All @@ -15,6 +15,9 @@ internal static class Constants_Core
public const string ObsoleteSchedulerThreadpool = ObsoleteRefactoring + " Consider using Scheduler.Default to obtain the platform's most appropriate pool-based scheduler. In order to access a specific pool-based scheduler, please add a reference to the System.Reactive.PlatformServices assembly for your target platform and use the appropriate scheduler in the System.Reactive.Concurrency namespace.";

public const string ObsoleteSchedulerequired = "This instance property is no longer supported. Use CurrentThreadScheduler.IsScheduleRequired instead.";

internal const string AsQueryableTrimIncompatibilityMessage = "This type uses Queryable.AsQueryable, which is not compatible with trimming because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods, and those IEnumerable methods might be trimmed.";
internal const string EventReflectionTrimIncompatibilityMessage = "This member uses reflection to discover event members and associated delegate types.";
}

// We can't make those based on the Strings_*.resx file, because the ObsoleteAttribute needs a compile-time constant.
Expand Down
4 changes: 4 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Internal/ReflectionUtils.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.Globalization;
using System.Reflection;

Expand All @@ -19,6 +20,9 @@ public static Delegate CreateDelegate(Type delegateType, object o, MethodInfo me
return method.CreateDelegate(delegateType, o);
}

#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static void GetEventMethods<TSender, TEventArgs>(Type targetType, object? target, string eventName, out MethodInfo addMethod, out MethodInfo removeMethod, out Type delegateType, out bool isWinRT)
{
EventInfo? e;
Expand Down
36 changes: 36 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Linq/IQueryLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,17 +433,53 @@ internal partial interface IQueryLanguage
IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Action<EventHandler<TEventArgs>> addHandler, Action<EventHandler<TEventArgs>> removeHandler, IScheduler scheduler);
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TDelegate, TSender, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler);
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TDelegate, TSender, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<object>> FromEventPattern(object target, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<object>> FromEventPattern(object target, string eventName, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName, IScheduler scheduler);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName);
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName, IScheduler scheduler);

IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler);
Expand Down
37 changes: 37 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Linq/Observable.Events.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.Reactive.Concurrency;
using System.Threading;

Expand Down Expand Up @@ -538,6 +539,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<object>> FromEventPattern(object target, string eventName)
{
if (target == null)
Expand Down Expand Up @@ -581,6 +585,9 @@ public static IObservable<EventPattern<object>> FromEventPattern(object target,
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<object>> FromEventPattern(object target, string eventName, IScheduler scheduler)
{
if (target == null)
Expand Down Expand Up @@ -633,6 +640,9 @@ public static IObservable<EventPattern<object>> FromEventPattern(object target,
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName)
{
if (target == null)
Expand Down Expand Up @@ -677,6 +687,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName, IScheduler scheduler)
{
if (target == null)
Expand Down Expand Up @@ -730,6 +743,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName)
{
if (target == null)
Expand Down Expand Up @@ -775,6 +791,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName, IScheduler scheduler)
{
if (target == null)
Expand Down Expand Up @@ -830,6 +849,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName)
{
if (type == null)
Expand Down Expand Up @@ -873,6 +895,9 @@ public static IObservable<EventPattern<object>> FromEventPattern(Type type, stri
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName, IScheduler scheduler)
{
if (type == null)
Expand Down Expand Up @@ -925,6 +950,9 @@ public static IObservable<EventPattern<object>> FromEventPattern(Type type, stri
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName)
{
if (type == null)
Expand Down Expand Up @@ -969,6 +997,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName, IScheduler scheduler)
{
if (type == null)
Expand Down Expand Up @@ -1022,6 +1053,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName)
{
if (type == null)
Expand Down Expand Up @@ -1067,6 +1101,9 @@ public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>
/// </para>
/// </remarks>
/// <seealso cref="ToEventPattern"/>
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]
#endif
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName, IScheduler scheduler)
{
if (type == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

#pragma warning disable 1591

using System.Diagnostics.CodeAnalysis;

namespace System.Reactive.Linq
{
#if HAS_TRIMMABILITY_ATTRIBUTES
[RequiresUnreferencedCode(Constants_Core.AsQueryableTrimIncompatibilityMessage)]
#endif
public static partial class Qbservable
{
#pragma warning disable IDE1006 // Naming Styles: 3rd party code is known to reflect for this specific field name
Expand Down
8 changes: 8 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Linq/Qbservable.Joins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public static partial class Qbservable
#if CRIPPLED_REFLECTION
InfoOf(() => And<TLeft, TRight>(default, default)),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TLeft), typeof(TRight)),
#pragma warning restore IL2060
#endif
left.Expression,
GetSourceExpression(right)
Expand Down Expand Up @@ -80,7 +82,9 @@ public static partial class Qbservable
#if CRIPPLED_REFLECTION
InfoOf(() => Then<TSource, TResult>(default, default)),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TSource), typeof(TResult)),
#pragma warning restore IL2060
#endif
source.Expression,
selector
Expand Down Expand Up @@ -114,7 +118,9 @@ public static IQbservable<TResult> When<TResult>(this IQbservableProvider provid
#if CRIPPLED_REFLECTION
InfoOf(() => When<TResult>(default, default)),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TResult)),
#pragma warning restore IL2060
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
Expression.NewArrayInit(
Expand Down Expand Up @@ -151,7 +157,9 @@ public static IQbservable<TResult> When<TResult>(this IQbservableProvider provid
#if CRIPPLED_REFLECTION
InfoOf(() => When(default, default(IEnumerable<QueryablePlan<TResult>>))),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TResult)),
#pragma warning restore IL2060
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
Expression.Constant(plans, typeof(IEnumerable<QueryablePlan<TResult>>))
Expand Down
4 changes: 4 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Linq/Qbservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ public static IQbservable<TSource> ToQbservable<TSource>(this IQueryable<TSource
#if CRIPPLED_REFLECTION
InfoOf(() => ToQbservable<TSource>(default)),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TSource)),
#pragma warning restore IL2060
#endif
source.Expression
)
Expand Down Expand Up @@ -90,7 +92,9 @@ public static IQbservable<TSource> ToQbservable<TSource>(this IQueryable<TSource
#if CRIPPLED_REFLECTION
InfoOf(() => ToQbservable<TSource>(default)),
#else
#pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed
((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TSource)),
#pragma warning restore IL2060
#endif
source.Expression,
Expression.Constant(scheduler)
Expand Down

0 comments on commit e7c8125

Please sign in to comment.