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

Code generation does not add template parameters for struct name when calling static methods #1025

Open
cg-jl opened this issue Aug 2, 2022 · 1 comment

Comments

@cg-jl
Copy link
Contributor

cg-jl commented Aug 2, 2022

Let's say I have the following Jakt code:

/// Expect:
/// - output: ""
struct SecretHolder<T> {
    private secret: T
    function create(secret: T) -> SecretHolder<T> => SecretHolder(secret)
}

function main() {
    let holder = SecretHolder::create(42i32)
}

It will typecheck and generate:

#include <lib.h>
namespace Jakt {
template <typename T>struct SecretHolder;
template <typename T>struct SecretHolder {
  public:
T secret;static SecretHolder<T> create(const T secret) {
{
return (SecretHolder());
}
}
SecretHolder(T a_secret) :secret(a_secret){}

ErrorOr<String> debug_description() const { auto builder = MUST(StringBuilder::create());TRY(builder.append("SecretHolder("));JaktInternal::_pretty_print_level++;
TRY(JaktInternal::_output_pretty_indent(builder));TRY(builder.append("secret: "));TRY(builder.appendff("{}", secret));
JaktInternal::_pretty_print_level--;
TRY(builder.append(")"));return builder.to_string(); }};ErrorOr<int> main(Array<String>) {
{
const SecretHolder<i32> holder = SecretHolder::create(static_cast<i32>(42));
}
return 0;
}

template<typename T>struct Formatter<SecretHolder<T>
> : Formatter<StringView>{
ErrorOr<void> format(FormatBuilder& builder, SecretHolder<T>
 const& value)
{ if (m_alternative_form) { JaktInternal::_pretty_print_enabled = true; }return Formatter<StringView>::format(builder, MUST(value.debug_description())); }};
} // namespace Jakt

Here, the typechecking is correct. It inferred correctly that I have created a SecretHolder<i32>, and that SecretHolder::create does not throw. The problem is that codegen did not add the template arguments in SecretHolder<T>::create, and this confuses clang++:

❯ clang++ -w -I. -I<path/to/runtime> test.cpp -std=c++20
test.cpp:18:34: error: 'SecretHolder' is not a class, namespace, or enumeration
const SecretHolder<i32> holder = SecretHolder::create(static_cast<i32>(42));
                                 ^
test.cpp:4:29: note: 'SecretHolder' declared here
template <typename T>struct SecretHolder {
                            ^
1 error generated.

Clang fails at recognizing SecretHolder as a struct, since it's really a template.

The correct behavior should use SecretHolder<i32>::create(static_cast<i32>), i.e instantiating the template explicitly.

EDIT: simplified sample snippet to contain just Jakt code.

@cg-jl
Copy link
Contributor Author

cg-jl commented Aug 3, 2022

Tracked it down to typechecker not filling the namespace.generic_parameters attribute in the resolved namespace. I tried checking if the last namespace was a struct then reference its generic_parameters array, but this doesn't resolve the T.

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

No branches or pull requests

1 participant