Универсальная конструкция требует, чтобы тип 'Cell <' T> 'был неуправляемым типом. - PullRequest
0 голосов
/ 07 сентября 2018

Почему я не могу иметь общую неуправляемую структуру в F #? Может быть, Cell<'T when 'T: unmanaged> не является неуправляемым, тогда как я могу это исправить?

type FloatCell =
    struct
        val x: float
        val y: nativeptr<FloatCell>
    end

[<Struct>]
[<StructLayout(LayoutKind.Sequential)>]
type Cell<'T when 'T: unmanaged> =
    struct
        val x: 'T
        val y: nativeptr<Cell<'T>>
    end   

Придает

ошибка FS0001: универсальная конструкция требует, чтобы тип 'Cell <' T> 'был неуправляемым типом [E: \ dzmitry \ src \ uncorefx \ src \ uncorefx \ uncorefx.fsproj]

UPDATE:

C # имеет то же самое.

   unsafe struct FloatCell
    {
        public float val;
        public FloatCell* next;
    }

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    unsafe struct Cell<T> where T: unmanaged
    {
        public float val;
        public Cell<T>* next;
    }

С ошибкой:

ошибка CS0208: невозможно получить адрес, получить размер или объявить указатель на управляемый тип ('Program.Cell')

Я не думаю, что это управляется.

UPDATE2:

Я попробовал атрибуты. Не помогло. Я использовал свойство extension для приведения. Возможное решение. Но вопрос, почему я не могу сделать это изначально? Или я могу сделать? Или я должен поднять вопрос C # / F #?

[<Struct>]
[<NativeCppClass>]
[<System.Runtime.CompilerServices.UnsafeValueType>]
[<StructLayout(LayoutKind.Sequential)>]
type Cell<'T when 'T: unmanaged> =
    struct
        val element: 'T
        val next:  voidptr
    end    

type Cell<'T when 'T: unmanaged> with
    member  x.Next = x.next |> NativePtr.ofVoidPtr<'T> 

Update3:

Я попытался свернуть указатели и попал в проблему без указателей.

    public struct UnmanagedStruct
    {
    }

    public struct UnmanagedStructWithSpecifiedGenerics
    {
        public EmptyCell<float> cell;
    }

    public ref struct RefUnmanagedStruct
    {
        public EmptyCell<float> cell;
    }

    public  struct EmptyCell<T> where T : unmanaged
    {
    }

А затем создать экземпляр:

        var compiles1 = new UnmanagedStructWithSpecifiedGenerics();
        var compiles2 = new EmptyCell<UnmanagedStruct>();
        var CS8377_1 = new EmptyCell<EmptyCell<float>>();
        var CS8377_1 = new EmptyCell<UnmanagedStructWithSpecifiedGenerics>();
        var CS0306 = new EmptyCell<RefUnmanagedStruct>();

Приводит к:

ошибка CS8377: тип «EmptyCell» должен быть типом значения, не допускающим значения NULL, вместе со всеми полями на любом уровне вложенности, чтобы использовать его в качестве параметра «T» в универсальном типе или методе «EmptyCell»

ошибка CS8377: тип 'UnmanagedStructWithSpecifiedGenerics' должен иметь тип значения, не допускающий значения NULL, вместе со всеми полями на любом уровне вложенности, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе 'EmptyCell'

ошибка CS0306: тип 'RefUnmanagedStruct' нельзя использовать в качестве аргумента типа

Неправильное сообщение об ошибке? Стоит ли поднимать проблему с компилятором Roslyn?

1 Ответ

0 голосов
/ 07 сентября 2018

Похоже, это сделано по задумке, хотя я не уверен в причине ограничения. Вот цитата из F # spec :

5.2.9 Неуправляемые ограничения

Неуправляемое ограничение имеет следующую форму: typar : unmanaged

Во время решения ограничения (§14.5) ограничение type : unmanaged выполняется, если type неуправляем, как указано ниже:

  • Типы sbyte, byte, char, nativeint, unativeint, float32, float, int16, uint16, int32, uint32, int64, uint64, decimal неуправляемые.
  • Тип nativeptr<type> неуправляемый.
  • Неуниверсальный тип структуры, все поля которого являются неуправляемыми типами, неуправляем.

Примечание неуниверсальные * struct типы явно упоминаются в последнем пункте.

...