Skip to content

Support multi-line error locations in traceback and other related improvements (PEP-657, 3.11) #106922

Closed
@williamwen42

Description

@williamwen42

Feature or enhancement

We propose a few improvements and fixes to PEP-657, namely:

  1. Support underlining errors that span across multiple lines instead of only showing the first line
  2. Use caret anchors for function calls as well
  3. Fix bracket/binary op heuristic in the caret anchor computation function

Pitch

We already implemented these items in PyTorch here: pytorch/pytorch#104676. We're seeing if these may be worth adding to CPython.

Rationale for 1

Multi-line expressions can negate the utility of PEP-657, for example:

really_long_expr_1 = 1
really_long_expr_2 = 2
really_long_expr_3 = 0
really_long_expr_4 = 4

y = (
    (
        really_long_expr_1 +
        really_long_expr_2
    ) /
    really_long_expr_2 /
    really_long_expr_3
)

Current traceback:

Traceback (most recent call last):
  File "/scratch/williamwen/work/pytorch/playground5.py", line 25, in <module>
    (
ZeroDivisionError: float division by zero

Better traceback:

Traceback (most recent call last):
  File "/scratch/williamwen/work/pytorch/playground5.py", line 25, in <module>
    (
    ~
        really_long_expr_1 +
        ~~~~~~~~~~~~~~~~~~~~
        really_long_expr_2
        ~~~~~~~~~~~~~~~~~~
    ) /
    ~~^
    really_long_expr_2 /
    ~~~~~~~~~~~~~~~~~~
ZeroDivisionError: float division by zero

Rationale for 2

Helpful for identifying function calls that cause errors in chained function calls. We may as well do it since we're already doing it for subscripts. For example:

def f1(x1):
    def f2(x2):
        raise RuntimeError()
    return f2
y = f1(1)(2)(3)

Current traceback:

Traceback (most recent call last):
  File "/scratch/williamwen/work/pytorch/playground5.py", line 22, in <module>
    y = f1(1)(2)(3)
        ^^^^^^^^
  File "/scratch/williamwen/work/pytorch/playground5.py", line 6, in f2
    raise RuntimeError()
RuntimeError

Better traceback:

Traceback (most recent call last):
  File "/scratch/williamwen/work/pytorch/playground5.py", line 22, in <module>
    y = f1(1)(2)(3)
        ~~~~~^^^
  File "/scratch/williamwen/work/pytorch/playground5.py", line 6, in f2
    raise RuntimeError()
RuntimeError

Rationale for 3

The binary op anchors are computed by taking the next non-space character after the left subexpression. This is incorrect in some simple cases:

    x = (3) / 0
        ~~^~~~~
ZeroDivisionError: division by zero

We should expect

    x = (3) / 0
        ~~~~^~~
ZeroDivisionError: division by zero

The fix is that we should continue advancing the anchor until we find a non-space character that is also not in )\# (for \#, we should move the anchor to the next line).

Subscript has a similar issue as well. We should continue advancing the left anchor until we find [, and the right anchor should be the end of the entire subscript expression.

cc @pablogsal @isidentical @ammaraskar @iritkatriel @ezyang

Linked PRs

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions