Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
f02b6f3a
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f02b6f3a
编写于
6月 01, 2014
作者:
P
Patrick Walton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
librustc: Implement sugar for the `FnMut` trait
上级
907d9618
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
343 addition
and
46 deletion
+343
-46
src/librustc/front/feature_gate.rs
src/librustc/front/feature_gate.rs
+6
-0
src/librustc/middle/resolve.rs
src/librustc/middle/resolve.rs
+10
-4
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+88
-8
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/collect.rs
+18
-5
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustc/middle/typeck/infer/error_reporting.rs
+3
-0
src/librustdoc/clean/mod.rs
src/librustdoc/clean/mod.rs
+4
-0
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+7
-0
src/libsyntax/fold.rs
src/libsyntax/fold.rs
+10
-0
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser.rs
+71
-13
src/libsyntax/print/pprust.rs
src/libsyntax/print/pprust.rs
+75
-16
src/libsyntax/visit.rs
src/libsyntax/visit.rs
+13
-0
src/test/run-pass/fn-trait-sugar.rs
src/test/run-pass/fn-trait-sugar.rs
+38
-0
未找到文件。
src/librustc/front/feature_gate.rs
浏览文件 @
f02b6f3a
...
...
@@ -57,6 +57,7 @@
(
"linkage"
,
Active
),
(
"struct_inherit"
,
Active
),
(
"overloaded_calls"
,
Active
),
(
"unboxed_closure_sugar"
,
Active
),
(
"quad_precision_float"
,
Active
),
...
...
@@ -291,6 +292,11 @@ fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
},
ast
::
TyBox
(
_
)
=>
{
self
.gate_box
(
t
.span
);
}
ast
::
TyUnboxedFn
(
_
)
=>
{
self
.gate_feature
(
"unboxed_closure_sugar"
,
t
.span
,
"unboxed closure trait sugar is experimental"
);
}
_
=>
{}
}
...
...
src/librustc/middle/resolve.rs
浏览文件 @
f02b6f3a
...
...
@@ -3856,14 +3856,20 @@ fn resolve_type_parameters(&mut self,
}
fn
resolve_type_parameter_bound
(
&
mut
self
,
id
:
NodeId
,
type_parameter_bound
:
&
TyParamBound
)
{
id
:
NodeId
,
type_parameter_bound
:
&
TyParamBound
)
{
match
*
type_parameter_bound
{
TraitTyParamBound
(
ref
tref
)
=>
{
self
.resolve_trait_reference
(
id
,
tref
,
TraitBoundingTypeParameter
)
}
StaticRegionTyParamBound
=>
{}
OtherRegionTyParamBound
(
_
)
=>
{}
UnboxedFnTyParamBound
(
ref
unboxed_function
)
=>
{
for
argument
in
unboxed_function
.decl.inputs
.iter
()
{
self
.resolve_type
(
argument
.ty
);
}
self
.resolve_type
(
unboxed_function
.decl.output
);
}
StaticRegionTyParamBound
|
OtherRegionTyParamBound
(
_
)
=>
{}
}
}
...
...
src/librustc/middle/typeck/astconv.rs
浏览文件 @
f02b6f3a
...
...
@@ -51,13 +51,14 @@
use
middle
::
const_eval
;
use
middle
::
def
;
use
middle
::
subst
;
use
middle
::
lang_items
::
FnMutTraitLangItem
;
use
middle
::
subst
::{
Subst
,
Substs
};
use
middle
::
ty
::{
ty_param_substs_and_ty
};
use
middle
::
subst
;
use
middle
::
ty
::
ty_param_substs_and_ty
;
use
middle
::
ty
;
use
middle
::
typeck
::
rscope
;
use
middle
::
typeck
::
rscope
::{
RegionScope
};
use
middle
::
typeck
::
lookup_def_tcx
;
use
middle
::
typeck
::
rscope
::
RegionScope
;
use
middle
::
typeck
::
rscope
;
use
util
::
ppaux
::
Repr
;
use
std
::
rc
::
Rc
;
...
...
@@ -469,6 +470,38 @@ fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
ty
::
mt
{
ty
:
ast_ty_to_ty
(
this
,
rscope
,
ty
),
mutbl
:
ast
::
MutImmutable
}
}
pub
fn
trait_ref_for_unboxed_function
<
AC
:
AstConv
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
unboxed_function
:
&
ast
::
UnboxedFnTy
)
->
ty
::
TraitRef
{
let
fn_mut_trait_did
=
this
.tcx
()
.lang_items
.require
(
FnMutTraitLangItem
)
.unwrap
();
let
input_types
=
unboxed_function
.decl
.inputs
.iter
()
.map
(|
input
|
{
ast_ty_to_ty
(
this
,
rscope
,
input
.ty
)
})
.collect
::
<
Vec
<
_
>>
();
let
input_tuple
=
ty
::
mk_tup
(
this
.tcx
(),
input_types
);
let
output_type
=
ast_ty_to_ty
(
this
,
rscope
,
unboxed_function
.decl.output
);
let
substs
=
subst
::
Substs
{
self_ty
:
None
,
tps
:
vec!
(
input_tuple
,
output_type
),
regions
:
subst
::
NonerasedRegions
(
Vec
::
new
()),
};
ty
::
TraitRef
{
def_id
:
fn_mut_trait_did
,
substs
:
substs
,
}
}
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
...
...
@@ -491,6 +524,32 @@ fn mk_pointer<AC:AstConv,
}
return
constr
(
ty
::
mk_vec
(
tcx
,
mt
,
None
));
}
ast
::
TyUnboxedFn
(
ref
unboxed_function
)
=>
{
let
trait_store
=
match
ptr_ty
{
Uniq
=>
ty
::
UniqTraitStore
,
RPtr
(
r
)
=>
{
ty
::
RegionTraitStore
(
r
,
a_seq_ty
.mutbl
)
}
_
=>
{
tcx
.sess
.span_err
(
a_seq_ty
.ty.span
,
"~trait or &trait are the only supported
\
forms of casting-to-trait"
);
return
ty
::
mk_err
();
}
};
let
ty
::
TraitRef
{
def_id
,
substs
}
=
trait_ref_for_unboxed_function
(
this
,
rscope
,
*
unboxed_function
);
return
ty
::
mk_trait
(
this
.tcx
(),
def_id
,
substs
,
trait_store
,
ty
::
empty_builtin_bounds
());
}
ast
::
TyPath
(
ref
path
,
ref
bounds
,
id
)
=>
{
// Note that the "bounds must be empty if path is not a trait"
// restriction is enforced in the below case for ty_path, which
...
...
@@ -528,7 +587,10 @@ fn mk_pointer<AC:AstConv,
return
ty
::
mk_err
();
}
};
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
bounds
,
trait_store
);
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
path
.span
,
bounds
,
trait_store
);
return
ty
::
mk_trait
(
tcx
,
result
.def_id
,
result
.substs
.clone
(),
...
...
@@ -621,7 +683,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
// Use corresponding trait store to figure out default bounds
// if none were specified.
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
&
f
.bounds
,
store
);
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
ast_ty
.span
,
&
f
.bounds
,
store
);
let
fn_decl
=
ty_of_closure
(
this
,
ast_ty
.id
,
...
...
@@ -636,7 +701,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
ast
::
TyProc
(
ref
f
)
=>
{
// Use corresponding trait store to figure out default bounds
// if none were specified.
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
&
f
.bounds
,
ty
::
UniqTraitStore
);
let
bounds
=
conv_builtin_bounds
(
this
.tcx
(),
ast_ty
.span
,
&
f
.bounds
,
ty
::
UniqTraitStore
);
let
fn_decl
=
ty_of_closure
(
this
,
ast_ty
.id
,
...
...
@@ -648,6 +716,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
None
);
ty
::
mk_closure
(
tcx
,
fn_decl
)
}
ast
::
TyUnboxedFn
(
_
)
=>
{
tcx
.sess
.span_err
(
ast_ty
.span
,
"cannot use unboxed functions here"
);
ty
::
mk_err
()
}
ast
::
TyPath
(
ref
path
,
ref
bounds
,
id
)
=>
{
let
a_def
=
match
tcx
.def_map
.borrow
()
.find
(
&
id
)
{
None
=>
{
...
...
@@ -891,7 +964,9 @@ pub fn ty_of_closure<AC:AstConv>(
}
}
fn
conv_builtin_bounds
(
tcx
:
&
ty
::
ctxt
,
ast_bounds
:
&
Option
<
OwnedSlice
<
ast
::
TyParamBound
>>
,
fn
conv_builtin_bounds
(
tcx
:
&
ty
::
ctxt
,
span
:
Span
,
ast_bounds
:
&
Option
<
OwnedSlice
<
ast
::
TyParamBound
>>
,
store
:
ty
::
TraitStore
)
->
ty
::
BuiltinBounds
{
//! Converts a list of bounds from the AST into a `BuiltinBounds`
...
...
@@ -928,6 +1003,11 @@ fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyPar
ast
::
StaticRegionTyParamBound
=>
{
builtin_bounds
.add
(
ty
::
BoundStatic
);
}
ast
::
UnboxedFnTyParamBound
(
_
)
=>
{
tcx
.sess
.span_err
(
span
,
"unboxed functions are not allowed
\
here"
);
}
ast
::
OtherRegionTyParamBound
(
span
)
=>
{
if
!
tcx
.sess.features.issue_5723_bootstrap
.get
()
{
tcx
.sess
.span_err
(
...
...
src/librustc/middle/typeck/collect.rs
浏览文件 @
f02b6f3a
...
...
@@ -48,22 +48,21 @@
use
util
::
ppaux
;
use
util
::
ppaux
::
Repr
;
use
std
::
rc
::
Rc
;
use
std
::
collections
::{
HashMap
,
HashSet
};
use
std
::
rc
::
Rc
;
use
syntax
::
abi
;
use
syntax
::
ast
::{
StaticRegionTyParamBound
,
OtherRegionTyParamBound
,
Trait
TyParamBound
};
use
syntax
::
ast
::{
StaticRegionTyParamBound
,
OtherRegionTyParamBound
};
use
syntax
::
ast
::{
TraitTyParamBound
,
UnboxedFn
TyParamBound
};
use
syntax
::
ast
;
use
syntax
::
ast_map
;
use
syntax
::
ast_util
::{
local_def
,
split_trait_methods
};
use
syntax
::
codemap
::
Span
;
use
syntax
::
codemap
;
use
syntax
::
owned_slice
::
OwnedSlice
;
use
syntax
::
parse
::
token
::
special_idents
;
use
syntax
::
parse
::
token
;
use
syntax
::
print
::
pprust
::{
path_to_str
};
use
syntax
::
visit
;
use
syntax
::
owned_slice
::
OwnedSlice
;
struct
CollectItemTypesVisitor
<
'a
>
{
ccx
:
&
'a
CrateCtxt
<
'a
>
...
...
@@ -1114,6 +1113,20 @@ fn compute_bounds(
param_bounds
.builtin_bounds
.add
(
ty
::
BoundStatic
);
}
UnboxedFnTyParamBound
(
ref
unboxed_function
)
=>
{
let
rscope
=
ExplicitRscope
;
let
mut
trait_ref
=
astconv
::
trait_ref_for_unboxed_function
(
ccx
,
&
rscope
,
unboxed_function
);
let
self_ty
=
ty
::
mk_param
(
ccx
.tcx
,
param_ty
.idx
,
param_ty
.def_id
);
trait_ref
.substs.self_ty
=
Some
(
self_ty
);
param_bounds
.trait_bounds
.push
(
Rc
::
new
(
trait_ref
));
}
OtherRegionTyParamBound
(
span
)
=>
{
if
!
ccx
.tcx.sess.features.issue_5723_bootstrap
.get
()
{
ccx
.tcx.sess
.span_err
(
...
...
src/librustc/middle/typeck/infer/error_reporting.rs
浏览文件 @
f02b6f3a
...
...
@@ -909,6 +909,9 @@ fn rebuild_ty_param_bounds(&self,
match
tpb
{
&
ast
::
StaticRegionTyParamBound
=>
ast
::
StaticRegionTyParamBound
,
&
ast
::
OtherRegionTyParamBound
(
s
)
=>
ast
::
OtherRegionTyParamBound
(
s
),
&
ast
::
UnboxedFnTyParamBound
(
unboxed_function_type
)
=>
{
ast
::
UnboxedFnTyParamBound
(
unboxed_function_type
)
}
&
ast
::
TraitTyParamBound
(
ref
tr
)
=>
{
let
last_seg
=
tr
.path.segments
.last
()
.unwrap
();
let
mut
insert
=
Vec
::
new
();
...
...
src/librustdoc/clean/mod.rs
浏览文件 @
f02b6f3a
...
...
@@ -477,6 +477,10 @@ fn clean(&self) -> TyParamBound {
match
*
self
{
ast
::
StaticRegionTyParamBound
=>
RegionBound
,
ast
::
OtherRegionTyParamBound
(
_
)
=>
RegionBound
,
ast
::
UnboxedFnTyParamBound
(
_
)
=>
{
// FIXME(pcwalton): Wrong.
RegionBound
}
ast
::
TraitTyParamBound
(
ref
t
)
=>
TraitBound
(
t
.clean
()),
}
}
...
...
src/libsyntax/ast.rs
浏览文件 @
f02b6f3a
...
...
@@ -175,6 +175,7 @@ pub struct DefId {
pub
enum
TyParamBound
{
TraitTyParamBound
(
TraitRef
),
StaticRegionTyParamBound
,
UnboxedFnTyParamBound
(
UnboxedFnTy
),
OtherRegionTyParamBound
(
Span
)
// FIXME -- just here until work for #5723 lands
}
...
...
@@ -769,6 +770,11 @@ pub struct BareFnTy {
pub
decl
:
P
<
FnDecl
>
}
#[deriving(Clone,
PartialEq,
Eq,
Encodable,
Decodable,
Hash)]
pub
struct
UnboxedFnTy
{
pub
decl
:
P
<
FnDecl
>
,
}
#[deriving(Clone,
PartialEq,
Eq,
Encodable,
Decodable,
Hash)]
pub
enum
Ty_
{
TyNil
,
...
...
@@ -782,6 +788,7 @@ pub enum Ty_ {
TyClosure
(
@
ClosureTy
,
Option
<
Lifetime
>
),
TyProc
(
@
ClosureTy
),
TyBareFn
(
@
BareFnTy
),
TyUnboxedFn
(
@
UnboxedFnTy
),
TyTup
(
Vec
<
P
<
Ty
>>
),
TyPath
(
Path
,
Option
<
OwnedSlice
<
TyParamBound
>>
,
NodeId
),
// for #7264; see above
TyTypeof
(
@
Expr
),
...
...
src/libsyntax/fold.rs
浏览文件 @
f02b6f3a
...
...
@@ -185,6 +185,11 @@ fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
decl
:
self
.fold_fn_decl
(
f
.decl
)
})
}
TyUnboxedFn
(
ref
f
)
=>
{
TyUnboxedFn
(
@
UnboxedFnTy
{
decl
:
self
.fold_fn_decl
(
f
.decl
),
})
}
TyTup
(
ref
tys
)
=>
TyTup
(
tys
.iter
()
.map
(|
&
ty
|
self
.fold_ty
(
ty
))
.collect
()),
TyPath
(
ref
path
,
ref
bounds
,
id
)
=>
{
let
id
=
self
.new_id
(
id
);
...
...
@@ -440,6 +445,11 @@ fn fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T)
match
*
tpb
{
TraitTyParamBound
(
ref
ty
)
=>
TraitTyParamBound
(
fold_trait_ref
(
ty
,
fld
)),
StaticRegionTyParamBound
=>
StaticRegionTyParamBound
,
UnboxedFnTyParamBound
(
ref
unboxed_function_type
)
=>
{
UnboxedFnTyParamBound
(
UnboxedFnTy
{
decl
:
fld
.fold_fn_decl
(
unboxed_function_type
.decl
),
})
}
OtherRegionTyParamBound
(
s
)
=>
OtherRegionTyParamBound
(
s
)
}
}
...
...
src/libsyntax/parse/parser.rs
浏览文件 @
f02b6f3a
...
...
@@ -52,9 +52,9 @@
use
ast
::{
TypeField
,
TyFixedLengthVec
,
TyClosure
,
TyProc
,
TyBareFn
};
use
ast
::{
TyTypeof
,
TyInfer
,
TypeMethod
};
use
ast
::{
TyNil
,
TyParam
,
TyParamBound
,
TyPath
,
TyPtr
,
TyRptr
};
use
ast
::{
TyTup
,
TyU32
,
TyUniq
,
TyVec
,
UnUniq
};
use
ast
::{
Un
namedField
,
UnsafeBlock
,
UnsafeFn
,
ViewItem
};
use
ast
::{
ViewItem_
,
ViewItemExternCrate
,
ViewItemUse
};
use
ast
::{
TyTup
,
TyU32
,
TyUn
boxedFn
,
TyUn
iq
,
TyVec
,
UnUniq
};
use
ast
::{
Un
boxedFnTy
,
UnboxedFnTyParamBound
,
UnnamedField
,
UnsafeBlock
};
use
ast
::{
UnsafeFn
,
ViewItem
,
ViewItem_
,
ViewItemExternCrate
,
ViewItemUse
};
use
ast
::{
ViewPath
,
ViewPathGlob
,
ViewPathList
,
ViewPathSimple
};
use
ast
::
Visibility
;
use
ast
;
...
...
@@ -1058,15 +1058,27 @@ pub fn parse_ty_closure(&mut self) -> Ty_ {
Vec
::
new
()
};
let
inputs
=
if
self
.eat
(
&
token
::
OROR
)
{
Vec
::
new
(
)
let
(
is_unboxed
,
inputs
)
=
if
self
.eat
(
&
token
::
OROR
)
{
(
false
,
Vec
::
new
()
)
}
else
{
self
.expect_or
();
let
is_unboxed
=
self
.token
==
token
::
BINOP
(
token
::
AND
)
&&
self
.look_ahead
(
1
,
|
t
|
{
token
::
is_keyword
(
keywords
::
Mut
,
t
)
})
&&
self
.look_ahead
(
2
,
|
t
|
*
t
==
token
::
COLON
);
if
is_unboxed
{
self
.bump
();
self
.bump
();
self
.bump
();
}
let
inputs
=
self
.parse_seq_to_before_or
(
&
token
::
COMMA
,
|
p
|
p
.parse_arg_general
(
false
));
self
.expect_or
();
inputs
(
is_unboxed
,
inputs
)
};
let
(
region
,
bounds
)
=
self
.parse_optional_ty_param_bounds
(
true
);
...
...
@@ -1079,13 +1091,19 @@ pub fn parse_ty_closure(&mut self) -> Ty_ {
variadic
:
false
});
TyClosure
(
@
ClosureTy
{
fn_style
:
fn_style
,
onceness
:
onceness
,
bounds
:
bounds
,
decl
:
decl
,
lifetimes
:
lifetimes
,
},
region
)
if
is_unboxed
{
TyUnboxedFn
(
@
UnboxedFnTy
{
decl
:
decl
,
})
}
else
{
TyClosure
(
@
ClosureTy
{
fn_style
:
fn_style
,
onceness
:
onceness
,
bounds
:
bounds
,
decl
:
decl
,
lifetimes
:
lifetimes
,
},
region
)
}
}
pub
fn
parse_unsafety
(
&
mut
self
)
->
FnStyle
{
...
...
@@ -3345,6 +3363,41 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
})
}
fn
parse_unboxed_function_type
(
&
mut
self
)
->
UnboxedFnTy
{
let
inputs
=
if
self
.eat
(
&
token
::
OROR
)
{
Vec
::
new
()
}
else
{
self
.expect_or
();
if
self
.token
==
token
::
BINOP
(
token
::
AND
)
&&
self
.look_ahead
(
1
,
|
t
|
{
token
::
is_keyword
(
keywords
::
Mut
,
t
)
})
&&
self
.look_ahead
(
2
,
|
t
|
*
t
==
token
::
COLON
)
{
self
.bump
();
self
.bump
();
self
.bump
();
}
let
inputs
=
self
.parse_seq_to_before_or
(
&
token
::
COMMA
,
|
p
|
{
p
.parse_arg_general
(
false
)
});
self
.expect_or
();
inputs
};
let
(
return_style
,
output
)
=
self
.parse_ret_ty
();
UnboxedFnTy
{
decl
:
P
(
FnDecl
{
inputs
:
inputs
,
output
:
output
,
cf
:
return_style
,
variadic
:
false
,
})
}
}
// matches optbounds = ( ( : ( boundseq )? )? )
// where boundseq = ( bound + boundseq ) | bound
// and bound = 'static | ty
...
...
@@ -3394,6 +3447,11 @@ fn parse_optional_ty_param_bounds(&mut self, allow_any_lifetime: bool)
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
));
}
_
=>
break
,
}
...
...
src/libsyntax/print/pprust.rs
浏览文件 @
f02b6f3a
...
...
@@ -10,7 +10,7 @@
use
abi
;
use
ast
::{
P
,
StaticRegionTyParamBound
,
OtherRegionTyParamBound
,
TraitTyParamBound
,
Required
,
Provided
};
TraitTyParamBound
,
UnboxedFnTyParamBound
,
Required
,
Provided
};
use
ast
;
use
ast_util
;
use
owned_slice
::
OwnedSlice
;
...
...
@@ -505,27 +505,64 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
lifetimes
:
f
.lifetimes
.clone
(),
ty_params
:
OwnedSlice
::
empty
()
};
try!
(
self
.print_ty_fn
(
Some
(
f
.abi
),
None
,
&
None
,
f
.fn_style
,
ast
::
Many
,
f
.decl
,
None
,
&
None
,
Some
(
&
generics
),
None
));
try!
(
self
.print_ty_fn
(
Some
(
f
.abi
),
None
,
&
None
,
f
.fn_style
,
ast
::
Many
,
f
.decl
,
None
,
&
None
,
Some
(
&
generics
),
None
,
false
));
}
ast
::
TyClosure
(
f
,
ref
region
)
=>
{
let
generics
=
ast
::
Generics
{
lifetimes
:
f
.lifetimes
.clone
(),
ty_params
:
OwnedSlice
::
empty
()
};
try!
(
self
.print_ty_fn
(
None
,
Some
(
'&'
),
region
,
f
.fn_style
,
f
.onceness
,
f
.decl
,
None
,
&
f
.bounds
,
Some
(
&
generics
),
None
));
try!
(
self
.print_ty_fn
(
None
,
Some
(
'&'
),
region
,
f
.fn_style
,
f
.onceness
,
f
.decl
,
None
,
&
f
.bounds
,
Some
(
&
generics
),
None
,
false
));
}
ast
::
TyProc
(
f
)
=>
{
let
generics
=
ast
::
Generics
{
lifetimes
:
f
.lifetimes
.clone
(),
ty_params
:
OwnedSlice
::
empty
()
};
try!
(
self
.print_ty_fn
(
None
,
Some
(
'~'
),
&
None
,
f
.fn_style
,
f
.onceness
,
f
.decl
,
None
,
&
f
.bounds
,
Some
(
&
generics
),
None
));
try!
(
self
.print_ty_fn
(
None
,
Some
(
'~'
),
&
None
,
f
.fn_style
,
f
.onceness
,
f
.decl
,
None
,
&
f
.bounds
,
Some
(
&
generics
),
None
,
false
));
}
ast
::
TyUnboxedFn
(
f
)
=>
{
try!
(
self
.print_ty_fn
(
None
,
None
,
&
None
,
ast
::
NormalFn
,
ast
::
Many
,
f
.decl
,
None
,
&
None
,
None
,
None
,
true
));
}
ast
::
TyPath
(
ref
path
,
ref
bounds
,
_
)
=>
{
try!
(
self
.print_bounded_path
(
path
,
bounds
));
...
...
@@ -930,7 +967,8 @@ pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> {
Some
(
m
.ident
),
&
None
,
Some
(
&
m
.generics
),
Some
(
m
.explicit_self.node
)));
Some
(
m
.explicit_self.node
),
false
));
word
(
&
mut
self
.s
,
";"
)
}
...
...
@@ -1925,6 +1963,19 @@ pub fn print_bounds(&mut self,
try!
(
match
*
bound
{
TraitTyParamBound
(
ref
tref
)
=>
self
.print_trait_ref
(
tref
),
StaticRegionTyParamBound
=>
word
(
&
mut
self
.s
,
"'static"
),
UnboxedFnTyParamBound
(
ref
unboxed_function_type
)
=>
{
self
.print_ty_fn
(
None
,
None
,
&
None
,
ast
::
NormalFn
,
ast
::
Many
,
unboxed_function_type
.decl
,
None
,
&
None
,
None
,
None
,
true
)
}
OtherRegionTyParamBound
(
_
)
=>
Ok
(())
})
}
...
...
@@ -2112,8 +2163,9 @@ pub fn print_ty_fn(&mut self,
id
:
Option
<
ast
::
Ident
>
,
opt_bounds
:
&
Option
<
OwnedSlice
<
ast
::
TyParamBound
>>
,
generics
:
Option
<&
ast
::
Generics
>
,
opt_explicit_self
:
Option
<
ast
::
ExplicitSelf_
>
)
->
IoResult
<
()
>
{
opt_explicit_self
:
Option
<
ast
::
ExplicitSelf_
>
,
is_unboxed
:
bool
)
->
IoResult
<
()
>
{
try!
(
self
.ibox
(
indent_unit
));
// Duplicates the logic in `print_fn_header_info()`. This is because that
...
...
@@ -2129,7 +2181,9 @@ pub fn print_ty_fn(&mut self,
try!
(
self
.print_fn_style
(
fn_style
));
try!
(
self
.print_opt_abi_and_extern_if_nondefault
(
opt_abi
));
try!
(
self
.print_onceness
(
onceness
));
try!
(
word
(
&
mut
self
.s
,
"fn"
));
if
!
is_unboxed
{
try!
(
word
(
&
mut
self
.s
,
"fn"
));
}
}
match
id
{
...
...
@@ -2143,15 +2197,20 @@ pub fn print_ty_fn(&mut self,
match
generics
{
Some
(
g
)
=>
try!
(
self
.print_generics
(
g
)),
_
=>
()
}
try!
(
zerobreak
(
&
mut
self
.s
));
if
opt_sigil
==
Some
(
'&'
)
{
if
is_unboxed
||
opt_sigil
==
Some
(
'&'
)
{
try!
(
word
(
&
mut
self
.s
,
"|"
));
}
else
{
try!
(
self
.popen
());
}
if
is_unboxed
{
try!
(
word
(
&
mut
self
.s
,
"&mut"
));
try!
(
self
.word_space
(
":"
));
}
try!
(
self
.print_fn_args
(
decl
,
opt_explicit_self
));
if
opt_sigil
==
Some
(
'&'
)
{
if
is_unboxed
||
opt_sigil
==
Some
(
'&'
)
{
try!
(
word
(
&
mut
self
.s
,
"|"
));
}
else
{
if
decl
.variadic
{
...
...
src/libsyntax/visit.rs
浏览文件 @
f02b6f3a
...
...
@@ -383,6 +383,12 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
walk_lifetime_decls
(
visitor
,
&
function_declaration
.lifetimes
,
env
.clone
());
}
TyUnboxedFn
(
ref
function_declaration
)
=>
{
for
argument
in
function_declaration
.decl.inputs
.iter
()
{
visitor
.visit_ty
(
argument
.ty
,
env
.clone
())
}
visitor
.visit_ty
(
function_declaration
.decl.output
,
env
.clone
());
}
TyPath
(
ref
path
,
ref
bounds
,
id
)
=>
{
visitor
.visit_path
(
path
,
id
,
env
.clone
());
for
bounds
in
bounds
.iter
()
{
...
...
@@ -501,6 +507,13 @@ pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V,
walk_trait_ref_helper
(
visitor
,
typ
,
env
.clone
())
}
StaticRegionTyParamBound
=>
{}
UnboxedFnTyParamBound
(
ref
function_declaration
)
=>
{
for
argument
in
function_declaration
.decl.inputs
.iter
()
{
visitor
.visit_ty
(
argument
.ty
,
env
.clone
())
}
visitor
.visit_ty
(
function_declaration
.decl.output
,
env
.clone
());
}
OtherRegionTyParamBound
(
..
)
=>
{}
}
}
...
...
src/test/run-pass/fn-trait-sugar.rs
0 → 100644
浏览文件 @
f02b6f3a
// 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.
#![feature(unboxed_closure_sugar)]
use
std
::
ops
::
FnMut
;
struct
S
;
impl
FnMut
<
(
int
,),
int
>
for
S
{
fn
call_mut
(
&
mut
self
,
(
x
,):
(
int
,))
->
int
{
x
*
x
}
}
fn
call_it
<
F
:|
int
|
->
int
>
(
mut
f
:
F
,
x
:
int
)
->
int
{
f
.call_mut
((
x
,))
+
3
}
fn
call_box
(
f
:
&
mut
|
&
mut
:
int
|
->
int
,
x
:
int
)
->
int
{
f
.call_mut
((
x
,))
+
3
}
fn
main
()
{
let
x
=
call_it
(
S
,
1
);
let
y
=
call_box
(
&
mut
S
,
1
);
assert
!
(
x
==
4
);
assert
!
(
y
==
4
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录