Skip to content

Conversation

@CatlessFish
Copy link
Contributor

基于Lattice的MFP不动点迭代算法的alias分析实现

算法设计

抽象状态(lattice)定义为MIR Place的幂集的幂集。

$$ L = \mathcal{P}(\mathcal{P}(\textit{Place})) $$

其中内层的P(Place)表示这若干个Place属于一个互相存在alias关系的等价类。
L上的merge( L1, L2 )操作定义为对L1和L2中每个等价类应用传递闭包进行合并。

merge操作是单调的,且Lattice的高度是有限的,可以用于不动点迭代。

使用函数摘要缓存+不动点迭代的方式进行过程间分析。

模块架构

rapx/src/analysis/core/alias_analysis/
|-- mod.rs # AliasAnalysis Trait定义
| -- mfp/
      | -- mod.rs # 顶层接口
      | -- intraproc.rs # 过程内分析
      | -- interproc.rs # 过程间分析
      | -- transfer.rs # 数据流转移函数

实现说明

  • 使用cargo rapx -alias-mfp 执行MFP版本的alias分析。
  • MfpAliasAnalyzer 实现了 AliasAnalysis Trait,理论上可以替换原有的MoP版本的AliasAnalyzer
  • 函数内的数据流分析使用rustc_mir_dataflow提供的框架实现。
  • 支持field-sensitive分析。

测试用例

复用了现有的alias分析测试,在现有测试中行为与MoP-alias一致。

Fixed a bug where MFP alias analysis failed to track field accesses
through reference types (e.g., (*p).x where p: &Point).

Root cause:
- PlaceInfo only created fields for direct ADT/Tuple types, not for
  types accessed through references/pointers
- Fields of primitive types (e.g., i32) were marked as may_drop=false,
  preventing alias tracking even when accessed through references

Solution:
1. Added deref_depth parameter to track dereference levels during
   field creation
2. Recursively create fields for inner types of Ref and RawPtr types
3. Force may_drop=true for fields created at deref_depth > 0, since
   memory accessed through references should be tracked regardless
   of the field's underlying type
4. Added MAX_DEREF_DEPTH=3 limit to prevent infinite recursion on
   self-referential types

This matches MOP analyzer's behavior where it checks the root local's
may_drop rather than the field's type.

Test case: test_function_param_alias(p: &Point) -> &i32
- Before: null
- After: (0, 1.0)
…hout MIR

Problem:
MFP alias analysis failed to detect aliases for library functions
without MIR (e.g., Vec::from_raw_parts), returning null instead of
expected alias pairs like (0,1).

Root Cause:
The conservative fallback mechanism was implemented in
apply_call_return_effect(), which is not invoked by rustc's dataflow
framework when using iterate_to_fixpoint().

Solution:
Move function call handling from apply_call_return_effect to
apply_primary_terminator_effect. Now both kill and gen effects
(summary application or fallback) are applied when processing Call
terminators, consistent with MOP's approach.

The fallback conservatively assumes return values may alias with all
may_drop arguments for functions without available summaries.
Problem:
MFP alias analysis failed to capture aliases like (0.0, 1) in functions
such as Vec::from_raw_parts_in, where the return value's internal pointer
field aliases with the input parameter through temporary variables.

Root Cause:
The summary extraction in extract_summary() filtered out all aliases
involving temporary variables (root > arg_count). When aliases were
connected through bridge variables at different structural levels
(e.g., _0.0.0.0 ≈ _15 and _1 ≈ _15.0), there was no direct alias
between parameters/return in all_pairs, causing the connection to be lost.

Solution:
1. Bridge Variable Derivation (Step 4.1):
   - Detect alias pairs connected through the same temporary variable
   - Check for parent-child field relationships (prefix, not siblings)
   - Derive direct aliases between parameters/return values
   - Compress deep field paths to first level for precision balance

2. Alias Filtering (Step 5):
   - Implement filter_redundant_aliases() to remove:
     * Self-aliases: (x, x)
     * Prefix-subsumed aliases: keep (0.0, 1), remove (0.0.0, 1)
   - Produce minimal, canonical summaries

3. Code Refactoring:
   - Unified candidate collection in Step 4 (4.1 + 4.2)
   - Single summary.add_alias() call point after filtering
   - Clearer separation of concerns and logic flow

Changes:
- interproc.rs: Restructure extract_summary() with bridge derivation
- Add filter_redundant_aliases() and is_strict_prefix() helpers
- Comprehensive comments explaining the algorithm and rationale

Result:
MFP now correctly captures (0.0, 1) for Vec::from_raw_parts_in and
similar patterns, matching MOP's behavior while maintaining the MFP
approach's theoretical foundation.
@CatlessFish
Copy link
Contributor Author

Find a bug. Will fix it and reopen later.

Pass function-level TypingEnv through create_fields_for_type recursion
to avoid param-env mismatch when checking needs_drop on generic fields.
@CatlessFish CatlessFish reopened this Jan 16, 2026
@hxuhack hxuhack merged commit cfcddf3 into safer-rust:main Jan 18, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants