Record spread that copies a mutable field is generalized (unsound)
メンテナーはふだん 1 日以内に返信
関連するプルリクエストがすでにマージされています。
- #9158 @cknitt による — マージ済み
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 38/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- ocaml
- 領域
- compilers
調査の方向性
The unsound generalization comes from the value restriction in Typecore.is_nonexpansive, specifically how it handles record literals with a spread: written mutable fields are checked, but copied ones are not. Start there and compare with the handling of a plain record literal, then reproduce with the cell<'a> snippet from the issue using an external base. Done means a spread that copies a mutable field is treated as expansive, the example no longer type-checks, and existing type tests still pass.
索引モデルが issue の本文から書いたものです。
説明
A record literal with a spread, {...base, field: value}, has its type generalized even when it copies a mutable field from base. The literal allocates a fresh record with that mutable field, so one binding can be written at one type and read at another:
type cell<'a> = {tag: int, mutable value: option<'a>}
@val external base: cell<'a> = "base"
let copy = {...base, tag: 1}
copy.value = Some(1)
let s: option<string> = copy.value
This compiles on master (8e26a9ca69) and generates:
let init = base;
let copy = {
tag: 1,
value: init.value
};
copy.value = 1;
let s = copy.value;
so s, typed option<string>, holds the number 1. The same happens with optional mutable fields ({tag?: int, mutable value?: 'a}).
Cause
The value restriction (Typecore.is_nonexpansive) checks a spread literal's written fields for mutability and requires the spread expression to be non-expansive, but treats the fields it copies from the spread as harmless. A spread literal allocates every field of the record, so a mutable field makes it expansive whether it is written or copied, just like a literal without a spread (#9149, #9152).
base has to be a polymorphic, non-expansive value of a record type with a mutable field. A record literal of such a type is itself expansive, so in practice base is an external, for example a binding to a default options object: @val external defaults: options<'a> followed by {...defaults, x: 1}.
- 主要言語
- OCaml
- スター
- 7.5k
- フォーク
- 484
- 平均マージ
- 17時間 2分
- マージ済み PR(30日)
- 249
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
rescript-lang/rescript のほかの issue
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
rescript-lang/rescript#9151 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
rescript-lang/rescript#9130 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 1〜2日 初心者へのやさしさ 55/100
rescript-lang/rescript#9122 ·
メンテナーはふだん 1 日以内に返信
-
Dev dependencies interacting対応中かも @CarlOlson が 6 日前に担当しました。 オープン
難易度 4/5 1〜2日 初心者へのやさしさ 25/100
rescript-lang/rescript#9089 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
rescript-lang/rescript#9074 ·
メンテナーはふだん 1 日以内に返信
rescript-lang/rescript の issue をすべて見る
似ている issue
-
Won't Fix
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
microsoft/TypeScript#65107 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
needs-triage type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
pytorch/executorch#24434 ·
メンテナーはふだん 1 日以内に返信
-
confirmed crash-on-valid regression:24
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
llvm/llvm-project#237977 ·
メンテナーはふだん 1 日以内に返信