@@ -931,6 +931,101 @@ package {name} is defined in two different locations:\n\
931931 Some ( self . id_of_name ( interface. package . unwrap ( ) , interface. name . as_ref ( ) ?) )
932932 }
933933
934+ /// Convert a world to an "importized" version where the world is updated
935+ /// in-place to reflect what it would look like to be imported.
936+ ///
937+ /// This is a transformation which is used as part of the process of
938+ /// importing a component today. For example when a component depends on
939+ /// another component this is useful for generating WIT which can be use to
940+ /// represent the component being imported. The general idea is that this
941+ /// function will update the `world_id` specified such it imports the
942+ /// functionality that it previously exported. The world will be left with
943+ /// no exports.
944+ ///
945+ /// This world is then suitable for merging into other worlds or generating
946+ /// bindings in a context that is importing the original world. This
947+ /// is intended to be used as part of language tooling when depending on
948+ /// other components.
949+ pub fn importize ( & mut self , world_id : WorldId ) -> Result < ( ) > {
950+ // Collect the set of interfaces which are depended on by exports. Also
951+ // all imported types are assumed to stay so collect any interfaces
952+ // they depend on.
953+ let mut live_through_exports = IndexSet :: default ( ) ;
954+ for ( _, export) in self . worlds [ world_id] . exports . iter ( ) {
955+ if let WorldItem :: Interface { id, .. } = export {
956+ self . collect_interface_deps ( * id, & mut live_through_exports) ;
957+ }
958+ }
959+ for ( _, import) in self . worlds [ world_id] . imports . iter ( ) {
960+ if let WorldItem :: Type ( ty) = import {
961+ if let Some ( dep) = self . type_interface_dep ( * ty) {
962+ self . collect_interface_deps ( dep, & mut live_through_exports) ;
963+ }
964+ }
965+ }
966+
967+ // Rename the world to avoid having it get confused with the original
968+ // name of the world. Add `-importized` to it for now. Precisely how
969+ // this new world is created may want to be updated over time if this
970+ // becomes problematic.
971+ let world = & mut self . worlds [ world_id] ;
972+ let pkg = & mut self . packages [ world. package . unwrap ( ) ] ;
973+ pkg. worlds . shift_remove ( & world. name ) ;
974+ world. name . push_str ( "-importized" ) ;
975+ pkg. worlds . insert ( world. name . clone ( ) , world_id) ;
976+
977+ // Trim all unnecessary imports first.
978+ world. imports . retain ( |name, item| match ( name, item) {
979+ // Remove imports which can't be used by import such as:
980+ //
981+ // * `import foo: interface { .. }`
982+ // * `import foo: func();`
983+ ( WorldKey :: Name ( _) , WorldItem :: Interface { .. } | WorldItem :: Function ( _) ) => false ,
984+
985+ // Coarsely say that all top-level types are required to avoid
986+ // calculating precise liveness of them right now.
987+ ( WorldKey :: Name ( _) , WorldItem :: Type ( _) ) => true ,
988+
989+ // Only retain interfaces if they're needed somehow transitively
990+ // for the exports.
991+ ( WorldKey :: Interface ( id) , _) => live_through_exports. contains ( id) ,
992+ } ) ;
993+
994+ // After all unnecessary imports are gone remove all exports and move
995+ // them all to imports, failing if there's an overlap.
996+ for ( name, export) in mem:: take ( & mut world. exports ) {
997+ match ( name. clone ( ) , world. imports . insert ( name, export) ) {
998+ // no previous item? this insertion was ok
999+ ( _, None ) => { }
1000+
1001+ // cannot overwrite an import with an export
1002+ ( WorldKey :: Name ( name) , _) => {
1003+ bail ! ( "world export `{name}` conflicts with import of same name" ) ;
1004+ }
1005+
1006+ // interface overlap is ok and is always allowed.
1007+ ( WorldKey :: Interface ( id) , Some ( WorldItem :: Interface { id : other, .. } ) ) => {
1008+ assert_eq ! ( id, other) ;
1009+ }
1010+
1011+ ( WorldKey :: Interface ( _) , _) => unreachable ! ( ) ,
1012+ }
1013+ }
1014+
1015+ #[ cfg( debug_assertions) ]
1016+ self . assert_valid ( ) ;
1017+ Ok ( ( ) )
1018+ }
1019+
1020+ fn collect_interface_deps ( & self , interface : InterfaceId , deps : & mut IndexSet < InterfaceId > ) {
1021+ if !deps. insert ( interface) {
1022+ return ;
1023+ }
1024+ for dep in self . interface_direct_deps ( interface) {
1025+ self . collect_interface_deps ( dep, deps) ;
1026+ }
1027+ }
1028+
9341029 /// Returns the ID of the specified `name` within the `pkg`.
9351030 pub fn id_of_name ( & self , pkg : PackageId , name : & str ) -> String {
9361031 let package = & self . packages [ pkg] ;
0 commit comments