Improve composition diagnostics

This commit is contained in:
2026-06-22 17:37:51 +09:00
parent 8b3df21cfa
commit cc5ab63922
10 changed files with 518 additions and 175 deletions
@@ -117,3 +117,9 @@ Abstract { constraints, default: None }
materialize は default を採用する唯一の段階である。
通常評価中に明示値が得られた場合、default は採用されない。
## Diagnostic context
Composition and materialization keep source spans for object fields, constraints, defaults, and thunks where possible.
When a conflict occurs, the diagnostic should identify the operation span and related participant spans, such as the left field, right field, constraint, or default value.
For object materialization errors, diagnostics also include the field path being processed when known.
@@ -10,10 +10,19 @@ Diagnostic {
kind: DiagnosticKind
span: Span
message: String
notes: Vec<Note>
labels: Vec<DiagnosticLabel>
}
DiagnosticLabel {
span: Span
message: String
}
```
`span` は primary location を示す。
`labels` は同じ error に関係する追加 location を示す。
合成や materialize の失敗では、衝突した constraint、value、default、または処理中 field path を label に含める。
代表的な diagnostic kind:
- syntax error
@@ -38,6 +47,18 @@ Result<RuntimeValue, Diagnostic>
これにより、制約違反、未定義識別子、循環依存、import 失敗などが通常値として流れることを避ける。
## 合成と materialize の diagnostic
合成や materialize の失敗は、以下を示す。
1. どの段階で失敗したか: composition、patch、materialization
2. どの field path を処理中だったか
3. どの constraint、value、default が衝突したか
4. なぜ合成または materialize できないか
例えば default が constraint を満たさない場合は、constraint の位置と default value の位置の両方を label として持つ。
object field の合成で concrete value が衝突する場合は、左辺 field と右辺 field の位置を label として持つ。
## `try / catch` は core に入れない
汎用 `try / catch` は core に入れない。
@@ -47,21 +68,6 @@ fallback は有限で明示的な仕組みに限定する。
- `default`: 未指定値の fallback。
- `match`: 有限 pattern に基づく分岐。
- optional import: ファイル不存在など、限定された失敗だけを fallback 可能にする候補。
- optional field access: field 不在だけを fallback 可能にする候補。
- union / tagged schema: 複数 schema の選択を明示的に表す将来候補。
## optional fallback の扱い
optional import や optional field access を導入する場合も、捕捉できる失敗は限定する。
例として optional import は、ファイル不存在だけを fallback 可能にし、parse error や import 先の制約違反は diagnostic として報告する方がよい。
```text
optional import:
file not found -> fallback
parse error -> diagnostic
eval error -> diagnostic
```
この方針により、fallback は通常の値選択として扱い、エラー内容に依存した実行時分岐は避ける。
Decodal は `unknown` / `any` を持たないため、field 不在や未解決 identifier を fallback 可能な通常値として扱わない。
それらは diagnostic として報告する。
+11 -2
View File
@@ -36,7 +36,11 @@ object は concrete structure として扱う。
```text
ObjectValue:
fields: Map<Symbol, ThunkId>
fields: Map<Symbol, ObjectField>
ObjectField:
value: ThunkId
span: Span
```
例えば以下の schema object は、object 自体は concrete だが、field の値は abstract value になる。
@@ -61,9 +65,14 @@ Concrete(Object {
```text
AbstractValue {
constraints: Vec<Constraint>
constraints: Vec<ConstraintEntry>
default: Option<ThunkId>
}
ConstraintEntry {
constraint: Constraint
span: Span
}
```
`default``AbstractValue` にだけ存在する。