Skip to content

[server sdk] Nested list shapes with constraints can result in unbuildable code #3868

Open
@nated0g

Description

@nated0g

We ran into an issue when modelling an existing API (that we do not control the shape of) as smithy and trying to generate a rust server sdk with smithy-rs. The following smithy model:

$version: "2"

namespace example

use aws.api#service
use aws.protocols#restJson1
use smithy.framework#ValidationException

/// Bars Quuxes into Foos.
@service(sdkId: "Foo")
@restJson1
service FooService {
    version: "2006-03-01"
    operations: [
        BarOperation
    ]
}

/// Performs a bar operation.
@http(uri: "/bar", method: "POST")
operation BarOperation {
    input: BarInput
    output: BarOutput
    errors: [
        ValidationException
    ]
}

string Foo

/// Output for the BarOperation.
structure BarOutput {
    /// The result of the bar operation.
    result: Foo
}

/// Input for the BarOperation.
structure BarInput {
    @required
    quuxes: QuuxList
}

@length(min: 0, max: 2)
list QuuxList {
    member: SubQuuxList
}

list SubQuuxList {
    member: Quux
}

structure Quux {
    @required
    quux: String
}

Will generate code that can't compile. After generating a server SDK and running cargo build on it, we encounter the following error:

   Compiling foo-rs v0.0.1 (/Users/nathaniel/workplace/smithy-openapi-issue-test/build/smithy/source/rust-server-codegen)
error[E0277]: the trait bound `QuuxList: TryFrom<Vec<SubQuuxListConstrained>>` is not satisfied
  --> src/unconstrained.rs:37:13
   |
37 |             Self::try_from(inner)
   |             ^^^^ the trait `From<Vec<SubQuuxListConstrained>>` is not implemented for `QuuxList`, which is required by `QuuxList: TryFrom<Vec<SubQuuxListConstrained>>`
   |
   = help: the following other types implement trait `TryFrom<T>`:
             `QuuxList` implements `TryFrom<QuuxListUnconstrained>`
             `QuuxList` implements `TryFrom<Vec<Vec<Quux>>>`
   = note: required for `Vec<SubQuuxListConstrained>` to implement `Into<QuuxList>`
   = note: required for `QuuxList` to implement `TryFrom<Vec<SubQuuxListConstrained>>`

error[E0308]: mismatched types
  --> src/unconstrained.rs:37:13
   |
19 |         fn try_from(value: QuuxListUnconstrained) -> Result<Self, Self::Error> {
   |                                                      ------------------------- expected `Result<QuuxList, quux_list::ConstraintViolation>` because of return type
...
37 |             Self::try_from(inner)
   |             ^^^^^^^^^^^^^^^^^^^^^ expected `Result<QuuxList, ConstraintViolation>`, found `Result<QuuxList, Infallible>`
   |
   = note: expected enum `Result<_, quux_list::ConstraintViolation>`
              found enum `Result<_, Infallible>`

error[E0277]: the trait bound `QuuxList: From<Vec<SubQuuxListConstrained>>` is not satisfied
  --> src/unconstrained.rs:37:13
   |
37 |             Self::try_from(inner)
   |             ^^^^^^^^^^^^^^^^^^^^^ the trait `From<Vec<SubQuuxListConstrained>>` is not implemented for `QuuxList`, which is required by `QuuxList: TryFrom<Vec<SubQuuxListConstrained>>`
   |
   = help: the following other types implement trait `TryFrom<T>`:
             `QuuxList` implements `TryFrom<QuuxListUnconstrained>`
             `QuuxList` implements `TryFrom<Vec<Vec<Quux>>>`
   = note: required for `Vec<SubQuuxListConstrained>` to implement `Into<QuuxList>`
   = note: required for `QuuxList` to implement `TryFrom<Vec<SubQuuxListConstrained>>`

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `foo-rs` (lib) due to 3 previous errors

Adding a length constraint to SubQuuxList,

@length(min: 1)
list SubQuuxList {
    member: Quux
}

or removing the @required trait from Quux:

structure Quux {
    quux: String
}

will generate valid code.


Setting aside how sane it is or isn't to allow entry of:

{
  "quuxes": [[]]
}

, this seems like a bug. I think valid smithy should generate valid code, or fail while running smithy build, if there is some limitation that makes it impossible to generate valid code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    serverRust server SDK

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions