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

Forward reference error #20965

Open
deadalnix opened this issue Mar 7, 2025 · 5 comments
Open

Forward reference error #20965

deadalnix opened this issue Mar 7, 2025 · 5 comments

Comments

@deadalnix
Copy link
Contributor

Sample code:

struct S {}

void foo()(S s) {
	bar(s);
}

auto bar(S s) {
	foo(s);
}

Leads to the following error:

fail.d(4): Error: forward reference to inferred return type of function call `bar(s)`
fail.d(8): Error: template instance `fail.foo!()` error instantiating

I don't think this forward reference error is justified, considering the return type for foo is known. If foo is instantiated somewhere else before it is in bar, the error goes away.

@RazvanN7 RazvanN7 changed the title Froward reference error Forward reference error Mar 7, 2025
@dkorpel
Copy link
Contributor

dkorpel commented Mar 7, 2025

I don't think this forward reference error is justified, considering the return type for foo is known.

It's not that simple, bar might end up returning a @mustuse type, which should raise an error in foo for discarding it. Whenever there's 2 mutually recursive functions and inference, things can get really tricky. There's also a long standing issue with inference of @safe (and other function attributes) in such cases. Sometimes it happens to work out when one of the two functions get analyzed first, but it's hard to define semantics that reliably handle such cases.

@deadalnix
Copy link
Contributor Author

These are all good reasons, but at the end of the day, this builds if foo is instantiated by a 3rd party, so it is likely that @mustuse and the other thing you mention are themselves broken as well. Either it's possible or it is not possible.

I'm going a bit off topic here, but this is also why adding a bunch of crap in the language continuously is bound to not yield very good results. Nobody cares about @mustuse if the code doesn't compile to begin with. This kind of things is also bound to randomly break people's code because they end up being dependent on the ordering the compiler picks to process things internally, which will constantly change.

@CyberShadow
Copy link
Member

CyberShadow commented Mar 7, 2025

@mustuse is unrelated here, this code didn't work as far back as 2.055.

@dkorpel
Copy link
Contributor

dkorpel commented Mar 7, 2025

I'm not saying @mustuse is the thing that introduced this issue. The problem is that the compiler insists on knowing the final type when analyzing a function call, and it insists on figuring that out by completing semantic analysis of the function body. @mustuse is just one example of why there are no easy short-cuts at the moment, even when the return value is discarded. Other examples are function attributes, escape analysis, and there are probably more that I don't know from the top my head.

I'm going a bit off topic here, but this is also why adding a bunch of crap in the language continuously is bound to not yield very good results.

I agree, but other people insist on getting features added.

@tgehr
Copy link
Contributor

tgehr commented Mar 7, 2025

There is not really a need to finish the semantic analysis of the template instance here to finish analysis of bar, bar does not really care about semantic errors in the body of foo. In my frontend this is resolved by the scheduler, but I guess in DMD this is quite a bit more tricky. It is able to give up on attribute inference when there are cycles though (not ideal but better than failing to compile). Maybe something similar can work to address this particular example, but there will always be forward reference issues without some comprehensive overarching design.

deadalnix pushed a commit to snazzy-d/sdc that referenced this issue Mar 10, 2025
See dlang/dmd#20965

The fix is to use a concrete return type (for now). Might actually be
clearer even, so we may want to keep it even if dmd gets fixed.

It does seem unlikely though...
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

4 participants