Sdk: Import path's affect class definitions?

Created on 26 Oct 2017  Â·  11Comments  Â·  Source: dart-lang/sdk

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.

area-language

Most helpful comment

But if you get a class via an export, it's the same as getting it via the source library.

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.

Feel very much like a bug!

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.

All 11 comments

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 the lib directory and to use a relative URI to import any other libraries (other than dart: libraries, of course). This minimizes the chance of running into this kind of issue.

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.

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!

But if you get a class via an export, it's the same as getting it via the source library.

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.

Feel very much like a bug!

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.

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 a package: reference.

If you're running dart lib/main.dart then you're treating model.dart in two ways:

1) as file:///my_pkg_dir/lib/model.dart
2) as package:hello/model.dart

dup of #33076

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:

import 'package:lumen/widgets/questions_flow/pages/select/presenter.dart';
import 'package:lumen/widgets/questions_flow//pages/select/presenter.dart';

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 ?

@bwilkerson - would it be appropriate to add a hint in the analyzer when a URI should be canonicalized in an import?

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.

Filed as a new feature request: https://github.com/dart-lang/sdk/issues/42829

Was this page helpful?
0 / 5 - 0 ratings

Related issues

emilniklas picture emilniklas  Â·  3Comments

ranquild picture ranquild  Â·  3Comments

xster picture xster  Â·  3Comments

brooth picture brooth  Â·  3Comments

DartBot picture DartBot  Â·  3Comments