Repository: numba/numba

Issue:
Improve missing type annotation errmsg
<!--

Thanks for wanting to contribute to Numba :)

First, if you need some help or want to chat to the core developers, please
visit https://gitter.im/numba/numba for real time chat or post to the Numba
mailing list https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

Here's some guidelines to help the review process go smoothly.

0. Please write a description in this text box of the changes that are being
   made.

1. Please ensure that you have written units tests for the changes made/features
   added.

2. If you are closing an issue please use one of the automatic closing words as
   noted here: https://help.github.com/articles/closing-issues-using-keywords/

3. If your pull request is not ready for review but you want to make use of the
   continuous integration testing facilities please label it with `[WIP]` and
   then remove the label when you'd like it to be reviewed.

4. Once review has taken place please do not add features or make changes out of
   the scope of those requested by the reviewer (doing this just add delays as
   already reviewed code ends up having to be re-reviewed/it is hard to tell
   what is new etc!). Further, please do not rebase your branch on master/force
   push/rewrite history, doing any of these causes the context of any comments
   made by reviewers to be lost. If conflicts occur against master they should
   be resolved by merging master into the branch used for making the pull
   request.

Many thanks in advance for your cooperation!

-->

The old message may confuse users with Python's type annotation, which had me tried this instead:

```
with objmode():
    start: float64 = time.time()
```


Discussion:
Thanks for submitting this PR to the Numba issue tracker, it's been added to the queue for review. Please be advised however that we are currently in a PR freeze as we are preparing to ship a release candidate (RC). We will begin reviewing PRs again once the RC is out and we thank you in advance for your patience!

Resolving patch:
diff --git a/numba/core/withcontexts.py b/numba/core/withcontexts.py
--- a/numba/core/withcontexts.py
+++ b/numba/core/withcontexts.py
@@ -225,8 +225,13 @@ def strip_var_ver(x):
         # Verify that all outputs are annotated
         not_annotated = set(stripped_outs) - set(typeanns)
         if not_annotated:
-            msg = 'missing type annotation on outgoing variables: {}'
-            raise errors.TypingError(msg.format(not_annotated))
+            msg = (
+                'Missing type annotation on outgoing variable(s): {0}\n\n'
+                'Example code: with objmode({1}=\'<'
+                'add_type_as_string_here>\')\n'
+            )
+            stable_ann = sorted(not_annotated)
+            raise errors.TypingError(msg.format(stable_ann, stable_ann[0]))
 
         # Get output types
         outtup = types.Tuple([typeanns[v] for v in stripped_outs])


Test patch:
diff --git a/numba/tests/test_withlifting.py b/numba/tests/test_withlifting.py
--- a/numba/tests/test_withlifting.py
+++ b/numba/tests/test_withlifting.py
@@ -522,15 +522,21 @@ def test_case07_mystery_key_error(self):
         def foo(x):
             with objmode_context():
                 t = {'a': x}
-            return x, t
+                u = 3
+            return x, t, u
         x = np.array([1, 2, 3])
         cfoo = njit(foo)
+
         with self.assertRaises(errors.TypingError) as raises:
             cfoo(x)
-        self.assertIn(
-            "missing type annotation on outgoing variables",
-            str(raises.exception),
-            )
+
+        exstr = str(raises.exception)
+        self.assertIn("Missing type annotation on outgoing variable(s): "
+                      "['t', 'u']",
+                      exstr)
+        self.assertIn("Example code: with objmode"
+                      "(t='<add_type_as_string_here>')",
+                      exstr)
 
     def test_case08_raise_from_external(self):
         # this segfaults, expect its because the dict needs to raise as '2' is