svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Svelte 5: unable to name a variable with the "same name" as a rune

Open WarningImHack3r opened this issue 1 year ago • 23 comments

Describe the bug

When naming a variable with the same name as a rune, without the $, like state or derived or others, the compiler considers them as the same, thus leading to errors like Cannot access 'state' before initialization or errors relating to rune re-affectation.

Even if it's not a bug, runes re-affectation should be prohibited.

Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACj2N0QqDMAxFfyUEH9wQHHsaVQf7jrkH10ZWqG1pU2GI_z46N99yT3JPFhy1oYjivqAdJkKBN--xQn77HOJMhgkrjC4FmUm7IeE8a2cjhGQpQn3tbW_bKIP2nGc2xCBdsgwdFJEHpvJ0aPJGOhsZvgg6uGS2U0VBz6Sggx5fZIzrsfnblEtPkyvF76rc_Ec4Z3Fb79-xwskpPWpSKDgkWh_rB8K78zLqAAAA

Logs

No response

System Info

REPL, Svelte 5 next 175

Severity

annoyance

WarningImHack3r avatar Jul 07 '24 19:07 WarningImHack3r

It's not really about runes but stores — if you declare a variable state, then $state is considered a store value, and thus, the error is that you are trying to read a store before its declaration. So, in general, the error is correct, though it can be misleading.

7nik avatar Jul 07 '24 19:07 7nik

@7nik yes indeed, makes sense! I'm quite new to using runes, so I kind of forgot about stores as I was focused on playing around with runes, but yeah, that makes sense.

In my opinion, there are two possible solutions here:

  • Allow naming variables with the same name as runes, but prohibit creating stores with those names (seems quite hard with JS versatility)
  • Completely disallow variable creation with those names

WarningImHack3r avatar Jul 07 '24 20:07 WarningImHack3r

Both are not easily feasible:

  • when you have code like let state = getSomeResultFromSomewhereElse(), it is not feasible for svelte to detect what type(s) that could be. That would make this a runtime warning, which is not ideal at all
  • Forbidding variables with the same names as runes would make adding new runes a breaking change (as more variable names are forbidden, which could break code).

Afaik because of those reasons, runes with the same names as variables are automatically disabled

MotionlessTrain avatar Jul 07 '24 20:07 MotionlessTrain

The first solution is impossible. Static analysis cannot cover all possible cases. IIRC, variables shadowing runes is intention behaviour - this allows the introduction of new runes without breaking existing code. But a warning should probably be emitted in this case. BTW, due to this, your REPL is considered to be in legacy mode.

7nik avatar Jul 07 '24 20:07 7nik

BTW, due to this, your REPL is considered to be in legacy mode.

What does that mean?

  • Forbidding variables with the same names as runes would make adding new runes a breaking change (as more variable names are forbidden, which could break code).

That's true... What's the best way around it then? A simply better warning message?

WarningImHack3r avatar Jul 07 '24 21:07 WarningImHack3r

BTW, due to this, your REPL is considered to be in legacy mode.

What does that mean?

Svelte 4 / non-rune mode. The mode can be switched with <svelte:options runes /> or runes: true in the compiler options.

7nik avatar Jul 08 '24 07:07 7nik

Svelte 4 / non-rune mode.

Weird, it was in Svelte 5 when I posted it. Fixed.

WarningImHack3r avatar Jul 08 '24 07:07 WarningImHack3r

There is already a warning for this problem, as you can see in the REPL.

trueadm avatar Jul 08 '24 11:07 trueadm

The current warning implies overriding runes is allowed, not that such a thing is not possible and the variable should be renamed

WarningImHack3r avatar Jul 08 '24 12:07 WarningImHack3r

The current warning implies overriding runes is allowed, not that such a thing is not possible and the variable should be renamed

I didn't interpret the warning to imply that you could override runes, more that the naming of your variable conflicts with a rune in scope, so rather than acting like a rune, it will act like a store. So renaming the variable avoids it from acting like a store.

