Skip to content
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

amended require resolution for init files #76

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions docs/amended-require-resolution-init.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Amended Require Resolution Semantics and Syntax as it Relates to `init` Files

## Summary

This proposes extended rules to require resolution with respect to `init` files.

## Motivation

An issue was discovered with previous semantics for require resolution when implemented in roblox, especially with the popular tool Rojo:

```
- folder/
- init
- module
```

With the above project, one could could require `module` from `init` with `./module` in the filesystem, but once Rojo or another tool had moved the project into Roblox, the require would fail because the structure would change into:

```
- folder/ (init)
- module (module)
```

Due to this, the proper require would be `./folder/module`. This is inconsistent with the filesystem, and disregarding that, it is unintuitive. This proposal corrects this issue.

## Design

For the purposes of this RFC, file extensions will be ommitted. Per previous RFCs, both `luau` and `lua` are valid extensions, but having both at the same path is an error due to ambiguity.

As written in previous RFCs, if a require string resolves to a directory instead of a file, then we will attempt to require a file in that directory named `init`. This RFC extends that rule to disallow requiring files named `init` directly.

This proposal changes require resolution when requiring from an `init` file. Relative requires from an `init` file will be resolved relative to the directory containing the `init` file, not the `init` file itself.

This makes requiring a child of a folder from the folder's `init` file unintuitive and inconvenient, `./{self}/child` instead of what currently is `./child`. The solution to this is the child require prefix, `self/`. This prefix allows requiring a child of the current directory from an `init` file to be done with `self/child`.

As an example, consider the following filesystem project structure and table of require resolutions:

```
- sibling
- folder/
- init
- module
- subfolder/
- init
- submodule
```

| From | To | Path |
| ---------------------------- | ---------------------------- | -------------------------- |
| `sibling` | `folder/init` | `./folder` |
| `folder/init` | `sibling` | `./sibling` |
| `folder/init` | `folder/module` | `self/module` |
| `folder/init` | `folder/subfolder/init` | `self/subfolder` |
| `folder/init` | `folder/subfolder/submodule` | `self/subfolder/submodule` |
| `folder/module` | `folder/init` | `.` |
| `folder/module` | `folder/subfolder/init` | `./subfolder` |
| `folder/subfolder/init` | `sibling` | `../sibling` |
| `folder/subfolder/init` | `folder/init` | `.` |
| `folder/subfolder/init` | `folder/module` | `./module` |
| `folder/subfolder/init` | `folder/subfolder/submodule` | `self/submodule` |
| `folder/subfolder/submodule` | `folder/subfolder/init` | `.` |
| `folder/subfolder/submodule` | `folder/init` | `..` |

## Drawbacks

This proposal has some significant drawbacks that deserve consideration:

- Some users have already migrated to the require resolution semantics that this proposal changes. However, as these require semantics have not made it into Luau's largest user, Roblox, or Luau's primary language server, Luau-LSP, these users are few.
- This proposal changes require resolution semantics to deviate from the filesystem in a significant way. This will be unintuitive to some users, although it is important to note that other languages like Rust have similar import semantics.

## Alternatives

- As it relates to requiring children of a folder from the folder's `init` file, the child require prefix could be changed to almost anything. Some notable examples include `@mod`, `@self`, `#`, `#self`, and `#mod`.
- If this proposal is not accepted and the status-quoe is maintained, then projects using Rojo will have to bear significant changes and inconvenience if they wish to benefit from new require resolution semantics. Roblox projects not using Rojo may not have such severe issues, but a common pattern will be made more annoying.