Skip to content

Commit d45faa5

Browse files
committed
Support for generic ADTs and implementations through more advanced generic handling. Expanded generics test case to verify this.
1 parent 9b28363 commit d45faa5

File tree

13 files changed

+647
-161
lines changed

13 files changed

+647
-161
lines changed

library/src/main/kotlin/org/rustlang/core/Core.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,10 @@ public fun core_slice_u8_starts_with(value: Any, prefix: Any): Boolean {
402402
}
403403

404404
// Determine the variant using instanceof (Kotlin 'is')
405-
if (optionObj::class.java.name.endsWith("Option\$Some")) {
405+
if (optionObj::class.java.name.endsWith("\$Some")) {
406406
// It's Some(value). Return false.
407407
return false
408-
} else if (optionObj::class.java.name.endsWith("Option\$None")) {
408+
} else if (optionObj::class.java.name.endsWith("\$None")) {
409409
// It's None. Return true.
410410
return true
411411
} else {

src/lib.rs

Lines changed: 98 additions & 31 deletions
Large diffs are not rendered by default.

src/lower1.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use types::ty_to_oomir_type;
1818

1919
mod closures;
2020
mod control_flow;
21+
pub mod naming;
2122
pub mod operand;
2223
pub mod place;
2324
pub mod types;
24-
pub mod naming;
2525

2626
pub use closures::{ClosureCallInfo, extract_closure_info, generate_closure_function_name};
2727

@@ -42,8 +42,8 @@ pub fn mir_to_oomir<'tcx>(
4242

4343
// Get a function name from the instance or use the provided override.
4444
// Prefer monomorphized naming to disambiguate generic instantiations.
45-
let fn_name = fn_name_override
46-
.unwrap_or_else(|| naming::mono_fn_name_from_instance(tcx, instance));
45+
let fn_name =
46+
fn_name_override.unwrap_or_else(|| naming::mono_fn_name_from_instance(tcx, instance));
4747

4848
// Extract function signature
4949
// Closures require special handling - we must use as_closure().sig() instead of fn_sig()
@@ -78,9 +78,10 @@ pub fn mir_to_oomir<'tcx>(
7878
.map(|(i, ty)| {
7979
// Arguments start at MIR local 1. The index `i` starts at 0.
8080
let local_index = rustc_middle::mir::Local::from_usize(i + 1);
81-
81+
8282
// Try to find the parameter name from var_debug_info
83-
let param_name = mir.var_debug_info
83+
let param_name = mir
84+
.var_debug_info
8485
.iter()
8586
.find_map(|var_info| {
8687
// Check if this debug info entry is for our parameter
@@ -92,14 +93,15 @@ pub fn mir_to_oomir<'tcx>(
9293
None
9394
})
9495
.unwrap_or_else(|| format!("arg{}", i));
95-
96-
let oomir_type = ty_to_oomir_type(*ty, tcx, data_types);
97-
96+
97+
let oomir_type = ty_to_oomir_type(*ty, tcx, data_types, instance);
98+
9899
// Return the (name, type) tuple
99100
(param_name, oomir_type)
100101
})
101102
.collect();
102-
let return_oomir_ty: oomir::Type = ty_to_oomir_type(return_ty.skip_binder(), tcx, data_types);
103+
let return_oomir_ty: oomir::Type =
104+
ty_to_oomir_type(return_ty.skip_binder(), tcx, data_types, instance);
103105

104106
let mut signature = oomir::Signature {
105107
params: params_oomir,
@@ -114,9 +116,12 @@ pub fn mir_to_oomir<'tcx>(
114116
if fn_name == "main" {
115117
// manually override the signature to match the JVM main method
116118
signature = oomir::Signature {
117-
params: vec![("args".to_string(), oomir::Type::Array(Box::new(oomir::Type::Class(
118-
"java/lang/String".to_string(),
119-
))))],
119+
params: vec![(
120+
"args".to_string(),
121+
oomir::Type::Array(Box::new(oomir::Type::Class(
122+
"java/lang/String".to_string(),
123+
))),
124+
)],
120125
ret: Box::new(oomir::Type::Void),
121126
};
122127
}

src/lower1/control_flow.rs

Lines changed: 104 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ pub fn convert_basic_block<'tcx>(
193193
}
194194
TerminatorKind::SwitchInt { discr, targets, .. } => {
195195
// --- GENERAL SwitchInt Handling ---
196-
let discr_operand = convert_operand(discr, tcx, instance, mir, data_types, &mut instructions);
196+
let discr_operand =
197+
convert_operand(discr, tcx, instance, mir, data_types, &mut instructions);
197198
// Get the actual type of the discriminant from MIR local declarations
198199
let discr_ty = discr.ty(&mir.local_decls, tcx);
199200

@@ -258,87 +259,154 @@ pub fn convert_basic_block<'tcx>(
258259
breadcrumbs::log!(
259260
breadcrumbs::LogLevel::Info,
260261
"mir-lowering",
261-
format!("FnDef detected: def_id={:?}, is_local={}, args={:?}", def_id, def_id.is_local(), args)
262+
format!(
263+
"FnDef detected: def_id={:?}, is_local={}, args={:?}",
264+
def_id,
265+
def_id.is_local(),
266+
args
267+
)
262268
);
263269
if def_id.is_local() {
264270
// Check if this is a trait method call
265271
if let Some(assoc_item) = tcx.opt_associated_item(*def_id) {
266272
breadcrumbs::log!(
267273
breadcrumbs::LogLevel::Info,
268274
"mir-lowering",
269-
format!("Associated item found: {:?}, trait_item_def_id={:?}, container={:?}", assoc_item, assoc_item.trait_item_def_id(), assoc_item.container)
275+
format!(
276+
"Associated item found: {:?}, trait_item_def_id={:?}, container={:?}",
277+
assoc_item,
278+
assoc_item.trait_item_def_id(),
279+
assoc_item.container
280+
)
270281
);
271282
// Check if this is a trait method (check if parent is a trait)
272283
let is_trait_method = tcx.is_trait(tcx.parent(*def_id));
273-
284+
274285
if is_trait_method {
275286
// Trait method call: check if it's monomorphized to a concrete type
276287
if let Some(first_arg) = args.get(0) {
277288
if let Some(ty) = first_arg.as_type() {
278289
// Check if it's NOT a trait object (dyn Trait)
279-
if !matches!(ty.kind(), rustc_middle::ty::TyKind::Dynamic(..)) {
290+
if !matches!(
291+
ty.kind(),
292+
rustc_middle::ty::TyKind::Dynamic(..)
293+
) {
280294
// Concrete type - use Type_method naming
281-
let type_name = super::types::ty_to_oomir_type(ty, tcx, &mut Default::default());
282-
let method_name = tcx.item_name(*def_id).to_string();
295+
let type_name = super::types::ty_to_oomir_type(
296+
ty,
297+
tcx,
298+
&mut Default::default(),
299+
instance,
300+
);
301+
let method_name =
302+
tcx.item_name(*def_id).to_string();
283303
// Extract class name from Type
284304
let class_name = match type_name {
285305
oomir::Type::Class(name) => name,
286-
oomir::Type::Reference(box oomir::Type::Class(name)) => name,
287-
oomir::Type::MutableReference(box oomir::Type::Class(name)) => name,
306+
oomir::Type::Reference(
307+
box oomir::Type::Class(name),
308+
) => name,
309+
oomir::Type::MutableReference(
310+
box oomir::Type::Class(name),
311+
) => name,
288312
_ => {
289313
// Fallback for unexpected types
290314
format!("{:?}", type_name)
291315
}
292316
};
293-
let full_name = format!("{}_{}", class_name, method_name);
317+
let full_name =
318+
format!("{}_{}", class_name, method_name);
294319
breadcrumbs::log!(
295320
breadcrumbs::LogLevel::Info,
296321
"mir-lowering",
297-
format!("Trait method call with concrete type: def_id={:?}, ty={:?}, using name: {}", def_id, ty, full_name)
322+
format!(
323+
"Trait method call with concrete type: def_id={:?}, ty={:?}, using name: {}",
324+
def_id, ty, full_name
325+
)
298326
);
299327
(full_name, false)
300328
} else {
301329
// Dynamic trait object - use dyn_Trait_method naming
302-
let trait_name = if let rustc_middle::ty::TyKind::Dynamic(preds, _) = ty.kind() {
303-
// Extract trait name from trait object
304-
if let Some(principal) = preds.principal() {
305-
let trait_ref = principal.skip_binder();
306-
tcx.item_name(trait_ref.def_id).to_string()
330+
let trait_name =
331+
if let rustc_middle::ty::TyKind::Dynamic(
332+
preds,
333+
_,
334+
) = ty.kind()
335+
{
336+
// Extract trait name from trait object
337+
if let Some(principal) =
338+
preds.principal()
339+
{
340+
let trait_ref =
341+
principal.skip_binder();
342+
tcx.item_name(trait_ref.def_id)
343+
.to_string()
344+
} else {
345+
"Unknown".to_string()
346+
}
307347
} else {
308348
"Unknown".to_string()
309-
}
310-
} else {
311-
"Unknown".to_string()
312-
};
313-
let method_name = tcx.item_name(*def_id).to_string();
314-
let full_name = format!("dyn_{}_{}", trait_name, method_name);
349+
};
350+
let method_name =
351+
tcx.item_name(*def_id).to_string();
352+
let full_name = format!(
353+
"dyn_{}_{}",
354+
trait_name, method_name
355+
);
315356
breadcrumbs::log!(
316357
breadcrumbs::LogLevel::Info,
317358
"mir-lowering",
318-
format!("Trait method call with dyn trait object, using name: {}", full_name)
359+
format!(
360+
"Trait method call with dyn trait object, using name: {}",
361+
full_name
362+
)
319363
);
320364
(full_name, false)
321365
}
322366
} else {
323367
// No type in args, use monomorphized name
324-
(super::naming::mono_fn_name_from_call_operand(func, tcx).unwrap(), false)
368+
(
369+
super::naming::mono_fn_name_from_call_operand(
370+
func, tcx, instance,
371+
)
372+
.unwrap(),
373+
false,
374+
)
325375
}
326376
} else {
327377
// No args, use monomorphized name
328-
(super::naming::mono_fn_name_from_call_operand(func, tcx).unwrap(), false)
378+
(
379+
super::naming::mono_fn_name_from_call_operand(
380+
func, tcx, instance,
381+
)
382+
.unwrap(),
383+
false,
384+
)
329385
}
330386
} else {
331387
// Not a trait method, use monomorphized name
332-
(super::naming::mono_fn_name_from_call_operand(func, tcx).unwrap(), false)
388+
(
389+
super::naming::mono_fn_name_from_call_operand(
390+
func, tcx, instance,
391+
)
392+
.unwrap(),
393+
false,
394+
)
333395
}
334396
} else {
335397
// Not an associated item, use monomorphized name
336-
(super::naming::mono_fn_name_from_call_operand(func, tcx).unwrap(), false)
398+
(
399+
super::naming::mono_fn_name_from_call_operand(
400+
func, tcx, instance,
401+
)
402+
.unwrap(),
403+
false,
404+
)
337405
}
338406
} else {
339407
// External function: check for special cases, otherwise use path-based key for shims
340408
let def_path = tcx.def_path_str(*def_id);
341-
409+
342410
// Special case: core::str::<impl str>::len maps to our Kotlin shim's len method
343411
if def_path.contains("::str::") && def_path.ends_with("::len") {
344412
("len".to_string(), false)
@@ -371,8 +439,14 @@ pub fn convert_basic_block<'tcx>(
371439
for arg in args_to_process {
372440
let mir_op = &arg.node;
373441
// Important: Pass pre_call_instructions here to collect setup code for this arg
374-
let oomir_op =
375-
convert_operand(mir_op, tcx, instance, mir, data_types, &mut pre_call_instructions);
442+
let oomir_op = convert_operand(
443+
mir_op,
444+
tcx,
445+
instance,
446+
mir,
447+
data_types,
448+
&mut pre_call_instructions,
449+
);
376450

377451
// Identify if the MIR operand is a direct use of a local Place
378452
let maybe_arg_place = match mir_op {

0 commit comments

Comments
 (0)