Skip to content

Role inference for foreign imported types without roles declaration is wrong #3895

@kl0tl

Description

@kl0tl

Description

In the absence of role declarations, roles of foreign imported types are computed from their kind by the following function:

rolesFromForeignTypeKind :: SourceType -> [Role]
rolesFromForeignTypeKind
= go []
where
go acc = \case
TypeApp _ (TypeApp _ fn k1) _k2 | eqType fn tyFunction ->
go (Nominal : acc) k1
_k ->
Nominal : acc

It is supposed to return of list of n nominal roles, where n is the kind arity of the type, but instead returns [Nominal] for Type and forall k. k -> … -> Type, [Nominal, Nominal] for Type -> Type and Type -> Type -> … -> Type, [Nominal, Nominal, Nominal] for (Type -> Type) -> Type

To Reproduce

module Example where

import Safe.Coerce (coerce)

foreign import data Foreign3 :: Type -> Type -> Type -> Type

-- We infer `nominal nominal` instead of `nominal nominal nominal`,
-- this is equivalent to giving a phantom role to `Foreign3` last parameter:

example ::  a b c d. Foreign3 a b c -> Foreign3 a b d
example = coerce
module Example where

import Safe.Coerce (coerce)

foreign import data Foreign2 ::  k. k -> k -> Type

-- We infer `nominal` instead of `nominal nominal`,
-- this is equivalent to giving a phantom role to `Foreign2` last parameter:

example ::  k (a :: k) (b :: k) (c :: k). Foreign2 a b -> Foreign2 a c
example = coerce

Expected behavior

We should recurse on the second argument of ->, recurse under foralls and return the accumulator untouched in the base case.

PureScript version

master (d7e8ef8)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions