Skip to content

[BUG] Function expressions outside a statement #385

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

Closed
JohelEGP opened this issue Apr 19, 2023 · 2 comments · Fixed by #601
Closed

[BUG] Function expressions outside a statement #385

JohelEGP opened this issue Apr 19, 2023 · 2 comments · Fixed by #601
Labels
bug Something isn't working

Comments

@JohelEGP
Copy link
Contributor

JohelEGP commented Apr 19, 2023

Besides the type with a requires, these attempt to forward declare a function expression.

Minimal reproducer (https://godbolt.org/z/b95ha454e):

z: <V: _> type == int;

a: z<:() = { }> = ();
b: <T> type requires :() -> _ = true;() = { }
c: <V: z<:() = { }>> () = { }
d: (_: z<:() = { }>) = { }

Commands:

cppfront x.cpp2
clang++17 -std=c++2b -stdlib=libc++ -I $CPPFRONT_INCLUDE_DIR x.cpp

Expected result: It's not possible in general to forward declare something that requires repeating a lambda in the definition and declaration due to the repeated lambda expressions having different types. See https://compiler-explorer.com/z/GxKcYnhMe. So maybe these uses of a function expression should be banned.

Actual result and error:

Generated Cpp1.
//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"


#line 4 "/app/main.cpp2"
template<typename T> requires( () )

class b;

//=== Cpp2 type definitions and function declarations ===========================

#line 1 "/app/main.cpp2"
template<auto V> using z = int;

extern z<[]() -> void;
> a; template<typename T> requires( public: []() -> auto;
() )
class b {
      public: b() = default;
      public: b(b const&) = delete;
      public: auto operator=(b const&) -> void = delete;

#line 4 "/app/main.cpp2"
};
template<z<[]() -> void;
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;


//=== Cpp2 function definitions =================================================


#line 3 "/app/main.cpp2"
z<[]() -> void{}> a {}; 

template<z<[]() -> void{}> V> auto c() -> void{}
auto d(cpp2::in<z<[]() -> void{}>> _) -> void{}
Many Cpp1 errors.
main.cpp2:4:33: error: expected expression
template<typename T> requires( () )
                                ^
main.cpp2:3:22: error: expected body of lambda expression
extern z<[]() -> void;
                     ^
main.cpp2:3:22: error: expected '>'
main.cpp2:3:9: note: to match this '<'
extern z<[]() -> void;
        ^
main.cpp2:4:1: error: expected unqualified-id
> a; template<typename T> requires( public: []() -> auto;
^
main.cpp2:4:37: error: expected expression
> a; template<typename T> requires( public: []() -> auto;
                                    ^
main.cpp2:5:2: error: expected unqualified-id
() )
 ^
main.cpp2:5:24: error: expected body of lambda expression
template<z<[]() -> void;
                       ^
main.cpp2:5:24: error: expected '>'
main.cpp2:5:11: note: to match this '<'
template<z<[]() -> void;
          ^
main.cpp2:5:24: error: expected ',' or '>' in template-parameter-list
template<z<[]() -> void;
                       ^
main.cpp2:5:24: error: declaration does not declare anything
main.cpp2:6:1: error: expected unqualified-id
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
^
main.cpp2:6:54: error: expected body of lambda expression
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                                     ^
main.cpp2:6:54: error: expected '>'
main.cpp2:6:41: note: to match this '<'
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                        ^
main.cpp2:6:54: error: type name requires a specifier or qualifier
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                                     ^
main.cpp2:6:54: error: expected '>'
main.cpp2:6:39: note: to match this '<'
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                      ^
main.cpp2:6:54: error: expected body of lambda expression
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                                     ^
main.cpp2:6:54: error: expected '>'
main.cpp2:6:41: note: to match this '<'
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                        ^
main.cpp2:6:54: error: type name requires a specifier or qualifier
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                                     ^
main.cpp2:6:54: error: expected '>'
main.cpp2:6:39: note: to match this '<'
> V> auto c() -> void; auto d(cpp2::in<z<[]() -> void;>> _) -> void;
                                      ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

Other observations: Now is #472.

@JohelEGP
Copy link
Contributor Author

Expected result: It's not possible in general to forward declare something that requires repeating a lambda in the definition and declaration due to the repeated lambda expressions having different types. See https://compiler-explorer.com/z/GxKcYnhMe. So maybe these uses of a function expression should be banned.

The above seems to only be a problem within a requires-clause (for order independence).
05d12f9 uses lambdas through UFCS in the signature of non-templated functions just fine.
Their use is fine in templates to some extent
(refer to https://eel.is/c++draft/temp.over.link, keywords "equivalent" and "functionally equivalent").

@JohelEGP
Copy link
Contributor Author

Another place where function expressions are fine due to being lowered only once:

  • The type of this data members.

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

Successfully merging a pull request may close this issue.

1 participant