Skip to content

Commit

Permalink
Merge pull request #784 from polyadic/aot
Browse files Browse the repository at this point in the history
Mark Funcky and Funcky.Async as AOT compatible
  • Loading branch information
bash authored Apr 25, 2024
2 parents 9a0266c + c0e54ca commit 611dcca
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 5 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,16 @@ jobs:
run: dotnet test --configuration Release --no-build

trimming-test:
name: Trimming Test
name: Trimming and AOT Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
name: Install Current .NET SDK
- name: Run trimming test
run: dotnet publish -c Release Funcky.TrimmingTest -r linux-x64 --self-contained /p:TreatWarningsAsErrors=true
- name: Run AOT test
run: dotnet publish -c Release Funcky.TrimmingTest -r linux-x64 --self-contained /p:TreatWarningsAsErrors=true /p:FunckyTestAot=true

nupkg:
name: Generate NuGet Packages
Expand Down
2 changes: 1 addition & 1 deletion FrameworkFeatureConstants.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<DefineConstants>$(DefineConstants);STACK_TRACE_HIDDEN_SUPPORTED;DATE_ONLY_SUPPORTED;TIME_ONLY_SUPPORTED;PRIORITY_QUEUE;TRY_GET_NON_ENUMERATED_COUNT;HTTP_HEADERS_NON_VALIDATED;ELEMENT_AT_INDEX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<DefineConstants>$(DefineConstants);GENERIC_MATH;GENERIC_PARSABLE</DefineConstants>
<DefineConstants>$(DefineConstants);GENERIC_MATH;GENERIC_PARSABLE;AOT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
<DefineConstants>$(DefineConstants);RANDOM_SHUFFLE;UTF8_SPAN_PARSABLE</DefineConstants>
Expand Down
3 changes: 3 additions & 0 deletions Funcky.Async/Funcky.Async.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<IsTrimmable>true</IsTrimmable>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Funcky\Internal\Aggregators\DecimalAverageAggregator.cs" Link="Internal\Aggregators\DecimalAverageAggregator.cs" />
<Compile Include="..\Funcky\Internal\Aggregators\DoubleAverageAggregator.cs" Link="Internal\Aggregators\DoubleAverageAggregator.cs" />
Expand Down
5 changes: 2 additions & 3 deletions Funcky.TrimmingTest/Funcky.TrimmingTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishTrimmed>true</PublishTrimmed>
<!-- Prevent warnings from unused code in dependencies -->
<TrimmerDefaultAction>link</TrimmerDefaultAction>
<PublishTrimmed Condition="'$(FunckyTestAot)' != 'true'">true</PublishTrimmed>
<PublishAot Condition="'$(FunckyTestAot)' == 'true'">true</PublishAot>
</PropertyGroup>
<ItemGroup>
<!-- Analyze the whole library, even if attributed with "IsTrimmable" -->
Expand Down
12 changes: 12 additions & 0 deletions Funcky/Extensions/QueryableExtensions/ElementAtOrNone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ namespace Funcky.Extensions;

public static partial class QueryableExtensions
{
#if NET7_0
// Starting with .NET 8.0 the Select, Filter, ... methods are no longer marked with [RequiresDynamicCode]
// so we only need this attribute for .NET 7.0.
private const string InMemoryQueryableExtensionMethodsRequiresDynamicCode = "Enumerating collections as IQueryable can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.";
#endif

/// <summary>
/// Returns the element at a specified index in a sequence or an <see cref="Option{T}.None" /> value if the index is out of range.
/// </summary>
Expand All @@ -10,6 +16,9 @@ public static partial class QueryableExtensions
/// <param name="index">The index for the element to retrieve.</param>
/// <returns>The item at the specified index, or <see cref="Option{T}.None" /> if the index is not found.</returns>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> ElementAtOrNone<TSource>(this IQueryable<TSource> source, int index)
where TSource : notnull
=> source
Expand All @@ -25,6 +34,9 @@ public static Option<TSource> ElementAtOrNone<TSource>(this IQueryable<TSource>
/// <param name="index">The index for the element to retrieve.</param>
/// <returns>The item at the specified index, or <see cref="Option{T}.None" /> if the index is not found.</returns>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> ElementAtOrNone<TSource>(this IQueryable<TSource> source, Index index)
where TSource : notnull
=> source
Expand Down
6 changes: 6 additions & 0 deletions Funcky/Extensions/QueryableExtensions/FirstOrNone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public static partial class QueryableExtensions
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> FirstOrNone<TSource>(this IQueryable<TSource> source)
where TSource : notnull
=> source
Expand All @@ -20,6 +23,9 @@ public static Option<TSource> FirstOrNone<TSource>(this IQueryable<TSource> sour
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> FirstOrNone<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
where TSource : notnull
=> source
Expand Down
6 changes: 6 additions & 0 deletions Funcky/Extensions/QueryableExtensions/LastOrNone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public static partial class QueryableExtensions
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> LastOrNone<TSource>(this IQueryable<TSource> source)
where TSource : notnull
=> source
Expand All @@ -20,6 +23,9 @@ public static Option<TSource> LastOrNone<TSource>(this IQueryable<TSource> sourc
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> LastOrNone<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
where TSource : notnull
=> source
Expand Down
6 changes: 6 additions & 0 deletions Funcky/Extensions/QueryableExtensions/SingleOrNone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public static partial class QueryableExtensions
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> SingleOrNone<TSource>(this IQueryable<TSource> source)
where TSource : notnull
=> source
Expand All @@ -20,6 +23,9 @@ public static Option<TSource> SingleOrNone<TSource>(this IQueryable<TSource> sou
/// </summary>
/// <typeparam name="TSource">the inner type of the queryable.</typeparam>
[Pure]
#if NET7_0
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode(InMemoryQueryableExtensionMethodsRequiresDynamicCode)]
#endif
public static Option<TSource> SingleOrNone<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
where TSource : notnull
=> source
Expand Down
3 changes: 3 additions & 0 deletions Funcky/Funcky.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<IsTrimmable>true</IsTrimmable>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<None Include="build/Funcky.targets" Pack="true" PackagePath="build" />
<None Include="build/Funcky.targets" Pack="true" PackagePath="buildTransitive" />
Expand Down
3 changes: 3 additions & 0 deletions Funcky/Monads/Option/OptionJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
namespace Funcky.Monads;

/// <summary>A JSON converter for <see cref="Option{TItem}"/> that serializes <see cref="Option.Some{TItem}"/> transparently and <see cref="Option{TItem}.None"/> as <c>null</c>.</summary>
#if AOT
[RequiresDynamicCode("The converter needs to be able to instantiate generics at runtime.")]
#endif
public sealed class OptionJsonConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
Expand Down

0 comments on commit 611dcca

Please sign in to comment.