Skip to content

VirtualFile isn't so virtual: "Illegal char <<> at index 0" #23057

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

Open
eed3si9n opened this issue Apr 27, 2025 · 4 comments
Open

VirtualFile isn't so virtual: "Illegal char <<> at index 0" #23057

eed3si9n opened this issue Apr 27, 2025 · 4 comments
Assignees
Labels

Comments

@eed3si9n
Copy link
Member

eed3si9n commented Apr 27, 2025

This was originally reported to Eval as eed3si9n/eval#15.

Compiler version

3.6.4

Minimized code

Here's a draft PR to Eval eed3si9n/eval#18 (GitHub Actions log). Eval internally creates

EvalSourceFile(srcName, startLine, contents)

  class EvalSourceFile(name: String, startLine: Int, contents: String)
      extends SourceFile(
        new VirtualFile(name, contents.getBytes(StandardCharsets.UTF_8)),
        contents.toArray[Char],
      ):
    override def lineToOffset(line: Int): Int = super.lineToOffset((line + startLine) max 0)
    override def offsetToLine(offset: Int): Int = super.offsetToLine(offset) - startLine
  end EvalSourceFile

https://github.com/eed3si9n/eval/blob/e1d49c668327bd389c1ee444b0c3b5a54ba94e89/src/main/scala-3/com/eed3si9n/eval/Eval.scala#L309C1-L316C21

where srcName is set to "<setting>".

Output

The test works fine on Linux and macOS, but it fails on Windows:

class dotty.tools.dotc.reporting.Diagnostic$Error at ?: invalid file path:
Illegal char <<> at index 0: <setting>

Expectation

  1. VirtualFile should be able to handle <setting> as the file name.
  2. There shouldn't be OS behavior differences in the virtual file name.

Notes

Somewhere along the file, something might be calling Paths.get(...)?

@eed3si9n eed3si9n added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 27, 2025
@som-snytt
Copy link
Contributor

No doubt, I did something wrong.

➜  i23057 sbt run
[info] welcome to sbt 1.10.11 (Eclipse Adoptium Java 23.0.2)
[info] loading project definition from /home/amarki/snips/i23057/project
[info] loading settings for project root from build.sbt...
[info] set current project to ScalaEvalProject (in build file:/home/amarki/snips/i23057/)
[info] Updating scalaevalproject_3
https://repo1.maven.org/maven2/com/eed3si9n/eval/eval_3.3.5/0.3.0/eval_3.3.5-0.3.0.pom
  100.0% [##########] 2.0 KiB (2.4 KiB / s)
[info] Resolved scalaevalproject_3 dependencies
[info] Fetching artifacts of scalaevalproject_3
[info] Fetched artifacts of scalaevalproject_3
[info] compiling 1 Scala source to /home/amarki/snips/i23057/target/scala-3.3.5/classes ...
[info] running main
[error] java.lang.ClassCastException: class dotty.tools.dotc.core.Symbols$NoSymbol$ cannot be cast to class dotty.tools.dotc.core.Symbols$ClassSymbol (dotty.tools.dotc.core.Symbols$NoSymbol$ and dotty.tools.dotc.core.Symbols$ClassSymbol are in unnamed module of loader sbt.internal.LayeredClassLoader @6d014890)
[error]         at dotty.tools.dotc.core.Symbols$Symbol.asClass(Symbols.scala:175)
[error]         at dotty.tools.dotc.core.Definitions.UnitClass(Definitions.scala:566)
[error]         at dotty.tools.dotc.typer.Namer.dealiasIfUnit$1(Namer.scala:1982)
[error]         at dotty.tools.dotc.typer.Namer.cookedRhsType$1(Namer.scala:1984)
[error]         at dotty.tools.dotc.typer.Namer.lhsType$1(Namer.scala:1985)
[error]         at dotty.tools.dotc.typer.Namer.inferredResultType(Namer.scala:1996)
[error]         at dotty.tools.dotc.typer.Namer.inferredType$1(Namer.scala:1742)
[error]         at dotty.tools.dotc.typer.Namer.valOrDefDefSig(Namer.scala:1749)
[error]         at dotty.tools.dotc.typer.Namer.defDefSig(Namer.scala:1840)
[error]         at dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:805)
[error]         at dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:954)
[error]         at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:828)
[error]         at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:174)
[error]         at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:188)
[error]         at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:190)
[error]         at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:392)
[error]         at dotty.tools.dotc.typer.Typer.retrieveSym(Typer.scala:3067)
[error]         at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3092)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3303)
[error]         at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3349)
[error]         at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1212)
[error]         at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1216)
[error]         at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3134)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.typedFunctionValue(Typer.scala:1681)
[error]         at dotty.tools.dotc.typer.Typer.typedFunction(Typer.scala:1432)
[error]         at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3136)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.adaptNoArgsUnappliedMethod$1(Typer.scala:4031)
[error]         at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:4174)
[error]         at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:4403)
[error]         at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3679)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.typedAsFunction(Typer.scala:2952)
[error]         at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3167)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3392)
[error]         at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1219)
[error]         at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3134)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3392)
[error]         at dotty.tools.dotc.typer.Namer.typedAheadExpr$$anonfun$1(Namer.scala:1704)
[error]         at dotty.tools.dotc.typer.Namer.typedAhead(Namer.scala:1694)
[error]         at dotty.tools.dotc.typer.Namer.typedAheadExpr(Namer.scala:1704)
[error]         at dotty.tools.dotc.typer.Namer.typedAheadRhs$1$$anonfun$1(Namer.scala:1958)
[error]         at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:242)
[error]         at dotty.tools.dotc.typer.Namer.typedAheadRhs$1(Namer.scala:1958)
[error]         at dotty.tools.dotc.typer.Namer.rhsType$1(Namer.scala:1966)
[error]         at dotty.tools.dotc.typer.Namer.cookedRhsType$1(Namer.scala:1984)
[error]         at dotty.tools.dotc.typer.Namer.lhsType$1(Namer.scala:1985)
[error]         at dotty.tools.dotc.typer.Namer.inferredResultType(Namer.scala:1996)
[error]         at dotty.tools.dotc.typer.Namer.inferredType$1(Namer.scala:1742)
[error]         at dotty.tools.dotc.typer.Namer.valOrDefDefSig(Namer.scala:1749)
[error]         at dotty.tools.dotc.typer.Namer.defDefSig(Namer.scala:1840)
[error]         at dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:805)
[error]         at dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:954)
[error]         at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:828)
[error]         at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:174)
[error]         at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:188)
[error]         at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:190)
[error]         at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:392)
[error]         at dotty.tools.dotc.typer.Typer.retrieveSym(Typer.scala:3067)
[error]         at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3092)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3303)
[error]         at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3349)
[error]         at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2746)
[error]         at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3114)
[error]         at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3118)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3303)
[error]         at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3349)
[error]         at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:2889)
[error]         at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3159)
[error]         at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3277)
[error]         at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
[error]         at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3392)
[error]         at dotty.tools.dotc.typer.TyperPhase.typeCheck$$anonfun$1(TyperPhase.scala:45)
[error]         at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error]         at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error]         at dotty.tools.dotc.core.Phases$Phase.monitor(Phases.scala:463)
[error]         at dotty.tools.dotc.typer.TyperPhase.typeCheck(TyperPhase.scala:51)
[error]         at dotty.tools.dotc.typer.TyperPhase.$anonfun$4(TyperPhase.scala:97)
[error]         at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:479)
[error]         at scala.collection.Iterator$$anon$9.hasNext(Iterator.scala:583)
[error]         at scala.collection.immutable.List.prependedAll(List.scala:152)
[error]         at scala.collection.immutable.List$.from(List.scala:685)
[error]         at scala.collection.immutable.List$.from(List.scala:682)
[error]         at scala.collection.IterableOps$WithFilter.map(Iterable.scala:900)
[error]         at dotty.tools.dotc.typer.TyperPhase.runOn(TyperPhase.scala:96)
[error]         at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:315)
[error]         at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error]         at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error]         at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
[error]         at dotty.tools.dotc.Run.runPhases$1(Run.scala:308)
[error]         at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:349)
[error]         at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:358)
[error]         at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
[error]         at dotty.tools.dotc.Run.compileUnits(Run.scala:358)
[error]         at dotty.tools.dotc.Run.compileSources(Run.scala:261)
[error]         at com.eed3si9n.eval.Eval.compileAndLoad(Eval.scala:223)
[error]         at com.eed3si9n.eval.Eval.evalCommon(Eval.scala:203)
[error]         at com.eed3si9n.eval.Eval.eval(Eval.scala:119)
[error]         at com.eed3si9n.eval.Eval.evalInfer(Eval.scala:71)
[error]         at Test$.main(Test.scala:15)
[error]         at main.main(Test.scala:4)
[error]         at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103
[error]         at java.base/java.lang.reflect.Method.invoke(Method.java:580)
[error] stack trace is suppressed; run last Compile / run for the full output
[error] (Compile / run) java.lang.ClassCastException: class dotty.tools.dotc.core.Symbols$NoSymbol$ cannot be cast to class dotty.tools.dotc.core.Symbols$ClassSymbol (dotty.tools.dotc.core.Symbols$NoSymbol$ and dotty.tools.dotc.core.Symbols$ClassSymbol are in unnamed module of loader sbt.internal.LayeredClassLoader @6d014890)
[error] Total time: 6 s, completed Apr 27, 2025, 5:10:29 PM

@eed3si9n
Copy link
Member Author

It's possible you'd need to fork := true to get proper isolation during run.

@som-snytt
Copy link
Contributor

I'm on a home windows box, my first swing was under WSL, then I'll try forking and also under Windoze. This is just with the supplied zip. I'm putting out because of my conflicted relationship with VirtualFile.

@Gedochao Gedochao added stat:needs minimization Needs a self contained minimization compat:windows and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 28, 2025
@som-snytt
Copy link
Contributor

I tried again with the test in Eval. It's due to the backend reconstituting the source file from the annotation. (It takes the string, turns it into a Name, then getFile assumes PlainFile.)

java.lang.Throwable: invalid file path: Illegal char <<> at index 0: <setting>
  | => rat testpkg.GetValueTest$$anon$1.doReport(GetValueTest.scala:23)
        at dotty.tools.dotc.reporting.Reporter.issueUnconfigured(Reporter.scala:160)
        at dotty.tools.dotc.reporting.Reporter.go$1(Reporter.scala:191)
        at dotty.tools.dotc.reporting.Reporter.issueIfNotSuppressed(Reporter.scala:210)
        at dotty.tools.dotc.reporting.Reporter.report(Reporter.scala:213)
        at dotty.tools.dotc.report$.error(report.scala:69)
        at dotty.tools.dotc.core.Contexts$Context.getFile(Contexts.scala:280)
        at dotty.tools.dotc.core.Contexts$Context.getSource(Contexts.scala:262)
        at dotty.tools.dotc.core.Contexts$Context.getSource(Contexts.scala:267)
        at dotty.tools.dotc.core.Symbols$ClassSymbol.sourceOfClass(Symbols.scala:523)
        at dotty.tools.dotc.core.Symbols$Symbol.source(Symbols.scala:328)
        at dotty.tools.dotc.core.Symbols$Symbol.sourcePos(Symbols.scala:377)
        at dotty.tools.backend.jvm.CodeGen.registerGeneratedClass$1(CodeGen.scala:78)
        at dotty.tools.backend.jvm.CodeGen.genClassDef$1(CodeGen.scala:83)
        at dotty.tools.backend.jvm.CodeGen.genClassDefs$1(CodeGen.scala:118)
        at dotty.tools.backend.jvm.CodeGen.genClassDefs$1$$anonfun$1(CodeGen.scala:116)

where GetValueTest

    val eval = Eval: () =>
      new Reporter:
        override def doReport(dia: Diagnostic)(using Context) =
          new Throwable(dia.message).printStackTrace()

I tried priming the map of sources in Eval.compileAndLoad

run.runContext.base.files.update(moduleName.toTermName, source.file)

probably I just didn't understand something about context construction

EvalSourceFile can encode new VirtualFile(name.toTermName.encode.toString, data) which works obviously but not conveniently.

ps) I followed the download instructions for windows and it just worked; I had a coursier.bat from 2023 and a jdk. Already had windows git, so cloned in powershell and ran sbt there. Edited from WSL, however. After windoze 10 expires, I won't be available for testing.

@som-snytt som-snytt self-assigned this May 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants