-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Support -Yimports for implicit preamble imports #6764
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
d333519 to
fcaf156
Compare
|
@lrytz Here is It occurs to me that maybe "disabling" should be scoped in the normal way, like a form of shadowing, where only the innermost import context from a root import is active. I didn't attempt that because the behavior is very different. This PR currently removes scanning for the predef module in this unit; I'll restore that, possibly using the same mechanism: when you notice you're typechecking your predef, disable the import. I may add a lint flag to warn when a predef is disabled; since there can be many Edit: I guess there is no test for not compiling |
lrytz
left a comment
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.
This looks really good!
For the "new trick" of filtering disabling module imports, could you
- explain the advantage (that it can be done symbolically?) (in the commit message)
- explain when imports are completed (in the commit message) and show in examples (and tests) in which cases filtering doesn't work. mention the limitations in
-Yimports:help.
The tests should also show that -Yimports are not relative, always _root_... - that could also go into to the -Yimports:help.
|
|
||
| ```scala | ||
| import java.lang._ | ||
| { |
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.
This is not valid Scala, unfortunately... I don't see how it could be expressed in source code. Maybe we can just explain that this is conceptual, not actual code.
We could add a note that this makes Predef.String work (right?)
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 added more words on the other PR.
| .withPostSetHook(bs => if (bs) imports.value = Nil) | ||
| val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.") | ||
| .withPostSetHook(bs => if (bs && !noimports) imports.value = "java.lang" :: "scala" :: Nil) | ||
| val imports = MultiStringSetting("-Yimports", "import", "Custom preamble imports, default is java.lang, scala, scala.Predef.") |
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.
Maybe remove the spaces in default is `java.lang,scala,scala.Predef`
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.
It would also be nice to define the helpText, it can be quite long (optInlineFrom uses it for example) and cover all the details (eg about neutralizing module imports).
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.
+1.
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.
That was a high bar. Or maybe a high bar stool.
| else imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) | ||
|
|
||
| private def isExcludedRootImport(imp: ImportInfo): Boolean = | ||
| imp.isRootImport && excludedRootImportsCached.get(unit).map(_.contains(imp.qual.symbol)).getOrElse(false) |
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.
.map(f).getOrElse(false) could be .exists(f)
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 had that during one version while trying to get everything working... :)
| // Top-level definition whose leading imports include Predef. | ||
| def isLeadingPredefImport(defn: Tree): Boolean = defn match { | ||
| case PackageDef(_, defs1) => defs1 exists isLeadingPredefImport | ||
| case Import(expr, _) => isReferenceToPredef(expr) |
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.
It seems isReferenceToPredef and isReferenceToPredef can be removed too.
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.
Thanks, not long ago I was still special-casing it for efficiency.
|
What are your thoughts about the cost/benefit of supporting module (and package) members in the Does |
|
When I reviewed Andy Scott, I remembered the feature of just making them look like regular imports. I did at least want to support members in the sense of members of stable member I thought I'd return again to whether |
fcaf156 to
dad17b0
Compare
|
More tests to come. More option syntax, something like |
5f9514d to
32e7276
Compare
|
I think There, a preamble would simply prepend to the compilation unit, without the special weirdness of root imports. A preamble is just some statements. I hope |
|
How about a preamble, Edit: I guess this is another reason everyone wants top-level defs. |
Take `-Yimports:x,y,z` to mean `x,y,z` are root imports
of the form:
```
import x._ { import y._ { import z._ { code } } }
```
and where the import from a module (non-package) can
be disabled with usual idiom, an import at the package level.
The disabling import is registered when the import
is completed, so it must precede all usages.
32e7276 to
4971e90
Compare
38dea40 to
15b1222
Compare
lrytz
left a comment
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.
LGTM!! Leaving open for @adriaanm's 👀
|
My 👀 had been lurking approvingly. |
|
Wohoo!! Thanks @som-snytt |
|
Thanks, what could go wrong? |
|
@SethTisue I'll The "root" imports which constitute the context for Scala source files can be managed explicitly. The default root context imports symbols from These imports can be turned off with A new option, Currently, root imports from |
|
This is actually really not useful in practice. I don't want The part that really hurts is, it seems like it would be absolutely trivial to fix this issue. Is there any chance of a PR fixing it getting in before this is completely unchangeable? |
|
there’s still time to change this. it’s just a |
|
(perhaps this is one where a thread on https://contributors.scala-lang.org might spark some design discussion even from folks who don’t follow the scala/scala PR queue) |
|
@edmundnoble I think you're asking for |
|
@edmundnoble Also please note I'm exercising everything I learned in Sunday school to respond to your comment that, "This is actually really not useful in practice." I took that to mean simply that I didn't address your use case. But I hope that |
|
Personally I think this is pretty useful, but yeah I agree that something more explicit would be even better. Thanks @som-snytt ! Had I more than (checks watch) 3 hours left doing scala, I'd be excited about typing this... |
|
|
|
@som-snytt |
|
@fommil Instead of crowd-sourced, fommil-sourced. I'll try out |
|
I had a branch if I can find it that goes the other way to support Andy Scott's syntax. (As in my previous comment #6764 (comment)) I liked this PR because it is not finicky: you define packages and Predef objects to wildcard import from. The follow-up was just to take regular import syntax, My concern about "import syntax" is that it could wind up very confusing, and it increases the surface area outside the source text. The dubious notion is that I need Another difference is that an explicit import has higher precedence, so it's harder to reason about Using import syntax seems familiar, but it's also true that everyone hates import syntax and it needs to be simplified. So this PR is simple, and import syntax would be finicky. If I can find the branch, though, I'll propose the finicky PR. |
|
This might be the wrong place to ask, but is dotty going to support this? As of right now I'm getting |
|
I agree with @edmundnoble observation that this feature, by limiting to coarse-grained, whole-package imports, ruled out too large a portion of the use cases where it could be valuable, eg:
At the time, there was talk of a However, I note that, somewhat contradictorily, when users then asked for custom prelude at scala/bug#9341 and scala/scala-dev#474, they were told "You've already got it with -Yimports". I myself would use the ability to set a fully custom prelude at the level of a SBT project, including fine-grained addition, hiding and renaming of members, and in Scala3, control of |
|
People are still confused whether To ask for a It's not obvious to me that an opinionated Scala 3 wants people plugging in arbitrary namespaces at all. Maybe there is a difference of understanding about the phrase "custom Predef"? You can say Sorry but the feature is custom root contexts. I'd suggest further commentary on a different Scala 3 ticket. I understand that "I myself would use" is a use case for a different feature. |
Take
-Yimports:x,y,zto meanx,y,zare root importsof the form:
and where the import from a module can be disabled
with usual idiom, an import at the package level.
in detail:
The "root" imports which constitute the context for Scala source files can be managed explicitly.
The default root context imports symbols from
java.lang,scala, andscala.Predef.These imports can be turned off with
-Yno-imports, or just thePredefwith-Yno-predef.A new option,
-Yimports, allows these root imports to be specified explicitly as fully-qualified names of packages and objects. Order is significant, because later imports shadow earlier ones, as though they were in nested scopes.Currently, root imports from
Predefcan be disabled in a source file by introducing an explicit import fromPredef. Typically,import Predef.{any2stringadd => _, _}. Now, any root import from a predef object can be disabled using the same idiom. (There are some restrictions due to the way a source file is processed: generally, the import should be at the package level and appear at the top of the file. Also, a package object is not subject to this idiom.)