Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Graph] error encoding a component: "import name conflicts with previous name" #65

Closed
rylev opened this issue Apr 5, 2024 · 4 comments · Fixed by #67
Closed

[Graph] error encoding a component: "import name conflicts with previous name" #65

rylev opened this issue Apr 5, 2024 · 4 comments · Fixed by #67

Comments

@rylev
Copy link
Collaborator

rylev commented Apr 5, 2024

Imagine two components targeting this world:

world {
  import wasi:http/[email protected];
  export wasi:http/[email protected];
}

The following code composes these components such that the export from component 2 is supplied as the import to component 1 and then the export from component 1 is ultimately exported from the composition:

    let component1 = wac_graph::types::Package::from_bytes("component1", None, Arc::new(component.into())).unwrap();
    let component2 = wac_graph::types::Package::from_bytes("component2", None, Arc::new(component.into())).unwrap();

    let mut graph = wac_graph::CompositionGraph::new();
    let component1 = graph.register_package(component1).unwrap();
    let component2 = graph.register_package(component2).unwrap();

    let component1 = graph.instantiate(component1).unwrap();
    let component2 = graph.instantiate(component2).unwrap();

    let alias = graph
        .alias_instance_export(component2, "wasi:http/[email protected]")
        .unwrap();

    graph
        .connect_argument(alias, component1, "wasi:http/[email protected]")
        .unwrap();
    let export = graph
        .alias_instance_export(component1, "wasi:http/[email protected]")
        .unwrap();

    graph
        .export(export, "wasi:http/[email protected]")
        .unwrap();

    graph.encode().unwrap();

This errors with the following message:

import name `wasi:http/[email protected]` conflicts with previous name `wasi:http/[email protected]

Looking into where implicit imports are encoded in CompositionGraphEncoder::populate_implicit_args, it seems that the type aggregator is not dedupping interfaces as I would expect. After aggregation the aggregator's Types collection has a duplicate copy of the wasi:http/[email protected] interface.

I believe the issue seems to be in remap_interface that the interface id associated with any used type is not in the same arena as the types in aggregated collection. The indices seem to be the same, but when doing look ups against the aggregated collection, None is returned.

This means that we treat the used type's interface as a completely unseen interface, and we'll remap and then add it to the interfaces collection instead of seeing that it's already been aggregated. Perhaps this is ultimately correct as we can't be sure that this interface is actually equivalent to the interfaces we've seen before.

However, instead of remapping the interface and adding it to the collection of interfaces, we need to try to merge the interface with any previously seen interface with the same name. This would indicate to me that instead of doing remapping when iterating through all the used types, we need to merge the used type's interface into an existing interface with the same name.

I believe this is what the aggregate method essentially does, so perhaps the right answer is to call aggregate instead of remap_interface. This would require threading the cache down into remap_interface and making remap_interface fallible as the merging could potentially fail. This would also require making a version of aggregate that does not consume self.

Am I thinking about this correctly or am I totally off base?

@peterhuene
Copy link
Member

I think your assessment is probably correct, something is going wrong in the aggregation such that the transitively "used" interface of wasi:http/types is not being properly deduped and merged.

@peterhuene
Copy link
Member

Which reminds me, I need to address #55 in the graph as well: encode on the graph should error if you attempt to implicitly import an argument that is used from another argument which has been supplied (i.e. incoming-handler is supplied, but types is not).

@peterhuene
Copy link
Member

Also, I think you're right about recursing with aggregate, as merging of usings is really a transitive import so we need to keep track of whether or not we've seen that "name" before.

I think we could probably replace the cache argument to aggregate with the checker and continue to just pass that down.

@peterhuene
Copy link
Member

Although, aggregate intentionally consumes self; let me see what a proper fix would look like.

peterhuene added a commit that referenced this issue Apr 5, 2024
This commit fixes aggregation of imports that have used types.

Previously, interfaces weren't being coalesced properly, resulting in duplicate
imports of used interfaces that would result in an encoding validation error.

The fix is to coalesce interfaces by interface identifier, merging interfaces
together during the remapping process.

Additionally, this fixes a bug in encoding where any implicitly imported
instances were not getting their encoded indexes recorded in the encoding state
properly.

Also changed the map in the type aggregator to store `Type`s rather than
`ItemKind`s, which makes things neater.

Fixes #65.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants