# 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.