-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix and reinstate repl/errmsgs #13459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
585cb8d
to
9b2446e
Compare
Might want [test_windows_full] ? |
9b2446e
to
ca8147d
Compare
Ideally someone can approve, this passes CI and we can get a clean nightly run. |
@@ -428,7 +428,7 @@ class ReplDriver(settings: Array[String], | |||
/** Like ConsoleReporter, but without file paths or real -Xprompt'ing */ | |||
private object ReplConsoleReporter extends ConsoleReporter( | |||
reader = null, // this short-circuits the -Xprompt display from waiting for an input | |||
writer = new PrintWriter(out, /* autoFlush = */ true), // write to out, not Console.err | |||
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)), /* autoFlush = */ true), // write to out, not Console.err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the BufferedWriter useful for something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering the same, but it already took me n hours today to figure out what was actually different (need to toInt chars to get real differences) and how it possibly broke, that I'm done. This combination comes from what the constructor in PrintWriter does when it's given a PrintStream (out).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it doesn't matter since there's autoFlush=true, but I'll note that the repl reporter in scala 2 doesn't use BufferedWriter.
Besides the CI run, someone should open cmd.exe on Windows and check that the output is actually correct. |
I would hope that's what we had the tests running on Windows for... Either way, I'd prefer to have the test reinstated even without that check. Worst case I'll inline the call to doReport and avoid using a PrintWriter. |
Tests are great but encoding and Windows are weird enough that this isn't enough in general to know what the user will see with their own eyes :). |
I'll try to take a look soon. I have a Windows machine I can test on. |
Could you try using ctx.settings.encoding.value instead of UTF-8? Presumably that shouldn't impact the tests since they're always run with UTF-8 encoding. |
No change -- same bad output on the console. |
FWIW the console output looks good if I run |
If we can discover the encoding used by the current console For example, this hack "works" on JDK < 16 /** Like ConsoleReporter, but without file paths or real -Xprompt'ing */
private object ReplConsoleReporter extends ConsoleReporter(
reader = null, // this short-circuits the -Xprompt display from waiting for an input
- writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)), /* autoFlush = */ true), // write to out, not Console.err
+ writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, encodingOfPrintStream(out))), /* autoFlush = */ true), // write to out, not Console.err
) {
override def posFileStr(pos: SourcePosition) = "" // omit file paths
}
+ private def encodingOfPrintStream(ps: PrintStream): String = {
+ val f = ps.getClass.getDeclaredField("charOut")
+ f.setAccessible(true)
+ f.get(ps).asInstanceOf[OutputStreamWriter].getEncoding
+ }
+ and gives the expected output on both my Windows machine (where it apparently uses encoding "Cp437") and Linux (where it uses "UTF8"). But can we get at this without the reflection hackery? |
…tream Based on the implementation of ConsoleReporter. Sidesteps issues on Windows where the default console encoding may be something other than UTF8 (such as Cp437), which PrintStream is aware of, but apparently there is no API to query.
I've pushed a commit 1632cb9 that takes that sort of approach, since there doesn't seem to be an API to get the encoding out of an existing PrintStream. I verified with that commit the output looks good again in Windows Console / Windows Terminal. |
It's weird this didn't work. What encoding was being used? Was it not Cp437? |
Just checked. UTF-8 in that case. |
Ah, so that's the encoding you're using for compiling the files but not for the console.. Hmm. |
Yes, I believe so. There seems to be API to ask for the former but not the latter (but the Console.out PrintStream automagically chooses the appropriate encoder, just doesn't want to share that tidbit) |
Everyone happy to land this now? |
I'll have time later today to look it over in detail if desired but at a glance LGTM. |
I'm seeing what looks like this problem for the first time, when I run Is this unexpected? Or is there some configuration step I need to take? Here's the output: -- [E007] Type Mismatch Error: -------------------------------------------------
1 | abstract class C { type T; val x: T; val s: Unit = { type T = String; var y: T = x; locally { def f() = { type T = Int; val z: T = y }; f() } }; }
| ^
|Found: (C.this.x : C.this.T)
|Required: T▓
|
|where: T is a type in class C
| T▓ is a type in the initializer of value s which is an alias of String
longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: -------------------------------------------------
1 | abstract class C { type T; val x: T; val s: Unit = { type T = String; var y: T = x; locally { def f() = { type T = Int; val z: T = y }; f() } }; }
| ^
|Found: (y : T)
|Required: T▓
|
|where: T is a type in the initializer of value s which is an alias of String
| T▓ is a type in method f which is an alias of Int
longer explanation available when compiling with `-explain` and here's the expected output: -- [E007] Type Mismatch Error: -------------------------------------------------
1 | abstract class C { type T; val x: T; val s: Unit = { type T = String; var y: T = x; locally { def f() = { type T = Int; val z: T = y }; f() } }; }
| ^
|Found: (C.this.x : C.this.T)
|Required: T┬▓
|
|where: T is a type in class C
| T┬▓ is a type in the initializer of value s which is an alias of String
longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: -------------------------------------------------
1 | abstract class C { type T; val x: T; val s: Unit = { type T = String; var y: T = x; locally { def f() = { type T = Int; val z: T = y }; f() } }; }
| ^
|Found: (y : T)
|Required: T┬▓
|
|where: T is a type in the initializer of value s which is an alias of String
| T┬▓ is a type in method f which is an alias of Int
longer explanation available when compiling with `-explain` |
[test_windows_full]
Fixes #13444