Skip to content

Commit 3debcd4

Browse files
committed
Resolve maximally specific inherited interface methods
1 parent 048f06c commit 3debcd4

14 files changed

Lines changed: 58 additions & 4 deletions

‎jvm/src/jvm.rs‎

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,15 +1306,40 @@ impl Jvm {
13061306
.and_then(|super_class| self.get_class(&super_class));
13071307
}
13081308

1309+
let mut visited = HashSet::new();
1310+
let mut candidates: Vec<(Class, Box<dyn Method>)> = Vec::new();
13091311
while let Some(interface_name) = interfaces.pop() {
1310-
let interface = self.get_class(&interface_name)?;
1311-
if let Some(method) = interface.definition.method(name, descriptor, false) {
1312-
return Some((interface, method));
1312+
if !visited.insert(interface_name.clone()) {
1313+
continue;
13131314
}
1315+
let interface = self.get_class(&interface_name)?;
13141316
interfaces.extend(interface.definition.interface_names());
1317+
if let Some(method) = interface.definition.method(name, descriptor, false)
1318+
&& !method.access_flags().contains(MethodAccessFlags::PRIVATE)
1319+
{
1320+
if candidates
1321+
.iter()
1322+
.any(|(candidate, _)| self.is_inherited_from(&*candidate.definition, &interface_name))
1323+
{
1324+
continue;
1325+
}
1326+
// Keep only declarations not overridden by a more specific interface.
1327+
candidates.retain(|(candidate, _)| !self.is_inherited_from(&*interface.definition, &candidate.definition.name()));
1328+
candidates.push((interface, method));
1329+
}
1330+
}
1331+
1332+
let mut concrete = candidates
1333+
.iter()
1334+
.enumerate()
1335+
.filter(|(_, (_, method))| !method.access_flags().contains(MethodAccessFlags::ABSTRACT));
1336+
if let Some((index, _)) = concrete.next()
1337+
&& concrete.next().is_none()
1338+
{
1339+
return Some(candidates.swap_remove(index));
13151340
}
13161341

1317-
None
1342+
candidates.into_iter().next()
13181343
}
13191344

13201345
pub(crate) fn find_field(&self, class: &dyn ClassDefinition, name: &str, descriptor: &str) -> Result<Option<Box<dyn Field>>> {
272 Bytes
Binary file not shown.
394 Bytes
Binary file not shown.
460 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
278 Bytes
Binary file not shown.
422 Bytes
Binary file not shown.
474 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)