Skip to content

feat!: Add enum type#1518

Merged
nicolaassolini-qntm merged 11 commits intomainfrom
feat/guppy-enum
Mar 18, 2026
Merged

feat!: Add enum type#1518
nicolaassolini-qntm merged 11 commits intomainfrom
feat/guppy-enum

Conversation

@nicolaassolini-qntm
Copy link
Copy Markdown
Contributor

@nicolaassolini-qntm nicolaassolini-qntm commented Feb 19, 2026

This pull request introduces enums in guppy, with all the compilation pipeline required, as well as a refactor to avoid code duplication.

  • Replaced references to StructField with a new, more general CheckedField type across the codebase, allowing for more flexible handling of both struct fields and enum variants in diagnostics and error messages.

  • Improved error messages for attribute access, especially for enums, by distinguishing between "field or method" and "variant or method" in the AttributeNotFoundError.

  • Added support for the instantiation of Enum and the use of Enum methods.

  • Added test cases for Enum

BREAKING CHANGES: renamed guppylang-internals/src/guppylang_internals/tys/printing.py:_visit_OpaqueType_StructType in visit_OpaqueType_StructType_EnumType

BREAKING CHANGES: removed default value for class_type, field of DuplicateFieldError in guppylang_internals/definition/util.py

BREAKING CHANGE: Moved shared parsing logic for classes (parse_py_class, extract_generic_params, try_parse_generic_base, extract_generic_params, params_from_ast) into a new utility module, definition/util.py, and updated both enum.py, struct.py and function.py to use these utilities.

BREAKING CHANGE: Moved error classes and parsing functions from struct.py and function.py (RepeatedTypeParamError, DuplicateFieldError, RedundantParamsError)

BREAKING CHANGE: Defined UncheckedField and CheckedField instead of UncheckedStructField and StructField

Not a guppylang breaking change