trueadm avatar Jul 08 '24 12:07 trueadm

This works as expected. We decided to give stores precedence over runes in this situation. We can revisit this decision in Svelte 6.

dummdidumm avatar Jul 08 '24 13:07 dummdidumm

It looks like this was a duplicate of #12218. I don't know which one we want to keep.

Conduitry avatar Jul 13 '24 00:07 Conduitry

That issue sounds different to me - I understand it as a request to not reserve the $ prefix

dummdidumm avatar Jul 13 '24 09:07 dummdidumm

@Conduitry I agree with Simon: my request was to better handle/warn about using "rune-named" variables, whereas the other issue is about allowing $-prefixed variables (which I didn't know was not allowed until now - don't such variables even conflict with stores?).

However, both issues would be solved by disabling some/all impacted runes when a conflicting name is found.

Out of curiosity, how did you come up with this idea of prefixing runes with $? I guess it might have something to do with how reactivity used to work in Svelte, but conflicts with stores and regular $-prefixed variables were inevitable, weren't they?
On the other hand, I can't think of a better way to differentiate runes. Maybe going the Solid way, moving the dollar sign at the end?

WarningImHack3r avatar Jul 13 '24 18:07 WarningImHack3r

Hi there! I'm confused!

I had this problem (with svelte 5.19.9):

const { state } = $props();
const value = $state(''); // CONFLICT with state variable

I was expecting this to be possible.

Why should state collide with $state? It's not the same name...

(I feel like i lack information about the mentioned stores... have a link for me?)

Finomosec avatar Feb 14 '25 17:02 Finomosec

https://svelte.dev/docs/svelte/stores

$foo is an automatically updating variable from the store foo. If foo is present as a variable, then $foo being a store subscription takes precedence over it being a rune. This is to avoid it being a breaking change every time we add a new rune. If someone were using foo and $foo as a store, and we happened to introduce $foo as a rune, it would be a breaking change for them if we started interpreting $foo as a rune.

Conduitry avatar Feb 14 '25 17:02 Conduitry

Ah! Thanks for explanation. Makes sense now.

But could this maybe be bound to a config switch?

That way old project don't break, but new ones can benefit from the improved behavior (when setting the config-flag).

Finomosec avatar Feb 21 '25 13:02 Finomosec

what about renaming variables that need to be protected (like "state") at static analysis time to something like "state_"? wouldn't that solve the problem?

  • No need to make special checks when editing code
  • Should be simple to do... right? Just analyze variable names before compiling and rename those that are problematic. "state" should be targeted but "$state" should be ignored
  • Some codebases happy to be able to use "state" variable names.

Chances are I'm missing something when it comes to it. Maybe targetting these variable names in the static analysis is not so simple after all 😅 just speaking from deep ignorance.

Arecsu avatar May 21 '25 18:05 Arecsu

The problem isn't what variables get renamed to in the compiled component. The problem is the store autosubscription thing I mentioned in my comment above.

Conduitry avatar May 21 '25 18:05 Conduitry

It's more for Svelte 6, but what about replacing auto-subscription with an explicit subscription via a rune:

let myStoreVal = $store(myStore);
myStoreVal = 42; // equivalent to myStore.set(42);
// or if you prefer
let $myStore = $store(myStore);

This also could be used in *.svelte.ts/js files within the reactive context.

7nik avatar May 21 '25 19:05 7nik

$store looks great, but adding a rune that will ultimately need to be removed in the next few major versions instead of getting rid of stores altogether doesn't sound like a good idea

WarningImHack3r avatar May 21 '25 19:05 WarningImHack3r

There is no any talks about removing stores.

7nik avatar May 21 '25 19:05 7nik

Not yet, but they'll very likely get sunset in the next majors

WarningImHack3r avatar May 21 '25 19:05 WarningImHack3r