Skip to content

Commit 198bb34

Browse files
committed
Add restricted generic trait companion contract
1 parent 5a96573 commit 198bb34

55 files changed

Lines changed: 1462 additions & 95 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,17 @@ paths. See the
182182
[structured annotated-class input view](docs/structured-annotated-class-input-view.md)
183183
and [handler authoring adapter](docs/annotated-class-view-handler-authoring-adapter.md).
184184

185+
Prompt 85 adds one deliberately restricted repository fixture:
186+
`@externalRestrictedTraitApply trait Show[A]`. The shared decoder now exposes
187+
additive raw family/variance/bound-status projections, while an internal profile admits
188+
only a top-level non-sealed trait with one invariant ordinary unbounded type
189+
parameter and no constructor/value parameters. Its precompiled handler leases,
190+
creates, or merges the same-name companion and manually inserts
191+
`def apply[A](using instance: Show[A]): Show[A] = instance`; an existing direct
192+
`apply` wins. All prior handlers remain class-only, and this adds no quasiquotes
193+
or AUXify dependency. See the
194+
[restricted generic trait companion contract](docs/restricted-generic-trait-companion-contract.md).
195+
185196
The packaged `pluginApi` boundary now has an exact-build, line-oriented JVM
186197
surface baseline at `project/experimental-plugin-api-surface-baseline.txt`.
187198
`verifyExperimentalPluginApiSurfaceBaseline` detects class, member descriptor,
@@ -204,10 +215,10 @@ state. See [`pluginApi` dependency-coordinate integrity](docs/plugin-api-depende
204215

205216
Prompt 80 adopts the Prompt 79 feasibility result as a real source/project
206217
split. `pluginApi` is contract-only; the new unpublished `pluginTestMarkers`
207-
project owns all 37 repository fixture markers plus the one fixture-support
208-
class. Their logical two-JAR union remains byte-for-byte the committed Prompt
209-
77 baseline with normalized SHA-256
210-
`039a25870ed7265a657bb5262f86e0af13a35672f942db7a81d4ba66184217e0`.
218+
project owns all 38 repository fixture markers plus the one fixture-support
219+
class. Their logical two-JAR union remains the committed exact-build surface;
220+
Prompt 85 intentionally refreshes its normalized SHA-256 to
221+
`9985dbb9012c2ec8452e42a8282a97b41c71faf94eef76de848dd4b94b514c3f`.
211222
Marker consumers now name that artifact explicitly while handler-only paths
212223
retain only the API contract. See the
213224
[experimental plugin API source-project split](docs/experimental-plugin-api-source-project-split.md).

bootstrap-prompt.md

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ The current project state is a minimal Scala 3 research compiler-plugin project
194194
global-state comparison, and cleanup proof are implemented in
195195
`project/IndependentExternalSbtConsumer.scala` and its spec. No production
196196
publishing setting, public coordinate, workflow, source project, or stable
197-
API is added.
197+
API is added. Because the repository-wide production guard is
198+
`ThisBuild / publish / skip := true`, the disposable publisher explicitly
199+
sets `pluginApi / publish / skip := false` and
200+
`plugin / publish / skip := false` only inside its copied source process.
198201
- Prompt 84 adds `project/ExternalApiPublicationReadiness.scala`, its 22-case
199202
spec, `docs/external-api-publication-readiness-decision.md`, and the explicit
200203
root task `verifyExternalApiPublicationReadiness`. The build sets
@@ -204,6 +207,15 @@ The current project state is a minimal Scala 3 research compiler-plugin project
204207
release mechanisms and production fixture contamination, and writes a
205208
line-oriented ignored-target report. Prompt 83 remains partial synthetic
206209
evidence only; no real coordinates or release implementation are added.
210+
- Prompt 85 adds one exact-build internal admission profile for
211+
`externalRestrictedTraitApply`. The shared `AnnotatedClassView` decoder now
212+
accepts raw class or trait templates and exposes additive definition-family,
213+
type-parameter variance, ordinary-unbounded, and context-bound projections
214+
while retaining the old constructor/factory/copy JVM shapes. The dedicated
215+
precompiled handler manually builds one contextual companion `apply`, uses
216+
the existing companion lease/create/merge and structured-output paths, and
217+
keeps every previous handler on the class-only envelope. It adds no
218+
quasiquotes or AUXify dependency and does not enable production publishing.
207219
- The build adds `Resolver.scalaNightlyRepository` because research plugins are only enabled on nightly or snapshot Scala 3 builds.
208220
- The plugin defines custom built-in marker annotations in `paradise3.gen` and `paradise3.debug`.
209221
- The experimental `pluginApi` project defines the handler contract,
@@ -212,7 +224,8 @@ The current project state is a minimal Scala 3 research compiler-plugin project
212224
`pluginTestMarkers` project owns `paradise3.externalDebug`,
213225
`externalCompanionDebug`, `externalSiblingDebug`, `externalLabel`,
214226
`externalTypedLabel`, `externalMarker`, fixture-only
215-
`externalQuasiquotesTerm`, and the hostile protocol marker/support fixtures.
227+
`externalQuasiquotesTerm`, fixture-only `externalRestrictedTraitApply`, and
228+
the hostile protocol marker/support fixtures.
216229
- `paradise3.externalDebug`, `paradise3.externalCompanionDebug`, `paradise3.externalSiblingDebug`, `paradise3.externalLabel`, and `paradise3.externalTypedLabel` carry `@expander(...)` metadata naming their `demo` handlers, so the plugin can discover those handlers from precompiled marker annotations when `handlerClasspath` is explicit.
217230
- The current annotation-owned bridge is metadata-owned only. `externalDebug` names a precompiled `ParadiseAnnotationExpander`; it does not implement Scala 2 `macroTransform`, Scala 3 `MacroAnnotation.transform`, general same-module handlers, or quasiquote integration.
218231
- The focused same-module staging note records a hardened Prototype success for one internal, test-only, normalized different-file relationship shared by two consumers. Current source wins over stale output and child loaders are scoped and closed. The incremental-compilation follow-up records Outcome 4: a handler-only implementation change recompiles only the handler because the compiler callback has no direct source dependency and ordinary Zinc class relations are API-sensitive. General same-module support is deferred, no dependency-recording code is retained, and `pluginTestHandlers` remains the reliable baseline.
@@ -469,6 +482,7 @@ The current project state is a minimal Scala 3 research compiler-plugin project
469482
- `plugin-test-markers/src/main/scala/paradise3/externalTypedLabel.scala`
470483
- `plugin-test-markers/src/main/scala/paradise3/externalMarker.scala`
471484
- `plugin-test-markers/src/main/scala/paradise3/externalQuasiquotesTerm.scala`
485+
- `plugin-test-markers/src/main/scala/paradise3/externalRestrictedTraitApply.scala`
472486
- `plugin-test-markers/src/main/java/paradise3/PreservedRuntimeMarker.java`
473487
- `plugin-test-markers/src/main/scala/paradise3/metadataEmpty.scala`
474488
- `plugin-test-markers/src/main/scala/paradise3/metadataMissing.scala`
@@ -494,10 +508,14 @@ The current project state is a minimal Scala 3 research compiler-plugin project
494508
- `plugin-test-handlers/src/main/scala/demo/ExternalDebugExpander.scala`
495509
- `plugin-test-handlers/src/main/scala/demo/LegacyExternalDebugExpander.scala`
496510
- `plugin-test-handlers/src/main/scala/demo/ExternalCompanionDebugExpander.scala`
511+
- `plugin-test-handlers/src/main/scala/demo/ExternalRestrictedTraitApplyExpander.scala`
497512
- `plugin-test-handlers/src/main/scala/demo/ExternalSiblingDebugExpander.scala`
498513
- `plugin-test-handlers/src/main/scala/demo/ExternalLabelExpander.scala`
499514
- `plugin-test-handlers/src/main/scala/demo/ExternalTypedLabelExpander.scala`
500515
- `plugin-test-handlers/src/main/scala/demo/ExternalMarkerExpander.scala`
516+
- `plugin-tests/src/main/scala/RestrictedGenericTraitApplyExample.scala`
517+
- `plugin-tests/src/test/scala/RestrictedGenericTraitContractSpec.scala`
518+
- `docs/restricted-generic-trait-companion-contract.md`
501519
- `plugin-test-handlers/src/main/scala/demo/DuplicateExternalDebugExpander.scala`
502520
- `plugin-test-handlers/src/main/scala/demo/GenNameExpander.scala`
503521
- `plugin-test-handlers/src/main/scala/demo/NotAnExpander.scala`
@@ -840,7 +858,7 @@ Create these files:
840858
241. `docs/experimental-plugin-api-source-project-split.md`
841859
242. `prompts/80.codex.experimental.plugin.api.contract.and.test.marker.source.project.split.prompt.md`
842860
243. `reviews/80_chatgpt_experimental_plugin_api_source_project_split_handoff/README.md`
843-
244. `plugin-test-markers/src/main/` (14 moved marker/support source files)
861+
244. `plugin-test-markers/src/main/` (15 marker/support source files)
844862
245. `plugin-api-handler-contract-probe/e2e/IndependentPackagedConsumer.scala`
845863
246. `project/IndependentPrecompiledHandlerPackagedConsumer.scala`
846864
247. `project/IndependentPrecompiledHandlerPackagedConsumerSpec.scala`
@@ -856,6 +874,19 @@ Create these files:
856874
257. `docs/task-owned-local-repository-external-sbt-consumer.md`
857875
258. `prompts/83.codex.task.owned.local.repository.external.sbt.consumer.staging.prompt.md`
858876
259. `reviews/83_chatgpt_task_owned_local_repository_external_sbt_consumer_handoff/`
877+
260. `project/ExternalApiPublicationReadiness.scala`
878+
261. `project/ExternalApiPublicationReadinessSpec.scala`
879+
262. `docs/external-api-publication-readiness-decision.md`
880+
263. `prompts/84.codex.external.api.publication.readiness.decision.and.no.publish.gate.prompt.md`
881+
264. `reviews/84_chatgpt_external_api_publication_readiness_decision_handoff/`
882+
265. `plugin-test-markers/src/main/scala/paradise3/externalRestrictedTraitApply.scala`
883+
266. `plugin-test-handlers/src/main/scala/demo/ExternalRestrictedTraitApplyExpander.scala`
884+
267. `plugin-tests/src/main/scala/RestrictedGenericTraitApplyExample.scala`
885+
268. `plugin-tests/src/test/scala/RestrictedGenericTraitContractSpec.scala`
886+
269. `docs/restricted-generic-trait-companion-contract.md`
887+
270. `input/17_quasiquotes_scala3_restricted_generic_trait_and_companion_contract_response.md`
888+
271. `prompts/85.codex.restricted.top.level.generic.trait.admission.and.companion.merge.contract.prompt.md`
889+
272. `reviews/85_chatgpt_restricted_generic_trait_companion_contract_handoff/`
859890

860891
## File Requirements
861892

@@ -2654,12 +2685,12 @@ Create these files:
26542685

26552686
- Keep the root aggregate exactly six projects by including the unpublished
26562687
`pluginTestMarkers` project beside the retained five projects.
2657-
- Keep five contract sources under `plugin-api/` and 14 moved marker/support
2688+
- Keep five contract sources under `plugin-api/` and 15 marker/support
26582689
sources under `plugin-test-markers/`; preserve packages/JVM names and never
26592690
retain duplicate copies.
26602691
- Keep `project/experimental-plugin-api-surface-baseline.txt` as the sole class
26612692
category authority. Its two-JAR logical union must retain normalized SHA-256
2662-
`039a25870ed7265a657bb5262f86e0af13a35672f942db7a81d4ba66184217e0`.
2693+
`9985dbb9012c2ec8452e42a8282a97b41c71faf94eef76de848dd4b94b514c3f`.
26632694
- Keep `PluginApiSourceProjectSplitPolicy`, the 18-case build-shape policy,
26642695
split surface verifier, source-built candidate-byte proof, marker metadata
26652696
proof, explicit marker consumer paths, expanded clean-resolution proof, and

docs/annotated-class-view-handler-authoring-adapter.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ hatch.
8585
| Five helper-backed fixtures | `withAnnotatedClassView` | helper-owned `Structured` | Current common path |
8686
| `ExternalMarkerExpander` | raw `annotatedClass` | raw `Expanded` | Retained power path |
8787
| `QuasiquotesConstructedTermExpander` | raw input plus exact peer adapter | raw/structured compiler trees under the exact artifact contract | Retained integration proof |
88+
| `ExternalRestrictedTraitApplyExpander` | `withAnnotatedClassView` plus bounded trait/type-parameter projections | low-level raw method construction wrapped in `Structured` | Prompt 85 repository-only fixture |
89+
90+
Prompt 85 extends the same decoder with additive exact-build projections for
91+
raw class-versus-trait family, type-parameter variance, ordinary-unbounded
92+
status, and context-bound presence. Only `externalRestrictedTraitApply` selects
93+
the plugin-owned restricted trait admission profile; the five common
94+
helper-backed handlers remain class-only.
8895

8996
## Evidence boundary
9097

docs/experimental-handler-contract-only-artifact-feasibility.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ After Prompt 80, the ordinary `pluginApi / Compile / packageBin` result is the
1919
source-built contract artifact:
2020

2121
```text
22-
bytes: 134654
23-
entries: 52
24-
classes: 39
22+
bytes: 148524
23+
entries: 58
24+
classes: 45
2525
Tasty: 9
26-
SHA-256: 9128b4561d9328576501a1b306fb39ecc8327df7dca699264d89d020d2eb3da4
26+
SHA-256: 08ca262f70e92040653f561098484d1db7e5fb90f31f2bd3b351979bc5f89b9c
2727
```
2828

29-
The separate unpublished marker artifact contains 38 classes and 36 Tasty
29+
The separate unpublished marker artifact contains 39 classes and 37 Tasty
3030
resources. Their logical union retains the Prompt 77 surface; neither copies
3131
entries from the other.
3232

@@ -36,11 +36,11 @@ The candidate is:
3636
target/experimental-plugin-api-handler-contract/
3737
macroparadise-scala3-plugin-api-handler-contract_3-0.1.0-SNAPSHOT.jar
3838
39-
bytes: 308506
40-
entries: 49
41-
classes: 39
39+
bytes: 342100
40+
entries: 55
41+
classes: 45
4242
Tasty: 9
43-
SHA-256: 2b93807da82fc33b745e484d02890bfd593856601df59f92cd5a449333cb1a84
43+
SHA-256: 999903e76c68ebcf8cab45550ea7ddb84ee0a9ce3dc2a71860014fcc6e1fe678
4444
```
4545

4646
Stored ZIP entries make the candidate larger than the compressed source-built
@@ -72,7 +72,7 @@ surface and compared with the committed Prompt 77 manifest. The normalized
7272
surface SHA remains exactly:
7373

7474
```text
75-
039a25870ed7265a657bb5262f86e0af13a35672f942db7a81d4ba66184217e0
75+
9985dbb9012c2ec8452e42a8282a97b41c71faf94eef76de848dd4b94b514c3f
7676
```
7777

7878
The candidate carrier retains runtime retention, `TYPE` and
@@ -96,15 +96,15 @@ diagnostics.
9696

9797
## All-current-handler compile proof
9898

99-
All 14 sources under `plugin-test-handlers/src/main/scala/` are passed to one
99+
All 15 sources under `plugin-test-handlers/src/main/scala/` are passed to one
100100
direct pinned compiler invocation using only the candidate, the exact
101101
compiler/library universe, and JDK classes. Two clean repetitions both exit 0
102-
and produce the same 85-file inventory:
102+
and produce the same 87-file inventory:
103103

104104
```text
105-
class files: 44
106-
Tasty files: 41
107-
ParadiseAnnotationExpander implementations: 37
105+
class files: 45
106+
Tasty files: 42
107+
ParadiseAnnotationExpander implementations: 38
108108
```
109109

110110
No `paradise3/api`, compiler, Scala, plugin implementation, or fixture-marker

docs/experimental-plugin-api-source-project-split.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ pluginTests
2929
```
3030

3131
`pluginApi` remains rooted at `plugin-api/` and contains five source files. Its
32-
package owns exactly 38 `HANDLER_CONTRACT` classes, the one
32+
package owns exactly 44 `HANDLER_CONTRACT` classes, the one
3333
`METADATA_CARRIER`, nine Tasty resources, and standard JAR metadata.
3434

3535
`pluginTestMarkers` is rooted at `plugin-test-markers/`, depends on
36-
`pluginApi` only for `paradise3.api.expander`, and is not published. Its 14
37-
source files own exactly 37 `INTEGRATION_FIXTURE_MARKER` classes, the one
38-
`INTEGRATION_FIXTURE_SUPPORT` class, and 36 Tasty resources. Packages and JVM
36+
`pluginApi` only for `paradise3.api.expander`, and is not published. Its 15
37+
source files own exactly 38 `INTEGRATION_FIXTURE_MARKER` classes, the one
38+
`INTEGRATION_FIXTURE_SUPPORT` class, and 37 Tasty resources. Packages and JVM
3939
names are unchanged. No moved source remains under `plugin-api/`, and neither
4040
artifact copies entries from the other.
4141

@@ -44,10 +44,10 @@ artifact copies entries from the other.
4444
`project/experimental-plugin-api-surface-baseline.txt` remains the sole class
4545
classification authority. `PluginApiSourceProjectSplitPolicy` compares the two
4646
source-built JAR inventories with those categories, rejects duplicate entries
47-
or ownership reversal, verifies the five/14 source layout, and checks the
47+
or ownership reversal, verifies the five/15 source layout, and checks the
4848
metadata and constructor shapes of the moved fixtures.
4949

50-
The marker proof covers all nine runtime metadata values, including empty and
50+
The marker proof covers all ten runtime metadata values, including empty and
5151
missing-handler values, without initializing `MetadataInitializationProbe`.
5252
It also preserves the generic `[A]` plus `String` constructor shape of
5353
`externalTypedLabel` and the runtime Java annotation shape of
@@ -59,24 +59,24 @@ Tasty entry.
5959
The surface verifier now reads contract classes from `pluginApi` and fixture
6060
classes from `pluginTestMarkers`, permits only the unavoidable standard
6161
manifest in both archives, and rejects all other duplicate entries. Their
62-
logical union renders byte-for-byte the committed Prompt 77 manifest:
62+
logical union renders byte-for-byte the committed exact-build manifest:
6363

6464
```text
6565
normalized surface SHA-256:
66-
039a25870ed7265a657bb5262f86e0af13a35672f942db7a81d4ba66184217e0
66+
9985dbb9012c2ec8452e42a8282a97b41c71faf94eef76de848dd4b94b514c3f
6767
6868
committed/rendered manifest file SHA-256:
69-
13e46917255adee612dd0920b0c03b205aec2381fde8c7ca2700a3543c8a9e4a
69+
43ef7d2883571f4fc8235790813e3c9e9c8826c931335380965f84c6e63a551f
7070
```
7171

7272
Current source-built artifact evidence from the reviewed pinned run is:
7373

7474
```text
75-
pluginApi: 134654 bytes, 52 entries, 39 classes, 9 Tasty
76-
SHA-256: 9128b4561d9328576501a1b306fb39ecc8327df7dca699264d89d020d2eb3da4
75+
pluginApi: 148524 bytes, 58 entries, 45 classes, 9 Tasty
76+
SHA-256: 08ca262f70e92040653f561098484d1db7e5fb90f31f2bd3b351979bc5f89b9c
7777
78-
pluginTestMarkers: 41887 bytes, 76 entries, 38 classes, 36 Tasty
79-
SHA-256: 8fe14a5124a690e57f7d8b150494d27d27803118b0dd1cce494f3d945b826562
78+
pluginTestMarkers: 43109 bytes, 78 entries, 39 classes, 37 Tasty
79+
SHA-256: 285054a9095cceb3db1743bdc534c8e0dfb285c62569550319e9d0ba97c85051
8080
```
8181

8282
JAR SHA values are build-output identities, not a published coordinate or a

docs/experimental-plugin-api-surface-baseline.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ line-oriented format is version 1 and contains:
5151
The current normalized SHA-256 is:
5252

5353
```text
54-
039a25870ed7265a657bb5262f86e0af13a35672f942db7a81d4ba66184217e0
54+
9985dbb9012c2ec8452e42a8282a97b41c71faf94eef76de848dd4b94b514c3f
5555
```
5656

57-
The baseline contains 38 handler-contract classes, one metadata carrier, 37
58-
integration fixture marker classes, one fixture-support class, 569
59-
public/protected member records, and 46 allowed resource records.
57+
The baseline contains 44 handler-contract classes, one metadata carrier, 38
58+
integration fixture marker classes, one fixture-support class, 658
59+
public/protected member records, and 47 allowed resource records.
6060

6161
## Surface categories
6262

@@ -83,7 +83,7 @@ but is not itself a handler contract or marker annotation.
8383
Prompt 80 makes the baseline a logical union of two normally packaged JARs.
8484
`pluginApi` owns only `HANDLER_CONTRACT`, `METADATA_CARRIER`, nine contract
8585
Tasty resources, and standard metadata. The unpublished `pluginTestMarkers`
86-
owns only the 37 fixture-marker classes, one support class, 36 fixture Tasty
86+
owns only the 38 fixture-marker classes, one support class, 37 fixture Tasty
8787
resources, and standard metadata. The verifier rejects duplicate non-manifest
8888
entries, ownership reversal, unclassified classes, unexpected resources, or
8989
entries owned by:
@@ -98,8 +98,8 @@ scala3/
9898
tasty/
9999
```
100100

101-
The reviewed source-built `pluginApi` JAR has 39 classes and nine Tasty
102-
resources; `pluginTestMarkers` has 38 classes and 36 Tasty resources. Neither
101+
The reviewed source-built `pluginApi` JAR has 45 classes and nine Tasty
102+
resources; `pluginTestMarkers` has 39 classes and 37 Tasty resources. Neither
103103
copies a compiler, Scala library, plugin implementation, handler fixture,
104104
peer artifact, consumer output, or entries owned by the other project. Exact
105105
reviewed identities are recorded in
@@ -167,7 +167,7 @@ Prompt 79 used these categories as the sole filtering authority for an ignored,
167167
deterministic handler-contract-only feasibility artifact. Prompt 80 adopts the
168168
corresponding source boundary and proves that the source-built contract entry
169169
names and uncompressed bytes equal a freshly rendered candidate. It proves the
170-
38 handler-contract classes, metadata carrier, and their nine Tasty resources
170+
44 handler-contract classes, metadata carrier, and their nine Tasty resources
171171
are sufficient to compile and link every current precompiled handler while
172172
excluding repository markers and support. See
173173
[Experimental handler-contract-only artifact feasibility](experimental-handler-contract-only-artifact-feasibility.md).

0 commit comments

Comments
 (0)