-
Notifications
You must be signed in to change notification settings - Fork 463
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
[PoC] Injectable source loc arg #7344
base: master
Are you sure you want to change the base?
Conversation
… up to injectable sourceLoc
This looks like a super useful feature 🔥 But maybe what would be nice is to split the object into separate arguments, so it doesn't needlessly add runtime overhead. If we are talking about logging use-case, I think this is an important point. Also, for the cases I personally see, I think in the beginning, it would be best to simply include the prepared path to the function call like: |
@DZakh thanks for the feedback! The current object is bloated, I agree, but I don't see where runtime performance would be an issue here...? Could you expand on that part? More opinions on what to include/not include would be good. cc @cknitt @fhammerschmidt @cometkim @tsnobip Also, there's an alternative solution where we could just allow all the constants ( |
These are two object allocations + quite a lot of duplicated strings, which increase the bundle |
Awesome work! I agree with @DZakh. While it can be nice in some situations to get everything in a single object, efficiency-wise it is not ideal, e.g. for a logger. Personally, for a logger, I would like to be able to obtain the |
So, how about this:
This gives a compact represenation (less bundle bloat, no uneccessary allocation of objects) while preserving the usefulness to the consumer, with the cost of running a function like What do you think? |
I'm still thinking about it. Maybe I need to do something similar in rescript-vitest, but without exposing it to the end user interface. I'm not sure if this is actually useful, since the "call site" is inside the library code anyway. |
One concern: Bundling error messages or source information from libraries used in the critical path is not a good idea and should be treated as a development-only feature. As we don't have such a flag, as other compilers have a
Some critical JS libraries (especially for the Web) have an additional compilation step for similar cases, like invariant. |
I like the idea of using abstract types to inject metadata, but at least there needs to be an option for the compiler to change its configuration depending on the target environment. |
I think for some cases stripping it out of release builds makes sense, but there are plenty of cases where it doesn't (like a logger you use in production). Voiding the string itself in build probably makes the most sense, we can't really change the fn signature depending on build env. Anyway, I lean towards saying that this is a separate issue since we don't have that type of setup today. For this particular feature we just need to decide whether to include it or not, and if so in which form. |
100% inspired by MoonBit's autofill
SourceLoc
function argument, this makes it possible to inject a labelled argument to any function, and as long as it's optionak, has the type ofsourceLocPos
and/orsourceLocValuePath
(builtin types), and has a default value of%autoFill
. Then each call to that function will inject information about the call site, without needing to pass those argument explicitly.This is useful in many different scenarios, like for example logging (see
rescript-logger
which does the same, but with a PPX), tests, error reporting, and so on.Example:
Tst.res
OtherFile.res
sourceLocValuePath
is a string at runtime in the form ofPath.To.Module.value
. So, if you'reMyModule
inSomeFile.res
, and inside of a let binding calledmyFunction
, you'll getSomeFile.MyModule.myFunction
.sourceLocPos
is a string at runtime in the form of<filename>;<startLine>;<startCol>;<endLine>;<endCol>
.Both are abstract types, and soon I'll add tools and functions that can be used to work with those abstract types.
Questions
Are what I've added so far enough? Do we want more/less information? Other things to think/worry about?
Things left to figure out
Figure out the editor tooling - do we just hide injectable args?Fixed by enforcing an optional arg instead of required.sourceLoc
which is a builtin