Skip to content

Reserve @self require alias to prevent user-defined overrides#215

Open
vrn-sn wants to merge 1 commit into
luau-lang:masterfrom
vrn-sn:vrn-sn/self-alias-no-overrides
Open

Reserve @self require alias to prevent user-defined overrides#215
vrn-sn wants to merge 1 commit into
luau-lang:masterfrom
vrn-sn:vrn-sn/self-alias-no-overrides

Conversation

@vrn-sn

@vrn-sn vrn-sn commented Jul 3, 2026

Copy link
Copy Markdown
Member

In #109, I had initially proposed that we allow users to override @self in their user-defined alias maps, as the semantics would then be similar to how the script global in Roblox scripts could be shadowed. We didn't want to encourage this pattern, but I didn't really see any harm at the time.

Over a year later, we have now exposed generalized require semantics through the Luau.Require library, and I've realized we made the wrong move (oops!). Using @self is turning out to be extremely common, both for code that runs in filesystem-targeting runtimes (e.g. Lute) and even in Roblox (e.g. Roblox's own Character Controller Library).

By allowing @self to be overridden, the generalized require resolver is forced to check all parent directories for a user-defined @self alias before proceeding with navigation, which is horrible for performance. If we forbid user-defined overrides of @self, we can immediately continue on with path navigation without this unnecessary cost.

Although we discussed these two options in the original RFC comments, it turns out nothing was ever cemented in the RFC document itself. In this PR, I've spelled these semantics out explicitly.

Backwards-compatibility: if anyone is currently overriding @self, this will be a breaking change. I think this is an acceptable cost for a few reasons:

  • I doubt anyone is actually doing this.
  • If someone is doing it, there is a migration path (change the alias name to something else).
  • The @self alias is the most commonly used alias today, and we should be optimizing for the common use case.

@jackhexed

Copy link
Copy Markdown
Contributor

What is the actual performance change? Is there any motivation beyond performance?

@TenebrisNoctua

Copy link
Copy Markdown

In our runtime, we've kind of already made this change to prevent the implementation becoming overly complex for our require. It would be nice to see this becoming official.

@vrn-sn

vrn-sn commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

What is the actual performance change?

The current performance cost depends on multiple factors - for example:

  • Where the requirer module sits in its filesystem (deeper = more expensive to determine @self was not redefined in a parent directory's configuration file).
  • Whether the runtime environment has implemented caching for configuration file lookups (if not, we might pay the same lookup cost for every @self/... require in a given file).
  • Whether require is walking an actual filesystem or a virtualized filesystem (syscalls in the former approach are more expensive due to the context switch).

This proposed change cuts that lookup cost entirely.

Is there any motivation beyond performance?

Performance is one motivation, and I would say that the other is language-wide consistency across different runtime environments. The other basic navigation operations are consistently defined (e.g. .. means "parent"; /xyz means "navigate down to 'xyz' child"), so it would be nice if @self was also guaranteed to always mean the same thing in different environments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants