Changes between Version 66 and Version 67 of Records/OverloadedRecordFields/Implementation


Ignore:
Timestamp:
Sep 10, 2013 8:22:03 AM (18 months ago)
Author:
adamgundry
Comment:

latest data representation

Legend:

Unmodified
Added
Removed
Modified
  • Records/OverloadedRecordFields/Implementation

    v66 v67  
    1616 
    1717{{{ 
    18 $sel_x_T :: T -> Int -- record selector (used to be called `x`) 
    19 $sel_x_T (MkT x) = x 
     18$sel:x:T :: T -> Int -- record selector (used to be called `x`) 
     19$sel:x:T (MkT x) = x 
    2020 
    2121$dfHasTx :: forall a . a ~ Int => Has T "x" a -- corresponds to the Has instance decl 
     
    3737{{{ 
    3838data FieldLbl a = FieldLabel { 
    39       flOccName   :: OccName,  -- ^ Label of the field 
    40       flSelector  :: a,         -- ^ Record selector function 
    41       flInstances :: FldInsts a -- ^ Instances for overloading 
     39      flLabel     :: FieldLabelString, -- ^ Label of the field 
     40      flSelector  :: a,                -- ^ Record selector function 
     41      flInstances :: FldInsts a        -- ^ Instances for overloading 
    4242    } 
    4343 
     44type FieldLabelString = FastString 
    4445type FieldLabel = FieldLbl Name 
    4546 
     
    5051}}} 
    5152 
    52 Every field has a label (`OccName`), selector, and names for the dfuns and axioms (currently stored together in the `FldInsts` record, but this could change). The `dcFields` field of `DataCon` stores a list of `FieldLabel`, whereas the `ifConFields` field of `IfaceConDecl` stores a list of `FieldLbl OccName`. The motivation for storing the names of the pieces is to avoid dragging `extendInteractiveContext` into the monad with `gresFromAvails`. 
     53Every field has a label (`FastString`), selector, and names for the dfuns and axioms (stored together in the `FldInsts` record). The `dcFields` field of `DataCon` stores a list of `FieldLabel`, whereas the `ifConFields` field of `IfaceConDecl` stores a list of `FieldLbl OccName`. 
    5354 
    5455 
     
    5960{{{ 
    6061data AvailInfo      = Avail Name | AvailTC Name [Name] AvailFields 
    61 data AvailFlds name = NonOverloaded [name] | Overloaded [(OccName, name)] 
     62data AvailFlds name = NonOverloaded [name] | Overloaded [(FieldLabelString, name)] 
    6263type AvailFields    = AvailFlds Name 
    6364}}} 
     
    6566The `AvailTC` constructor represents a type and its pieces that are in scope. Record fields are now stored separately in the third argument. If the fields are not overloaded, we store only the selector names, whereas if they are overloaded, we store the labels as well. The `IEThingWith name [name] (AvailFlds name)` constructor of `IE` represents a thing that can be imported or exported, and also has a separate argument for fields. 
    6667 
    67 Note that an `OccName` and parent is not enough to uniquely identify a selector, because of data families: if we have 
     68Note that a `FieldLabelString` and parent is not enough to uniquely identify a selector, because of data families: if we have 
    6869 
    6970{{{ 
     
    7778}}} 
    7879 
    79 then `N` exports two different selectors with the `OccName` `"foo"`. 
     80then `N` exports two different selectors with the `FieldLabelString` `"foo"`. 
    8081 
    8182 
    8283=== `Parent` and `GlobalRdrElt` === 
    8384 
    84 The `Parent` type has an extra constructor `FldParent Name OccName` that stores the parent `Name` and the field `OccName`. The `GlobalRdrElt` (`GRE`) for a field stores the selector name directly, and uses the `FldParent` constructor to store the field. Thus a field `x` of type `T` gives rise this entry in the `GlobalRdrEnv`: 
    85  
    86 {{{ 
    87 x |->  GRE $sel_x_T (FldParent T x) LocalDef 
    88 }}} 
    89  
    90 Note that the `OccName` used when adding a GRE to the environment (`greOccName`) now depends on the parent field: for `FldParent` it is the field label rather than the selector name. Since `AvailInfo` does not store selectors for overloaded fields, `gresFromAvails` is now defined in the `TcRnIf` monad so that it can call `lookupOrig` to find the selectors. As a consequence of this, `GHC.getPackageModuleInfo` cannot call `gresFromAvails`, so it now returns `Nothing` in `minf_rdr_env`. 
     85The `Parent` type has an extra constructor `FldParent Name FastString` that stores the parent `Name` and the field label `FastString`. The `GlobalRdrElt` (`GRE`) for a field stores the selector name directly, and uses the `FldParent` constructor to store the field. Thus a field `x` of type `T` gives rise this entry in the `GlobalRdrEnv`: 
     86 
     87{{{ 
     88x |->  GRE $sel:x:T (FldParent T x) LocalDef 
     89}}} 
     90 
     91Note that the `OccName` used when adding a GRE to the environment (`greOccName`) now depends on the parent field: for `FldParent` it is the field label rather than the selector name. 
    9192 
    9293 
    9394== Source expressions == 
    9495 
    95 The `HsExpr` type has extra constructors `HsOverloadedRecFld OccName` and `HsSingleRecFld OccName id`. When `-XOverloadedRecordFields` is enabled, and `rnExpr` encounters `HsVar "x"` where `x` refers to multiple `GRE`s that are all record fields, it replaces it with `HsOverloadedRecFld "x"`. When the typechecker sees `HsOverloadedRecFld x` it emits a wanted constraint `Has alpha x beta` and returns type `alpha -> beta` where `alpha` and `beta` are fresh unification variables. 
    96  
    97 When the flag is not enabled, `rnExpr` turns an unambiguous record field `foo` into `HsSingleRecFld foo $sel_foo_T`. The point of this constructor is so we can pretty-print the field name but store the selector name for typechecking. 
     96The `HsExpr` type has extra constructors `HsOverloadedRecFld FieldLabelString` and `HsSingleRecFld RdrName id`. When `-XOverloadedRecordFields` is enabled, and `rnExpr` encounters `HsVar "x"` where `x` refers to multiple `GRE`s that are all record fields, it replaces it with `HsOverloadedRecFld "x"`. When the typechecker sees `HsOverloadedRecFld x` it emits a wanted constraint `Has alpha x beta` and returns type `alpha -> beta` where `alpha` and `beta` are fresh unification variables. 
     97 
     98When the flag is not enabled, `rnExpr` turns an unambiguous record field `foo` into `HsSingleRecFld foo $sel_foo_T`. The point of this constructor is so we can pretty-print the field name (as the user typed it, hence a `RdrName`), but store the selector name for typechecking. 
    9899 
    99100Where an AST representation type (e.g. `HsRecField` or `ConDeclField`) contained an argument of type `Located id` for a field, it now stores a `Located RdrName` for the label, and some representation of the selector. The parser uses an error thunk for the selector; it is filled in by the renamer  (by `rnHsRecFields1` in `RnPat`, and `rnField` in `RnTypes`). The new definition of `ConDeclField` (used in types) is: 
     
    128129== Automatic instance generation == 
    129130 
    130 Typeclass and family instances are generated and typechecked by `makeOverloadedRecFldInsts` in `TcInstDecls`, regardless of whether or not the extension is enabled. This is called by `tcTopSrcDecls` to generate instances for fields from datatypes in the current group (just after derived instances, from '''deriving''' clauses, are generated). Overloaded record field instances are not exported to other modules (via `tcg_insts`), though underlying dfun ids and axioms are exported from the module as usual. 
    131  
    132 Since the instances are not in scope in the usual way, `matchClassInst` and `tcLookupFamInst` look for the relevant constraints or type families and find the instances directly, rather than consulting `tcg_inst_env` or `tcg_fam_inst_env`. They first perform a lookup to check that the field name is in scope. A new field `tcg_fld_inst_env` in `TcGblEnv` maps a selector name in the current module to its `DFunId`s and `FamInst`s; this is needed for solving constraints that arise while checking the automatically generated instances themselves. 
     131Typeclass and family instances are generated and typechecked by `makeOverloadedRecFldInsts` in `TcInstDecls`, regardless of whether or not the extension is enabled. This is called by `tcTopSrcDecls` to generate instances for fields from datatypes in the current group (just after derived instances, from '''deriving''' clauses, are generated). Overloaded record field instances are not exported to other modules (via `tcg_insts` and `tcg_fam_insts`), though underlying dfun ids and axioms are exported from the module as usual (via `tcg_binds` and a new field `tcg_axioms`). The new field is needed because there is otherwise no way to export an axiom without exporting the corresponding family instance. 
     132 
     133Since the instances are not in scope in the usual way, `matchClassInst` and `tcLookupFamInst` look for the relevant constraints or type families and find the instances directly, rather than consulting `tcg_inst_env` or `tcg_fam_inst_env`. They first perform a lookup to check that the field name is in scope. 
    133134 
    134135 
     
    224225}}} 
    225226 
    226 Thus we use the name of the representation tycon, rather than the family tycon, when naming the record selectors: we get `$sel_foo_R:FInt` and `$sel_foo_R:FBool`. This requires a bit of care, because lexically (in the `GlobalRdrEnv`) the selectors still have the family tycon are their parent. 
     227Thus we use the name of the representation tycon, rather than the family tycon, when naming the record selectors: we get `$sel:foo:R:FInt` and `$sel:foo:R:FBool`. This requires a bit of care, because lexically (in the `GlobalRdrEnv`) the selectors still have the family tycon are their parent. 
    227228 
    228229In order to have access to the representation tycon name in the renamer, it is generated by `getLocalNonValBinders` and stored in a new field `dfid_rep_tycon` of `DataFamInstDecl`. It would be nice if we could do the same for all the derived names, in order to localise the set of names that have been used (currently stored in the `tcg_dfun_n` mutable field). However, this is tricky: 
     
    234235== Mangling selector names == 
    235236 
    236 We could mangle selector names (using `$sel_foo_T` instead of `foo`) even when the extension is disabled, but we decided not to because the selectors really should be in scope with their original names, and doing otherwise leads to: 
     237We could mangle selector names (using `$sel:foo:T` instead of `foo`) even when the extension is disabled, but we decided not to because the selectors really should be in scope with their original names, and doing otherwise leads to: 
    237238  * Trouble with import/export 
    238239  * Trouble with deriving instances in GHC.Generics (makes up un-renamed syntax using field `RdrName`s) 
     
    249250* Add `HsVarOut RdrName id` instead of `HsSingleRecFld` (or perhaps rename `HsVar` to `HsVarIn`)? 
    250251  * This would also be useful to recall how the user referred to something. 
    251  
    252 * When there is only one thing in scope, what should we do? See [wiki:Records/OverloadedRecordFields/Plan#Scopeissuesorwhywemissdot discussion here]. 
    253 * Is the story about `-fwarn-unused-binds` okay? 
     252* Is it worth generating all the derived names early, to get rid of `tcg_dfun_n`? 
     253 
    254254* Is `TcInstDcls.tcFldInsts` correct in its use of `simplifyTop` and assuming there will be no `ev_binds`? 
    255 * Is it worth generating all the derived names early, to get rid of `tcg_dfun_n`? 
    256255 
    257256* Consider syntactic sugar for `Upd` constraints.