Skip to content

Conversation

zainab-ali
Copy link
Contributor

@zainab-ali zainab-ali commented Jul 11, 2025

All weaver expectations have an implicit SourceLocation parameter. Developers can use this to customize the location displayed in failure messages. For example:

def myHelper(x: Int, y: Int)(implicit loc: SourceLocation): Expectations = {
  expect.same(x, y) // This failure message displays the call site of `myHelper` as the location.
}

The expect macros don't do this. Instead, they synthezise the source location to be that of the macro call site.

def myHelper(x: Int, y: Int)(implicit loc: SourceLocation): Expectations = {
  expect(x > y) // This failure message displays this line as the location. It ignores `loc`.
}

This PR modifies the macros to support an implicit location.

Compatibility

This change is binary compatible since it only alters macro signatures. It's source compatible, in the sense that all existing calls to expect should still compile.

@@ -30,7 +30,7 @@ object TracingTests extends SimpleIOSuite {
val locations = e.head.locations.toList
val paths = locations.map(_.fileRelativePath).map(standardise)
forEach(paths)(p => expect(p == thisFile)) &&
expect(locations.map(_.line).distinct.size == 4)
expect(locations.map(_.line).distinct.size == 3)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behaviour has changed.

Previously, the locations would be:

    val result = isOdd(2) // Line 24
      .traced(here) // Line 25
      .traced(here) // Line 26
      
 ...
   def isOdd(i: Int)(implicit loc: SourceLocation): Expectations =
    expect(i % 2 == 1).traced(loc) // Line 39, since `expect` would capture it's own location

With this changeset, expect doesn't capture its location, and uses the source location passed to isOdd instead. This means we no longer get line 39 as part of the trace.

This aligns the behaviour to other expectations. We could replace expect(1 % 2 == 1) with expect.eql(1 % 2, 1) and the trace would still have three locations.

@@ -181,7 +181,7 @@ object DogFoodTests extends IOSuite {
| of
| multiline
| (failure)
| assertion failed (modules/framework-cats/shared/src/test/scala/Meta.scala:34)
| assertion failed (src/main/DogFoodTests.scala:5)
Copy link
Contributor Author

@zainab-ali zainab-ali Jul 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests now display the implicit source location defined in the test suite object.

@zainab-ali zainab-ali merged commit f747b1e into typelevel:main Jul 25, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants