classfile,passes: model Nest attributes as IR (fix ClassFormatError)

NestHost/NestMembers were carried as Attribute::Raw with constant-pool
indices baked in. During writing the pool is rebuilt in a different order,
so those indices pointed at the wrong entries and the JVM rejected the
class: ClassFormatError: Nest member/host class_info_index N has bad
constant type.

Model them explicitly in the IR, convert on parse and write (resolving
class names through the new pool), and remap their class names during
rename. Add a NestMembers round-trip regression test. Verified on a real
jar: all Nest ClassFormatErrors gone.
This commit is contained in:
Loki 2026-10-08 22:26:58 +02:00
parent 8b107cf1b3
commit 2674d7fc89
7 changed files with 145 additions and 66 deletions

View file

@ -205,6 +205,30 @@ fn bootstrap_methods_round_trip() {
assert!(format!("{:?}", ir.attributes[0]).contains("BootstrapMethods"));
}
/// `NestMembers` переживает пересборку пула (баг: `ClassFormatError`).
#[test]
fn nest_attributes_round_trip() {
let mut pool = ConstantPool::default();
let this = pool.add_class("demo/Nest").expect("c");
let object = pool.add_class("java/lang/Object").expect("o");
let member = pool.add_class("demo/Nest$Inner").expect("m");
let mn = pool.add_utf8("NestMembers").expect("n");
let mems = RtAttr::NestMembers {
name_index: mn,
class_indexes: vec![this, member],
};
let rt = RtClass {
version: JAVA_21,
constant_pool: pool,
this_class: this,
super_class: object,
attributes: vec![mems],
..RtClass::default()
};
let ir = round_trip(&rt);
assert!(format!("{:?}", ir.attributes).contains("NestMembers"));
}
/// `parse → write → parse` даёт тот же IR; записанное верифицируется.
fn round_trip(rt: &RtClass<'_>) -> ClassFile {
let mut original = Vec::new();