課題1: ライフタイムの形式的理解
マンダトリー要件(80点)
問題1: ライフタイムの数学的定義(15点)
1.1 基本概念(5点)
以下の質問に答えなさい:
- ライフタイムを集合論的に定義しなさい。(2点)
- プログラムポイント(Program Point)とは何か説明しなさい。(1点)
'a: 'bの意味を集合の包含関係で説明しなさい。(2点)- 反射律(Reflexivity)
- 反対称律(Antisymmetry)
- 推移律(Transitivity)
1.2 半順序集合(5点)
ライフタイムが半順序集合を形成することを証明しなさい。以下の3つの性質を示すこと:
各性質について、数式とRustの例を示しなさい。
1.3 制約解析(5点)
以下のコードについて、ライフタイム制約を書き出し、解を求めなさい:
fn example() {
let x = 5; // L1
let y = 10; // L2
let r = &x; // L3
let s = r; // L4
println!("{}", s); // L5
}
---
問題2: Tofte-Talpin領域推論(20点)
2.1 型付け規則(10点)
以下の型付け規則をRustのコードで具体化しなさい:
REF規則:
Γ ⊢ e : τ ρ fresh
─────────────────────
Γ ⊢ ref e : ref^ρ τ
- この規則の意味を日本語で説明しなさい。(3点)
- Rustで対応するコード例を示しなさい。(3点)
- 領域(region)とライフタイムの対応を説明しなさい。(4点)
2.2 DEREF規則(10点)
以下の型付け規則を分析しなさい:
DEREF規則:
Γ ⊢ e : ref^ρ τ
────────────────
Γ ⊢ !e : τ
- この規則をRustの構文で表現しなさい。(4点)
- 参照の読み取りと領域の関係を説明しなさい。(3点)
- なぜ領域注釈が必要か説明しなさい。(3点)
&'a Tがcovariantである定義を書きなさい。(3点)- なぜ安全なのか、時間軸の図を使って説明しなさい。(4点)
- 以下のコードが正しい理由を説明しなさい:
---
問題3: Variance(変性)(25点)
3.1 Covariant(10点)
以下の質問に答えなさい:
fn extend<'long, 'short>(x: &'long i32) -> &'short i32
where
'long: 'short,
{
x
}
(3点)
3.2 Invariant(10点)
以下の質問に答えなさい:
&'a mut T はinvariantでなければならないか説明しなさい。(4点)&'a mut T がcovariantだったらどうなるか、反例を示しなさい:fn evil<'a>(short: &'a mut &'static str) {
let local = String::from("local");
*short = &local; // もしcovariantなら...
}
この関数がなぜ危険か、ステップバイステップで説明しなさい。(6点)
3.3 Contravariant(5点)
以下のコードについて説明しなさい:
fn contravariant() {
let f: fn(&'static str) = |s| println!("{}", s);
let g: fn(&str) = f;
let local = String::from("local");
g(&local);
}
---
問題4: Higher-Ranked Trait Bounds(20点)
4.1 基本概念(8点)
for<'a> の形式的意味を論理式で表現しなさい。(3点)4.2 実装問題(12点)
以下の関数を完成させなさい:
// 問題A: クロージャを返す関数(6点)
fn returns_closure() -> ??? {
Box::new(|x: &str| x)
}
// 問題B: apply関数の実装(6点)
fn apply<F>(f: F, x: &i32) -> &i32
where
F: ???, // ここを埋めなさい
{
f(x)
}
各問題について:
- 正しい型注釈を書きなさい。(各3点)
- なぜその型が必要か説明しなさい。(各3点)
---
ボーナス課題(20点)
ボーナス1: Variance表の完成(8点)
以下の表を完成させ、各型のvarianceとその理由を説明しなさい:
| 型 | Variance | 理由 |
|---|---|---|
| `&'a T` | ? | ? |
| `&'a mut T` | ? | ? |
| `*const T` | ? | ? |
| `*mut T` | ? | ? |
| `fn(&'a T)` | ? | ? |
| `fn() -> &'a T` | ? | ? |
| `Box |
? | ? |
| `Cell |
? | ? |
各行について:
- Variance(共変/反変/不変)を答えなさい。(各0.5点)
- 理由を簡潔に説明しなさい。(各0.5点)
- 論文の要約(3点)
---
ボーナス2: Tofte-Talpin論文の調査(7点)
以下の課題を実施し、レポートを作成しなさい:
- Rustへの影響(2点)
- 他言語との比較(2点)
提出形式:
- Markdown形式のレポート(1500文字以上)
- 参照文献を明記すること
参考文献:
- Tofte, Mads, and Jean-Pierre Talpin. "Region-based memory management." Information and Computation 132.2 (1997): 109-176.
---
ボーナス3: ライフタイム制約ソルバーの実装(5点)
ライフタイム制約を解くシンプルなソルバーを実装しなさい:
use std::collections::{HashMap, HashSet};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Lifetime(u32);
#[derive(Debug, Clone)]
struct Constraint {
// 'a: 'b を表す('a outlives 'b)
outlives: Lifetime,
outlived: Lifetime,
}
struct LifetimeConstraintSolver {
constraints: Vec<Constraint>,
}
impl LifetimeConstraintSolver {
fn new() -> Self {
// ここを実装
}
fn add_constraint(&mut self, outlives: Lifetime, outlived: Lifetime) {
// ここを実装
}
fn solve(&self) -> Result<HashMap<Lifetime, HashSet<Lifetime>>, String> {
// ここを実装
// 推移律を適用して、各ライフタイムがoutliveする
// ライフタイムの集合を返す
}
fn check_consistency(&self) -> Result<(), String> {
// ここを実装
// 循環依存をチェック
}
}
// テストケース
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple_constraint() {
let mut solver = LifetimeConstraintSolver::new();
let a = Lifetime(1);
let b = Lifetime(2);
solver.add_constraint(a, b); // 'a: 'b
let result = solver.solve().unwrap();
assert!(result[&a].contains(&b));
}
#[test]
fn test_transitive() {
let mut solver = LifetimeConstraintSolver::new();
let a = Lifetime(1);
let b = Lifetime(2);
let c = Lifetime(3);
solver.add_constraint(a, b); // 'a: 'b
solver.add_constraint(b, c); // 'b: 'c
let result = solver.solve().unwrap();
// 推移律により 'a: 'c も成立
assert!(result[&a].contains(&c));
}
#[test]
fn test_cycle_detection() {
let mut solver = LifetimeConstraintSolver::new();
let a = Lifetime(1);
let b = Lifetime(2);
solver.add_constraint(a, b); // 'a: 'b
solver.add_constraint(b, a); // 'b: 'a
// 循環依存はエラー('a = 'b の場合を除く)
assert!(solver.check_consistency().is_ok()); // 'a = 'b
}
}
要件:
- 制約を追加できること(2点)
- 推移律を適用して解を求められること(2点)
- テストが全て通ること(1点)
---
評価基準
マンダトリー部分(80点)
| 項目 | 配点 | 評価ポイント |
|---|---|---|
| 問題1:数学的定義 | 15点 | 集合論的理解、制約解析の正確性 |
| 問題2:Tofte-Talpin | 20点 | 型付け規則の理解と応用 |
| 問題3:Variance | 25点 | 3種類のvarianceの理解と証明 |
| 問題4:HRTBs | 20点 | 全称量化の理解と実装 |
ボーナス部分(20点)
| 項目 | 配点 | 評価ポイント |
|---|---|---|
| ボーナス1:Variance表 | 8点 | 網羅的な理解 |
| ボーナス2:論文調査 | 7点 | 理論的背景の深い理解 |
| ボーナス3:ソルバー実装 | 5点 | アルゴリズムの実装能力 |
注: ボーナスは最大20点まで加算されます。
---
提出方法
ファイル構成
rust-lifetime-mastery-01/
├── answers.md # マンダトリー問題の回答
├── bonus1-variance-table.md # ボーナス1の表
├── bonus2-tofte-talpin.md # ボーナス2のレポート
└── bonus3-solver/
├── src/
│ └── lib.rs # ソルバーの実装
└── Cargo.toml
提出期限
---
ヒント
問題1のヒント
数学的定義:
- ライフタイムは時間区間の集合
- プログラムポイントはコード中の位置
- 包含関係は部分集合関係
半順序集合:
- 反射律: 'a ⊇ 'a
- 反対称律: 'a ⊇ 'b ∧ 'b ⊇ 'a ⇒ 'a = 'b
- 推移律: 'a ⊇ 'b ∧ 'b ⊇ 'c ⇒ 'a ⊇ 'c
制約解析:
変数のライフタイム:
'x = [L1, end)
'r = [L3, end)
制約:
'r ⊆ 'x
's = 'r
問題2のヒント
REF規則:
let x = 5; // e: i32
let r = &x; // ref^'a x: &'a i32
DEREF規則:
let x = 5;
let r = &x; // r: &'a i32
let y = *r; // y: i32
問題3のヒント
Covariant:
長いライフタイム → 短いライフタイムは安全
&'long i32 <: &'short i32 ('long: 'short のとき)
Invariant:
&'a mut T がcovariantだと、
短いライフタイムを長いライフタイムに拡張できてしまう
→ ダングリングポインタ
Contravariant:
関数が長いライフタイムを要求 → 短いもので呼び出しても安全
fn(&'long T) <: fn(&'short T) ('long: 'short のとき)
問題4のヒント
HRTBs:
// 通常のライフタイムパラメータ
fn foo<'a, F>(f: F)
where
F: Fn(&'a i32), // 'a は固定
// HRTBs
fn bar<F>(f: F)
where
F: for<'a> Fn(&'a i32), // 任意の 'a
型注釈:
Box<dyn for<'a> Fn(&'a str) -> &'a str>
ボーナス3のヒント
ソルバーのアルゴリズム:
- 制約をグラフで表現
- 推移閉包を計算(Warshall-Floyd)
- 循環依存をチェック
fn solve(&self) -> Result<HashMap<Lifetime, HashSet<Lifetime>>, String> {
// 1. 初期化
let mut outlives_map = HashMap::new();
// 2. 直接的な制約を追加
for constraint in &self.constraints {
outlives_map
.entry(constraint.outlives)
.or_insert_with(HashSet::new)
.insert(constraint.outlived);
}
// 3. 推移律を適用(不動点まで)
loop {
let mut changed = false;
// outlives_map を更新
// ...
if !changed { break; }
}
Ok(outlives_map)
}
---
学習の確認
この課題を通じて、以下を理解できたか確認してください:
次の章では、複数のライフタイムパラメータと省略規則を学びます。