Skip to content

if_expr.md: Outline behavior regarding rustc E0317 #1090

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

daerich
Copy link

@daerich daerich commented Sep 9, 2021

Change 2nd substatement from being factual to being a possibility to hint at the following behavior:

fn main() {
let ex0 = if true {42;}; /* Passes, value is () */
let ex1 = if false {42;}; /* ditto */ 
let ex2 = if false {()}; /* Passes also */
let ex3 = if true {42}; /* Error E0317 */
}

@ehuss
Copy link
Contributor

ehuss commented Sep 14, 2021

Thanks for the contribution! I'm having a hard time trying to understand either the original or the proposed changes, and was wondering if you could maybe clarify or work towards improving this.

I'm not sure I follow the original "() if no block is evaluated". I'm guessing that is trying to cover your let ex2 = if false {()}; example, where no else blocks were technically evaluated in that example.

I'm not quite following the connection to the final expression of the blocks here. Either the block is evaluated are it isn't, so I would not expect there to be a significance here. Can you say more about why this is adding that qualification?

A detail that I think is missing here is that if there is no else block, the type of the blocks must coerce to (). I think that covers the ex3 example you have.

@daerich
Copy link
Author

daerich commented Sep 16, 2021

First off: Thanks for taking the time to review my proposed changes!

I intially wanted to incoporate two findings, when doing arbitrary tests with the compiler:

  • Firstly, when the final operand expression is present in the if- block, even if it surely will execute ( like "ex3") the compiler
    is certainly very conservative and coerces the return type to unit (): Then the original sentence in the reference is false, stating that it only does this coercion, when no block is executed. But ex3 would be executed, even though it is a laboratory example. A (useless) loophole in the reference, if you will...

  • Secondly the first finding can be disproven if there is no final operand expression to evaluate to (ex0,ex1): Then my constructed corner case passes (type) analysis ,even if its condition operand is false and returns unit () to its caller.

So I came to the conclusion that:

  • If the to be compiled code has a final condition operand it must cover all cases in its subexpressions to have it return the value of the desired type, regardless of the exact circumstances of the whole if expression(if true, should always return as intended). Otherwise an E0317 is raised (and the return type would be unit).
  • On the other hand if you don't return anything over the final operand in block expression route, the compiler doesn't, and need not care, about the exact circumstances of the if-expression, as it will be unit () anyways in Rusts type theory, and lets the code pass. This seems to be also the case for ex2.

Since I am in no way affiliated with compiler and language development I can only speculate, that the Error E0317 and the behavior regarding types and the if- expression is about declared intent, especially since ex2 passes, at least for now.
So changed the factual statement "if no block is evaluated" to a possibility "can (possibly) be evaluated" to reflect finding no. 1 and added "not any block's final operand expression" in light of my second finding.

I hope my intentions were clarified, I honestly tried :).

@ehuss
Copy link
Contributor

ehuss commented Sep 26, 2021

Thanks for trying to clarify. I think this can be fixed perhaps by changing the sentence to something like the following:

If there is no else block, the type of all the blocks must coerce to ().
An if expression evaluates to the same value as the executed block.
If no blocks are executed, as in the case where there is no else block and the condition is false, the if expression evaluates to ().

From your examples, I think this should cover them:

  • ex0: All blocks must be () which this is.
  • ex1: All blocks must be (), and the if expression evaluates to () because no blocks were executed.
  • ex2: Pretty much the same as ex1.
  • ex3: This is an error because not all blocks can coerce their types to () (42 in this case).

@ehuss
Copy link
Contributor

ehuss commented Nov 29, 2021

@daerich Just checking in to see if you are still interested in working on clarifying this? Were there any questions you had from the last suggestion?

@daerich
Copy link
Author

daerich commented Dec 4, 2021

Hey @ehuss ,
sorry for my absence lately but I am very busy with my CS Studies atm. Sure, I am still interested in clarification of that behavior.
I will look into that matter around Christmas time, when I will hopefully have time to do other work than my academic assignments.

@traviscross
Copy link
Contributor

@rustbot author

@rustbot rustbot added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Oct 22, 2024
@rustbot
Copy link
Collaborator

rustbot commented Jan 31, 2025

☔ The latest upstream changes (possibly 4249fb4) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants