[commit: ghc] wip/orf-reboot: Comments only (deaf8f1)
git at git.haskell.org
git at git.haskell.org
Fri Jul 24 16:39:53 UTC 2015
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/orf-reboot
Link : http://ghc.haskell.org/trac/ghc/changeset/deaf8f18a4cd2b4d6176504eb13c10ac287db146/ghc
>---------------------------------------------------------------
commit deaf8f18a4cd2b4d6176504eb13c10ac287db146
Author: Adam Gundry <adam at well-typed.com>
Date: Fri Jul 24 16:17:10 2015 +0100
Comments only
>---------------------------------------------------------------
deaf8f18a4cd2b4d6176504eb13c10ac287db146
compiler/typecheck/TcExpr.hs | 53 +++++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 16 deletions(-)
diff --git a/compiler/typecheck/TcExpr.hs b/compiler/typecheck/TcExpr.hs
index 1839010..b9cc300 100644
--- a/compiler/typecheck/TcExpr.hs
+++ b/compiler/typecheck/TcExpr.hs
@@ -1348,35 +1348,56 @@ getFixedTyVars upd_fld_occs tvs1 cons
{-
Note [Disambiguating record updates]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If the -XDuplicateRecordFields extension is used, the renamer may not
-be able to determine exactly which fields are being updated. Consider:
+
+When the -XDuplicateRecordFields extension is used, and the renamer
+encounters a record update that it cannot immediately disambiguate
+(because it involves fields that belong to multiple datatypes), it
+will defer resolution of the ambiguity to the typechecker. In this
+case, the `hsRecUpdFieldSel` field of the `HsRecUpdField` stores a
+list of candidate selectors.
+
+Consider the following definitions:
data S = MkS { foo :: Int }
data T = MkT { foo :: Int, bar :: Int }
- data U = MkU { bar :: Int }
+ data U = MkU { bar :: Int, baz :: Int }
+
+When the renamer sees an update of `foo`, it will not know which
+parent datatype is in use. The `disambiguateRecordBinds` function
+tries to determine the parent in three ways:
+
+1. Check for types that have all the fields being updated. For example:
f x = x { foo = 3, bar = 2 }
+ Here `f` must be updating `T` because neither `S` nor `U` have
+ both fields. This may also discover that no possible type exists.
+ For example the following will be rejected:
+
+ f' x = x { foo = 3, baz = 3 }
+
+2. Use the type being pushed in, if it is already a TyConApp. The
+ following are valid updates to `T`:
+
g :: T -> T
g x = x { foo = 3 }
- h x = (x :: T) { foo = 3 }
+ g' x = x { foo = 3 } :: T
+
+3. Use the type signature of the record expression, if it exists and
+ is a TyConApp. Thus this is valid update to `T`:
-In this situation, the renamer sees an update of `foo` but doesn't
-know which parent datatype is in use. In this case, the
-`hsRecFieldSel` field of the `HsRecField` stores a list of candidate
-selectors. The disambiguateRecordBinds function tries to determine the
-parent in three ways:
+ h x = (x :: T) { foo = 3 }
-1. Check for types that have all the fields being updated. In the
- example, `f` must be updating `T` because neither `S` nor `U` have
- both fields. This may also discover that no suitable type exists.
+Note that we do not look up the types of variables being updated, and
+no constraint-solving is performed, so for example the following will
+be rejected as ambiguous:
-2. Use the type being pushed in, if it is already a TyConApp. Thus `g`
- is obviously an update to `T`.
+ let r :: T
+ r = blah
+ in r { foo = 3 }
-3. Use the type signature of the record expression, if it exists and
- is a TyConApp. Thus `h` is an update to `T`.
+ \r. (r { foo = 3 }, r :: T )
We could add further tests, of a more heuristic nature. For example,
rather than looking for an explicit signature, we could try to infer
More information about the ghc-commits
mailing list