components: Fix bindgen! with renamed interfaces (#5968)

This follows the same strategy pioneered by the `wit-bindgen` guest Rust
bindgen which keeps track of the latest name of an interface for how to
refer to an interface.

Closes #5961
This commit is contained in:
Alex Crichton
2023-03-08 17:15:58 -06:00
committed by GitHub
parent 8a08fedc69
commit 9141fcf8cf
3 changed files with 34 additions and 17 deletions

View File

@@ -0,0 +1,14 @@
interface red {
use self.green.{thing}
foo: func() -> thing
}
interface green {
type thing = s32
}
default world neptune {
import blue: self.red
import orange: self.green
}

View File

@@ -1,7 +1,7 @@
use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode}; use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode};
use crate::types::{TypeInfo, Types}; use crate::types::{TypeInfo, Types};
use heck::*; use heck::*;
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashMap};
use std::fmt::Write as _; use std::fmt::Write as _;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::mem; use std::mem;
@@ -33,6 +33,7 @@ struct Wasmtime {
exports: Exports, exports: Exports,
types: Types, types: Types,
sizes: SizeAlign, sizes: SizeAlign,
interface_names: HashMap<InterfaceId, String>,
} }
enum Import { enum Import {
@@ -113,6 +114,7 @@ impl Wasmtime {
Import::Function { sig, add_to_linker } Import::Function { sig, add_to_linker }
} }
WorldItem::Interface(id) => { WorldItem::Interface(id) => {
gen.gen.interface_names.insert(*id, snake.clone());
gen.current_interface = Some(*id); gen.current_interface = Some(*id);
gen.types(*id); gen.types(*id);
gen.generate_trappable_error_types(TypeOwner::Interface(*id)); gen.generate_trappable_error_types(TypeOwner::Interface(*id));
@@ -159,6 +161,7 @@ impl Wasmtime {
} }
WorldItem::Type(_) => unreachable!(), WorldItem::Type(_) => unreachable!(),
WorldItem::Interface(id) => { WorldItem::Interface(id) => {
gen.gen.interface_names.insert(*id, snake.clone());
gen.current_interface = Some(*id); gen.current_interface = Some(*id);
gen.types(*id); gen.types(*id);
gen.generate_trappable_error_types(TypeOwner::Interface(*id)); gen.generate_trappable_error_types(TypeOwner::Interface(*id));
@@ -1382,8 +1385,18 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
self.resolve self.resolve
} }
fn current_interface(&self) -> Option<InterfaceId> { fn path_to_interface(&self, interface: InterfaceId) -> Option<String> {
self.current_interface match self.current_interface {
Some(id) if id == interface => None,
_ => {
let name = &self.gen.interface_names[&interface];
Some(if self.current_interface.is_some() {
format!("super::{name}")
} else {
name.clone()
})
}
}
} }
fn push_str(&mut self, s: &str) { fn push_str(&mut self, s: &str) {

View File

@@ -15,7 +15,7 @@ pub trait RustGenerator<'a> {
fn push_str(&mut self, s: &str); fn push_str(&mut self, s: &str);
fn info(&self, ty: TypeId) -> TypeInfo; fn info(&self, ty: TypeId) -> TypeInfo;
fn current_interface(&self) -> Option<InterfaceId>; fn path_to_interface(&self, interface: InterfaceId) -> Option<String>;
fn print_ty(&mut self, ty: &Type, mode: TypeMode) { fn print_ty(&mut self, ty: &Type, mode: TypeMode) {
match ty { match ty {
@@ -64,20 +64,10 @@ pub trait RustGenerator<'a> {
self.result_name(id) self.result_name(id)
}; };
if let TypeOwner::Interface(id) = ty.owner { if let TypeOwner::Interface(id) = ty.owner {
if let Some(name) = &self.resolve().interfaces[id].name { if let Some(path) = self.path_to_interface(id) {
match self.current_interface() { self.push_str(&path);
Some(cur) if cur == id => {}
Some(_other) => {
self.push_str("super::");
self.push_str(&name.to_snake_case());
self.push_str("::"); self.push_str("::");
} }
None => {
self.push_str(&name.to_snake_case());
self.push_str("::");
}
}
}
} }
self.push_str(&name); self.push_str(&name);