-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
deferImport: allows cyclic dependencies #18251
Conversation
Isn't one of the perks coming out of IC would be to enable cyclic imports? With IC nearing completion, why would we need this magic? |
how does IC enable cyclic imports?
Based on what evidence? compiling or partial recompiling with This PR solves real problems and simplifies working with cyclic dependencies. |
Based on what @Araq has been saying on multiple chat platforms for as long as IC was talked about. IC and the packedast that come with it was said to enable the implementation of cyclic imports and the removal of forward declaration.
https://github.com/nim-lang/Nim/projects/1 There's only one TODO left.
I don't want to solve language issues with hacks. |
IC does not enable cyclic imports but I don't want to enable cyclic imports until we have IC as I don't want a solution that conflicts with IC. I don't see how we need |
Also, encourage better software engineering by separating interface and implementation(s). Having been subjected to code bases in languages that allow this I've invariably had to untangle the mess it creates. |
uhm... do you realize that this PR actually enables separating interface and implementation for code that requires it? And that there is no cyclic import dependencies involved? It enables cyclic dependencies between APIs (procs from A calling procs from B and vice versa) without creating a cyclic import graph. See tests, or this example: # foo.nim
proc foo_fn1(){.importc.}
proc fn1*() = foo_fn1()
deferImport "foo_impl"
# foo_impl.nim
# implementation file; can contain more imports, even ones that import foo or main
proc foo_fn1(){.exportc.} = discard
# main.nim
import foo
fn1() import graph after calling
no conflict with IC, if anything it's the opposite, it makes incremental compilation easier because it allows one to separate interface from implementation in cases where this is needed; if only the implementation changes and interface is unchanged, only the modules involved in implementation need to be recompiled. Again, this doesn't cause cyclic dependencies in the import graph
and what does that prove exactly? the TODO only concerns gc:arc and makes no mention of the other points i raised in #18251 (comment). It's great if IC eventually works, IC is a key feature (either via nimrod files or CAAS), but claiming it's nearly complete doesn't resonate with my experience.
can you please elaborate? |
Congratulations on missing the point. You're pointing to sem and separation of implementation and interface. This doesn't help it just encourages bad design. What would help sem would be to slowly remove the includes and reshape the code such that it's not organized only by loose topic of proc but phases and lifecycles. The latter are much more difficult to model in ones head and far more useful than modules like "bag of generic handling stuff". Right now the code is arranged for rapid indexing of proc by topic, but seeing as go to definition has consistently gotten better along with symbol search this is less important. Your minimized example doesn't make sense either, there are two classic cases:
There is no reason why foo needs to refer to foo impl's anything and some very straightforward rearrangement of code should address that. Your PR fails to provide a motivating example. |
That is not important though -- while many examples of "I need cyclic imports" can be fought with "no, you don't and it's a bad architecture" it is considered by me a key missing feature for multiple reasons:
But as I said, allowing cyclic imports does not need to be done via |
776a095
to
19bea9e
Compare
19bea9e
to
ee93ddc
Compare
It's not |
notes
after this PR, nim could avoid a lot of include files included from sem.nim, by using exportc proc; and, with future work noted below, the exportc requirement could also be lifted.
future work
provide a way to use cyclic dependency APIs without exportc/importc, by specifying which module the API comes from, so that the regular nim mangling applies; this should allow using overloaded procs, maybe even generic procs, and avoid caveats of C mangling.