Closed
Description
While working on some Flutter code in Fuchsia I noticed some weird behavior, it took some head scratching to figure out a bug that was caused by it.
If you import the same file using different paths it changes the class/type definition:
import 'package:hello/models.dart' as pkg;
import 'models.dart';
void main() {
pkg.HelloModel a = new pkg.HelloModel();
HelloModel b = new HelloModel();
assert(b is pkg.HelloModel);
assert(a is HelloModel);
}
The asserts above will fail.
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
bwilkerson commentedon Oct 26, 2017
That is correct. Library equality in Dart is defined in terms of the URI used to reference the library rather than the path to the file containing the library. The code above is loading two different libraries (that happen to be defined by the same file), and hence two different classes (that happen to have the same name).
I've been advising people for a long time to always use a
package:
URI to import libraries defined in thelib
directory and to use a relative URI to import any other libraries (other thandart:
libraries, of course). This minimizes the chance of running into this kind of issue.yjbanov commentedon Oct 26, 2017
IMHO, these semantics made sense in the JITted web world, where URL, not the file, gives identity to the downloaded code. In AOT (dart4web, Flutter) and command-line Dart VM, it's just confusing.
kevmoo commentedon Oct 27, 2017
But if you get a class via an export, it's the same as getting it via the source library.
...and it shouldn't matter if the export got the type via package: or relative URI.
Feel very much like a bug!
bwilkerson commentedon Oct 27, 2017
I don't know what you mean by "source library". When you import library A, and library A exports a class from library B, the class is still defined in library B, and the URI used to reference the library (in the export directive) is still used to identify the library.
The description above is the way I read the current specification. I'd be happy to find out I'm wrong.
Personally, I think we should change the specification to use file paths rather than URI's, because I think the days of loading code into a VM running in the browser are gone. That's why I marked this as a language issue.
kevmoo commentedon Oct 27, 2017
Actually, @jxson – I have a question.
It looks like you put this file in
lib/main.dart
(or something) and running it from there?Try moving it to
bin/main.dart
and run it then.If it works, I'm with Brian. I'm arguing for semantics that I'm about 98% are valid. If you're in file X and you're resolved as a
package:
reference, any relative paths are also treated as apackage:
reference.If you're running
dart lib/main.dart
then you're treatingmodel.dart
in two ways:file:///my_pkg_dir/lib/model.dart
package:hello/model.dart
zoechi commentedon Jul 17, 2018
dup of #33076
matanlurey commentedon Jul 18, 2018
Duplicate of #33076.
avi-mastov commentedon Jul 23, 2020
I had this issue in Dart 2.8.4. when the 2 URLs were practically the same, but one of them didn't have a canonical path:
See the extra slash in the 2nd URL? I would expect the Dart VM/Compiler to canonise it or issue a warning and/or have the "Optimize imports" command in Android Studio canonise it, but none of these happened/worked. I just got a runtime error. Should I open a new issue on it @matanlurey ?
natebosch commentedon Jul 24, 2020
@bwilkerson - would it be appropriate to add a hint in the analyzer when a URI should be canonicalized in an import?
bwilkerson commentedon Jul 24, 2020
I would say, yes. I doubt that anyone is intentionally using URIs that are not canonical in order to prevent a file from being seen as being the same, so I expect there'd be zero false positives.
natebosch commentedon Jul 24, 2020
Filed as a new feature request: #42829