IntersectMBO / IntersectMBO/plutus
BuiltinCasing crashes on GHC.Prim.Addr# when a join point exposes Data in its type
- Dominant language
- Haskell
- Stars
- 1.6k
- Forks
- 508
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 22
Description
The plugin crashes when compiling a function with `datatypes=BuiltinCasing` if the GHC Core contains a join point with `PlutusCore.Data.Data` in its type:
```
Context: Compiling type: PlutusCore.Data.Data
Context: Compiling data constructor type: PlutusCore.Data.B
Context: Compiling type: Data.ByteString.Internal.Type.ByteString
Context: Compiling data constructor type: Data.ByteString.Internal.Type.BS
Context: Compiling type: GHC.Prim.Addr#
Error: Unsupported feature: Type constructor: GHC.Prim.Addr#
```
## What happens
`BuiltinData` wraps `PlutusCore.Data.Data`. Normally the plugin treats `BuiltinData` as a builtin and never looks inside. But GHC's simplifier can produce join points where `Data` appears naked in the type signature:
```
$j :: Data -> BuiltinUnit
```
The plugin with BuiltinCasing tries to compile `Data` as a regular ADT, follows `B ByteString` → `BS Addr# Int`, and crashes because `Addr#` has no Plutus Core equivalent.
## Reproduction
Branch with a failing test: [`yura/builtin-casing-addr-joinpoint`](https://github.com/IntersectMBO/plutus/tree/yura/builtin-casing-addr-joinpoint)
Minimal trigger — `caseList'` applied twice to the same value in a separate module without BuiltinCasing:
```haskell
failsToCompile :: BuiltinData -> BuiltinUnit
failsToCompile bd =
case toBuiltinData (firstOf items) of
_ -> case toBuiltinData (firstOf items) of
_ -> unitval
where
items = unsafeFromBuiltinData bd
firstOf = caseList' Nothing (\(h :: BuiltinData) _t -> Just h)
```
Compiled from `Spec.hs` (which has `datatypes=BuiltinCasing`) via `$$(compile [||Lib.failsToCompile||])`.
```bash
cabal build plutus-tx-plugin-tests
```
No dependencies beyond `plutus-tx` and `plutus-tx-plugin`.
## Originally discovered as
A cross-library compilation failure: a Plinth validator using `findOwnInput` + `getContinuingOutputs` from `plutus-ledger-api` crashed when compiled with BuiltinCasing. `getContinuingOutputs` calls `findOwnInput` internally, producing the double-call pattern that triggers the join point.
Contributor guide
Assessment
This issue has not been assessed yet.