Skip to content

Commit

Permalink
Allow import/export overlap in wit-parser
Browse files Browse the repository at this point in the history
Updates to WebAssembly/component-model#259 by relaxing some checks here
and there.

Closes bytecodealliance#1396
  • Loading branch information
alexcrichton committed Feb 2, 2024
1 parent 56d0d94 commit c14f197
Show file tree
Hide file tree
Showing 14 changed files with 219 additions and 49 deletions.
11 changes: 7 additions & 4 deletions crates/wit-parser/src/ast/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,12 @@ impl<'a> Resolver<'a> {

let mut export_spans = Vec::new();
let mut import_spans = Vec::new();
let mut used_names = HashMap::new();
let mut import_names = HashMap::new();
let mut export_names = HashMap::new();
for (name, (item, span)) in self.type_lookup.iter() {
match *item {
TypeOrItem::Type(id) => {
let prev = used_names.insert(*name, "import");
let prev = import_names.insert(*name, "import");
if let Some(prev) = prev {
return Err(Error {
span: *span,
Expand All @@ -617,20 +618,22 @@ impl<'a> Resolver<'a> {
let mut imported_interfaces = HashSet::new();
let mut exported_interfaces = HashSet::new();
for item in world.items.iter() {
let (docs, kind, desc, spans, interfaces) = match item {
let (docs, kind, desc, spans, interfaces, names) = match item {
ast::WorldItem::Import(import) => (
&import.docs,
&import.kind,
"import",
&mut import_spans,
&mut imported_interfaces,
&mut import_names,
),
ast::WorldItem::Export(export) => (
&export.docs,
&export.kind,
"export",
&mut export_spans,
&mut exported_interfaces,
&mut export_names,
),

ast::WorldItem::Type(ast::TypeDef {
Expand Down Expand Up @@ -659,7 +662,7 @@ impl<'a> Resolver<'a> {
};
let key = match kind {
ast::ExternKind::Interface(name, _) | ast::ExternKind::Func(name, _) => {
let prev = used_names.insert(name.name, desc);
let prev = names.insert(name.name, desc);
if let Some(prev) = prev {
return Err(Error {
span: kind.span(),
Expand Down
30 changes: 1 addition & 29 deletions crates/wit-parser/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1463,14 +1463,6 @@ impl Remap {
span,
})
}

// check if this type has name conflict with any of the exported item.
if world.exports.contains_key(&WorldKey::Name(name.clone())) {
bail!(Error {
msg: format!("import type `{name}` conflicts with prior export of interface",),
span,
})
}
}

for (name, func, span) in import_funcs {
Expand All @@ -1485,40 +1477,20 @@ impl Remap {
span,
})
}

// check if this function has name conflict with any of the exported item.
if world.exports.contains_key(&WorldKey::Name(name.clone())) {
bail!(Error {
msg: format!(
"import of function `{name}` conflicts with prior export of interface",
),
span,
})
}
}

for (name, func, span) in export_funcs {
let prev = world
.exports
.insert(WorldKey::Name(name.clone()), WorldItem::Function(func));
if prev.is_some() || world.imports.contains_key(&WorldKey::Name(name.clone())) {
if prev.is_some() {
bail!(Error {
msg: format!(
"export of function `{name}` shadows previously exported interface"
),
span,
})
}

// check if this function has name conflict with any of the import item.
if world.imports.contains_key(&WorldKey::Name(name.clone())) {
bail!(Error {
msg: format!(
"export of function `{name}` conflicts with prior import of interface",
),
span,
})
}
}

// After all that sort functions in exports to come before interfaces in
Expand Down
39 changes: 39 additions & 0 deletions crates/wit-parser/tests/ui/import-export-overlap1.wit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"worlds": [
{
"name": "foo",
"imports": {
"a": {
"function": {
"name": "a",
"kind": "freestanding",
"params": [],
"results": []
}
}
},
"exports": {
"a": {
"function": {
"name": "a",
"kind": "freestanding",
"params": [],
"results": []
}
}
},
"package": 0
}
],
"interfaces": [],
"types": [],
"packages": [
{
"name": "foo:foo",
"interfaces": {},
"worlds": {
"foo": 0
}
}
]
}
41 changes: 41 additions & 0 deletions crates/wit-parser/tests/ui/import-export-overlap2.wit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"worlds": [
{
"name": "foo",
"imports": {
"a": {
"function": {
"name": "a",
"kind": "freestanding",
"params": [],
"results": []
}
}
},
"exports": {
"a": {
"interface": 0
}
},
"package": 0
}
],
"interfaces": [
{
"name": null,
"types": {},
"functions": {},
"package": 0
}
],
"types": [],
"packages": [
{
"name": "foo:foo",
"interfaces": {},
"worlds": {
"foo": 0
}
}
]
}

This file was deleted.

This file was deleted.

5 changes: 0 additions & 5 deletions crates/wit-parser/tests/ui/parse-fail/union-fuzz-2.wit.result

This file was deleted.

6 changes: 6 additions & 0 deletions crates/wit-parser/tests/ui/same-name-import-export.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package demo:greeter;

world greeter {
import greet: func() -> string;
export greet: func() -> string;
}
47 changes: 47 additions & 0 deletions crates/wit-parser/tests/ui/same-name-import-export.wit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"worlds": [
{
"name": "greeter",
"imports": {
"greet": {
"function": {
"name": "greet",
"kind": "freestanding",
"params": [],
"results": [
{
"type": "string"
}
]
}
}
},
"exports": {
"greet": {
"function": {
"name": "greet",
"kind": "freestanding",
"params": [],
"results": [
{
"type": "string"
}
]
}
}
},
"package": 0
}
],
"interfaces": [],
"types": [],
"packages": [
{
"name": "demo:greeter",
"interfaces": {},
"worlds": {
"greeter": 0
}
}
]
}
File renamed without changes.
72 changes: 72 additions & 0 deletions crates/wit-parser/tests/ui/union-fuzz-2.wit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"worlds": [
{
"name": "foo",
"imports": {},
"exports": {
"foo": {
"function": {
"name": "foo",
"kind": "freestanding",
"params": [],
"results": [
{
"name": "name2",
"type": "float32"
}
]
}
}
},
"package": 0
},
{
"name": "bar",
"imports": {
"foo": {
"type": 0
}
},
"exports": {
"foo": {
"function": {
"name": "foo",
"kind": "freestanding",
"params": [],
"results": [
{
"name": "name2",
"type": "float32"
}
]
}
}
},
"package": 0
}
],
"interfaces": [],
"types": [
{
"name": "foo",
"kind": {
"record": {
"fields": []
}
},
"owner": {
"world": 1
}
}
],
"packages": [
{
"name": "foo:bar",
"interfaces": {},
"worlds": {
"foo": 0,
"bar": 1
}
}
]
}
7 changes: 6 additions & 1 deletion crates/wit-smith/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ impl<'a> InterfaceGenerator<'a> {
let mut parts = Vec::new();
let mut imported_interfaces = HashSet::new();
let mut exported_interfaces = HashSet::new();
let mut export_names = HashSet::new();

while parts.len() < self.config.max_world_items && !u.is_empty() && u.arbitrary()? {
let kind = u.arbitrary::<ItemKind>()?;
Expand All @@ -432,7 +433,11 @@ impl<'a> InterfaceGenerator<'a> {
}

let name = if named {
let name = gen_unique_name(u, &mut self.unique_names)?;
let names = match direction {
Some(Direction::Import) | None => &mut self.unique_names,
Some(Direction::Export) => &mut export_names,
};
let name = gen_unique_name(u, names)?;
if direction.is_some() {
part.push_str("%");
part.push_str(&name);
Expand Down

0 comments on commit c14f197

Please sign in to comment.