diff options
| author | bors <bors@rust-lang.org> | 2014-07-25 07:46:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-07-25 07:46:12 +0000 |
| commit | e5984640e63d2e9f613d857ad2d48ff57b310655 (patch) | |
| tree | 73f74ca586a4c1ab3f6c816ae3d59592ef264204 | |
| parent | 4e388859a2e12f4019a09224d626eb07b8333651 (diff) | |
| parent | d1dcd19d26ae8ed8a3836defb3e7f4166ca178b8 (diff) | |
| download | rust-e5984640e63d2e9f613d857ad2d48ff57b310655.tar.gz rust-e5984640e63d2e9f613d857ad2d48ff57b310655.zip | |
auto merge of #15961 : pcwalton/rust/fn-pointer-in-iterator, r=huonw
This breaks code like:
struct A<'a> {
func: &'a fn() -> Option<int>
}
fn foo() -> Option<int> { ... }
fn create() -> A<'static> {
A {
func: &foo
}
}
Change this code to not take functions by reference. For example:
struct A {
func: extern "Rust" fn() -> Option<int>
}
fn foo() -> Option<int> { ... }
fn create() -> A {
A {
func: foo
}
}
Closes #13595.
[breaking-change]
r? @huonw
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 6 | ||||
| -rw-r--r-- | src/test/compile-fail/static-reference-to-fn-1.rs | 34 | ||||
| -rw-r--r-- | src/test/compile-fail/static-reference-to-fn-2.rs | 58 |
3 files changed, 95 insertions, 3 deletions
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 317fdb5c387..a690d588214 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -499,11 +499,11 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { id, expr_ty.repr(self.tcx()), def); match def { - def::DefStruct(..) | def::DefVariant(..) => { + def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) | + def::DefStaticMethod(..) => { Ok(self.cat_rvalue_node(id, span, expr_ty)) } - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMod(_) | - def::DefForeignMod(_) | def::DefStatic(_, false) | + def::DefMod(_) | def::DefForeignMod(_) | def::DefStatic(_, false) | def::DefUse(_) | def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => { diff --git a/src/test/compile-fail/static-reference-to-fn-1.rs b/src/test/compile-fail/static-reference-to-fn-1.rs new file mode 100644 index 00000000000..c0d430908a1 --- /dev/null +++ b/src/test/compile-fail/static-reference-to-fn-1.rs @@ -0,0 +1,34 @@ +// 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. + +struct A<'a> { + func: &'a fn() -> Option<int> +} + +impl<'a> A<'a> { + fn call(&self) -> Option<int> { + (*self.func)() + } +} + +fn foo() -> Option<int> { + None +} + +fn create() -> A<'static> { + A { + func: &foo, //~ ERROR borrowed value does not live long enough + } +} + +fn main() { + let a = create(); + a.call(); +} diff --git a/src/test/compile-fail/static-reference-to-fn-2.rs b/src/test/compile-fail/static-reference-to-fn-2.rs new file mode 100644 index 00000000000..3a0f0a193cf --- /dev/null +++ b/src/test/compile-fail/static-reference-to-fn-2.rs @@ -0,0 +1,58 @@ +// 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. + +struct StateMachineIter<'a> { + statefn: &'a fn(&mut StateMachineIter<'a>) -> Option<&'static str> +} + +impl<'a> Iterator<&'static str> for StateMachineIter<'a> { + fn next(&mut self) -> Option<&'static str> { + return (*self.statefn)(self); + } +} + +fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { + self_.statefn = &state2; + //~^ ERROR borrowed value does not live long enough + return Some("state1"); +} + +fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { + self_.statefn = &state3; + //~^ ERROR borrowed value does not live long enough + return Some("state2"); +} + +fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { + self_.statefn = &finished; + //~^ ERROR borrowed value does not live long enough + return Some("state3"); +} + +fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> { + return None; +} + +fn state_iter() -> StateMachineIter<'static> { + StateMachineIter { + statefn: &state1 //~ ERROR borrowed value does not live long enough + } +} + + +fn main() { + let mut it = state_iter(); + println!("{}",it.next()); + println!("{}",it.next()); + println!("{}",it.next()); + println!("{}",it.next()); + println!("{}",it.next()); +} + |
