LoweringEq

scalus.compiler.sir.lowering.LoweringEq
object LoweringEq

Equality lowering — recognizes equalsRepr(a, b) (and the FunctionalInterface Eq path) and emits the most efficient comparison for the lhs/rhs representation pair.

Dispatch order in generateEqualsForRepr:

  • Primitives (Integer, ByteString, String): specialized builtins
  • BLS curve elements: bls12_381_G1/G2_equal
  • BLS MlResult, Fun: compile error (no equality)
  • @UplcRepr(UplcConstr) products: field-by-field via generateProdUplcConstrEquals
  • @UplcRepr(UplcConstr) sums: native letrec via generateSumUplcConstrEquals
  • Everything else: convert to Data, equalsData

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
LoweringEq.type

Members list

Value members

Concrete methods

Generate equalsData after converting both values to their Data representation.

Generate equalsData after converting both values to their Data representation.

Attributes

Generate repr-specific equality comparison.

Generate repr-specific equality comparison.

Dispatches based on resolved type and representation; see LoweringEq doc for the dispatch order.

Attributes

Generate Case-based field comparison for ProdUplcConstr values. Each field is extracted via genSelect and compared recursively.

Generate Case-based field comparison for ProdUplcConstr values. Each field is extracted via genSelect and compared recursively.

Value parameters

knownType

concrete type for field extraction (may differ from lhs.sirType when lhs has TypeVar type but the concrete type is known from annotation)

Attributes

Native equality for SumUplcConstr-represented values.

Native equality for SumUplcConstr-represented values.

Emits letrec eqSum(a, b) = case a of ... where each variant branch matches b against the same variant tag (returning False on mismatch) and ANDs field comparisons. For fields whose substituted type matches the outer sum type, the recursive eqSum reference is used instead of recursing into a fresh generateEqualsForRepr (which would emit a duplicate letrec for self-referential types like List).

For non-recursive sums (e.g., Option) the letrec is harmless overhead — the function never references itself.

Attributes

def isEqIntrinsicApp(app: Apply): Boolean

Check if this is a fully-applied FunctionalInterface call with known Eq semantics.

Check if this is a fully-applied FunctionalInterface call with known Eq semantics.

Attributes

def isEqualsReprApp(app: Apply): Boolean

Check if this is equalsRepr(a, b) — the outer Apply of curried application. Handles both Apply(Apply(ExternalVar, a), b) and Apply(Apply(TypeApply(ExternalVar, A), a), b) (when type parameter is present).

Check if this is equalsRepr(a, b) — the outer Apply of curried application. Handles both Apply(Apply(ExternalVar, a), b) and Apply(Apply(TypeApply(ExternalVar, A), a), b) (when type parameter is present).

Attributes

Lower an Eq application using repr-specific equality.

Lower an Eq application using repr-specific equality.

The plugin annotates Apply nodes for FunctionalInterface types with "functionalInterfaceType". For Eq, we always inline an optimal comparison based on the argument representation instead of calling the Eq function. This is sound when the user's Eq instance satisfies the equivalence-relation contract (reflexive / symmetric / transitive AND structurally consistent — i.e. a === b iff a.toData == b.toData).

Custom Eq instances that violate this contract (notably Eq.keyPairEq[A, B] which compares only _1, ignoring _2) are buggy by definition: any code that relies on === to mean "structurally equal" — like List.distinct — will misbehave. We surface this by emitting a compile-time warning whenever the Eq instance is not provably one of the standard type-default forms (Eq.derived[T], summon[Eq[T]], or a prelude given Eq[...]). The warning steers users toward derived/summoned forms; the optimization itself proceeds uniformly in either case to keep the perf characteristics consistent.

Attributes

Lower equalsRepr(a, b) — picks the optimal comparison for the resolved types/reprs.

Lower equalsRepr(a, b) — picks the optimal comparison for the resolved types/reprs.

Attributes

Concrete fields

val EqTypeName: String
val EqualsReprName: String