v0.2.12
This commit is contained in:
164
chapters/034-packages-identite-et-collisions-de-namespaces.md
Normal file
164
chapters/034-packages-identite-et-collisions-de-namespaces.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# 34. Packages, identité et collisions de namespaces
|
||||
|
||||
## 34.1 Identité indépendante du namespace — V1 REQUIS — FIGÉ
|
||||
|
||||
L'identité d'un package est indépendante de ses namespaces internes.
|
||||
|
||||
Identité canonique :
|
||||
|
||||
```text
|
||||
vendor/package
|
||||
```
|
||||
|
||||
Coordonnée exacte :
|
||||
|
||||
```text
|
||||
vendor/package@version
|
||||
```
|
||||
|
||||
Sélecteur de dépendance :
|
||||
|
||||
```text
|
||||
vendor/package@requirement
|
||||
```
|
||||
|
||||
Exemples :
|
||||
|
||||
```text
|
||||
saselang/core@1.4.0
|
||||
saselang/compiler-core@^0.8
|
||||
acme/http-client@>=2.5,<3.0
|
||||
sdl/sdl@3.1.*
|
||||
```
|
||||
|
||||
Le `vendor/package` désigne l'identité logique. La version exacte ou l'exigence SemVer ne change jamais cette identité ; elle sélectionne une instance/résolution de cette identité.
|
||||
|
||||
Le namespace interne peut être totalement différent et ne doit pas être dérivé automatiquement de `vendor/package`.
|
||||
|
||||
## 34.2 Syntaxe des identifiants package — V1 REQUIS — FIGÉE EN PRINCIPE
|
||||
|
||||
Pour `vendor` et `package` :
|
||||
|
||||
```regex
|
||||
[a-z][a-z0-9]*(?:-[a-z0-9]+)*
|
||||
```
|
||||
|
||||
Règles :
|
||||
|
||||
- ASCII lowercase ;
|
||||
- `-` sépare les mots à l'intérieur d'un composant ;
|
||||
- `_` est interdit ;
|
||||
- aucune conversion automatique `-` <-> `_` n'existe ;
|
||||
- `/` sépare `vendor` et `package` ;
|
||||
- `@` introduit une version exacte ou un requirement SemVer.
|
||||
|
||||
Cette convention doit fonctionner de manière identique dans les manifests, le resolver, le lockfile, les outils et la qualification `from` des imports.
|
||||
|
||||
## 34.3 Collision de namespaces — V1 REQUIS — FIGÉ
|
||||
|
||||
Deux packages peuvent légalement définir le même namespace et le même nom de symbole sans représenter le même type.
|
||||
|
||||
Par exemple, deux packages peuvent chacun fournir :
|
||||
|
||||
```text
|
||||
namespace parser.ast;
|
||||
public class Node
|
||||
```
|
||||
|
||||
L'identité sémantique réelle d'un symbole inclut au minimum :
|
||||
|
||||
```text
|
||||
instance de package résolue
|
||||
+ namespace
|
||||
+ symbole
|
||||
```
|
||||
|
||||
Ainsi :
|
||||
|
||||
```text
|
||||
acme/parser@2.4.1 :: parser.ast.Node
|
||||
other/parser@5.0.0 :: parser.ast.Node
|
||||
```
|
||||
|
||||
sont deux types distincts.
|
||||
|
||||
## 34.4 Qualification d'import par dépendance — V1 REQUIS — FIGÉ
|
||||
|
||||
Tout symbole provenant d'une dépendance externe doit être importé explicitement avec une clause `from` contenant son sélecteur canonique :
|
||||
|
||||
```text
|
||||
from "vendor/package@requirement"
|
||||
```
|
||||
|
||||
Direction syntaxique :
|
||||
|
||||
```text
|
||||
import func some.namespace::function from "sdl/sdl@2.1.*" as sdlfun1;
|
||||
import type some.namespace.Type from "acme/parser@^3.0" as ParserType;
|
||||
```
|
||||
|
||||
La grammaire finale des différentes formes `import type|func|const|var` reste à harmoniser avec la grammaire lexicale complète, mais les règles sémantiques suivantes sont figées :
|
||||
|
||||
- `from` est **obligatoire** pour toute provenance extérieure au package courant ;
|
||||
- le sélecteur `vendor/package@requirement` doit correspondre à un requirement effectivement déclaré dans le scope de dépendances applicable au fichier/package ;
|
||||
- `from` ne déclenche jamais une résolution ad hoc ;
|
||||
- le lockfile associe ce requirement à une version exacte résolue ;
|
||||
- les dépendances transitives ne sont pas directement importables : un package qui utilise directement leur API doit les déclarer comme dépendances directes ;
|
||||
- après l'import, le code utilise le nom local du symbole ou son alias ; la coordonnée package n'apparaît pas dans les expressions ordinaires.
|
||||
|
||||
Sans `from`, un `import` ne peut viser que le package courant.
|
||||
|
||||
L'alias `as` reste facultatif lorsque le nom local obtenu est unique dans le fichier. Il devient nécessaire lorsque plusieurs imports produiraient le même nom local ou lorsqu'un renommage explicite est souhaité.
|
||||
|
||||
## 34.5 Plusieurs versions directes d'une même identité — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Un même package consommateur peut déclarer plusieurs requirements directs pour le même `vendor/package` afin d'utiliser plusieurs lignées incompatibles en parallèle.
|
||||
|
||||
Exemple conceptuel :
|
||||
|
||||
```text
|
||||
sdl/sdl@2.1.*
|
||||
sdl/sdl@^3.0
|
||||
```
|
||||
|
||||
Le code choisit explicitement l'instance souhaitée avec `from` :
|
||||
|
||||
```text
|
||||
import func ... from "sdl/sdl@2.1.*" as sdlfun1;
|
||||
import func ... from "sdl/sdl@^3.0" as sdlfun2;
|
||||
```
|
||||
|
||||
Si les deux imports exposent le même nom terminal dans le même fichier, des alias locaux distincts sont obligatoires. La sélection de version ne peut pas être reportée à un chemin pleinement qualifié utilisé directement dans le corps du code.
|
||||
|
||||
Pour un même scope effectif de dépendances, deux requirements portant sur le même `vendor/package` doivent être **disjoints**.
|
||||
|
||||
Exemples autorisés :
|
||||
|
||||
```text
|
||||
sdl/sdl@2.1.*
|
||||
sdl/sdl@^3.0
|
||||
```
|
||||
|
||||
Exemples interdits :
|
||||
|
||||
```text
|
||||
sdl/sdl@>=1.0
|
||||
sdl/sdl@^4.5
|
||||
```
|
||||
|
||||
car les ensembles de versions acceptées se recouvrent.
|
||||
|
||||
De même :
|
||||
|
||||
```text
|
||||
sdl/sdl@^3.0
|
||||
sdl/sdl@3.1.*
|
||||
```
|
||||
|
||||
est interdit puisque `3.1.*` appartient déjà à `^3.0`.
|
||||
|
||||
Le resolver doit détecter l'intersection SemVer des requirements avant résolution. Une intersection non vide est une erreur de manifest, même si une version particulière permettrait techniquement de satisfaire les deux requirements.
|
||||
|
||||
Cette règle supprime toute ambiguïté entre plusieurs slots directs de la même identité et rend `from "vendor/package@requirement"` déterministe.
|
||||
|
||||
Le graphe transitif peut lui aussi contenir plusieurs versions d'une même identité. Chaque instance résolue conserve une identité de type distincte lorsque les versions ne sont pas unifiées par le resolver.
|
||||
Reference in New Issue
Block a user