Auto merge of #42634 - Zoxc:for-desugar2, r=nikomatsakis
Change the for-loop desugar so the `break` does not affect type inference. Fixes #42618 Rewrite the `for` loop desugaring to avoid contaminating the inference results. Under the older desugaring, `for x in vec![] { .. }` would erroneously type-check, even though the type of `vec![]` is unconstrained. (written by @nikomatsakis)
This commit is contained in:
commit
ab5bec2553
6 changed files with 137 additions and 12 deletions
19
src/test/compile-fail/for-loop-unconstrained-element-type.rs
Normal file
19
src/test/compile-fail/for-loop-unconstrained-element-type.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that `for` loops don't introduce artificial
|
||||
// constraints on the type of the binding (`i`).
|
||||
// Subtle changes in the desugaring can cause the
|
||||
// type of elements in the vector to (incorrectly)
|
||||
// fallback to `!` or `()`.
|
||||
|
||||
fn main() {
|
||||
for i in Vec::new() { } //~ ERROR type annotations needed
|
||||
}
|
||||
43
src/test/run-pass/for-loop-lifetime-of-unbound-values.rs
Normal file
43
src/test/run-pass/for-loop-lifetime-of-unbound-values.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test when destructors run in a for loop. The intention is
|
||||
// that the value for each iteration is dropped *after* the loop
|
||||
// body has executed. This is true even when the value is assigned
|
||||
// to a `_` pattern (and hence ignored).
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
struct Flag<'a>(&'a Cell<bool>);
|
||||
|
||||
impl<'a> Drop for Flag<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.0.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let alive2 = Cell::new(true);
|
||||
for _i in std::iter::once(Flag(&alive2)) {
|
||||
// The Flag value should be alive in the for loop body
|
||||
assert_eq!(alive2.get(), true);
|
||||
}
|
||||
// The Flag value should be dead outside of the loop
|
||||
assert_eq!(alive2.get(), false);
|
||||
|
||||
let alive = Cell::new(true);
|
||||
for _ in std::iter::once(Flag(&alive)) {
|
||||
// The Flag value should be alive in the for loop body even if it wasn't
|
||||
// bound by the for loop
|
||||
assert_eq!(alive.get(), true);
|
||||
}
|
||||
// The Flag value should be dead outside of the loop
|
||||
assert_eq!(alive.get(), false);
|
||||
}
|
||||
15
src/test/run-pass/for-loop-mut-ref-element.rs
Normal file
15
src/test/run-pass/for-loop-mut-ref-element.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that for loops can bind elements as mutable references
|
||||
|
||||
fn main() {
|
||||
for ref mut _a in std::iter::once(true) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the type of `sum` falls back to `i32` here,
|
||||
// and that the for loop desugaring doesn't inferfere with
|
||||
// that.
|
||||
|
||||
fn main() {
|
||||
let mut sum = 0;
|
||||
for i in Vec::new() {
|
||||
sum += i;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue