Skip to content

feat: add C3 linearization printer for inheritance analysis#2917

Merged
dguido merged 5 commits intocrytic:masterfrom
ep0chzer0:feature/c3-linearization-printer
Jan 20, 2026
Merged

feat: add C3 linearization printer for inheritance analysis#2917
dguido merged 5 commits intocrytic:masterfrom
ep0chzer0:feature/c3-linearization-printer

Conversation

@ep0chzer0
Copy link
Copy Markdown
Contributor

Summary

Fixes #2784

Adds a new printer that displays the C3 linearization order for contract inheritance, helping developers understand:

  • Method resolution order (MRO) - Which implementation is called
  • Constructor execution order - Important for proper initialization
  • Super call resolution - Which parent implementation super refers to

Features

  • Shows linearization order with contract type labels (SELF/BASE/INHERITED)
  • Displays source file locations for each contract
  • Shows constructor presence (✓/✗) for each contract
  • Lists constructor execution order (reverse of linearization)
  • Outputs both human-readable format and structured JSON

Example Output

C3 Linearization for D
======================================
  0. [SELF]       D (diamond.sol:42)  [constructor: ✓]
  1. [BASE]       C (diamond.sol:32)  [constructor: ✓]
  2. [BASE]       B (diamond.sol:21)  [constructor: ✓]
  3. [INHERITED]  A (diamond.sol:7)   [constructor: ✓]

  Constructor Execution Order:
    1. A.constructor()
    2. B.constructor()
    3. C.constructor()
    4. D.constructor()

Usage

slither . --print c3-linearization

Test Plan

  • Added test with diamond inheritance pattern (A <- B, A <- C, B,C <- D)
  • Verifies linearization order matches expected C3 algorithm output
  • Verifies constructor execution order is reverse of linearization

@ep0chzer0 ep0chzer0 requested a review from smonicas as a code owner January 16, 2026 12:53
@ep0chzer0 ep0chzer0 force-pushed the feature/c3-linearization-printer branch 2 times, most recently from e6c6dd1 to aae6a83 Compare January 16, 2026 23:28
Copy link
Copy Markdown
Member

@dguido dguido left a comment

Choose a reason for hiding this comment

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

Code Review: C3 Linearization Printer

Reviewing: PR #2917 - feat: add C3 linearization printer for inheritance analysis

Summary

This PR adds a useful C3 linearization printer that addresses the core requirements of issue #2784. The implementation is clean and follows existing printer patterns well. A few issues worth addressing:


Critical Issues (Confidence: 90+)

1. WIKI URL uses trailofbits instead of crytic (Confidence: 92)

File: slither/printers/inheritance/c3_linearization.py, line 17

The codebase is migrating WIKI URLs from trailofbits/slither to crytic/slither. The existing inheritance.py uses trailofbits, but the newer constructor_calls.py uses crytic. For consistency with the current repository ownership, consider:

# Current:
WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#c3-linearization"

# Suggested:
WIKI = "https://github.com/crytic/slither/wiki/Printer-documentation#c3-linearization"

2. Potential IndexError when source_mapping.lines is empty (Confidence: 85)

File: slither/printers/inheritance/c3_linearization.py, line 56

The code accesses c.source_mapping.lines[0] without checking if lines is non-empty. While rare, lines can be an empty list:

# Current:
if c.source_mapping:
    source_loc = f" ({c.source_mapping.filename.short}:{c.source_mapping.lines[0]})"

# Suggested:
if c.source_mapping and c.source_mapping.lines:
    source_loc = f" ({c.source_mapping.filename.short}:{c.source_mapping.lines[0]})"

Important Issues (Confidence: 80-89)

3. Lambda used for identity function (Confidence: 82)

File: slither/printers/inheritance/c3_linearization.py, line 52

Using a lambda for an identity function is functional but could be cleaner:

# Current:
color_fn = lambda x: x  # no color for inherited

# Suggested (avoid lambda assignment per PEP 8):
def identity(x):
    return x
color_fn = identity
# Or simply inline the logic to avoid the function call

Suggestions (Not blocking)

  1. Consider adding start_line to JSON output - The JSON includes source filename but not the line number, which could be useful for tooling.

  2. Test coverage - The test verifies the diamond pattern well. Consider adding a test case for contracts without constructors to ensure the empty constructor handling works correctly.

  3. Issue #2784 scope - The issue requested several advanced features (verbose mode, conflict detection, super resolution). This PR implements the core functionality, which is a reasonable first step. Those could be follow-up enhancements.


Positive Observations

  • Clean implementation following existing printer patterns
  • Good use of contract.is_interface to skip interfaces (per CLAUDE.md guidance)
  • JSON output structure is well-designed
  • Test case covers the classic diamond inheritance pattern
  • Constructor execution order display is a nice touch

Overall, this is a solid contribution. The two issues above (WIKI URL and potential IndexError) should be addressed before merging.

@dguido
Copy link
Copy Markdown
Member

dguido commented Jan 20, 2026

PR Review Summary

Research Findings

PR Purpose: This PR adds a new C3 linearization printer (c3-linearization) that displays the method resolution order (MRO) for contract inheritance, addressing issue #2784. The printer shows:

  • Linearization order with contract type labels (SELF/BASE/INHERITED)
  • Source file locations for each contract
  • Constructor presence indicators
  • Constructor execution order (reverse of linearization)

The implementation correctly leverages contract.inheritance which already contains the C3 linearized order in Slither.

Test Status

All printer tests pass after merging master:

  • test_c3_linearization_printer PASSED
  • test_inheritance_graph_printer PASSED
  • test_slithir_printer PASSED
  • test_inheritance_text_printer PASSED

The failing unit tests (Vyper-related) are pre-existing and unrelated to this PR - they fail due to missing Vyper installation in the test environment.

Code Review Issues Found and Fixed

All issues from the initial review by @dguido have been addressed:

  1. WIKI URL (line 18): Changed from trailofbits to crytic to match current repository ownership.

  2. Potential IndexError (line 56-57): Added guard for empty source_mapping.lines list.

  3. Lambda assignment (line 55): Removed PEP 8 violation by inlining the color logic directly.

  4. Additional improvements made:

    • Added type hints to match AbstractPrinter.output() signature
    • Replaced unicode checkmark/x with ASCII +/- for cross-platform compatibility
    • Removed unused variable ctor in constructor iteration
    • Simplified docstring format

Merge Readiness

Ready to merge after the author applies these changes. The implementation is solid and follows existing printer patterns well. The test coverage is appropriate for a new printer.

The suggested fixes have been prepared and tested locally - I can provide a patch or diff if helpful.

@ep0chzer0 ep0chzer0 force-pushed the feature/c3-linearization-printer branch from aae6a83 to 59e7521 Compare January 20, 2026 09:45
Add a new printer that displays the C3 linearization order for contract
inheritance. This helps developers understand the method resolution order
(MRO), constructor execution order, and super call resolution.

Features:
- Shows linearization order with contract type labels (SELF/BASE/INHERITED)
- Displays source file locations
- Shows constructor presence for each contract
- Lists constructor execution order (reverse of linearization)
- Outputs both human-readable format and structured JSON

Fixes crytic#2784
- Update WIKI URL from trailofbits to crytic
- Check source_mapping.lines is non-empty before accessing [0]
- Replace lambda with named function for identity (PEP 8 E731)

Addresses review feedback from @dguido
@ep0chzer0 ep0chzer0 force-pushed the feature/c3-linearization-printer branch from 7a755fe to 5ccb6e9 Compare January 20, 2026 16:46
- Add defensive null check for `filename` before accessing `.short`
- Extract identity function outside loop for cleaner code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@dguido dguido merged commit 7493778 into crytic:master Jan 20, 2026
35 checks passed
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.

Enhancement: Add C3 Linearization Order Printer

2 participants