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

Possibly-uninitialized error message doesn't indicate where value isn't initialized #97956

Closed
jonhoo opened this issue Jun 10, 2022 · 4 comments · Fixed by #98360
Closed

Possibly-uninitialized error message doesn't indicate where value isn't initialized #97956

jonhoo opened this issue Jun 10, 2022 · 4 comments · Fixed by #98360
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@jonhoo
Copy link
Contributor

jonhoo commented Jun 10, 2022

Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d0d96c280bcde85e4d524178fefca741

let pkg;
if true {
    pkg = 1;
} else {
    // I forgot to initialize pkg!
}
drop(pkg);

The current output is:

error[[E0381]](https://doc.rust-lang.org/stable/error-index.html#E0381): use of possibly-uninitialized variable: `pkg`
 --> src/main.rs:8:10
  |
8 |     drop(pkg);
  |          ^^^ use of possibly-uninitialized `pkg`

Ideally the output should look like:

error[[E0381]](https://doc.rust-lang.org/stable/error-index.html#E0381): use of possibly-uninitialized variable: `pkg`
 --> src/main.rs:8:10
  |
8 |     drop(pkg);
  |          ^^^ use of possibly-uninitialized `pkg`
  |
  | hint: the value is not assigned in the branch starting on src/main.rs:5:
  |
5 |     } else {
  |

Because it can be difficult to figure out exactly which branch is failing to initialize a value, especially if it's not as simple as one if as above. For example, there may be a whole tree of conditionals between the let and the use, where only one sub-branch fails to initialize the variable, but spotting that amidst all the code isn't easy.

@jonhoo jonhoo added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 10, 2022
@jonhoo
Copy link
Contributor Author

jonhoo commented Jun 10, 2022

Here's a more elaborate case simplified from where this originally hit me: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a43b50d67a4b2f30f06b9b8f2efb7af

@rseymour
Copy link

Would a successful fix for this step you through the locations more than blast out all of them? i.e. hint: the value is *first* not assigned in the branch starting on ...

@jonhoo
Copy link
Contributor Author

jonhoo commented Jun 10, 2022

It's a good question. I think you would actually want all of them at once, because you will have to fix each one anyway. One possible exception is if the value isn't set in any branch, in which case I think just pointing out that it needs to be set is sufficient.

@estebank
Copy link
Contributor

Output with #98360:

error[E0381]: used binding `pkg` isn't initialized in all conditions
 --> f43.rs:8:10
  |
2 |     let pkg;
  |         --- binding declared here but left uninitialized
...
5 |     } else {
  |      ------ `pkg` is uninitialized if this `else` arm is executed
...
8 |     drop(pkg);
  |          ^^^ `pkg` used here but it isn't initialized in all conditions

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 25, 2022
 On partial uninit error point at where we need init

When a binding is declared without a value, borrowck verifies that all
codepaths have *one* assignment to them to initialize them fully. If
there are any cases where a condition can be met that leaves the binding
uninitialized or we attempt to initialize a field of an uninitialized
binding, we emit E0381.

We now look at all the statements that initialize the binding, and use
them to explore branching code paths that *don't* and point at them. If
we find *no* potential places where an assignment to the binding might
be missing, we display the spans of all the existing initializers to
provide some context.

Fix rust-lang#97956.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 25, 2022
 On partial uninit error point at where we need init

When a binding is declared without a value, borrowck verifies that all
codepaths have *one* assignment to them to initialize them fully. If
there are any cases where a condition can be met that leaves the binding
uninitialized or we attempt to initialize a field of an uninitialized
binding, we emit E0381.

We now look at all the statements that initialize the binding, and use
them to explore branching code paths that *don't* and point at them. If
we find *no* potential places where an assignment to the binding might
be missing, we display the spans of all the existing initializers to
provide some context.

Fix rust-lang#97956.
@bors bors closed this as completed in 9b21131 Jul 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants