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

internal compiler error: trans_lvalue reached fall-through case #7507

Closed
DaGenix opened this issue Jun 30, 2013 · 8 comments · Fixed by #10123
Closed

internal compiler error: trans_lvalue reached fall-through case #7507

DaGenix opened this issue Jun 30, 2013 · 8 comments · Fixed by #10123

Comments

@DaGenix
Copy link

DaGenix commented Jun 30, 2013

When compiling the following code:

fn test() -> (u32, u32) {
    return (0, 0);
}

fn main() {
    let mut X0 = 0u32;
    let mut X1 = 0u32;
    (X0, X1) = test();
}

I get the error:

multi-bind-issue.rs:9:4: 9:12 error: internal compiler error: trans_lvalue reached fall-through case: expr_tup(~[@{id: 24, node: expr_path(@{span: {lo: {__field__: 113}, hi: {__field__: 115}, expn_info: None}, global: false, idents: ~[{name: 68, ctxt: 0}], rp: None, types: ~[]}), span: {lo: {__field__: 113}, hi: {__field__: 115}, expn_info: None}}, @{id: 25, node: expr_path(@{span: {lo: {__field__: 117}, hi: {__field__: 119}, expn_info: None}, global: false, idents: ~[{name: 69, ctxt: 0}], rp: None, types: ~[]}), span: {lo: {__field__: 117}, hi: {__field__: 119}, expn_info: None}}])
multi-bind-issue.rs:9     (X0, X1) = test();
                          ^~~~~~~~

Compiled with: 8883099

@bstrie
Copy link
Contributor

bstrie commented Jul 25, 2013

I also just hit this today. An even simpler test case:

fn main() {
    let (x,y) = (1,2);
    (x,y) = (3,4);
}
tup.rs:3:4: 3:9 error: internal compiler error: trans_lvalue reached fall-through case: expr_tup(~[@{id: 11, node: expr_path({span: {lo: {__field__: 40}, hi: {__field__: 41}, expn_info: None}, global: false, idents: ~[{name: 66, ctxt: 0}], rp: None, types: ~[]}), span: {lo: {__field__: 40}, hi: {__field__: 41}, expn_info: None}}, @{id: 12, node: expr_path({span: {lo: {__field__: 42}, hi: {__field__: 43}, expn_info: None}, global: false, idents: ~[{name: 67, ctxt: 0}], rp: None, types: ~[]}), span: {lo: {__field__: 42}, hi: {__field__: 43}, expn_info: None}}])
tup.rs:3     (x,y) = (3,4);
             ^~~~~

@klutzy
Copy link
Contributor

klutzy commented Aug 30, 2013

Reproduced with 5ef8cdb (both cases).
Interestingly, rustc warns that X0 and X1 don't need to be mutable on the first case.

@klutzy
Copy link
Contributor

klutzy commented Aug 30, 2013

Similar ICE with structs:

struct X { x: int, y: int }
let (a, b) = (1, 2);
A { x: a, y: b } = A { x: 3, y: 4 };

@klutzy
Copy link
Contributor

klutzy commented Aug 30, 2013

The simplest case I think:

1 = 2;

@klutzy
Copy link
Contributor

klutzy commented Aug 30, 2013

It's because trans_lvalue_unadjusted() assumes only one of ast::expr_{unary, index, field, path, paren} will come but it met ast::expr_{tup, struct, lit}.

So 1 = 2; seems easy to fix, but what about tuples/structs? (x, y) = (3, 4) is also not allowed, right?
I initially thought it is allowed because let (x, y) = (3, 4) is. But previous discussions seem that it's not: #7508, #8273.

@lilyball
Copy link
Contributor

lilyball commented Sep 1, 2013

My impression is that (x, y) = (3, 4) isn't supposed to be allowed. That said, it would be kinda neat if it was. Right now I'm writing the same 3 lines over and over that look like

let (a,b) = some_func();
self.a = a;
self.b = b;

and I'd love to be able to just say

(self.a, self.b) = some_func();

@klutzy
Copy link
Contributor

klutzy commented Sep 1, 2013

I forgot to mention about mutability; currently let mut (a, b) = ... is obsolete, and (heard from irc) it may be because it's confusing that immutable tuples are with mut. I don't know any previous discussion about it. anyone?
If it is true, (x, y) = (3, 4) should be disallowed in the same manner, because (x, y) is immutable while x and y are.

Anyway, I agree with @kballard; it's not cool to unpack manually.

@nikomatsakis
Copy link
Contributor

Clearly something in the compiler is not checking that the LHS of an assignment is actually an lvalue. Kind of amusing. Rather surprising that this gets through borrowck, I'll have to look at that. It's probably assuming that an earlier pass would have caught such cases.

Anyway, it'd be nice to permit (self.a, self.b) = some_func(), certainly, but it is not currently allowed. I think that'd be a post-Rust 1.0 sort of extension. I previously thought it would introduce horrible ambiguities into parsing, but I realize now that it would not, so long as you only have two cases: let, which assigns to a pattern, and which always declares new bindings, and lhs = rhs, which always overwrites existing lvalues.

bors added a commit that referenced this issue Oct 30, 2013
This patch fixes rustc to emit explicit error if LHS of assignment is
not allowed.

Fixes #7507
Fixes #7508
@bors bors closed this as completed in 47abdbd Oct 30, 2013
flip1995 pushed a commit to flip1995/rust that referenced this issue Aug 12, 2021
Remove `or_patterns` feature gate in example

changelog: removed `or_patterns` feature gate in the code example for the [`unnested_or_patterns`] lint
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

Successfully merging a pull request may close this issue.

5 participants