BEGIN_COMMIT_OVERRIDE
feat: Add enum type (#1518)
END_COMMIT_OVERRIDE

nicolaassolini-qntm and others added 5 commits February 9, 2026 13:59
…arsing and checking (#1419)

* Added a new module `guppylang_internals/definition/enum.py` containing
`RawEnumDef`, `ParsedEnumDef`, and `CheckedEnumDef`(WIP)
* Added a `guppylang_internals/definition/util.py` module with common
function and classes used by `enum.py`, `struct.py` and `function.py`
* Improved error diagnostics for unexpected statements in enum and
struct definitions by adding contextual help messages

BREAKING CHANGE:
Refactoring and code organization:

* Moved shared parsing logic for classes (`parse_py_class`,
`extract_generic_params`, `try_parse_generic_base`,
`extract_generic_params`, `params_from_ast`) into a new utility module,
`definition/util.py`, and updated both `enum.py`, `struct.py` and
`function.py` to use these utilities.
* Moved error classes and parsing functions from `struct.py` and
`function.py` (`RepeatedTypeParamError`, `DuplicateFieldError`,
`RedundantParamsError`)
* Defined UncheckedField and CheckedField instead of
UncheckedStructField and StructField

---------

Co-authored-by: tatiana-s <tatiana.sedelnikov@quantinuum.com>
Co-authored-by: Mark Koch <48097969+mark-koch@users.noreply.github.com>
# PR 1: Minimal Enum Infrastructure

  

## Summary

  

This PR implements the minimal foundation for enum support with
recursion checking.

  

**Implements**: Issue #1423 (check_not_recursive for enum)

**Related**: Issue #1333 (Enums tracking), Issue #1422 (Future cleanup)

  

## Changes

  

### New Files

- `guppylang-internals/src/guppylang_internals/definition/enum.py` (~300
lines)

-  `ParsedEnumDef`, `CheckedEnumDef` classes

-  `UncheckedEnumVariant`, `EnumVariant` classes

-  `check_not_recursive()` function

  

### Modified Files

-  `guppylang-internals/src/guppylang_internals/tys/ty.py`

- Added `EnumType` class (~50 lines)

- Updated `ParametrizedType` TypeAlias

- Added forward references

  

### Tests

-  `tests/error/enum_errors/test_recursive_minimal.py`

- Manual test for direct recursion detection

  

## What This Enables

  

✅ Basic enum type definitions
✅ Recursion checking (prevents infinite loops)
✅ Type system integration
✅ Foundation for future enum features

  

## What's NOT Included (Future PRs)

  

❌ `@guppy.enum` decorator (PR 3)
❌ Enhanced error messages (PR 2)
❌ Auto-generated constructors (PR 3)
❌ DefId refactoring (PR 4)

  

## Testing

  

```bash

# Run minimal test

python  tests/error/enum_errors/test_recursive_minimal.py

  

# Check for syntax errors

python  -m  py_compile  guppylang-internals/src/guppylang_internals/definition/enum.py

```

  

## Next Steps

  

After this PR:

- PR 2 will add better error handling
- PR 3 will add the decorator and full API
- PR 4 will replace the hacky implementation with DefId approach

```

---------

Co-authored-by: nicolaassolini-qntm <nicola.assolini@quantinuum.com>
Co-authored-by: tatiana-s <tatiana.sedelnikov@quantinuum.com>
Co-authored-by: Mark Koch <48097969+mark-koch@users.noreply.github.com>
Co-authored-by: Craig Roy <craig.roy@quantinuum.com>
Co-authored-by: Craig Roy <croyzor@users.noreply.github.com>
…n enums and structs, added two error tests (#1470)

BREAKING CHANGES
removed default value for `class_type`, field of `DuplicateFieldError`
in `guppylang_internals/definition/util.py`

---------

Co-authored-by: tatiana-s <tatiana.sedelnikov@quantinuum.com>
…1505)

BREAKING CHANGES: renamed `guppylang-internals/src/guppylang_internals/tys/printing.py:_visit_OpaqueType_StructType` in `visit_OpaqueType_StructType_EnumType`



Co-authored-by: tatiana-s <tatiana.sedelnikov@quantinuum.com>
@hugrbot
Copy link
Copy Markdown
Collaborator

hugrbot commented Feb 19, 2026

This PR contains breaking changes to the public Python API.

Breaking changes summary
guppylang-internals/src/guppylang_internals/definition/struct.py:0: UncheckedStructField:
Public object was removed

guppylang-internals/src/guppylang_internals/definition/struct.py:0: StructField:
Public object was removed

guppylang-internals/src/guppylang_internals/definition/struct.py:0: RedundantParamsError:
Public object was removed

guppylang-internals/src/guppylang_internals/definition/struct.py:0: try_parse_generic_base:
Public object was removed

guppylang-internals/src/guppylang_internals/definition/struct.py:0: RepeatedTypeParamError:
Public object was removed

guppylang-internals/src/guppylang_internals/definition/struct.py:0: params_from_ast:
Public object was removed

guppylang-internals/src/guppylang_internals/checker/errors/type_errors.py:130: AttributeNotFoundError.span_label:
Attribute value was changed:
Old: '`{ty}` has no attribute `{attribute}`'
New: '`{ty}` has no {element_name} `{attribute}`'

guppylang-internals/src/guppylang_internals/tys/ty.py:791: ParametrizedType:
Attribute value was changed:
Old: FunctionType | TupleType | OpaqueType | StructType
New: FunctionType | TupleType | OpaqueType | StructType | EnumType


@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 19, 2026

🐰 Bencher Report

Branchfeat/guppy-enum
TestbedLinux
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
tests/benchmarks/test_big_array.py::test_big_array_check📈 view plot
🚷 view threshold
694,387.79 µs
(-0.93%)Baseline: 700,885.50 µs
735,929.78 µs
(94.36%)
tests/benchmarks/test_big_array.py::test_big_array_compile📈 view plot
🚷 view threshold
1,854,297.87 µs
(-0.61%)Baseline: 1,865,766.49 µs
1,959,054.81 µs
(94.65%)
tests/benchmarks/test_big_array.py::test_big_array_executable📈 view plot
🚷 view threshold
8,020,212.00 µs
(+0.22%)Baseline: 8,002,520.26 µs
8,402,646.27 µs
(95.45%)
tests/benchmarks/test_ctrl_flow.py::test_many_ctrl_flow_check📈 view plot
🚷 view threshold
49,214.70 µs
(-56.76%)Baseline: 113,828.95 µs
119,520.40 µs
(41.18%)
tests/benchmarks/test_ctrl_flow.py::test_many_ctrl_flow_compile📈 view plot
🚷 view threshold
104,295.60 µs
(-1.04%)Baseline: 105,388.64 µs
110,658.07 µs
(94.25%)
tests/benchmarks/test_ctrl_flow.py::test_many_ctrl_flow_executable📈 view plot
🚷 view threshold
596,349.55 µs
(-1.15%)Baseline: 603,269.57 µs
633,433.05 µs
(94.15%)
tests/benchmarks/test_prelude.py::test_import_guppy📈 view plot
🚷 view threshold
51.81 µs
(-3.38%)Baseline: 53.62 µs
56.30 µs
(92.01%)
🐰 View full continuous benchmarking report in Bencher

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 97.75910% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.53%. Comparing base (436d032) to head (b99c771).

Files with missing lines Patch % Lines
...ternals/src/guppylang_internals/definition/enum.py 97.26% 4 Missing ⚠️
...ternals/src/guppylang_internals/definition/util.py 97.39% 3 Missing ⚠️
.../guppylang_internals/checker/errors/type_errors.py 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1518      +/-   ##
==========================================
+ Coverage   93.43%   93.53%   +0.10%     
==========================================
  Files         128      130       +2     
  Lines       12056    12291     +235     
==========================================
+ Hits        11264    11496     +232     
- Misses        792      795       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nicolaassolini-qntm nicolaassolini-qntm marked this pull request as ready for review February 19, 2026 12:26
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 20, 2026

🐰 Bencher Report

Branchfeat/guppy-enum
TestbedLinux
Click to view all benchmark results
Benchmarkhugr_bytesBenchmark Result
bytes x 1e3
(Result Δ%)
Upper Boundary
bytes x 1e3
(Limit %)
hugr_nodesBenchmark Result
nodes
(Result Δ%)
Upper Boundary
nodes
(Limit %)
tests/benchmarks/test_big_array.py::test_big_array_compile📈 view plot
🚷 view threshold
141.79 x 1e3
(-0.01%)Baseline: 141.81 x 1e3
143.23 x 1e3
(99.00%)
📈 view plot
🚷 view threshold
6,620.00
(0.00%)Baseline: 6,620.00
6,686.20
(99.01%)
tests/benchmarks/test_ctrl_flow.py::test_many_ctrl_flow_compile📈 view plot
🚷 view threshold
17.57 x 1e3
(-0.09%)Baseline: 17.59 x 1e3
17.76 x 1e3
(98.93%)
📈 view plot
🚷 view threshold
581.00
(0.00%)Baseline: 581.00
586.81
(99.01%)
🐰 View full continuous benchmarking report in Bencher

Copy link
Copy Markdown
Contributor

@tatiana-s tatiana-s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this has mostly been reviewed already, looks good to me besides a few smaller comments - regarding the PR title, I think something like "feat!: Add enum type" seems better for the release summary as the rest of the current title is a bit redundant

Comment thread guppylang-internals/src/guppylang_internals/definition/enum.py Outdated
Comment thread guppylang-internals/src/guppylang_internals/definition/enum.py Outdated
Comment thread guppylang-internals/src/guppylang_internals/definition/struct.py
Comment thread guppylang/src/guppylang/decorator.py Outdated
Comment thread guppylang/src/guppylang/decorator.py
Comment thread tests/error/enum_errors/bad_variant_def1.err Outdated
Comment thread guppylang-internals/src/guppylang_internals/tys/ty.py Outdated
@nicolaassolini-qntm nicolaassolini-qntm changed the title feat!: added Enum to guppy, including a new type, with parsing, checking and compilation feat!: Add enum type Mar 18, 2026
@nicolaassolini-qntm nicolaassolini-qntm added this pull request to the merge queue Mar 18, 2026
Merged via the queue into main with commit 57c75db Mar 18, 2026
12 checks passed
@nicolaassolini-qntm nicolaassolini-qntm deleted the feat/guppy-enum branch March 18, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants