docs(base): Override 서브타입 Modifier 타입 시그니처 미검증 기록

FrameModifier/GuiObjectModifier처럼 서브타입 관계인 Modifier끼리
Override로 섞을 때 필드 setter 리턴 타입이 갈려 구조적 서브타이핑이
안 풀릴 수 있음을 modifier-plan.md 9-2번에 남기고, 실 Luau 테스트가
필요한 항목으로 ROADMAP.md M7에 추가.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
qwreey 2026-08-07 16:01:05 +09:00
parent 18d6942366
commit 4dd7659620
Signed by: qwreey
GPG key ID: D28DB79297A214BD
2 changed files with 34 additions and 0 deletions

View file

@ -389,6 +389,36 @@ Modifier 값을 변수/모듈 상수로 만들어 재사용하는, 기존에도
근거 없는 선제 최적화라 설계하지 않음 — CLAUDE.md의 "드문 오용/가상 미래
요구까지 방어/최적화하려고 구조를 복잡하게 만들지 않는다" 원칙과 동일.
### 9-2. `Override`가 서로 다른(그러나 상하위 관계인) Modifier 타입을 섞는 경우 —
타입 시그니처 미확정, 실 Luau 테스트 필요 (2026-08-07 다섯 번째 세션 후속)
**문제**: Modifier 타입은 위 4번 절 "FrameModifier 타입" 언급대로 Roblox
클래스별로 생성기가 뽑아내는 flat 타입인데, 그 밑의 Roblox 클래스 자체엔
서브타입 관계가 있음(`Frame`이 `GuiObject`의 서브클래스) — 그럼 생성된
`FrameModifier``GuiObjectModifier`의 서브타입이어야 자연스럽고, 실제로
`Modifier.Override(guiObjectMod, frameMod)`처럼 공통 상위 클래스 스타일
프리셋과 하위 클래스 전용 보정을 섞어 합치는 패턴이 필요해 보임(사용자
지적, 2026-08-07).
**막히는 지점**: 필드 setter 메소드(`:FontSize` 류)는 각 타입마다 반환
타입이 자기 자신(`self`, 즉 `FrameModifier``FrameModifier`를,
`GuiObjectModifier``GuiObjectModifier`를 리턴)이라, 같은 이름의 메소드
필드끼리 리턴 타입이 갈려서 단순 구조적 서브타이핑만으로는 안 풀릴 가능성이
있음.
**후보안(미검증)**: 같은 이름의 메소드 필드는 리턴 타입이 다르니 그냥
`any`로 뭉개고, 나머지(메소드가 아닌 순수 데이터 필드) 쪽만 `[string]: nil`
인덱스 시그니처 조건이 성립하면 통과시키는 식으로 서브타입 호환을 흉내낼 수
있는지 — 이게 실제로 Luau 솔버에서 받아들여지는 타입 구성인지는 추론만으로
결론 낼 수 없고 실제 코드로 테스트해봐야 함(M0가 이미 검증 대상으로 삼은
"추론만으로 확정하고 실제 Luau로 부딪혀본 적 없는 것"과 같은 성격의 모호함).
**당장의 fallback**: 위 후보안이 Luau에서 실제로 안 먹히는 걸로 확인되면,
`Modifier.Override`의 타입 시그니처를 일단 `Override(...: any): any`류로
느슨하게 열어 정적 체크를 포기 — 이건 임시 처치로 명시하고, M7 실제 구현
시점에 실 테스트 결과에 따라 다시 좁히는 걸 목표로 로드맵에 남김
(`ROADMAP.md` M7).
**`:Peek<<T>>(key): T | State<T> | nil`** — Modifier 필드를 확정하지
않고 그대로 읽는 접근자. 이름을 `Get`이 아니라 `Peek`로 정한 이유: 이
프로젝트 전역에서 `State:Get()`은 "확정한다"(pull + recompute + 최종값

View file

@ -94,6 +94,10 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
- [ ] flatten-before-dispatch, immutable `table.clone` 체이닝
- [ ] `Modifier.Override(mod1, mod2, ...)`(가칭, 구 `Merge`) — 필드별 raw
덮어쓰기, 특별한 State/함수 분기 불필요(`modifier-plan.md` 9번)
- [ ] `Override`가 서브타입 관계인 서로 다른 Modifier 타입(예: `FrameModifier`/
`GuiObjectModifier`)을 섞을 때의 타입 시그니처 실 Luau 테스트
(`modifier-plan.md` 9-2번, 미검증 — 안 되면 일단 `Override(...: any):
any`로 느슨하게 열어두고 이 항목으로 되돌아올 것)
- [ ] `State<Modifier>` 조합 타입 차단 확인(`modifier-plan.md` 7번, UB 확정)
- [ ] `:Apply(factory)` 팩토리 함수 체이닝(`modifier-plan.md` 8번, 예약 키
`Apply`가 제네릭 `__index` 필드 setter와 안 겹치는지 확인)