rollup merge of #17041 : pcwalton/right-unboxed-closure-sugar
This commit is contained in:
commit
63cee1ada3
src
librustc/middle
libsyntax
test
@ -4328,6 +4328,34 @@ impl<'a> Resolver<'a> {
|
||||
self.resolve_trait_reference(id, tref, reference_type)
|
||||
}
|
||||
UnboxedFnTyParamBound(ref unboxed_function) => {
|
||||
match self.resolve_path(unboxed_function.ref_id,
|
||||
&unboxed_function.path,
|
||||
TypeNS,
|
||||
true) {
|
||||
None => {
|
||||
let path_str = self.path_idents_to_string(
|
||||
&unboxed_function.path);
|
||||
self.resolve_error(unboxed_function.path.span,
|
||||
format!("unresolved trait `{}`",
|
||||
path_str).as_slice())
|
||||
}
|
||||
Some(def) => {
|
||||
match def {
|
||||
(DefTrait(_), _) => {
|
||||
self.record_def(unboxed_function.ref_id, def);
|
||||
}
|
||||
_ => {
|
||||
let msg =
|
||||
format!("`{}` is not a trait",
|
||||
self.path_idents_to_string(
|
||||
&unboxed_function.path));
|
||||
self.resolve_error(unboxed_function.path.span,
|
||||
msg.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for argument in unboxed_function.decl.inputs.iter() {
|
||||
self.resolve_type(&*argument.ty);
|
||||
}
|
||||
|
@ -585,32 +585,29 @@ pub fn trait_ref_for_unboxed_function<'tcx, AC: AstConv<'tcx>,
|
||||
RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
unboxed_function: &ast::UnboxedFnTy,
|
||||
kind: ast::UnboxedClosureKind,
|
||||
decl: &ast::FnDecl,
|
||||
self_ty: Option<ty::t>)
|
||||
-> ty::TraitRef {
|
||||
let lang_item = match unboxed_function.kind {
|
||||
let lang_item = match kind {
|
||||
ast::FnUnboxedClosureKind => FnTraitLangItem,
|
||||
ast::FnMutUnboxedClosureKind => FnMutTraitLangItem,
|
||||
ast::FnOnceUnboxedClosureKind => FnOnceTraitLangItem,
|
||||
};
|
||||
let trait_did = this.tcx().lang_items.require(lang_item).unwrap();
|
||||
let input_types =
|
||||
unboxed_function.decl
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|input| {
|
||||
let input_types = decl.inputs
|
||||
.iter()
|
||||
.map(|input| {
|
||||
ast_ty_to_ty(this, rscope, &*input.ty)
|
||||
}).collect::<Vec<_>>();
|
||||
}).collect::<Vec<_>>();
|
||||
let input_tuple = if input_types.len() == 0 {
|
||||
ty::mk_nil()
|
||||
} else {
|
||||
ty::mk_tup(this.tcx(), input_types)
|
||||
};
|
||||
let output_type = ast_ty_to_ty(this,
|
||||
rscope,
|
||||
&*unboxed_function.decl.output);
|
||||
let output_type = ast_ty_to_ty(this, rscope, &*decl.output);
|
||||
let mut substs = Substs::new_type(vec!(input_tuple, output_type),
|
||||
Vec::new());
|
||||
Vec::new());
|
||||
|
||||
match self_ty {
|
||||
Some(s) => substs.types.push(SelfSpace, s),
|
||||
@ -648,7 +645,8 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
substs
|
||||
} = trait_ref_for_unboxed_function(this,
|
||||
rscope,
|
||||
&**unboxed_function,
|
||||
unboxed_function.kind,
|
||||
&*unboxed_function.decl,
|
||||
None);
|
||||
let r = ptr_ty.default_region();
|
||||
let tr = ty::mk_trait(this.tcx(),
|
||||
@ -1510,7 +1508,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
pub struct PartitionedBounds<'a> {
|
||||
pub builtin_bounds: ty::BuiltinBounds,
|
||||
pub trait_bounds: Vec<&'a ast::TraitRef>,
|
||||
pub unboxed_fn_ty_bounds: Vec<&'a ast::UnboxedFnTy>,
|
||||
pub unboxed_fn_ty_bounds: Vec<&'a ast::UnboxedFnBound>,
|
||||
pub region_bounds: Vec<&'a ast::Lifetime>,
|
||||
}
|
||||
|
||||
@ -1574,7 +1572,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
||||
region_bounds.push(l);
|
||||
}
|
||||
ast::UnboxedFnTyParamBound(ref unboxed_function) => {
|
||||
unboxed_fn_ty_bounds.push(unboxed_function);
|
||||
unboxed_fn_ty_bounds.push(&**unboxed_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1427,7 +1427,8 @@ pub fn instantiate_unboxed_fn_ty<'tcx,AC>(this: &AC,
|
||||
let param_ty = param_ty.to_ty(this.tcx());
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(this,
|
||||
&rscope,
|
||||
unboxed_function,
|
||||
unboxed_function.kind,
|
||||
&*unboxed_function.decl,
|
||||
Some(param_ty)))
|
||||
}
|
||||
|
||||
@ -2165,9 +2166,42 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
region_bounds,
|
||||
unboxed_fn_ty_bounds } =
|
||||
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
|
||||
let unboxed_fn_ty_bounds =
|
||||
unboxed_fn_ty_bounds.into_iter()
|
||||
.map(|b| instantiate_unboxed_fn_ty(this, b, param_ty));
|
||||
|
||||
let unboxed_fn_ty_bounds = unboxed_fn_ty_bounds.move_iter().map(|b| {
|
||||
let trait_id = this.tcx().def_map.borrow().get(&b.ref_id).def_id();
|
||||
let mut kind = None;
|
||||
for &(lang_item, this_kind) in [
|
||||
(this.tcx().lang_items.fn_trait(), ast::FnUnboxedClosureKind),
|
||||
(this.tcx().lang_items.fn_mut_trait(),
|
||||
ast::FnMutUnboxedClosureKind),
|
||||
(this.tcx().lang_items.fn_once_trait(),
|
||||
ast::FnOnceUnboxedClosureKind)
|
||||
].iter() {
|
||||
if Some(trait_id) == lang_item {
|
||||
kind = Some(this_kind);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let kind = match kind {
|
||||
Some(kind) => kind,
|
||||
None => {
|
||||
this.tcx().sess.span_err(b.path.span,
|
||||
"unboxed function trait must be one \
|
||||
of `Fn`, `FnMut`, or `FnOnce`");
|
||||
ast::FnMutUnboxedClosureKind
|
||||
}
|
||||
};
|
||||
|
||||
let rscope = ExplicitRscope;
|
||||
let param_ty = param_ty.to_ty(this.tcx());
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(this,
|
||||
&rscope,
|
||||
kind,
|
||||
&*b.decl,
|
||||
Some(param_ty)))
|
||||
});
|
||||
|
||||
let trait_bounds: Vec<Rc<ty::TraitRef>> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|b| {
|
||||
|
@ -213,12 +213,19 @@ pub static DUMMY_NODE_ID: NodeId = -1;
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(TraitRef),
|
||||
UnboxedFnTyParamBound(UnboxedFnTy),
|
||||
UnboxedFnTyParamBound(P<UnboxedFnBound>),
|
||||
RegionTyParamBound(Lifetime)
|
||||
}
|
||||
|
||||
pub type TyParamBounds = OwnedSlice<TyParamBound>;
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct UnboxedFnBound {
|
||||
pub path: Path,
|
||||
pub decl: P<FnDecl>,
|
||||
pub ref_id: NodeId,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct TyParam {
|
||||
pub ident: Ident,
|
||||
|
@ -657,16 +657,26 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_ty_param_bound<T: Folder>(tpb: TyParamBound, fld: &mut T)
|
||||
-> TyParamBound {
|
||||
pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
|
||||
-> TyParamBound
|
||||
where T: Folder {
|
||||
match tpb {
|
||||
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
|
||||
RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
|
||||
UnboxedFnTyParamBound(UnboxedFnTy {decl, kind}) => {
|
||||
UnboxedFnTyParamBound(UnboxedFnTy {
|
||||
decl: fld.fold_fn_decl(decl),
|
||||
kind: kind,
|
||||
})
|
||||
UnboxedFnTyParamBound(bound) => {
|
||||
match *bound {
|
||||
UnboxedFnBound {
|
||||
ref path,
|
||||
ref decl,
|
||||
ref_id
|
||||
} => {
|
||||
UnboxedFnTyParamBound(P(UnboxedFnBound {
|
||||
path: fld.fold_path(path.clone()),
|
||||
decl: fld.fold_fn_decl(decl.clone()),
|
||||
ref_id: fld.new_id(ref_id),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
|
||||
use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
|
||||
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
|
||||
use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
|
||||
use ast::{UnboxedFnBound, UnboxedFnTy, UnboxedFnTyParamBound};
|
||||
use ast::{UnnamedField, UnsafeBlock};
|
||||
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
|
||||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use ast::{Visibility, WhereClause, WherePredicate};
|
||||
@ -3666,39 +3667,6 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
|
||||
let (optional_unboxed_closure_kind, inputs) =
|
||||
if self.eat(&token::OROR) {
|
||||
(None, Vec::new())
|
||||
} else {
|
||||
self.expect_or();
|
||||
|
||||
let optional_unboxed_closure_kind =
|
||||
self.parse_optional_unboxed_closure_kind();
|
||||
|
||||
let inputs = self.parse_seq_to_before_or(&token::COMMA,
|
||||
|p| {
|
||||
p.parse_arg_general(false)
|
||||
});
|
||||
self.expect_or();
|
||||
(optional_unboxed_closure_kind, inputs)
|
||||
};
|
||||
|
||||
let (return_style, output) = self.parse_ret_ty();
|
||||
UnboxedFnTy {
|
||||
decl: P(FnDecl {
|
||||
inputs: inputs,
|
||||
output: output,
|
||||
cf: return_style,
|
||||
variadic: false,
|
||||
}),
|
||||
kind: match optional_unboxed_closure_kind {
|
||||
Some(kind) => kind,
|
||||
None => FnMutUnboxedClosureKind,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a sequence of bounds if a `:` is found,
|
||||
// otherwise returns empty list.
|
||||
fn parse_colon_then_ty_param_bounds(&mut self)
|
||||
@ -3730,13 +3698,31 @@ impl<'a> Parser<'a> {
|
||||
self.bump();
|
||||
}
|
||||
token::MOD_SEP | token::IDENT(..) => {
|
||||
let tref = self.parse_trait_ref();
|
||||
result.push(TraitTyParamBound(tref));
|
||||
}
|
||||
token::BINOP(token::OR) | token::OROR => {
|
||||
let unboxed_function_type =
|
||||
self.parse_unboxed_function_type();
|
||||
result.push(UnboxedFnTyParamBound(unboxed_function_type));
|
||||
let path =
|
||||
self.parse_path(LifetimeAndTypesWithoutColons).path;
|
||||
if self.token == token::LPAREN {
|
||||
self.bump();
|
||||
let inputs = self.parse_seq_to_end(
|
||||
&token::RPAREN,
|
||||
seq_sep_trailing_allowed(token::COMMA),
|
||||
|p| p.parse_arg_general(false));
|
||||
let (return_style, output) = self.parse_ret_ty();
|
||||
result.push(UnboxedFnTyParamBound(P(UnboxedFnBound {
|
||||
path: path,
|
||||
decl: P(FnDecl {
|
||||
inputs: inputs,
|
||||
output: output,
|
||||
cf: return_style,
|
||||
variadic: false,
|
||||
}),
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
})));
|
||||
} else {
|
||||
result.push(TraitTyParamBound(ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
}))
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
@ -4423,14 +4409,6 @@ impl<'a> Parser<'a> {
|
||||
Some(attrs))
|
||||
}
|
||||
|
||||
/// Parse a::B<String,int>
|
||||
fn parse_trait_ref(&mut self) -> TraitRef {
|
||||
ast::TraitRef {
|
||||
path: self.parse_path(LifetimeAndTypesWithoutColons).path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse struct Foo { ... }
|
||||
fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo {
|
||||
let class_name = self.parse_ident();
|
||||
|
@ -2190,16 +2190,13 @@ impl<'a> State<'a> {
|
||||
self.print_lifetime(lt)
|
||||
}
|
||||
UnboxedFnTyParamBound(ref unboxed_function_type) => {
|
||||
self.print_ty_fn(None,
|
||||
None,
|
||||
ast::NormalFn,
|
||||
ast::Many,
|
||||
&*unboxed_function_type.decl,
|
||||
None,
|
||||
&OwnedSlice::empty(),
|
||||
None,
|
||||
None,
|
||||
Some(unboxed_function_type.kind))
|
||||
try!(self.print_path(&unboxed_function_type.path,
|
||||
false));
|
||||
try!(self.popen());
|
||||
try!(self.print_fn_args(&*unboxed_function_type.decl,
|
||||
None));
|
||||
try!(self.pclose());
|
||||
self.print_fn_output(&*unboxed_function_type.decl)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -2430,6 +2427,23 @@ impl<'a> State<'a> {
|
||||
self.end()
|
||||
}
|
||||
|
||||
pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
|
||||
match decl.output.node {
|
||||
ast::TyNil => Ok(()),
|
||||
_ => {
|
||||
try!(self.space_if_not_bol());
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(self.word_space("->"));
|
||||
if decl.cf == ast::NoReturn {
|
||||
try!(self.word_nbsp("!"));
|
||||
} else {
|
||||
try!(self.print_type(&*decl.output));
|
||||
}
|
||||
self.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_ty_fn(&mut self,
|
||||
opt_abi: Option<abi::Abi>,
|
||||
opt_sigil: Option<char>,
|
||||
@ -2510,20 +2524,7 @@ impl<'a> State<'a> {
|
||||
|
||||
try!(self.maybe_print_comment(decl.output.span.lo));
|
||||
|
||||
match decl.output.node {
|
||||
ast::TyNil => {}
|
||||
_ => {
|
||||
try!(self.space_if_not_bol());
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(self.word_space("->"));
|
||||
if decl.cf == ast::NoReturn {
|
||||
try!(self.word_nbsp("!"));
|
||||
} else {
|
||||
try!(self.print_type(&*decl.output));
|
||||
}
|
||||
try!(self.end());
|
||||
}
|
||||
}
|
||||
try!(self.print_fn_output(decl));
|
||||
|
||||
match generics {
|
||||
Some(generics) => try!(self.print_where_clause(generics)),
|
||||
|
@ -10,17 +10,17 @@
|
||||
|
||||
#![feature(overloaded_calls)]
|
||||
|
||||
fn a<F:|&: int, int| -> int>(mut f: F) {
|
||||
fn a<F:Fn(int, int) -> int>(mut f: F) {
|
||||
let g = &mut f;
|
||||
f(1, 2); //~ ERROR cannot borrow `f` as immutable
|
||||
//~^ ERROR cannot borrow `f` as immutable
|
||||
}
|
||||
|
||||
fn b<F:|&mut: int, int| -> int>(f: F) {
|
||||
fn b<F:FnMut(int, int) -> int>(f: F) {
|
||||
f(1, 2); //~ ERROR cannot borrow immutable argument
|
||||
}
|
||||
|
||||
fn c<F:|: int, int| -> int>(f: F) {
|
||||
fn c<F:FnOnce(int, int) -> int>(f: F) {
|
||||
f(1, 2);
|
||||
f(1, 2); //~ ERROR use of moved value
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
// 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.
|
||||
|
||||
fn f<F:Nonexist(int) -> int>(x: F) {} //~ ERROR unresolved trait
|
||||
|
||||
type Typedef = int;
|
||||
|
||||
fn g<F:Typedef(int) -> int>(x: F) {} //~ ERROR `Typedef` is not a trait
|
||||
|
||||
fn main() {}
|
||||
|
17
src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs
Normal file
17
src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
trait Trait {}
|
||||
|
||||
fn f<F:Trait(int) -> int>(x: F) {}
|
||||
//~^ ERROR unboxed function trait must be one of `Fn`, `FnMut`, or `FnOnce`
|
||||
|
||||
fn main() {}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#![feature(lang_items, overloaded_calls, unboxed_closures)]
|
||||
|
||||
fn c<F:|: int, int| -> int>(f: F) -> int {
|
||||
fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
|
||||
f(5, 6)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ impl FnMut<(int,),int> for S {
|
||||
}
|
||||
}
|
||||
|
||||
fn call_it<F:|int|->int>(mut f: F, x: int) -> int {
|
||||
fn call_it<F:FnMut(int)->int>(mut f: F, x: int) -> int {
|
||||
f.call_mut((x,)) + 3
|
||||
}
|
||||
|
||||
|
@ -10,15 +10,15 @@
|
||||
|
||||
#![feature(lang_items, overloaded_calls, unboxed_closures)]
|
||||
|
||||
fn a<F:|&: int, int| -> int>(f: F) -> int {
|
||||
fn a<F:Fn(int, int) -> int>(f: F) -> int {
|
||||
f(1, 2)
|
||||
}
|
||||
|
||||
fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
|
||||
fn b<F:FnMut(int, int) -> int>(mut f: F) -> int {
|
||||
f(3, 4)
|
||||
}
|
||||
|
||||
fn c<F:|: int, int| -> int>(f: F) -> int {
|
||||
fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
|
||||
f(5, 6)
|
||||
}
|
||||
|
||||
|
@ -41,15 +41,15 @@ impl Drop for Droppable {
|
||||
}
|
||||
}
|
||||
|
||||
fn a<F:|&: int, int| -> int>(f: F) -> int {
|
||||
fn a<F:Fn(int, int) -> int>(f: F) -> int {
|
||||
f(1, 2)
|
||||
}
|
||||
|
||||
fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
|
||||
fn b<F:FnMut(int, int) -> int>(mut f: F) -> int {
|
||||
f(3, 4)
|
||||
}
|
||||
|
||||
fn c<F:|: int, int| -> int>(f: F) -> int {
|
||||
fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
|
||||
f(5, 6)
|
||||
}
|
||||
|
||||
|
@ -13,15 +13,15 @@
|
||||
|
||||
#![feature(overloaded_calls, unboxed_closures)]
|
||||
|
||||
fn a<F:|&: int, int| -> int>(f: F) -> int {
|
||||
fn a<F:Fn(int, int) -> int>(f: F) -> int {
|
||||
f(1, 2)
|
||||
}
|
||||
|
||||
fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
|
||||
fn b<F:FnMut(int, int) -> int>(mut f: F) -> int {
|
||||
f(3, 4)
|
||||
}
|
||||
|
||||
fn c<F:|: int, int| -> int>(f: F) -> int {
|
||||
fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
|
||||
f(5, 6)
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
use std::ptr;
|
||||
|
||||
pub fn replace_map<'a, T, F>(src: &mut T, prod: F)
|
||||
where F: |: T| -> T {
|
||||
pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
|
||||
unsafe { *src = prod(ptr::read(src as *mut T as *const T)); }
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
struct Bencher;
|
||||
|
||||
// ICE
|
||||
fn warm_up<'a, F>(f: F) where F: |&: &'a mut Bencher| {
|
||||
fn warm_up<'a, F>(f: F) where F: Fn(&'a mut Bencher) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user