dart-lang / language

Design of the Dart language
Other
2.67k stars 205 forks source link

Disallow `part of dotted.name;`. #2358

Open lrhn opened 2 years ago

lrhn commented 2 years ago

We introduced the part of "librarypath.dart"; part-of syntax because it allows tools to go from a part file to the containing library file without needing to guess the context of compilation. It was an alternative to, and improvement on, the existing part of name.of.library; syntax.

And we also did it because we have moved away from requiring libraries to have names, and needing to add a name to a library, just to let it have a part declaration, seemed unnecessary. (Like library names in general.)

I suggest that we remove the old syntax entirely for Dart 3.0.

There is no lint for this, but it's in the style guide. There might still be uses in the wild. It should be an easy migration to implement for dartfix.

The internal dart: platform libraries are heavy users of part files and does not work if you write part of "dart:async"; (at least didn't at some point in the past, where we tried migration away from the name-based syntax). We should fix that too.

(Preferably also fix #1073, so users can completely stop using unnecessary library names).

a14n commented 2 years ago

https://github.com/dart-lang/linter/pull/3567 added a lint to enforce using strings in part of directives.

cedvdb commented 2 years ago

Can something be done to also remove part of with the static meta programing advancements ? (like auto generating the part of by default if a part is found.

lrhn commented 2 years ago

Not sure how auto-generating part of would work.

The reason for part files having a part of is that tools looking directly at the part file can figure out which environment to interpret the file in, without having to search "the world" for the library with that part declaration pointing in the other direction. While editing the part file, you can get completion and type checking, which you can't if the owning library isn't known.

Generating part of, just from looking at the part file, would require something like @partOf("library.dart") to provide the necessary information. Not much of an improvement :)

cedvdb commented 2 years ago

Won't the macro be able to add code to arbitrary file ? When it see a part (which would be a macro) it can add the part of part to the relevant file. That's what I meant. Maybe that makes no sense though as it seems it would be the same context problem as before.

lrhn commented 2 years ago

Macros won't save their generated code back to disk. They generate code during compilation, so the code can react to changes in the macro tag, macro implementation or the library the macro applies to.

If a tool sees the part file first, it doesn't know which library to find and therefore not which macro to apply to generate the part of. It's a blind chicken and egg problem :)

eernstg commented 2 years ago

part of dotted.name is a conditional compilation mechanism, and we should at least be aware of this fact when we're discussing how to get rid of it.

// ----- Library 'lib1.dart'.
library lib;
import 'dart:io';
part 'part.dart';

// ----- Library 'lib2.dart'.
library lib;
import 'some_other_library_that_provides_replacements_for_some_io_things';
part 'part.dart';

// ----- Part file 'part.dart'.
part of lib;

// Implementation of something that needs io-ish features, but which can
// be compiled using 'dart:io' as well as 'some_other_...'.
...

A program could then import 'lib1.dart' or 'lib2.dart', depending on whether it's possible or impossible to have an import 'dart:io'; on the given platform, and all the code in 'part.dart' would not have to be duplicated.