Idris2 icon indicating copy to clipboard operation
Idris2 copied to clipboard

Access modifiers of definitions overwrite forward definitions

Open ohad opened this issue 4 years ago • 5 comments

Steps to Reproduce

$ cat Mutual.idr
module Mutual
private
data Foo : Type 

public export
data Foo : Type where
------------------------------
$ cat Import.idr
import Mutual

x : Foo

Expected Behavior

Type-checking Mutual.idr should report an error because the access modifiers are incompatible.

Observed Behavior

The latest definition overwrites the access modifier, and Import.idr type-checks fine.

ohad avatar Mar 26 '21 16:03 ohad

I'm going to go ahead and tag this as good first issue because I assume it's something silly like overwriting the existing value with a record update instead of making sure it's not set yet.

gallais avatar Apr 27 '21 08:04 gallais

Right now, https://github.com/idris-lang/Idris2/commit/f76c4c4307 "fixes" this by forcing the maximum visibility to apply. This makes any combination of the three modifiers on either of the forward or actual declaration result in the higher of the two, e.g.

module Mutual

private
data Foo : Type

export
data Foo : Type where
module Mutual

export
data Foo : Type

private
data Foo : Type where

both work as if a single declaration with export was defined.

We can either leave it like this and close the issue (unsatisfying) or modify the max-merge to instead check whether they're the same and throw an error if not - this however makes the following not work anymore:

module Mutual

export
data Foo : Type

-- no visibility
data Foo : Type where

Which, while technically consistent (no visibility == private, and private != export), means you would need to repeat the same visibility in both places. This breaks code in an unsatisfying way, while the general idea of removing the max-check itself breaks code that relied on what seemed like buggy behaviour?

Making the above export+<nothing> declaration possible would require modifying either Visibility - add Unspecified which means "Can be overriden, otherwise means private" or change most occurrences of Visibility to Maybe Visibility, but could be done.

I'll put this up here before I tackle solving it, so please add your input which solution would be the best!

Might even be a good idea to add votes, so:

  1. 👀 Leave situation as-is
  2. 🚀 Change max-merge to equals check without Visibility change
  3. 🎉 Change max-merge to equals check with the Visibility change

Adowrath avatar Aug 28 '23 12:08 Adowrath

If only we had a gadget that allowed us to express that something is the default without conflating it with the default value it takes. :thinking:

http://gallais.github.io/blog/ceci-pas-default

gallais avatar Aug 28 '23 12:08 gallais

If only we had a gadget that allowed us to express that something is the default without conflating it with the default value it takes. 🤔

http://gallais.github.io/blog/ceci-pas-default

Are you suggesting I use this to implement Nr. 3? Or just a general comment? Where would I place it? src/Libraries/Data/WithDefault.idr or would it warrant a placement in base?

Adowrath avatar Aug 28 '23 13:08 Adowrath

Yeah I think it'd be nice to complain if there are conflicting declarations which means changing the merge strategy to take into account lack of value vs. value that happens to equal the default.

gallais avatar Aug 28 '23 13:08 gallais

Is this still an issue? It seems like we get correctly warned now...

emdash avatar Jul 25 '24 05:07 emdash