-
Notifications
You must be signed in to change notification settings - Fork 214
Dart uses raw URIs for library identity. #939
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
Comments
Generally sounds good! However, hardlinks on UN*X-ish systems (and probably a bunch of similar mechanisms on same or other OS'es, and specialized file systems) will make it tricky to determine exactly when something is "the same underlying file". But that shouldn't stop us from allowing an import/export URI normalization in tools, and trusting them to keep it so restricted that it doesn't hurt in practice. |
SGTM and agreed with Erik. There's probably some weird corner cases a user could jam themselves into if they tried to hard enough around symlinks, but they could just... not do that. |
I probably wouldn't treat files with different paths in the same file system as the same file. It's mostly when we use |
Having had more time, and more reasons, to think about this issue, I think we should actually ensure that resolution is mostly the same across platforms. At least, it should be predictable whether two imports denote the same library or different libraries.
To decide if files are in the same package, or if a file has a This will mainly help people who do things like
That is, it's a compile-time error to reach into another package's
|
@lrhn can you add a few example of what we accept and what we reject? |
Proposed behavior:
/// in package foo, bin/foo.dart -- which has no `package:` URI, so must be file path.
import "../lib/foo.dart"; // Accepted, becomes "package:foo/foo.dart".
// In package `bar`, bin/bar.dart -- which has no `package:` URI, so must be file path.
import "../../foo/lib/foo.dart"; // Rejected, now compile-time error.
// ^^^^^^^^^^
// This file has canonical URI 'package:foo/foo.dart'. Use it!
import "package:foo/foo.dart";
import "package:foo//foo.dart";
import "package:foo/Foo.dart"; // At least on Windows. If any two of these occur in the same program, and they refer to the same file, we give an error because different URIs refer to the same file. We want the URI for a file to be canonical, so pick one. That allows us to safely conflate URI and file path in the compiler, which we already do unsafely. (We should probably warn you that For better or worse, it's trying to reintroduce the protection against importing the same library twice which was the original goal of the "no two libraries with the same name" rule (which also prevented different versions of the same library). That just didn't work because library names weren't good for anything else, and did not carry their own weight. |
I'm not sure we can do the last part. |
How about we start with
? Both of these should be doable and bring value on their own. |
I'd be fine with that. We'll probably need at least a comment in the language specification, saying that compilers are allowed to canonicalize URIs in some ways, without getting into too many details. Any objections? |
It would be better if we had not allowed imports like |
One thing to note is that |
I would actually prefer a different approach:
So, in terms of @lrhn's examples, this would mean: /// in package foo, bin/foo.dart
import "../lib/foo.dart"; // Accepted, refers to file "lib/foo.dart" in package foo. No hint. // In package `bar`, bin/bar.dart -- which has no `package:` URI, so must be file path.
import "../../foo/lib/foo.dart"; // Allowed, refers to the same file as `package:foo/foo.dart`
// However, the analyzer issues a hint suggesting that the import be changed to `package:foo/foo.dart`
// And `pub` refuses to publish the package. // Assuming Windows, and that listing the `lib` directory of package `foo` yields a file called `foo.dart`:
import "package:foo/foo.dart"; // (1)
import "package:foo//foo.dart"; // (2)
import "package:foo/Foo.dart"; // (3)
// (1), (2), and (3) are all permissible in isolation, but (3) causes a hint (and blocks publishing of the package).
// (1) and (2) can be used in the same program, because they both canonicalize to the same path
// Attempting to use (3) in the same program as (1) or (2) results in an error (even if the imports occur in different files). |
As before I'm not sure we can do that. E.g. the VM has a I'm all for not issuing an error when dotting from |
Any new thoughts and/or decisions on this one? |
ping. |
FWIW I think it is fine to remove support for HTTP imports from Dart VM. I don't think it really pulls its weight these days. |
@jensjoha if we do indeed de-support the HTTP-based imports, are all your concerns addressed? |
Will the frontend server still be able to use |
Not really, that was just a good example of us not being able to do it 100%. I think we'll in practise have trouble "canonicalizing correctly" for all file systems. I would also much prefer rules we could enforce without asking the filesystem (if nothing else, asking the filesystem is slow). (It could even be "dart files (and as a consequence all imports and exports) users only lower case", but that might be too extreme.) This on top of "package canonicalization, non-package URI references to own package's lib/ directory" and "no cross package canonicalization of files" would probably fix most issues I think -- and be doable. |
If we don't want to look at the file system, then rules that would prevent conflict could be, as you mention:
WDYT? |
Sounds good to me. |
SGTM |
Dart currently identifies libraries by their import URI.
That causes troubles in some situations:
dart lib/main.dart
("Interpreting this as package URI" message is confusing sdk#37978)I suggest that we loosen the language specification to the point where the compiler is in charge of detecting when two URIs represent the same library, and it is allowed to canonicalize the URI of the library prior to resolving imports.
If the compiler can recognize that the underlying file system is case insensitive, then it is free (and encouraged) to consider
Foo.dart
andfoo.dart
the same library. It might still want to give a warning/hint that the code won't work on case-sensitive platforms.If someone runs or imports
lib/main.dart
, the compiler is free to rewrite that topackage:currentPackage/main.dart
. We already do that for entry points (see also dart-lang/sdk#37978), but it sometimes fails for direct imports from thebin/
directory or other cases.In general, allow the compiler to recognize that two URIs are actually referring the same library file using any available information, not just what the language specification can predict.
It still have to be in some way predictable. Generally, if it's the same underlying file, then it should be the same library.
The text was updated successfully, but these errors were encountered: