Skip to content

Fix all REPL tests when production behavior is enabled - #25449

Merged
hamzaremmal merged 3 commits into
scala:mainfrom
dotty-staging:solal/repl-insanity
Mar 13, 2026
Merged

Fix all REPL tests when production behavior is enabled#25449
hamzaremmal merged 3 commits into
scala:mainfrom
dotty-staging:solal/repl-insanity

Conversation

@SolalPirelli

@SolalPirelli SolalPirelli commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Depends on #25444

Fixes #25445

How much have your relied on LLM-based tools in this contribution?

not

How was the solution tested?

existing tests

@SolalPirelli
SolalPirelli force-pushed the solal/repl-insanity branch from 4cb9152 to 1232da6 Compare March 6, 2026 15:23
Comment thread repl/test-resources/repl/i7644 Outdated
| Cannot extend sealed trait CanEqual in a different source file
|
| longer explanation available when compiling with `-explain`
2 warnings found

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

see the change below for why this happens but we don't print the warnings

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if it's about the stale symbol, I believe it should be fixed.

@SolalPirelli

Copy link
Copy Markdown
Contributor Author

@hamzaremmal I'm interested in your thoughts on the 2nd commit.

@SolalPirelli
SolalPirelli requested a review from hamzaremmal March 9, 2026 08:08
@SolalPirelli
SolalPirelli marked this pull request as ready for review March 10, 2026 11:47
@SolalPirelli

Copy link
Copy Markdown
Contributor Author

@hamzaremmal I've removed the 2nd commit, will probably reintroduce it in a later PR simplifying Vulpix in general, but I want to get the fixes to REPL tests in first

@hamzaremmal

Copy link
Copy Markdown
Member

@hamzaremmal I'm interested in your thoughts on the 2nd commit.

For the record, we discussed it over Slack.

@hamzaremmal

hamzaremmal commented Mar 11, 2026

Copy link
Copy Markdown
Member

@hamzaremmal I've removed the 2nd commit, will probably reintroduce it in a later PR simplifying Vulpix in general, but I want to get the fixes to REPL tests in first

In this case, I think your second commit had some merits. It added the com.lihaoyi properties to the classpath. I believe we should do that but just hold on the other changes. No need to query the classpath and filter it yet. (What I said here: https://github.com/scala/scala3/pull/25444/changes#r2895927959)

@SolalPirelli

Copy link
Copy Markdown
Contributor Author

The com.lihaoyi additions in #25444 were merged so I'm not sure I understand what you mean

@hamzaremmal

Copy link
Copy Markdown
Member

Right, sorry sorry. I lost track of what was done where. Let me check again the full context and I'll approve it if it all seems ok.

// We run the repl with `-Ydebug` to not use the fallback if there's a class load exception so we can notice these,
// but as a consequence we get debug messages; ignore the stale symbol one, whose contents include symbol IDs
// that depend on the exact compiler.
(optsLine :: buf.toList).filter(nonBlank).filter(!_.startsWith("stale symbol;"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Mmmh, this feels like a hack, why remove an error that was effectively produced? We should either fix it if it was not supposed to be produced or keep it, but hiding it is not a good idea in my opinion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, it's preexisting, it was just hidden before because we didn't run with -Ydebug. I'm not sure if it's fixable since we are, by design, creating a symbol with the same name twice, so isn't it normal that we end up with funny things?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think so. We might create the same symbol twice but during different run of the compiler, right?
Anyways, it's either we can do it then we should not have a stale symbol because the compiler knows how to handle it (it's part of it's business logic: "we can redefine symbols in the same REPL session") or we cannot do it then we should have a proper error saying "you cannot redefine this symbol during the same REPL session". This feels like it's in the middle of both possibilities; allowing you to redefine but at the same time the compiler is not very happy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah that's true, I'll be less lazy and try to actually fix it

@SolalPirelli

SolalPirelli commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

@hamzaremmal Fixed, at some cost to my sanity. Turns out we were not propagating the new State in case of errors, so the next executed line used the same index for the result value name (resX) and unsurprisingly that causes funny things to happen.

Also I deleted results.scala because it was a poor attempt at abstracting Either that no longer works once you have to sometimes also propagate the state on error.

There's plenty more that could be cleaned up in the REPL, or for starters in the compiler (why are we hardcoding behavior for the REPL in the compiler??), but tests passing will do for now.

1 error found
scala> while ((( foo ))) {}
-- [E006] Not Found Error: -----------------------------------------------------
-- [E007] Type Mismatch Error: -------------------------------------------------

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we define it in the previous command...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Indeed

@hamzaremmal

Copy link
Copy Markdown
Member

@hamzaremmal Fixed, at some cost to my sanity.

I very much understand what you are saying 😞

There's plenty more that could be cleaned up in the REPL, or for starters in the compiler (why are we hardcoding behavior for the REPL in the compiler??), but tests passing will do for now.

The REPL was until recently shipped in the same artifact as the compiler. We have just recently split it and it still needs A LOT of work to fully split the business logic.

@SolalPirelli

Copy link
Copy Markdown
Contributor Author

tbh the repl should be a good use case to "validate" the compiler API... if you can't easily implement a REPL, the compiler API needs work :)

@hamzaremmal

Copy link
Copy Markdown
Member

tbh the repl should be a good use case to "validate" the compiler API... if you can't easily implement a REPL, the compiler API needs work :)

Agreed!

@hamzaremmal hamzaremmal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, I just have a question I would like to know the answer to before approving.

1 error found
scala> while ((( foo ))) {}
-- [E006] Not Found Error: -----------------------------------------------------
-- [E007] Type Mismatch Error: -------------------------------------------------

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Indeed

1 error found
scala> ((1, 2): Foo3.T[Int][Int][Int]): Foo3.T[Any][Int][Int]
val res2: Foo3.T[Any][Int][Int] = (1, 2)
val res3: Foo3.T[Any][Int][Int] = (1, 2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So the basis of the fix is propagating the new state which makes indices increment even on errors.
As I see it, it's a fix but not the root cause probably. The context (the compiler's) and ofc the name table is still polluted. My question now is: what happens if we refer to res2 (a not found??)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it prints the error itself, which is kind of interesting:

scala> 42 + java.lang.Integer.TYPE
-- [E134] Type Error: ----------------------------------------------------------
1 |42 + java.lang.Integer.TYPE
  |^^^^
  |None of the overloaded alternatives of method + in class Int with types
  | (x: Double): Double
  | (x: Float): Float
  | (x: Long): Long
  | (x: Int): Int
  | (x: Char): Int
  | (x: Short): Int
  | (x: Byte): Int
  | (x: String): String
  |match arguments ((Integer.TYPE : Class[Integer]))
1 error found

scala> 44
val res3: Int = 44

scala> res2
-- [E134] Type Error: ----------------------------------------------------------
1 |res2
  |^^^^
  |None of the overloaded alternatives of method + in class Int with types
  | (x: Double): Double
  | (x: Float): Float
  | (x: Long): Long
  | (x: Int): Int
  | (x: Char): Int
  | (x: Short): Int
  | (x: Byte): Int
  | (x: String): String
  |match arguments ((Integer.TYPE : Class[Integer]))
1 error found

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(I wouldn't enshrine this into a test though, I don't think anyone should rely on this... for now at least)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Mmmh, so this is not what we want to have obviously but the proposed fix brings it closer to what we would like to have (at least the test suite behaves correctly). I'm inclined to approve this but only if we dig further to check how we can rollback the changes in the context (compiler's Context).

Now, I find this funny because what would happen if we define a value class, say class Foo and add an expression that is broken afterwards (in the same cycle). Can we still use that same class in the next run of the REPL? Would it also show the error or do we just have something that is half working (Foo works and resX shows the error)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

these are good question and I encourage you to create an issue for them, but let's please solve one problem at a time so we don't keep PRs open forever :-)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

these are good question and I encourage you to create an issue for them, but let's please solve one problem at a time so we don't keep PRs open forever :-)

We are not, I just want to understand what I'm approving.

I'm inclined to approve this but only if we dig further to check how we can rollback the changes in the context (compiler's Context).

I didn't mean here to say to do it right now, as long as we have an issue that highlights all of these problems, I'll approve the PR since it brings it closer to what we want.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@hamzaremmal ping on clicking approve? 😇

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I thought you will create the issue first.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

1 error found
scala> buf ++= xs
val res0: mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)
val res1: mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I imagine all of those will be the same comment I made above.

@hamzaremmal
hamzaremmal merged commit 0922097 into scala:main Mar 13, 2026
64 checks passed
@hamzaremmal
hamzaremmal deleted the solal/repl-insanity branch March 13, 2026 12:30
@WojciechMazur WojciechMazur added this to the 3.8.4 milestone Mar 31, 2026
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.

Fix scala3-repl tests to match production behavior

4 participants