Burst is perceiving extension methods as managed

I have this code

[MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static IComparer<T> CreateEuclideanFarthestFrom<T>(this float2 origin)
            where T : struct, IFloat2Getter
        {
            return new EuclideanFarthestFromFloat2<T>
            {
                origin = origin
            };
        }

        private struct EuclideanFarthestFromFloat2<T> : IComparer<T>
            where T : struct, IFloat2Getter
        {
            public float2 origin;

            public int Compare(T x, T y)
            {
                var diff = math.distancesq(x.GetFloat2(), origin) - math.distancesq(y.GetFloat2(), origin);
                if(Hint.Unlikely(diff == 0))
                {
                    return 0;
                }
                else
                {
                    return diff > 0 ? -1 : 1;
                }
            }
        }

Which causes the following error

Users/Local/Collapse/Assets/Collapse/Scripts/Actor/Task/Formation/FormationRallySystem.cs(119,13): Burst error BC1016: The managed function `Collapse.Float2Ext.CreateEuclideanFarthestFrom<Collapse.FormationRallyRankAndIndex>(Unity.Mathematics.float2 origin)` is not supported

at Collapse.FormationRallyActions.OrderFormationDestinationsByFarthestEuclideanDistanceFromLocation(int numFilledRanks, Unity.Collections.NativeArray`1<Collapse.FormationRankActualElement>* ranks, Unity.Mathematics.float2 offsetLocation, ref Unity.Collections.NativeArray`1<Collapse.FormationRallyRankAndIndex> orderedRanks) (at /Users/Local/Collapse/Assets/Collapse/Scripts/Actor/Task/Formation/FormationRallySystem.cs:119)
at Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob.Execute(Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob* this, Unity.Entities.ArchetypeChunk* chunk, int chunkIndex) (at /Users/Local/Collapse/Assets/Collapse/Scripts/Actor/Task/Formation/Wedge/FormationWedgeRallySystem.cs:161)
at Unity.Entities.JobEntityBatchExtensions.JobEntityBatchProducer`1<Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob>.ExecuteInternal(ref Unity.Entities.JobEntityBatchExtensions.JobEntityBatchWrapper`1<Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob> jobWrapper, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) (at /Users/Local/Collapse/Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobEntityBatch.cs:593)
at Unity.Entities.JobEntityBatchExtensions.JobEntityBatchProducer`1<Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob>.Execute(ref Unity.Entities.JobEntityBatchExtensions.JobEntityBatchWrapper`1<Collapse.FormationWedgeRallySystem.FormationWedgeRallyJob> jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) (at /Users/Local/Collapse/Library/PackageCache/com.unity.entities@0.17.0-preview.42/Unity.Entities/IJobEntityBatch.cs:513)


While compiling job: System.Void Unity.Entities.JobEntityBatchExtensions/JobEntityBatchProducer`1<Collapse.FormationWedgeRallySystem/FormationWedgeRallyJob>::Execute(Unity.Entities.JobEntityBatchExtensions/JobEntityBatchWrapper`1<T>&,System.IntPtr,System.IntPtr,Unity.Jobs.LowLevel.Unsafe.JobRanges&,System.Int32)
at /Users/Local/Collapse/Assets/Collapse/Scripts/Actor/Task/Formation/FormationRallySystem.cs:line 119

All my code uses structs. Strange thing is that a nearly identical method does not cause issues with Burst

[MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static IComparer<T> CreateEuclideanClosestTo<T>(this float2 origin)
            where T : struct, IFloat2Getter
        {
            return new EuclideanClosestToFloat2<T>
            {
                origin = origin
            };
        }

        private struct EuclideanClosestToFloat2<T> : IComparer<T>
            where T : struct, IFloat2Getter
        {
            public float2 origin;

            public int Compare(T x, T y)
            {
                var diff = math.distancesq(x.GetFloat2(), origin) - math.distancesq(y.GetFloat2(), origin);
                if (Hint.Unlikely(diff == 0))
                {
                    return 0;
                }
                else
                {
                    return diff > 0 ? 1 : -1;
                }
            }
        }

What is Collapse.FormationRallyRankAndIndex

-edit-

oh the issue is your return, IComparer

You can’t return an interface that’s managed

2 Likes

Gotcha. I’m guessing that only struct types are allowed to be returned? Since interface types may be implemented by a class?

Correct. Burst only works with concrete types, not partial types defined by interfaces and inheritance. However, it works well with generics as long as all usages of those generics are concrete within Burst’s scope or in the case of generic jobs accessible by the typespec.