본문으로 건너뛰기
피드

Quadratic Micropass Type Inference — 타입 추론 에러 메시지를 인간 사고방식에 맞추는 새로운 알고리즘

backend 약 4분
vote
0
댓글
북마크

코드 순서가 아니라 사용자가 중요시하는 순서로 타입 추론을 수행하는 새 알고리즘 제안. 여러 마이크로패스를 우선순위 순으로 실행해서 에러 메시지가 개발자 직관에 부합하도록 함.

  • 1

    기존 inside-out 추론 방식의 혼란스러운 에러 메시지 문제 해결

  • 2

    9개 마이크로패스를 사용자 사고방식 우선순위로 정렬하여 순차 실행

  • 3

    i7 13700k에서 100 이터레이션 7.79ms 성능, 실용적으로 충분

문제: 타입 추론이 만드는 혼란스러운 에러 메시지

  • 타입 추론이 풍부한 언어들은 에러 메시지가 혼란스러운 경우가 많음. 컴파일러가 타입을 추론하는 과정에서 잘못된 가정을 먼저 하고, 그 가정에 기반한 에러를 보여주기 때문임
  • 예를 들어 fn example(x) -> Point[int]에서 xlog(["origin: ", x])에 넣고 Point(x, x)를 리턴하면, 기존 방식은 코드 순서대로 추론해서 xstring으로 먼저 잡음. 그래서 "expected int, got string" 에러가 뜨는데 — 개발자 입장에서는 xint인 게 훨씬 자연스러움. 리턴 타입이 Point[int]니까

해법: 사용자가 중요하게 여기는 순서로 타입을 추론

  • 코드 순서(top-to-bottom)가 아니라, 사용자가 가장 중요하게 여길 법한 순서로 타입 통합(unification)을 수행하는 알고리즘을 제안함
  • 하나의 큰 추론 패스 대신 여러 개의 마이크로패스로 분리:
    1. known_applications — 함수 파라미터 타입 추론
    2. known_assignments — 할당 대상 타입 추론
    3. known_return_types — 리턴 타입 기반 추론
    4. known_same_as_unifications — 같은 리스트/분기 내 타입 통합
    5. known_record_fields — 레코드 필드 타입 추론
    6. resolve_records — 필드명으로 레코드 타입 결정
    7. less_known_functions — 호출 패턴으로 함수 타입 추론
    8. default_numbers — 숫자 리터럴 기본 타입 결정
    9. default_unknown_to_unit_or_lift — 미추론 타입 처리
  • 리스트 위쪽일수록 사용자 사고방식에 가까운 패스임. 각 패스 실행 후 이전 패스를 다시 돌려서 새로 알게 된 타입 정보가 전파되게 함

왜 "Quadratic"인가

  • 각 패스 후 이전 패스를 전부 다시 돌리니까 이론상 O(n²)임. 하지만 OCaml처럼 작은 함수가 많은 언어에서는 quadratic 특성의 심각도가 줄어듦
  • 벤치마크 (Intel i7 13700k @ 5.3GHz): 100 이터레이션에 7.79ms, 50,000 이터레이션에 2.78초. 캐시된 번역 단위 사용 시 실용적으로 충분한 성능

ℹ️참고

> 에러 생성은 추론 중이 아니라 추론 완료 후 타입 체킹 단계에서 수행됨. 각 패스는 에러를 무시하고 자기가 처리할 수 있는 타입만 건드림. 최종적으로 타입 변수 → 정적 타입 매핑을 만들어서 단순 동등 비교로 타입 체킹

  • 결과: 아까 문제의 예제에서 known_applications 패스가 먼저 돌아가면서 리턴 타입 Point[int]에서 x = int를 추론함. 그래서 에러가 "expected string, got int"로 바뀜 — 개발자 직관에 훨씬 부합하는 메시지

에러 메시지 품질은 컴파일러 UX의 핵심인데, 타입 추론 순서를 '인간이 생각하는 순서'로 바꾸는 접근이 참신함. Rust나 TypeScript처럼 추론이 복잡한 언어에 적용되면 DX가 크게 개선될 수 있음.

댓글

댓글

댓글을 불러오는 중...

backend

잘못된 추상화보다 중복이 낫다는 샌디 메츠의 고전 조언

샌디 메츠는 중복을 없애려다 잘못된 추상화를 만들면 코드가 조건문과 파라미터로 부풀어 더 위험해진다고 말한다. 이미 틀어진 추상화는 억지로 보존하지 말고, 다시 호출부에 인라인해서 중복을 되살린 뒤 현재 요구사항에 맞는 새 구조를 찾는 편이 빠르다는 주장이다.

backend

리눅스 커널, 6년·360개 넘는 패치 끝에 strncpy 제거

리눅스 커널이 오랫동안 버그의 원인이던 strncpy API 사용을 Linux 7.2에서 제거했어. NUL 종료 동작이 직관적이지 않고 불필요한 zero-fill로 성능 문제도 있던 API를 6년 동안 약 362개 커밋으로 걷어낸 작업임.

backend

덕디비는 왜 빠를까: 서버 없는 분석 엔진의 내부 구조 뜯어보기

DuckDB가 단일 바이너리, 인프로세스 실행, 컬럼형 저장, 최적화 패스, Parquet 푸시다운으로 빠른 분석 쿼리를 처리하는 방식을 깊게 설명한 글이다. 6GB Parquet 파일을 노트북에서 바로 SQL로 읽는 경험 뒤에 어떤 설계가 깔려 있는지 따라간다.

backend

피지독, 포스트그레스를 수평 확장시키겠다고 550만 달러 투자 유치

피지독은 포스트그레스 앞단에 프록시를 두고 샤딩과 라우팅을 처리해 수평 확장을 가능하게 하겠다는 오픈소스 프로젝트다. 이미 프로덕션에서 초당 200만 건이 넘는 쿼리를 처리하고, 확인된 규모만 20테라바이트 이상을 샤딩했다고 밝히며 550만 달러 투자를 공개했다.

backend

펜타시스템, EDB 포스트그레SQL로 국내 엔터프라이즈 DB 전환 시장 공략

펜타시스템테크놀러지가 EDB와 파트너 계약을 맺고 국내에 EDB 포스트그레SQL 기반 데이터 플랫폼을 공급한다. 기존 상용 DBMS 정책 변화로 비용 부담이 커진 기업들을 겨냥해, 오픈소스 기반 엔터프라이즈 데이터 플랫폼 전환 수요를 잡겠다는 전략이다. 금융, 공공, 제조, 유통, 클라우드, AI 데이터 분석 환경까지 적용 범위를 넓히려는 움직임이다.