Rust와 Fil-C를 잇는 메모리 안전 외부 함수 인터페이스가 필요한 이유와, 이를 함께 구축하자는 제안입니다.
Rust의 C FFI는 수십 년간 축적된 유용한 소프트웨어에 접근하게 해 주지만, 이 거래의 방향은 거꾸로다.
우리는 Rust를 사용해 컴파일 시점에 메모리 안전성을 증명한다. 그러고 나서 unsafe 경계를 건너, 어느 언어도 강제할 수 없는 계약을 C 라이브러리가 지킬 것이라고 신뢰한다. 기존 코드는 저렴한 경로로 남고, 이를 다시 작성하는 일은 비싼 선택이 된다.
Fil-C는 더 흥미로운 거래를 제안한다. 이 도구는 C와 C++를 능력, 실행 시간 검사, 동시성 가비지 컬렉터와 함께 다시 컴파일한다. 메모리 안전성 위반은 익스플로잇이 되는 대신 패닉을 일으킨다. 기존 소프트웨어는 종종 소스 변경이 거의 또는 전혀 필요 없지만, 안전성의 비용을 실행 시간에 치른다.
나는 Fil-C ABI를 구사하는 Rust FFI를 원한다.
첫 버전은 의도적으로 범위를 좁힐 수 있다. 스칼라 값, 복사된 문자열과 슬라이스, 불투명 핸들만 지원하는 것이다. 안전한 Rust 래퍼를 생성하고, 완전한 C 의존성 그래프를 Fil-C로 컴파일하며, 일반적인 안전하지 않은 C로 되돌아가는 탈출구는 제공하지 않는다. 공유 메모리는 나중에 추가할 수 있다. 다리가 Fil-C에 Rust가 신뢰성 있게 철회할 수 있는 능력을 제공할 수 있게 된 뒤에 말이다.
이는 bindgen의 새로운 선택지가 아니다. Fil-C는 C와는 소스 호환이 되지만 의도적으로 ABI 호환은 되지 않으며, 일반적인 Rust extern "C"는 Fil-C가 Yolo-C라고 부르는 ABI를 사용한다. 이 다리를 구축하려면 Rust, Fil-C, 또는 생성된 스텁 한 쌍이 Fil-C의 보장을 잃지 않고 값을 교환하도록 가르쳐야 한다. 쉬운 일이었다면 이미 존재했을 것이다.
이 스택의 중요한 한 부분은 이미 형태를 갖춰 가고 있다. filnix는 Fil-C를 Nix 크로스 컴파일 플랫폼으로 패키징하며, 100개가 넘는 nixpkgs 패키지용 포트를 보유하고 있다. Fil-C를 플랫폼으로 취급한다는 것은 Nix가 일반 C를 실수로 여기에 연결하는 대신 Fil-C ABI를 위해 전이적 의존성 클로저를 다시 빌드한다는 뜻이다. filnix는 아직 Rust 다리가 아니지만, 이를 구축할 수 있는 재현 가능한 도구 모음, 패키지 세계, 시험 환경을 제공한다.
Zig는 다른 방향에서 같은 문제에 접근하고 있다. Andrew Kelley는 Fil-C에서 영감을 받은 선택적 fil ABI를 제안했다. 이는 Zig 컴파일러와 표준 라이브러리에서 독립적으로 구현되며, Zig 프로그램과 그 전체 C 및 C++ 의존성 트리를 실행 시간 메모리 안전성과 함께 컴파일하는 것을 목표로 한다. 이는 Rust 다리가 진입해야 할 세계와 놀랄 만큼 가깝다.
하지만 그 결과는 우리에게 정확히 올바른 유인을 제공할 것이다.
우리는 컴파일 시점 안전성을 위해 Rust를 사용하고, 그다음 C 사용에 대해 성능 페널티를 지불할 수 있다.
기존 라이브러리를 유지하면 메모리 안전성은 유지되지만, 모든 포인터 연산이 검사되고 그 메모리는 가비지 컬렉션에 참여한다. 뜨거운 경로를 Rust로 다시 작성하면 그 검사는 정적 검사가 되므로 부담금은 사라진다. C는 영구적인 빠른 경로가 아니라 안전한 호환성 경로가 된다.
여기서 “100% 안전”은 지원되는 전체 경계에 걸친 메모리 안전성을 뜻하며, 논리 버그, 교착 상태, 나쁜 API가 없다는 뜻은 아니다. 그 경계가 어려운 부분이다. Fil-C는 현재 전체 프로그램과 그 의존성이 자신의 ABI를 사용해야 한다고 요구한다. 이 프로젝트는 일반 C와의 상호운용성도 비목표로 여긴다. Rust 다리는 그 전체 세계 보장을 보존해야 하며, 그 안에 Yolo 모양의 구멍을 조용히 뚫어서는 안 된다.
나는 extern "fil-c"를 원한다. 빠른 경로에는 Rust를, 안전한 경로에는 오래된 C를, 그리고 마이그레이션을 끝낼 성능상의 이유를 원한다.
여러 거의 호환되는 섬 대신 생태계 간 협업도 보고 싶다. Fil-C에는 능력 모델과 작동하는 실행 환경이 있다. Rust에는 컴파일 시점 안전성이 있다. Zig는 Fil-C에서 영감을 받은 ABI를 탐색하고 있다. Nix와 filnix는 완전한 의존성 그래프를 다시 빌드하고 시험할 수 있다. 이 문제는 네 공동체의 가장 뛰어난 사람들이 한 방에 모일 가치가 있다.
그러니 여기 초대장이 있다. 내년에 Lanzarote에서 열리는 OceanSprint에 합류해 함께 만들자. filnix를 구축하고 있는 Mikael Brockman은 이미 수락했다.
누가 더 합류할 것인가?