Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Overloaded" records with constructors in patterns fail instead of getting a proper warning. #260

Closed
j14159 opened this issue Nov 12, 2018 · 0 comments

Comments

@j14159
Copy link
Collaborator

j14159 commented Nov 12, 2018

This came up while exploring the native AST in a little more depth for a future version.

type renameable = Named string | Renamed { name: string, original: string }

type symbol = Symbol { line: int, name: renameable }

let symbol_rename (Symbol {line=l, name=Named n}) new_name =
  Symbol {line=l, name=Renamed {name=new_name, original=n}}
-- Interesting!  This is not a type error, but rather requires that the record
-- coming in simply has `orig` in addition to `name` and `original`.  Didn't think of
-- this at all as a possible library-writer-side problem.
let symbol_rename (Symbol {line=l, name=Renamed {orig=o}}) new_name =
  Symbol {line=l, name=Renamed {name=new_name, original=o}}

Two problems:

  1. Serious: instead of warning that symbol_rename performs an incomplete match (no wildcard for Renamed, no checks for original or name), we get a {badkey, orig} error.
  2. Less immediate, if still serious: while Renamed { orig=o } is completely legitimate, the type system right now would actually forget the orig: String member per Records lose information in type constructors #125 without additional work to define renameable with an explicit row variable (and this is a hypothetical solution that I'm not sure would work properly), meaning that a caller could never satisfy this pattern.

Full stack trace from eunit:

     Failure/Error: {error,
                        {badkey,orig},
                        [{maps,get,[orig,#{name => '_',original => '_'}],[]},
                         {alpaca_exhaustiveness,'-matches_record/2-fun-0-',2,
                             [{file,
                                  "/home/jeremy/code/erlang/alpaca/_build/test/lib/alpaca/src/alpaca_exhaustiveness.erl"},
                              {line,280}]},
                         {lists,all,2,[{file,"lists.erl"},{line,1213}]},
                         {alpaca_exhaustiveness,matches,2,
                             [{file,
                                  "/home/jeremy/code/erlang/alpaca/_build/test/lib/alpaca/src/alpaca_exhaustiveness.erl"},
                              {line,292}]},
                         {lists,any,2,[{file,"lists.erl"},{line,1225}]},
                         {alpaca_exhaustiveness,'-missing_patterns/4-fun-1-',
                             2,
                             [{file,
                                  "/home/jeremy/code/erlang/alpaca/_build/test/lib/alpaca/src/alpaca_exhaustiveness.erl"},
                              {line,86}]},
                         {lists,flatmap,2,[{file,"lists.erl"},{line,1250}]}]}
j14159 added a commit to j14159/alpaca that referenced this issue Nov 12, 2018
Closes alpaca-lang#260.

Just adds a default value indicating that a record field is extraneous
if it can't be found in the actual specified type (e.g. via type
constructor.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant