summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/users_guide/exts/implicit_parameters.rst23
-rw-r--r--testsuite/tests/simplCore/should_run/T23289.hs13
-rw-r--r--testsuite/tests/simplCore/should_run/T23289.stdout2
-rw-r--r--testsuite/tests/simplCore/should_run/all.T1
4 files changed, 37 insertions, 2 deletions
diff --git a/docs/users_guide/exts/implicit_parameters.rst b/docs/users_guide/exts/implicit_parameters.rst
index a8da87e416..ee6234e55a 100644
--- a/docs/users_guide/exts/implicit_parameters.rst
+++ b/docs/users_guide/exts/implicit_parameters.rst
@@ -180,6 +180,27 @@ parameter. So we get the following results in GHCi:
Adding a type signature dramatically changes the result! This is a
rather counter-intuitive phenomenon, worth watching out for.
+Implicit parameters scoping guarantees
+-------------------------------------
+
+GHC always takes the most nested implicit parameter binding from the
+context to find the value. Consider the following code::
+
+ let ?f = 1 in let ?f = 2 in ?f
+
+This expression will always return 2.
+
+Another example of this rule is matching over constructors with constraints.
+For example::
+
+ data T where
+ MkT :: (?f :: Int) => T
+
+ f :: T -> T -> Int
+ f MkT MkT = ?f
+
+Here GHC will always take ``?f`` from the last match.
+
Implicit parameters and monomorphism
------------------------------------
@@ -199,5 +220,3 @@ a type signature for ``y``, then ``y`` will get type
``(?x::Int) => Int``, so the occurrence of ``y`` in the body of the
``let`` will see the inner binding of ``?x``, so ``(f 9)`` will return
``14``.
-
-
diff --git a/testsuite/tests/simplCore/should_run/T23289.hs b/testsuite/tests/simplCore/should_run/T23289.hs
new file mode 100644
index 0000000000..38e32ae279
--- /dev/null
+++ b/testsuite/tests/simplCore/should_run/T23289.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE ImplicitParams, GADTs #-}
+module Main where
+
+data T where
+ MkT :: (?f :: Int) => T
+
+f :: T -> T -> Int
+f MkT MkT = ?f
+
+main :: IO ()
+main = do
+ print (let ?g = 1 in let ?g = 2 in ?g)
+ print $ f (let ?f = 3 in MkT) (let ?f = 4 in MkT)
diff --git a/testsuite/tests/simplCore/should_run/T23289.stdout b/testsuite/tests/simplCore/should_run/T23289.stdout
new file mode 100644
index 0000000000..da7f84740b
--- /dev/null
+++ b/testsuite/tests/simplCore/should_run/T23289.stdout
@@ -0,0 +1,2 @@
+2
+4
diff --git a/testsuite/tests/simplCore/should_run/all.T b/testsuite/tests/simplCore/should_run/all.T
index bb23475071..7348e1015a 100644
--- a/testsuite/tests/simplCore/should_run/all.T
+++ b/testsuite/tests/simplCore/should_run/all.T
@@ -111,3 +111,4 @@ test('T22448', normal, compile_and_run, ['-O1'])
test('T22998', normal, compile_and_run, ['-O0 -fspecialise -dcore-lint'])
test('T23184', normal, compile_and_run, ['-O'])
test('T23134', normal, compile_and_run, ['-O0 -fcatch-nonexhaustive-cases'])
+test('T23289', normal, compile_and_run, [''])