Took a crack at it, it's big and ugly and I'm sure I missed some edge cases, but:
<https://play.nim-lang.org/#ix=2wrM> proc ifReturn(a,b,fld:NimNode):NimNode = newIfStmt( (infix(newDotExpr(a,fld),"!=",newDotExpr(b,fld)), nnkReturnStmt.newTree(newLit(false)) ) ) macro equalsImpl[T:object](a,b:T): untyped= let tImpl = a.getTypeImpl result = newStmtList() result.add quote do: result = true let records = tImpl[2] records.expectKind(nnkRecList) for field in records: case field.kind of nnkIdentDefs: result.add(ifReturn(a,b,field[0])) of nnkRecCase: let discrim = field[0][0] result.add(ifReturn(a,b,discrim)) var casestmt = newNimNode(nnkCaseStmt) casestmt.add newDotExpr(a,discrim) for ofbranch in field[1..^1]: case ofbranch.kind of nnkOfBranch: let testVal = ofbranch[0] let reclst = ofbranch[1] expectKind(reclst,nnkRecList) var ifstmts = newStmtList() for idDef in reclst: ifstmts.add(ifReturn(a,b,idDef[0])) casestmt.add nnkOfBranch.newTree(testVal,ifstmts) of nnkElse: let reclst = ofbranch[0] expectKind(reclst,nnkRecList) var ifstmts = newStmtList() for idDef in reclst: ifstmts.add(ifReturn(a,b,idDef[0])) casestmt.add nnkElse.newTree(ifstmts) else: error "Unsupported branch" & ofbranch.repr result.add casestmt else: error "Unsupported kind" & field.repr #echo result.repr proc `==`*[T:object](a,b:T):bool = equalsImpl(a,b) Run