# How to resolve unresolved parameter?

**URL:** <https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944>\
**Category:** Mojo\
**Created:** [April 8, 2026, 6:16am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944 "2026-04-08T06:16:10Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![cloudhan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/cloudhan/32/1035_2.png) [@cloudhan](https://forum.modular.com/u/cloudhan)\
**Post date:** [April 8, 2026, 6:16am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/1 "2026-04-08T06:16:11Z")

</div>

Consider I have two or more `Tuple`s in a struct.

```mojo
from std.reflection import get_type_name

def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):
    print(get_type_name[type_of(obj)]())

struct Container[
    Tuple1: Copyable,
    Tuple2: Copyable,
](ImplicitlyCopyable):
    def __init__ (out self, v1: Self.Tuple1, v2: Self.Tuple2):
        work_with_tuple(v1)

def main():
    Container((1,2), (3,4,5))

```

This, however creates a

```auto
tmp.mojo:11:9: error: invalid call to 'work_with_tuple': value passed to 'obj' cannot be converted from 'Tuple1' to 'Tuple[elems]', it depends on an unresolved parameter 'elems'
        work_with_tuple(v1)
        ^ ~~~~~~~~~~~~~~~~
/home/cloud/tmp.mojo:3:5: note: function declared here
def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):

```

You can have something like the following

```mojo
struct Container[
    # Tuple1: Copyable,
    Tuple2: Copyable,
](ImplicitlyCopyable):
    def __init__ [*elems: Movable](out self, v1: Tuple[*elems], v2: Self.Tuple2):
        work_with_tuple(v1)
        # work_with_tuple(v2)

```

Then `v1` can `work_with_tuple`, but `v2` still not. You cannot have Tuple1 type now as it is dis-associated with the ctor, but you can `comptime Tuple1 = Tuple[*Self.elems]` by moving the elems to struct parameter.

But how to deal with `v2` then? You `cannot have two ‘*’ markers in the same parameter list`.

---

<div class="post-metadata">

**Author:** ![cloudhan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/cloudhan/32/1035_2.png) [@cloudhan](https://forum.modular.com/u/cloudhan)\
**Post date:** [April 8, 2026, 7:45am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/2 "2026-04-08T07:45:45Z")

</div>

In C++, the following is easily achievable. [Compiler Explorer](https://godbolt.org/z/Ka1sPqdKq)

```cpp
#include <cstdio>
#include <tuple>

template <typename... Ts>
void work_with_tuple(std::tuple<Ts...>&& obj) {
    printf("work_with_tuple");
}

template <typename Tuple1_, typename Tuple2_>
struct Container {
    using Tuple1 = Tuple1_;
    using Tuple2 = Tuple2_;
    Container(Tuple1_&& v1, Tuple2_&& v2) {
        work_with_tuple(std::forward<Tuple1>(v1));
    }
};

int main() {
    Container(std::tuple(1,2), std::tuple(3,4,5));
}

```

as C++ template is unchecked.

Template parameters for `Tuple1` and `Tuple2` can be retrieved by other metaprogramming tricks then. I am wondering how to achieve these type of metaprogramming in mojo.

---

<div class="post-metadata">

**Author:** ![nate](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/nate/32/740_2.png) [@nate](https://forum.modular.com/u/nate)\
**Post date:** [April 8, 2026, 5:05pm UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/3 "2026-04-08T17:05:29Z")

</div>

The reason this doesn’t work in Mojo is due to how the Mojo compilation model differs from the C++ one.  
In C++ you can write

```cpp
    Container(Tuple1_&& v1, Tuple2_&& v2) {
        work_with_tuple(std::forward<Tuple1>(v1));
    }

```

because c++ doesn’t do any type checking of templated types/functions until that template is actually instantiated. Since you _could_ in C++ do

```auto
int main() {
    Container(1, 2);
}

```

And the error wouldn’t manifest until the compiler sees that `work_with_tuple` expects a tuple

```auto
In instantiation of 'Container<Tuple1_, Tuple2_>::Container(Tuple1_&&, Tuple2_&&) [with Tuple1_ = int; Tuple2_ = int]':
<source>:19:19: required from here
   19 | Container(1, 2);
      | ^
<source>:14:24: error: no matching function for call to 'work_with_tuple(int)'
   14 | work_with_tuple(std::forward<Tuple1>(v1));
      | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:14:24: note: there is 1 candidate
<source>:5:6: note: candidate 1: 'template<class ... Ts> void work_with_tuple(std::tuple<_Elements ...>&&)'
    5 | void work_with_tuple(std::tuple<Ts...>&& obj) {
      | ^ ~~~~~~~~~~~~~~
<source>:5:6: note: template argument deduction/substitution failed:
<source>:14:24: note: mismatched types 'std::tuple<_Elements ...>' and 'int'
   14 | work_with_tuple(std::forward<Tuple1>(v1));
      | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

```

* * *

However, in Mojo the compiler needs _proof_ that the values passed to `work_with_tuple` are actually tuples and not just anytype.  
Which is why

```mojo
struct Container[
    Tuple1: Copyable,
    Tuple2: Copyable,
](ImplicitlyCopyable):
    def __init__ (out self, v1: Self.Tuple1, v2: Self.Tuple2):
        work_with_tuple(v1)

```

does not work. `v1` and `v1` could be any `Copyable` type, not just a `Tuple`. We need to _prove_ to the compiler that `v1` and `v2` are actually tuples. The way you can write this is something as such:

```mojo
from std.reflection import get_type_name

def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):
    print(get_type_name[type_of(obj)]())

struct Container(ImplicitlyCopyable):
    def __init__ (out self, v1: Tuple[...], v2: Tuple[...]):
        work_with_tuple(v1)
        work_with_tuple(v2)

def main():
    Container((1,2), (3,4,5))

```

Here we proving to the compiler that `v1` and `v2` are actually tuples. So it knows you can call `work_with_tuple` and never get a type error.

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 8, 2026, 7:32pm UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/4 "2026-04-08T19:32:33Z")

</div>

I think it’s important to note here that this behavior difference from C++ is one of the reasons that Mojo compiles so much faster. Local reasoning is a super important policy for performance.

---

<div class="post-metadata">

**Author:** ![cloudhan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/cloudhan/32/1035_2.png) [@cloudhan](https://forum.modular.com/u/cloudhan)\
**Post date:** [April 9, 2026, 12:47am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/5 "2026-04-09T00:47:35Z")

</div>

> [@nate](#):
>
> ```auto
> struct Container(ImplicitlyCopyable):
> def __init__ (out self, v1: Tuple[...], v2: Tuple[...]):
> work_with_tuple(v1)
> work_with_tuple(v2)
> 
> ```

This doesn’t work. Things are passed to ctor with reasons.

```mojo
struct Container(ImplicitlyCopyable):
    var v1: ???
    var v2: ???????????????
    def __init__ (out self, v1: Tuple[...], v2: Tuple[...]):
        work_with_tuple(v1)
        work_with_tuple(v2)

```

---

<div class="post-metadata">

**Author:** ![cloudhan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/cloudhan/32/1035_2.png) [@cloudhan](https://forum.modular.com/u/cloudhan)\
**Post date:** [April 9, 2026, 6:04am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/6 "2026-04-09T06:04:15Z")

</div>

After playing around with this problem a little bit more during C++ compiling 😅 , I made some progress:

```mojo
from std.reflection import get_type_name

def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):
    print(get_type_name[type_of(obj)]())

struct Container[
    T1: type_of(Tuple[...]), # So type_of(Tuple[...]) is a Trait for TupleLike?
    T2: type_of(Tuple[...]),
]:
    # Since T1 and T2 are TupleLike, they have .element_types, good!
    comptime Elems1 = Self.T1.element_types
    comptime Elems2 = Self.T2.element_types

    # Since T1 and T2 is known now, so we can store v1 and v2, good!
    var v1: Self.T1
    var v2: Self.T2

    def __init__ (out self, var v1: Self.T1, var v2: Self.T2):
        work_with_tuple(v1)
        work_with_tuple(v2)
        # we need to move it unfortunately, Copyable is not inferred correctly.
        self.v1 = v1^
        self.v2 = v2^

def main():
    var v1 = (1,2)
    var v2 = (3,4,5)
    Container[type_of(v1), type_of(v2)](v1, v2)
    # Container(v1, v2) # this does not compile, bad!

```

The last line failed, if uncommented, with errror as follows,

```bash
<source>:29:14: error: invalid initialization: failed to infer parameter 'T1' of parent struct 'Container'
    Container(v1, v2) # this does not compile, bad!
    ~~~~~~~~~^~~~~~~~
<source>:6:8: note: struct declared here
struct Container[
       ^
<source>:18:9: note: function declared here
    def __init__ (out self, var v1: Self.T1, var v2: Self.T2):

```

@owenhilyard @nate any idea?

---

<div class="post-metadata">

**Author:** ![cloudhan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/cloudhan/32/1035_2.png) [@cloudhan](https://forum.modular.com/u/cloudhan)\
**Post date:** [April 9, 2026, 8:14am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/7 "2026-04-09T08:14:48Z")

</div>

OK, more progress during more C++ compilation 😅

```mojo
from std.reflection import get_type_name

def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):
    print(get_type_name[type_of(obj)]())

struct Container[
    T1: type_of(Tuple[...]), # So type_of(Tuple[...]) is a Trait for TupleLike?
    T2: type_of(Tuple[...]),
]:
    # Since T1 and T2 are TupleLike, they have .element_types, good!
    comptime Elems1 = Self.T1.element_types
    comptime Elems2 = Self.T2.element_types

    # Since T1 and T2 is known now, so we can store v1 and v2, good!
    var v1: Self.T1
    var v2: Self.T2

    def __init__ (out self, var v1: Self.T1, var v2: Self.T2):
        work_with_tuple(v1)
        work_with_tuple(v2)
        # we need to move it unfortunately, Copyable is not inferred correctly.
        self.v1 = v1^
        self.v2 = v2^

def detour(var v1: Tuple[...], var v2: Tuple[...]) -> Container[type_of(v1), type_of(v2)]:
    return Container[type_of(v1), type_of(v2)](v1^, v2^)

def main():
    _ = detour((1,2), (3,4,5)) # It worked! Ugly!

```

Is there any chance we can omit the `detour` to enforce the type inference?

---

<div class="post-metadata">

**Author:** ![jbemmel](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@jbemmel](https://forum.modular.com/u/jbemmel)\
**Post date:** [April 9, 2026, 2:33pm UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/8 "2026-04-09T14:33:45Z")

</div>

This is similar to [Comptime parameterized return type - #12 by jbemmel](https://forum.modular.com/t/comptime-parameterized-return-type/2847/12)

The ‘rebind’ would ideally be inferred

---

<div class="post-metadata">

**Author:** ![Peiming](https://avatars.discourse-cdn.com/v4/letter/p/49beb7/32.png) [@Peiming](https://forum.modular.com/u/Peiming)\
**Post date:** [April 10, 2026, 3:33am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/9 "2026-04-10T03:33:02Z")

</div>

Try

```auto
from std.reflection import get_type_name

def work_with_tuple[*elems: Movable](obj: Tuple[*elems]):
    print(get_type_name[type_of(obj)]())

struct Container[
    Elems1: Variadic.TypesOfTrait[Movable],
    Elems2: Variadic.TypesOfTrait[Movable],
]:
    # Since T1 and T2 is known now, so we can store v1 and v2, good!
    var v1: Tuple[*Self.Elems1]
    var v2: Tuple[*Self.Elems2]

    def __init__ (
        out self, var v1: Tuple[*Self.Elems1], var v2: Tuple[*Self.Elems2]
    ):
        work_with_tuple(v1)
        work_with_tuple(v2)
        # we need to move it unfortunately, Copyable is not inferred correctly.
        self.v1 = v1^
        self.v2 = v2^

def main():
    _ = Container((1, 2), (3, 4, 5))

```

BTW, I think Chris is working on improving variadics as well, this will be improved soon.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex001/uploads/modular/original/1X/2751e0fbdc595a99718b216730957e9db4448cfd.jpeg) [@system](https://forum.modular.com/u/system)\
**Post date:** [April 17, 2026, 3:33am UTC](https://forum.modular.com/t/how-to-resolve-unresolved-parameter/2944/10 "2026-04-17T03:33:41Z")

</div>

Closed on April 17, 2026, 3:33am UTC

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.
