Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
380 changes: 376 additions & 4 deletions src/hyperlight_component_util/src/emit.rs

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/hyperlight_component_util/src/guest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use proc_macro2::TokenStream;
use quote::{format_ident, quote};

use crate::emit::{
FnName, ResolvedBoundVar, ResourceItemName, State, WitName, kebab_to_exports_name, kebab_to_fn,
kebab_to_getter, kebab_to_imports_name, kebab_to_namespace, kebab_to_type, kebab_to_var,
split_wit_name,
FnName, ResolvedBoundVar, ResourceItemName, State, WitName, find_colliding_import_names,
import_member_names, kebab_to_exports_name, kebab_to_fn, kebab_to_getter,
kebab_to_imports_name, kebab_to_namespace, kebab_to_type, kebab_to_var, split_wit_name,
};
use crate::etypes::{Component, Defined, ExternDecl, ExternDesc, Handleable, Instance, Tyvar};
use crate::hl::{
Expand Down Expand Up @@ -117,8 +117,7 @@ fn emit_import_extern_decl<'a, 'b, 'c>(
let wn = split_wit_name(ed.kebab_name);
emit_import_instance(s, wn.clone(), it);

let getter = kebab_to_getter(wn.name);
let tn = kebab_to_type(wn.name);
let (tn, getter) = import_member_names(&wn, &s.colliding_import_names);
quote! {
type #tn = Self;
#[allow(refining_impl_trait)]
Expand Down Expand Up @@ -287,6 +286,7 @@ fn emit_component<'a, 'b, 'c>(
let export_trait = kebab_to_exports_name(wn.name);
s.import_param_var = Some(format_ident!("I"));
s.self_param_var = Some(format_ident!("S"));
s.colliding_import_names = find_colliding_import_names(&ct.imports);

let rtsid = format_ident!("{}Resources", r#trait);
resource::emit_tables(
Expand Down
11 changes: 6 additions & 5 deletions src/hyperlight_component_util/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};

use crate::emit::{
FnName, ResourceItemName, State, WitName, kebab_to_exports_name, kebab_to_fn, kebab_to_getter,
kebab_to_imports_name, kebab_to_namespace, kebab_to_type, kebab_to_var, split_wit_name,
FnName, ResourceItemName, State, WitName, find_colliding_import_names, import_member_names,
kebab_to_exports_name, kebab_to_fn, kebab_to_getter, kebab_to_imports_name, kebab_to_namespace,
kebab_to_type, kebab_to_var, split_wit_name,
};
use crate::etypes::{Component, ExternDecl, ExternDesc, Instance, Tyvar};
use crate::hl::{
Expand Down Expand Up @@ -264,10 +265,9 @@ fn emit_import_extern_decl<'a, 'b, 'c>(
ExternDesc::Instance(it) => {
let mut s = s.clone();
let wn = split_wit_name(ed.kebab_name);
let type_name = kebab_to_type(wn.name);
let getter = kebab_to_getter(wn.name);
let (type_name, getter) = import_member_names(&wn, &s.colliding_import_names);
let tp = s.cur_trait_path();
let get_self = get_self.with_getter(tp, type_name, getter); //quote! { #get_self let mut slf = &mut #tp::#getter(&mut *slf); };
let get_self = get_self.with_getter(tp, type_name, getter);
emit_import_instance(&mut s, get_self, wn.clone(), it)
}
ExternDesc::Component(_) => {
Expand Down Expand Up @@ -326,6 +326,7 @@ fn emit_component<'a, 'b, 'c>(s: &'c mut State<'a, 'b>, wn: WitName, ct: &'c Com

let rtsid = format_ident!("{}Resources", r#trait);
s.import_param_var = Some(format_ident!("I"));
s.colliding_import_names = find_colliding_import_names(&ct.imports);
resource::emit_tables(
&mut s,
rtsid.clone(),
Expand Down
52 changes: 35 additions & 17 deletions src/hyperlight_component_util/src/rtypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use quote::{format_ident, quote};
use syn::Ident;

use crate::emit::{
FnName, ResourceItemName, State, WitName, kebab_to_cons, kebab_to_exports_name, kebab_to_fn,
kebab_to_getter, kebab_to_imports_name, kebab_to_namespace, kebab_to_type, kebab_to_var,
split_wit_name,
FnName, ResourceItemName, State, WitName, find_colliding_import_names, import_member_names,
kebab_to_cons, kebab_to_exports_name, kebab_to_fn, kebab_to_getter, kebab_to_imports_name,
kebab_to_namespace, kebab_to_type, kebab_to_var, split_wit_name,
};
use crate::etypes::{
self, Component, Defined, ExternDecl, ExternDesc, Func, Handleable, ImportExport, Instance,
Expand Down Expand Up @@ -68,9 +68,10 @@ fn emit_resource_ref(s: &mut State, n: u32, path: Vec<ImportExport>) -> TokenStr
let id = format_ident!("HostResource{}", n);
return quote! { #id };
}
// There is always at least one element in the path, which names
// the thing we are referring to
let rtrait = kebab_to_type(path[path.len() - 1].name());
let Some(resource) = path.last() else {
panic!("resource reference path must contain the resource type");
};
let rtrait = kebab_to_type(resource.name());

// Deal specially with being in the local instance, where there is
// no instance type & so it is not easy to resolve the
Expand All @@ -92,22 +93,34 @@ fn emit_resource_ref(s: &mut State, n: u32, path: Vec<ImportExport>) -> TokenStr
// followed by the resource type itself. We locate the resource
// trait by using that final instance name directly; any other
// names are just used to get to the type that implements it
let instance = path[path.len() - 2].name();
let iwn = split_wit_name(instance);
let instance = &path[path.len() - 2];
let iwn = split_wit_name(instance.name());
let extras = path[0..path.len() - 2]
.iter()
.map(|p| {
let wn = split_wit_name(p.name());
kebab_to_type(wn.name)
if p.imported() && s.colliding_import_names.contains(wn.name) {
let (tn, _) = import_member_names(&wn, &s.colliding_import_names);
tn
} else {
kebab_to_type(wn.name)
}
})
.collect::<Vec<_>>();
let extras = quote! { #(#extras::)* };
let rp = s.root_path();
let tns = iwn.namespace_path();
let instance_mod = kebab_to_namespace(iwn.name);
let instance_type = kebab_to_type(iwn.name);
// Use the disambiguated trait member only for imported instances. Exported
// instances must keep their public WIT member names.
let instance_type = if instance.imported() {
let (tn, _) = import_member_names(&iwn, &s.colliding_import_names);
tn
} else {
kebab_to_type(iwn.name)
};
let mut sv = quote! { Self };
if path[path.len() - 2].imported() {
if instance.imported() {
if let Some(iv) = &s.import_param_var {
sv = quote! { #iv }
};
Expand Down Expand Up @@ -740,18 +753,22 @@ fn emit_extern_decl<'a, 'b, 'c>(
TokenStream::new()
};

let getter = kebab_to_getter(wn.name);
let (member_tn, member_getter) = if origin_was_export {
(kebab_to_type(wn.name), kebab_to_getter(wn.name))
} else {
import_member_names(&wn, &s.colliding_import_names)
};
let rp = s.root_path();
let tns = wn.namespace_path();
let tn = kebab_to_type(wn.name);
let trait_tn = kebab_to_type(wn.name);
let trait_bound = if tns.is_empty() {
quote! { #rp #tn }
quote! { #rp #trait_tn }
} else {
quote! { #rp #tns::#tn }
quote! { #rp #tns::#trait_tn }
};
quote! {
type #tn: #trait_bound #vs;
fn #getter(&mut self) -> impl ::core::borrow::BorrowMut<Self::#tn>;
type #member_tn: #trait_bound #vs;
fn #member_getter(&mut self) -> impl ::core::borrow::BorrowMut<Self::#member_tn>;
}
}
ExternDesc::Component(_) => {
Expand Down Expand Up @@ -844,6 +861,7 @@ fn emit_component<'a, 'b, 'c>(s: &'c mut State<'a, 'b>, wn: WitName, ct: &'c Com
.map(Clone::clone)
.collect::<VecDeque<_>>();
s.cur_trait = Some(import_name.clone());
s.colliding_import_names = find_colliding_import_names(&ct.imports);
let imports = ct
.imports
.iter()
Expand Down
49 changes: 49 additions & 0 deletions src/hyperlight_host/tests/wit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,4 +487,53 @@ mod bindgen_test_cases {
};
assert_eq!(result.message, "executed");
}

#[allow(dead_code)]
struct ExportHost;

impl test::bindgen_test_cases::Executor for ExportHost {
fn execute(&mut self) -> test::bindgen_test_cases::executor::ExecutionResult {
test::bindgen_test_cases::executor::ExecutionResult {
message: String::from("executed"),
}
}
}

impl test::bindgen_test_cases::Types for ExportHost {
fn get_status(&mut self) -> test::bindgen_test_cases::types::Status {
test::bindgen_test_cases::types::Status {
message: String::from("ok"),
}
}
}

impl test::bindgen_test_cases::UsesExportedTypes<test::bindgen_test_cases::types::Status>
for ExportHost
{
fn get_status(&mut self) -> test::bindgen_test_cases::types::Status {
test::bindgen_test_cases::types::Status {
message: String::from("ok"),
}
}
}

#[allow(refining_impl_trait)]
impl<I: test::bindgen_test_cases::BindgenTestCasesImports + Send>
test::bindgen_test_cases::BindgenTestCasesExports<I> for ExportHost
{
type Executor = Self;
fn executor(&mut self) -> &mut Self {
self
}

type Types = Self;
fn types(&mut self) -> &mut Self {
self
}

type UsesExportedTypes = Self;
fn uses_exported_types(&mut self) -> &mut Self {
self
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a:bc;

interface types {
resource thing;

record plain-bc-info {
label: string,
}
get-plain-bc-info: func() -> plain-bc-info;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a:b-c;

interface types {
resource thing;

record bc-info {
label: string,
}
get-bc-info: func() -> bc-info;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package a:pkg;

interface types {
resource thing;

record info {
name: string,
value: u32,
}
get-info: func() -> info;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a-b:c;

interface types {
resource thing;

record ab-c-info {
tag: string,
}
get-ab-c-info: func() -> ab-c-info;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package b:pkg;

interface types {
resource thing;

record detail {
label: string,
count: u64,
}
get-detail: func() -> detail;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package c:pkg@1.0.0;

interface types {
resource thing;

record info {
value: u32,
}
get-info: func() -> info;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package c:pkg@2.0.0;

interface types {
resource thing;

record info {
value: u32,
}
get-info: func() -> info;
}
67 changes: 67 additions & 0 deletions src/tests/rust_guests/witguest/bindgen-test-cases/world.wit
Original file line number Diff line number Diff line change
@@ -1,7 +1,61 @@
package test:bindgen-test-cases;

world bindgen-test-cases {
import types: interface {
get-status: func() -> string;
}
import a:pkg/types;
import b:pkg/types;
import c:pkg/types@1.0.0;
import c:pkg/types@2.0.0;
import a:bc/types;
import a:b-c/types;
import a-b:c/types;
import uses-a-pkg-resource;
import uses-b-pkg-resource;
import uses-c-pkg-v1-resource;
import uses-c-pkg-v2-resource;
import uses-a-bc-plain-resource;
import uses-a-bc-resource;
import uses-ab-c-resource;
export executor;
export types;
export uses-exported-types;
}

interface uses-a-pkg-resource {
use a:pkg/types.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-b-pkg-resource {
use b:pkg/types.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-c-pkg-v1-resource {
use c:pkg/types@1.0.0.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-c-pkg-v2-resource {
use c:pkg/types@2.0.0.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-a-bc-plain-resource {
use a:bc/types.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-a-bc-resource {
use a:b-c/types.{thing};
use-thing: func(x: borrow<thing>);
}

interface uses-ab-c-resource {
use a-b:c/types.{thing};
use-thing: func(x: borrow<thing>);
}

interface executor {
Expand All @@ -11,3 +65,16 @@ interface executor {

execute: func() -> execution-result;
}

interface types {
record status {
message: string,
}

get-status: func() -> status;
}

interface uses-exported-types {
use types.{status};
get-status: func() -> status;
}
Loading