Auto merge of #27087 - nikomatsakis:closure-exploration, r=nrc
Refactors the "desugaring" of closures to expose the types of the upvars. This is necessary to be faithful with how actual structs work. The reasoning of the particular desugaring that I chose is explained in a fairly detailed comment. As a side-effect, recursive closure types are prohibited unless a trait object intermediary is used. This fixes #25954 and also eliminates concerns about unrepresentable closure types that have infinite size, I believe. I don't believe this can cause regressions because of #25954. (As for motivation, besides #25954 etc, this work is also intended as refactoring in support of incremental compilation, since closures are one of the thornier cases encountered when attempting to split node-ids into item-ids and within-item-ids. The goal is to eliminate the "internal def-id" distinction in astdecoding. However, I have to do more work on trans to really make progress there.) r? @nrc
This commit is contained in:
commit
5e6b534362
35 changed files with 536 additions and 371 deletions
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2012 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.
|
||||
|
||||
// Regression test for #25954: detect and reject a closure type that
|
||||
// references itself.
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
struct A<T: Fn()> {
|
||||
x: RefCell<Option<T>>,
|
||||
b: Cell<i32>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = A{x: RefCell::new(None), b: Cell::new(4i32)};
|
||||
|
||||
// This is an error about types of infinite size:
|
||||
let q = || p.b.set(5i32); //~ ERROR mismatched types
|
||||
|
||||
*(p.x.borrow_mut()) = Some(q);
|
||||
}
|
||||
23
src/test/compile-fail/issue-25368.rs
Normal file
23
src/test/compile-fail/issue-25368.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2014-2015 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.
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread::spawn;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Foo<T> {foo: PhantomData<T>}
|
||||
|
||||
fn main() {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(move || {
|
||||
tx.send(Foo{ foo: PhantomData }); //~ ERROR E0282
|
||||
});
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<FnMut()->(isize) + 'a> {
|
|||
|
||||
fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
|
||||
// This is illegal, because the region bound on `proc` is 'static.
|
||||
Box::new(move|| { *x }) //~ ERROR captured variable `x` does not outlive the enclosing closure
|
||||
Box::new(move|| { *x }) //~ ERROR does not fulfill the required lifetime
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue