@@ -1259,6 +1259,89 @@ impl CompositionGraph {
12591259 generation : entry. generation ,
12601260 }
12611261 }
1262+
1263+ /// Yields an iterator over the resolved imports of the graph.
1264+ pub fn imports ( & self ) -> Result < impl Iterator < Item = ( & str , NodeId ) > , EncodeError > {
1265+ let import_nodes = self
1266+ . node_ids ( )
1267+ . filter_map ( |n| match & self [ n] . kind ( ) {
1268+ NodeKind :: Import ( _) => Some ( n) ,
1269+ _ => None ,
1270+ } )
1271+ . collect ( ) ;
1272+ let mut implicit_imports = Default :: default ( ) ;
1273+ let mut explicit_imports = Default :: default ( ) ;
1274+ let _ = self . resolve_imports ( import_nodes, & mut implicit_imports, & mut explicit_imports) ?;
1275+
1276+ Ok ( implicit_imports. into_iter ( ) . chain ( explicit_imports) )
1277+ }
1278+
1279+ /// Resolves the imports (both implicit and explicit) of the given nodes.
1280+ ///
1281+ /// Populates hashmaps that map the implicit and explicit import nodes to their import names.
1282+ /// Returns a type aggregator that contains the resolved types of the imports.
1283+ pub fn resolve_imports < ' a > (
1284+ & ' a self ,
1285+ import_nodes : Vec < NodeId > ,
1286+ implicit_imports : & mut HashMap < & ' a str , NodeId > ,
1287+ explicit_imports : & mut HashMap < & ' a str , NodeId > ,
1288+ ) -> Result < TypeAggregator , EncodeError > {
1289+ let mut instantiations = HashMap :: new ( ) ;
1290+ let mut aggregator = TypeAggregator :: default ( ) ;
1291+ let mut cache = Default :: default ( ) ;
1292+ let mut checker = SubtypeChecker :: new ( & mut cache) ;
1293+ log:: debug!( "populating implicit imports" ) ;
1294+ for index in self . graph . node_indices ( ) {
1295+ let node = & self . graph [ index] ;
1296+ if !matches ! ( node. kind, NodeKind :: Instantiation ( _) ) {
1297+ continue ;
1298+ }
1299+
1300+ let package = & self [ node. package . unwrap ( ) ] ;
1301+ let world = & self . types [ package. ty ( ) ] ;
1302+
1303+ let unsatisfied_args = world
1304+ . imports
1305+ . iter ( )
1306+ . enumerate ( )
1307+ . filter ( |( i, _) | !node. is_arg_satisfied ( * i) ) ;
1308+
1309+ // Go through the unsatisfied arguments and import them
1310+ for ( _, ( name, kind) ) in unsatisfied_args {
1311+ if let Some ( import) = self . imports . get ( name) . copied ( ) {
1312+ return Err ( EncodeError :: ImplicitImportConflict {
1313+ import : NodeId ( import) ,
1314+ instantiation : NodeId ( index) ,
1315+ package : PackageKey :: new ( package) ,
1316+ name : name. to_string ( ) ,
1317+ } ) ;
1318+ }
1319+
1320+ instantiations. entry ( name) . or_insert ( index) ;
1321+
1322+ aggregator = aggregator
1323+ . aggregate ( name, & self . types , * kind, & mut checker)
1324+ . map_err ( |e| EncodeError :: ImportTypeMergeConflict {
1325+ import : name. clone ( ) ,
1326+ first : NodeId ( instantiations[ & name] ) ,
1327+ second : NodeId ( index) ,
1328+ source : e,
1329+ } ) ?;
1330+ implicit_imports. insert ( name, NodeId ( index) ) ;
1331+ }
1332+ }
1333+ log:: debug!( "populating explicit imports" ) ;
1334+ for n in import_nodes {
1335+ let node = & self . graph [ n. 0 ] ;
1336+ if let NodeKind :: Import ( name) = & node. kind {
1337+ explicit_imports. insert ( name. as_str ( ) , n) ;
1338+ aggregator = aggregator
1339+ . aggregate ( name, self . types ( ) , node. item_kind , & mut checker)
1340+ . unwrap ( ) ;
1341+ }
1342+ }
1343+ Ok ( aggregator)
1344+ }
12621345}
12631346
12641347impl Index < NodeId > for CompositionGraph {
@@ -1382,8 +1465,9 @@ impl<'a> CompositionGraphEncoder<'a> {
13821465 . toposort ( )
13831466 . map_err ( |n| EncodeError :: GraphContainsCycle { node : NodeId ( n) } ) ?
13841467 . into_iter ( )
1468+ . map ( NodeId )
13851469 . partition :: < Vec < _ > , _ > ( |index| {
1386- let node = & self . 0 . graph [ * index] ;
1470+ let node = & self . 0 . graph [ index. 0 ] ;
13871471 matches ! ( node. kind, NodeKind :: Import ( _) )
13881472 } ) ;
13891473
@@ -1392,16 +1476,16 @@ impl<'a> CompositionGraphEncoder<'a> {
13921476
13931477 // Encode non-import nodes in the graph in topographical order
13941478 for n in other_nodes {
1395- let node = & self . 0 . graph [ n] ;
1479+ let node = & self . 0 . graph [ n. 0 ] ;
13961480 let index = match & node. kind {
13971481 NodeKind :: Definition => self . definition ( & mut state, node) ,
1398- NodeKind :: Instantiation ( _) => self . instantiation ( & mut state, n, node, options) ,
1399- NodeKind :: Alias => self . alias ( & mut state, n) ,
1482+ NodeKind :: Instantiation ( _) => self . instantiation ( & mut state, n. 0 , node, options) ,
1483+ NodeKind :: Alias => self . alias ( & mut state, n. 0 ) ,
14001484 // `other_nodes` does not contain any import nodes
14011485 NodeKind :: Import ( _) => unreachable ! ( ) ,
14021486 } ;
14031487
1404- let prev = state. node_indexes . insert ( n, index) ;
1488+ let prev = state. node_indexes . insert ( n. 0 , index) ;
14051489 assert ! ( prev. is_none( ) ) ;
14061490 }
14071491
@@ -1489,73 +1573,20 @@ impl<'a> CompositionGraphEncoder<'a> {
14891573 }
14901574
14911575 /// Encode both implicit and explicit imports.
1576+ ///
1577+ /// `import_nodes` are expected to only be `NodeKind::Import` nodes.
14921578 fn encode_imports (
14931579 & self ,
14941580 state : & mut State ,
1495- import_nodes : Vec < NodeIndex > ,
1581+ import_nodes : Vec < NodeId > ,
14961582 ) -> Result < ( ) , EncodeError > {
1497- let mut aggregator = TypeAggregator :: default ( ) ;
1498- let mut instantiations = HashMap :: new ( ) ;
1499- let mut arguments = Vec :: new ( ) ;
1500- let mut encoded = HashMap :: new ( ) ;
1501- let mut cache = Default :: default ( ) ;
1502- let mut checker = SubtypeChecker :: new ( & mut cache) ;
15031583 let mut explicit_imports = HashMap :: new ( ) ;
1584+ let mut implicit_imports = HashMap :: new ( ) ;
1585+ let aggregator =
1586+ self . 0
1587+ . resolve_imports ( import_nodes, & mut implicit_imports, & mut explicit_imports) ?;
15041588
1505- log:: debug!( "populating implicit imports" ) ;
1506-
1507- // Enumerate the instantiation nodes and populate the import types
1508- for index in self . 0 . graph . node_indices ( ) {
1509- let node = & self . 0 . graph [ index] ;
1510- if !matches ! ( node. kind, NodeKind :: Instantiation ( _) ) {
1511- continue ;
1512- }
1513-
1514- let package = & self . 0 [ node. package . unwrap ( ) ] ;
1515- let world = & self . 0 . types [ package. ty ( ) ] ;
1516-
1517- let unsatisfied_args = world
1518- . imports
1519- . iter ( )
1520- . enumerate ( )
1521- . filter ( |( i, _) | !node. is_arg_satisfied ( * i) ) ;
1522-
1523- // Go through the unsatisfied arguments and import them
1524- for ( _, ( name, kind) ) in unsatisfied_args {
1525- if let Some ( import) = self . 0 . imports . get ( name) . copied ( ) {
1526- return Err ( EncodeError :: ImplicitImportConflict {
1527- import : NodeId ( import) ,
1528- instantiation : NodeId ( index) ,
1529- package : PackageKey :: new ( package) ,
1530- name : name. to_string ( ) ,
1531- } ) ;
1532- }
1533-
1534- instantiations. entry ( name) . or_insert ( index) ;
1535-
1536- aggregator = aggregator
1537- . aggregate ( name, & self . 0 . types , * kind, & mut checker)
1538- . map_err ( |e| EncodeError :: ImportTypeMergeConflict {
1539- import : name. clone ( ) ,
1540- first : NodeId ( instantiations[ & name] ) ,
1541- second : NodeId ( index) ,
1542- source : e,
1543- } ) ?;
1544- arguments. push ( ( index, name) ) ;
1545- }
1546- }
1547-
1548- log:: debug!( "populating explicit imports" ) ;
1549-
1550- for n in import_nodes {
1551- let node = & self . 0 . graph [ n] ;
1552- if let NodeKind :: Import ( name) = & node. kind {
1553- explicit_imports. insert ( name. as_str ( ) , n) ;
1554- aggregator = aggregator
1555- . aggregate ( name, self . 0 . types ( ) , node. item_kind , & mut checker)
1556- . unwrap ( ) ;
1557- }
1558- }
1589+ let mut encoded = HashMap :: new ( ) ;
15591590
15601591 // Next encode the imports
15611592 for ( name, kind) in aggregator. imports ( ) {
@@ -1565,19 +1596,19 @@ impl<'a> CompositionGraphEncoder<'a> {
15651596 }
15661597
15671598 // Populate the implicit argument map
1568- for ( node , name ) in arguments {
1569- let ( kind, index) = encoded[ name. as_str ( ) ] ;
1599+ for ( name , node ) in implicit_imports {
1600+ let ( kind, index) = encoded[ name] ;
15701601 state
15711602 . implicit_args
1572- . entry ( node)
1603+ . entry ( node. 0 )
15731604 . or_default ( )
1574- . push ( ( name. clone ( ) , kind, index) ) ;
1605+ . push ( ( name. to_owned ( ) , kind, index) ) ;
15751606 }
15761607
15771608 // Finally, populate the node indexes with the encoded explicit imports
15781609 for ( name, node_index) in explicit_imports {
15791610 let ( _, encoded_index) = encoded[ name] ;
1580- state. node_indexes . insert ( node_index, encoded_index) ;
1611+ state. node_indexes . insert ( node_index. 0 , encoded_index) ;
15811612 }
15821613
15831614 Ok ( ( ) )
0 commit comments