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

[BUG] Forward declaration of deduced namespace scope variable is ill-formed #315

Closed
JohelEGP opened this issue Apr 2, 2023 · 10 comments
Closed
Labels
bug Something isn't working

Comments

@JohelEGP
Copy link
Contributor

JohelEGP commented Apr 2, 2023

Describe the bug

error: declaration of variable 'y' with deduced type 'auto' requires an initializer
extern auto y;
            ^

To Reproduce
Steps to reproduce the behavior:

  1. Sample code - distilled down to minimal essentials please
y := 0;
  1. Command lines including which C++ compiler you are using
~/root/bin/cppfront x.cpp2 
~/root/clang/bin/clang++ -std=c++20 -I $CPPFRONT_INCLUDE_DIR x.cpp
clang version 17.0.0
  1. Expected result - what you expected to happen
    To generate working code, if possible. Perhaps by replacing auto with decltype(initializing expression).

  2. Actual result/error

x.cpp2:1:13: error: declaration of variable 'y' with deduced type 'auto' requires an initializer
extern auto y;
            ^
1 error generated.
@JohelEGP JohelEGP added the bug Something isn't working label Apr 2, 2023
@hsutter
Copy link
Owner

hsutter commented Apr 2, 2023

Good catch, thanks. Namespace-scope variables have constraints (and I will likely be adding more, such as constexpr-ness, if I continue supporting them at all). One of those should be that they must have a concrete type, not a deduced type, because deduction interferes with order-independence. Thanks!

@hsutter hsutter closed this as completed in cd961d1 Apr 2, 2023
@AbhinavK00
Copy link

I will likely be adding more, such as constexpr-ness

Would there be a way to opt-out of it? Like some anti-constexpr keyword or such?
Also, I was thinking if in a similar fashion to this, you would like to make all thread_local objects constinit? with some dyn-init to opt out, or (preferably) a supress block.

@JohelEGP
Copy link
Contributor Author

they must have a concrete type, not a deduced type, because deduction interferes with order-independence.

What about this example? https://godbolt.org/z/n1azY7zbP:

g: () -> _ = f();
f: () -> _ = 0;
main.cpp2:1:41: error: function 'f' with deduced return type cannot be used before it is defined
[[nodiscard]] auto g() -> auto { return f();  }
                                        ^
main.cpp2:2:20: note: 'f' declared here
[[nodiscard]] auto f() -> auto;
                   ^

Where is the line drawn?

I think it's great being able to have some order independence.
But I think that'd better be a feature of using concrete types.

That's because I'm dubious.
About the benefits of the seemingly artificial limitations being introduced.
And whether we won't end up running into corner cases all the way.
(Lowering to Cpp1 means corner cases abound).

Even a full-fledged Cpp2 compiler would have to define what order independence means
in face of the many things that are order dependent in Cpp1.
Maybe that would be possible in a modules-only world.

@hsutter
Copy link
Owner

hsutter commented Apr 19, 2023

Quick ack re "interferes": Some examples of deduced return types can work more easily, such as when the body doesn't involve a function call that involves another deduced return type. Other examples (like yours above) are inherently order-dependent because the would require a dependency graph walk to resolve. Still other examples can be unresolvable (if there's a dependency cycle) and so the graph walk would have to flag and reject those cases, but I'm not sure that's a scalable approach especially when it can be affected by overload resolution and what overloads are visible.

@HALL9kv0
Copy link

Hello everyone. Once again I want to congratulate Herb and the rest of the contributors for the amazing work. I truly believe that your work is of utmost importance for the future of c++. If C++ doesn’t make the leap with the new syntax soon, it will not be able to attract new developers, which will eventually push companies to use other languages (i.e. Rust) for which they will be able to find developers.

Now that namespace scoped objects cannot be of a deduced type (i.e. lambdas), I find that I have to copy/paste multiple times in different functions the same lambda function (to use it in different vector of lambda variants), which leads do many lines of duplicate code.

One solution would be to create those vectors of lambdas in main function and pass it to the other functions which would have to be templated.

To avoid that I tried to make these lambdas concrete types, (i.e. Functors) but I haven’t found the way to make operator() work. I would like to ask if is a way to make operator() work currently either like a member function or UFCS, or like a free function such as in the case of the operator<< overload (since we don’t have friend yet), or is it planned for the future? A code example is available here

I understand the complexities of solving the dependency graph, but in all honesty this limitation takes away a lot of convenience.

Once again, thank you for cpp2, I’ve been trying it out converting some small projects in cpp2 and now it is really hard to go back and write cpp1 again.. I only miss clang-format and the highlighting.

@JohelEGP
Copy link
Contributor Author

I only miss clang-format

I can't even begin without it ;)
Hopefully I'll have something ready soon.

@JohelEGP
Copy link
Contributor Author

I would like to ask if is a way to make operator() work currently

Mixed mode and a macro works: https://godbolt.org/z/xoE8ra8jo.

#define call_op operator()

Functor: type ={
    call_op:(inout this)-> std::string = "Functor"; // NOT COMPILING
}

@HALL9kv0
Copy link

Nice hack!!! Thank you :)

@JohelEGP
Copy link
Contributor Author

JohelEGP commented Apr 29, 2023

Can you open a bug report for operator() not working? It's in grammar, and it's necessary for operator= to work. See #387 (comment).
The issue seems to be that () is not an operator.
Neither is [].

@hsutter
Copy link
Owner

hsutter commented Apr 29, 2023

Thanks for pointing that out -- this was an oversight (I just didn't notice () and [] didn't work), and that hack shouldn't be needed.

hsutter added a commit that referenced this issue Apr 29, 2023
zaucy pushed a commit to zaucy/cppfront that referenced this issue Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants