Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
74a1041a
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,发现更多精彩内容 >>
提交
74a1041a
编写于
11月 20, 2014
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement the new parsing rules for types in the parser, modifying the AST appropriately.
上级
8fb027e3
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
262 addition
and
234 deletion
+262
-234
src/librustc/diagnostics.rs
src/librustc/diagnostics.rs
+3
-1
src/librustc/middle/resolve.rs
src/librustc/middle/resolve.rs
+56
-39
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+98
-77
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+3
-1
src/libsyntax/parse/mod.rs
src/libsyntax/parse/mod.rs
+1
-1
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser.rs
+85
-107
src/libsyntax/print/pprust.rs
src/libsyntax/print/pprust.rs
+16
-8
未找到文件。
src/librustc/diagnostics.rs
浏览文件 @
74a1041a
...
...
@@ -145,5 +145,7 @@
E0166
,
E0167
,
E0168
,
E0169
E0169
,
E0170
,
E0171
)
src/librustc/middle/resolve.rs
浏览文件 @
74a1041a
...
...
@@ -1396,29 +1396,53 @@ fn build_reduced_graph_for_item(&mut self,
// methods within to a new module, if the type was defined
// within this module.
// Create the module and add all methods.
match
ty
.node
{
TyPath
(
ref
path
,
_
,
_
)
if
path
.segments
.len
()
==
1
=>
{
let
mod_name
=
match
ty
.node
{
TyPath
(
ref
path
,
_
)
if
path
.segments
.len
()
==
1
=>
{
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
let
mod_name
=
path
.segments
.last
()
.unwrap
()
.identifier.name
;
Some
(
path
.segments
.last
()
.unwrap
()
.identifier.name
)
}
TyObjectSum
(
ref
lhs_ty
,
_
)
=>
{
match
lhs_ty
.node
{
TyPath
(
ref
path
,
_
)
if
path
.segments
.len
()
==
1
=>
{
Some
(
path
.segments
.last
()
.unwrap
()
.identifier.name
)
}
_
=>
{
None
}
}
}
_
=>
{
None
}
};
match
mod_name
{
None
=>
{
self
.resolve_error
(
ty
.span
,
"inherent implementations may
\
only be implemented in the same
\
module as the type they are
\
implemented for"
)
}
Some
(
mod_name
)
=>
{
// Create the module and add all methods.
let
parent_opt
=
parent
.module
()
.children
.borrow
()
.get
(
&
mod_name
)
.cloned
();
.get
(
&
mod_name
)
.cloned
();
let
new_parent
=
match
parent_opt
{
// It already exists
Some
(
ref
child
)
if
child
.get_module_if_available
()
.is_some
()
&&
(
child
.get_module
()
.kind
.get
()
==
ImplModuleKind
||
child
.get_module
()
.kind
.get
()
==
TraitModuleKind
)
=>
{
ModuleReducedGraphParent
(
child
.get_module
())
}
.is_some
()
&&
(
child
.get_module
()
.kind
.get
()
==
ImplModuleKind
||
child
.get_module
()
.kind
.get
()
==
TraitModuleKind
)
=>
{
ModuleReducedGraphParent
(
child
.get_module
())
}
Some
(
ref
child
)
if
child
.get_module_if_available
()
.is_some
()
&&
child
.get_module
()
.kind
.get
()
==
EnumModuleKind
=>
{
ModuleReducedGraphParent
(
child
.get_module
())
}
.is_some
()
&&
child
.get_module
()
.kind
.get
()
==
EnumModuleKind
=>
{
ModuleReducedGraphParent
(
child
.get_module
())
}
// Create the module
_
=>
{
let
name_bindings
=
...
...
@@ -1433,7 +1457,7 @@ fn build_reduced_graph_for_item(&mut self,
let
ns
=
TypeNS
;
let
is_public
=
!
name_bindings
.defined_in_namespace
(
ns
)
||
name_bindings
.defined_in_public_namespace
(
ns
);
name_bindings
.defined_in_public_namespace
(
ns
);
name_bindings
.define_module
(
parent_link
,
Some
(
def_id
),
...
...
@@ -1459,21 +1483,21 @@ fn build_reduced_graph_for_item(&mut self,
ForbidDuplicateValues
,
method
.span
);
let
def
=
match
method
.pe_explicit_self
()
.node
{
SelfStatic
=>
{
// Static methods become
// `DefStaticMethod`s.
DefStaticMethod
(
local_def
(
method
.id
),
FromImpl
(
local_def
(
item
.id
)))
}
_
=>
{
// Non-static methods become
// `DefMethod`s.
DefMethod
(
local_def
(
method
.id
),
None
,
FromImpl
(
local_def
(
item
.id
)))
}
};
.node
{
SelfStatic
=>
{
// Static methods become
// `DefStaticMethod`s.
DefStaticMethod
(
local_def
(
method
.id
),
FromImpl
(
local_def
(
item
.id
)))
}
_
=>
{
// Non-static methods become
// `DefMethod`s.
DefMethod
(
local_def
(
method
.id
),
None
,
FromImpl
(
local_def
(
item
.id
)))
}
};
// NB: not IMPORTABLE
let
modifiers
=
if
method
.pe_vis
()
==
ast
::
Public
{
...
...
@@ -1496,7 +1520,7 @@ fn build_reduced_graph_for_item(&mut self,
ForbidDuplicateTypesAndModules
,
typedef
.span
);
let
def
=
DefAssociatedTy
(
local_def
(
typedef
.id
));
typedef
.id
));
// NB: not IMPORTABLE
let
modifiers
=
if
typedef
.vis
==
ast
::
Public
{
PUBLIC
...
...
@@ -1511,13 +1535,6 @@ fn build_reduced_graph_for_item(&mut self,
}
}
}
_
=>
{
self
.resolve_error
(
ty
.span
,
"inherent implementations may
\
only be implemented in the same
\
module as the type they are
\
implemented for"
)
}
}
parent
...
...
src/librustc/middle/typeck/astconv.rs
浏览文件 @
74a1041a
...
...
@@ -59,8 +59,9 @@
ShiftedRscope
,
BindingRscope
};
use
middle
::
typeck
::
rscope
;
use
middle
::
typeck
::
TypeAndSubsts
;
use
util
::
common
::
ErrorReported
;
use
util
::
nodemap
::
DefIdMap
;
use
util
::
ppaux
::{
Repr
,
UserString
};
use
util
::
ppaux
::{
mod
,
Repr
,
UserString
};
use
std
::
rc
::
Rc
;
use
std
::
iter
::
AdditiveIterator
;
...
...
@@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt,
pub
fn
ast_ty_to_prim_ty
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
ast_ty
:
&
ast
::
Ty
)
->
Option
<
Ty
<
'tcx
>>
{
match
ast_ty
.node
{
ast
::
TyPath
(
ref
path
,
_
,
id
)
=>
{
ast
::
TyPath
(
ref
path
,
id
)
=>
{
let
a_def
=
match
tcx
.def_map
.borrow
()
.get
(
&
id
)
{
None
=>
{
tcx
.sess
.span_bug
(
ast_ty
.span
,
...
...
@@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
match
ast_ty
.node
{
ast
::
TyPath
(
ref
path
,
_
,
id
)
=>
{
ast
::
TyPath
(
ref
path
,
id
)
=>
{
let
a_def
=
match
this
.tcx
()
.def_map
.borrow
()
.get
(
&
id
)
{
None
=>
{
this
.tcx
()
...
...
@@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
}
// 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.
fn
mk_pointer
<
'tcx
,
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
a_seq_mutbl
:
ast
::
Mutability
,
a_seq_ty
:
&
ast
::
Ty
,
region
:
ty
::
Region
,
constr
:
|
Ty
<
'tcx
>
|
->
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
fn
ast_ty_to_trait_ref
<
'tcx
,
AC
,
RS
>
(
this
:
&
AC
,
rscope
:
&
RS
,
ty
:
&
ast
::
Ty
,
bounds
:
&
[
ast
::
TyParamBound
])
->
Result
<
ty
::
TraitRef
<
'tcx
>
,
ErrorReported
>
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
let
tcx
=
this
.tcx
();
debug!
(
"mk_pointer(region={}, a_seq_ty={})"
,
region
,
a_seq_ty
.repr
(
tcx
));
/*!
* In a type like `Foo + Send`, we want to wait to collect the
* full set of bounds before we make the object type, because we
* need them to infer a region bound. (For example, if we tried
* made a type from just `Foo`, then it wouldn't be enough to
* infer a 'static bound, and hence the user would get an error.)
* So this function is used when we're dealing with a sum type to
* convert the LHS. It only accepts a type that refers to a trait
* name, and reports an error otherwise.
*/
match
a_seq_ty
.node
{
ast
::
TyVec
(
ref
ty
)
=>
{
let
ty
=
ast_ty_to_ty
(
this
,
rscope
,
&**
ty
);
return
constr
(
ty
::
mk_vec
(
tcx
,
ty
,
None
));
match
ty
.node
{
ast
::
TyPath
(
ref
path
,
id
)
=>
{
match
this
.tcx
()
.def_map
.borrow
()
.get
(
&
id
)
{
Some
(
&
def
::
DefTrait
(
trait_def_id
))
=>
{
return
Ok
(
ast_path_to_trait_ref
(
this
,
rscope
,
trait_def_id
,
None
,
path
));
}
_
=>
{
span_err!
(
this
.tcx
()
.sess
,
ty
.span
,
E0170
,
"expected a reference to a trait"
);
Err
(
ErrorReported
)
}
}
}
ast
::
TyPath
(
ref
path
,
ref
opt_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
// will run after this as long as the path isn't a trait.
match
tcx
.def_map
.borrow
()
.get
(
&
id
)
{
Some
(
&
def
::
DefPrimTy
(
ast
::
TyStr
))
=>
{
check_path_args
(
tcx
,
path
,
NO_TPS
|
NO_REGIONS
);
return
ty
::
mk_str_slice
(
tcx
,
region
,
a_seq_mutbl
);
_
=>
{
span_err!
(
this
.tcx
()
.sess
,
ty
.span
,
E0171
,
"expected a path on the left-hand side of `+`, not `{}`"
,
pprust
::
ty_to_string
(
ty
));
match
ty
.node
{
ast
::
TyRptr
(
None
,
ref
mut_ty
)
=>
{
span_note!
(
this
.tcx
()
.sess
,
ty
.span
,
"perhaps you meant `&{}({} +{})`? (per RFC 248)"
,
ppaux
::
mutability_to_string
(
mut_ty
.mutbl
),
pprust
::
ty_to_string
(
&*
mut_ty
.ty
),
pprust
::
bounds_to_string
(
bounds
));
}
Some
(
&
def
::
DefTrait
(
trait_def_id
))
=>
{
let
result
=
ast_path_to_trait_ref
(
this
,
rscope
,
trait_def_id
,
None
,
path
);
let
empty_vec
=
[];
let
bounds
=
match
*
opt_bounds
{
None
=>
empty_vec
.as_slice
(),
Some
(
ref
bounds
)
=>
bounds
.as_slice
()
};
let
existential_bounds
=
conv_existential_bounds
(
this
,
rscope
,
path
.span
,
&
[
Rc
::
new
(
result
.clone
())],
bounds
);
let
tr
=
ty
::
mk_trait
(
tcx
,
result
,
existential_bounds
);
return
ty
::
mk_rptr
(
tcx
,
region
,
ty
::
mt
{
mutbl
:
a_seq_mutbl
,
ty
:
tr
});
ast
::
TyRptr
(
Some
(
ref
lt
),
ref
mut_ty
)
=>
{
span_note!
(
this
.tcx
()
.sess
,
ty
.span
,
"perhaps you meant `&{} {}({} +{})`? (per RFC 248)"
,
pprust
::
lifetime_to_string
(
lt
),
ppaux
::
mutability_to_string
(
mut_ty
.mutbl
),
pprust
::
ty_to_string
(
&*
mut_ty
.ty
),
pprust
::
bounds_to_string
(
bounds
));
}
_
=>
{
span_note!
(
this
.tcx
()
.sess
,
ty
.span
,
"perhaps you forget parentheses? (per RFC 248)"
);
}
_
=>
{}
}
Err
(
ErrorReported
)
}
_
=>
{}
}
constr
(
ast_ty_to_ty
(
this
,
rscope
,
a_seq_ty
))
}
fn
trait_ref_to_object_type
<
'tcx
,
AC
,
RS
>
(
this
:
&
AC
,
rscope
:
&
RS
,
span
:
Span
,
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
bounds
:
&
[
ast
::
TyParamBound
])
->
Ty
<
'tcx
>
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
let
existential_bounds
=
conv_existential_bounds
(
this
,
rscope
,
span
,
&
[
Rc
::
new
(
trait_ref
.clone
())],
bounds
);
let
result
=
ty
::
mk_trait
(
this
.tcx
(),
trait_ref
,
existential_bounds
);
debug!
(
"trait_ref_to_object_type: result={}"
,
result
.repr
(
this
.tcx
()));
result
}
fn
qpath_to_ty
<
'tcx
,
AC
,
RS
>
(
this
:
&
AC
,
...
...
@@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast
::
TyVec
(
ref
ty
)
=>
{
ty
::
mk_vec
(
tcx
,
ast_ty_to_ty
(
this
,
rscope
,
&**
ty
),
None
)
}
ast
::
TyObjectSum
(
ref
ty
,
ref
bounds
)
=>
{
match
ast_ty_to_trait_ref
(
this
,
rscope
,
&**
ty
,
bounds
.as_slice
())
{
Ok
(
trait_ref
)
=>
{
trait_ref_to_object_type
(
this
,
rscope
,
ast_ty
.span
,
trait_ref
,
bounds
.as_slice
())
}
Err
(
ErrorReported
)
=>
{
ty
::
mk_err
()
}
}
}
ast
::
TyPtr
(
ref
mt
)
=>
{
ty
::
mk_ptr
(
tcx
,
ty
::
mt
{
ty
:
ast_ty_to_ty
(
this
,
rscope
,
&*
mt
.ty
),
...
...
@@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast
::
TyRptr
(
ref
region
,
ref
mt
)
=>
{
let
r
=
opt_ast_region_to_region
(
this
,
rscope
,
ast_ty
.span
,
region
);
debug!
(
"ty_rptr r={}"
,
r
.repr
(
this
.tcx
()));
mk_pointer
(
this
,
rscope
,
mt
.mutbl
,
&*
mt
.ty
,
r
,
|
ty
|
ty
::
mk_rptr
(
tcx
,
r
,
ty
::
mt
{
ty
:
ty
,
mutbl
:
mt
.mutbl
})
)
let
t
=
ast_ty_to_ty
(
this
,
rscope
,
&*
mt
.ty
);
ty
::
mk_rptr
(
tcx
,
r
,
ty
::
mt
{
ty
:
t
,
mutbl
:
mt
.mutbl
}
)
}
ast
::
TyTup
(
ref
fields
)
=>
{
let
flds
=
fields
.iter
()
...
...
@@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast
::
TyPolyTraitRef
(
ref
bounds
)
=>
{
conv_ty_poly_trait_ref
(
this
,
rscope
,
ast_ty
.span
,
bounds
.as_slice
())
}
ast
::
TyPath
(
ref
path
,
ref
bounds
,
id
)
=>
{
ast
::
TyPath
(
ref
path
,
id
)
=>
{
let
a_def
=
match
tcx
.def_map
.borrow
()
.get
(
&
id
)
{
None
=>
{
tcx
.sess
...
...
@@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
Some
(
&
d
)
=>
d
};
// Kind bounds on path types are only supported for traits.
match
a_def
{
// But don't emit the error if the user meant to do a trait anyway.
def
::
DefTrait
(
..
)
=>
{
},
_
if
bounds
.is_some
()
=>
tcx
.sess
.span_err
(
ast_ty
.span
,
"kind bounds can only be used on trait types"
),
_
=>
{
},
}
match
a_def
{
def
::
DefTrait
(
trait_def_id
)
=>
{
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let
result
=
ast_path_to_trait_ref
(
this
,
rscope
,
trait_def_id
,
None
,
path
);
let
empty_bounds
:
&
[
ast
::
TyParamBound
]
=
&
[];
let
ast_bounds
=
match
*
bounds
{
Some
(
ref
b
)
=>
b
.as_slice
(),
None
=>
empty_bounds
};
let
bounds
=
conv_existential_bounds
(
this
,
rscope
,
ast_ty
.span
,
&
[
Rc
::
new
(
result
.clone
())],
ast_bounds
);
let
result_ty
=
ty
::
mk_trait
(
tcx
,
result
,
bounds
);
debug!
(
"ast_ty_to_ty: result_ty={}"
,
result_ty
.repr
(
this
.tcx
()));
result_ty
trait_ref_to_object_type
(
this
,
rscope
,
path
.span
,
result
,
&
[])
}
def
::
DefTy
(
did
,
_
)
|
def
::
DefStruct
(
did
)
=>
{
ast_path_to_ty
(
this
,
rscope
,
did
,
path
)
.ty
...
...
src/libsyntax/ast.rs
浏览文件 @
74a1041a
...
...
@@ -1151,7 +1151,9 @@ pub enum Ty_ {
/// A path (`module::module::...::Type`) or primitive
///
/// Type parameters are stored in the Path itself
TyPath
(
Path
,
Option
<
TyParamBounds
>
,
NodeId
),
// for #7264; see above
TyPath
(
Path
,
NodeId
),
/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum
(
P
<
Ty
>
,
TyParamBounds
),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef
(
TyParamBounds
),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
...
...
src/libsyntax/parse/mod.rs
浏览文件 @
74a1041a
...
...
@@ -1029,7 +1029,7 @@ fn parser_done(p: Parser){
parameters
:
ast
::
PathParameters
::
none
(),
}
),
},
None
,
ast
::
DUMMY_NODE_ID
),
},
ast
::
DUMMY_NODE_ID
),
span
:
sp
(
10
,
13
)
}),
pat
:
P
(
ast
::
Pat
{
...
...
src/libsyntax/parse/parser.rs
浏览文件 @
74a1041a
...
...
@@ -111,16 +111,6 @@ pub enum PathParsingMode {
/// A path with a lifetime and type parameters with double colons before
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
LifetimeAndTypesWithColons
,
/// A path with a lifetime and type parameters with bounds before the last
/// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
/// form does not use extra double colons.
LifetimeAndTypesAndBounds
,
}
/// A path paired with optional type bounds.
pub
struct
PathAndBounds
{
pub
path
:
ast
::
Path
,
pub
bounds
:
Option
<
ast
::
TyParamBounds
>
,
}
enum
ItemOrViewItem
{
...
...
@@ -1053,17 +1043,9 @@ pub fn parse_for_in_type(&mut self) -> Ty_ {
}
}
pub
fn
parse_ty_path
(
&
mut
self
,
plus_allowed
:
bool
)
->
Ty_
{
let
mode
=
if
plus_allowed
{
LifetimeAndTypesAndBounds
}
else
{
LifetimeAndTypesWithoutColons
};
let
PathAndBounds
{
path
,
bounds
}
=
self
.parse_path
(
mode
);
TyPath
(
path
,
bounds
,
ast
::
DUMMY_NODE_ID
)
pub
fn
parse_ty_path
(
&
mut
self
)
->
Ty_
{
let
path
=
self
.parse_path
(
LifetimeAndTypesWithoutColons
);
TyPath
(
path
,
ast
::
DUMMY_NODE_ID
)
}
/// parse a TyBareFn type:
...
...
@@ -1286,7 +1268,7 @@ fn parse_typedef(&mut self, attrs: Vec<Attribute>, vis: Visibility)
let
lo
=
self
.span.lo
;
let
ident
=
self
.parse_ident
();
self
.expect
(
&
token
::
Eq
);
let
typ
=
self
.parse_ty
(
true
);
let
typ
=
self
.parse_ty
_sum
(
);
let
hi
=
self
.span.hi
;
self
.expect
(
&
token
::
Semi
);
Typedef
{
...
...
@@ -1385,7 +1367,7 @@ pub fn parse_trait_items(&mut self) -> Vec<TraitItem> {
/// Parse a possibly mutable type
pub
fn
parse_mt
(
&
mut
self
)
->
MutTy
{
let
mutbl
=
self
.parse_mutability
();
let
t
=
self
.parse_ty
(
true
);
let
t
=
self
.parse_ty
();
MutTy
{
ty
:
t
,
mutbl
:
mutbl
}
}
...
...
@@ -1396,7 +1378,7 @@ pub fn parse_ty_field(&mut self) -> TypeField {
let
mutbl
=
self
.parse_mutability
();
let
id
=
self
.parse_ident
();
self
.expect
(
&
token
::
Colon
);
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
let
hi
=
ty
.span.hi
;
ast
::
TypeField
{
ident
:
id
,
...
...
@@ -1411,7 +1393,19 @@ pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
if
self
.eat
(
&
token
::
Not
)
{
NoReturn
(
self
.span
)
}
else
{
Return
(
self
.parse_ty
(
true
))
let
t
=
self
.parse_ty
();
// We used to allow `fn foo() -> &T + U`, but don't
// anymore. If we see it, report a useful error. This
// only makes sense because `parse_ret_ty` is only
// used in fn *declarations*, not fn types or where
// clauses (i.e., not when parsing something like
// `FnMut() -> T + Send`, where the `+` is legal).
if
self
.token
==
token
::
BinOp
(
token
::
Plus
)
{
self
.warn
(
"deprecated syntax: `()` are required, see RFC 248 for details"
);
}
Return
(
t
)
}
}
else
{
let
pos
=
self
.span.lo
;
...
...
@@ -1423,11 +1417,36 @@ pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
}
}
/// Parse a type in a context where `T1+T2` is allowed.
pub
fn
parse_ty_sum
(
&
mut
self
)
->
P
<
Ty
>
{
let
lo
=
self
.span.lo
;
let
lhs
=
self
.parse_ty
();
if
!
self
.eat
(
&
token
::
BinOp
(
token
::
Plus
))
{
return
lhs
;
}
let
bounds
=
self
.parse_ty_param_bounds
();
// In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required.
if
bounds
.len
()
==
0
{
let
last_span
=
self
.last_span
;
self
.span_err
(
last_span
,
"at least one type parameter bound
\
must be specified"
);
}
let
sp
=
mk_sp
(
lo
,
self
.last_span.hi
);
let
sum
=
ast
::
TyObjectSum
(
lhs
,
bounds
);
P
(
Ty
{
id
:
ast
::
DUMMY_NODE_ID
,
node
:
sum
,
span
:
sp
})
}
/// Parse a type.
///
/// The second parameter specifies whether the `+` binary operator is
/// allowed in the type grammar.
pub
fn
parse_ty
(
&
mut
self
,
plus_allowed
:
bool
)
->
P
<
Ty
>
{
pub
fn
parse_ty
(
&
mut
self
)
->
P
<
Ty
>
{
maybe_whole!
(
no_clone
self
,
NtTy
);
let
lo
=
self
.span.lo
;
...
...
@@ -1441,7 +1460,7 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
let
mut
ts
=
vec!
[];
let
mut
last_comma
=
false
;
while
self
.token
!=
token
::
CloseDelim
(
token
::
Paren
)
{
ts
.push
(
self
.parse_ty
(
true
));
ts
.push
(
self
.parse_ty
_sum
(
));
if
self
.token
==
token
::
Comma
{
last_comma
=
true
;
self
.bump
();
...
...
@@ -1465,7 +1484,7 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
token
::
OpenDelim
(
token
::
Bracket
)
=>
self
.obsolete
(
last_span
,
ObsoleteOwnedVector
),
_
=>
self
.obsolete
(
last_span
,
ObsoleteOwnedType
)
}
TyTup
(
vec!
[
self
.parse_ty
(
false
)])
TyTup
(
vec!
[
self
.parse_ty
()])
}
else
if
self
.token
==
token
::
BinOp
(
token
::
Star
)
{
// STAR POINTER (bare pointer?)
self
.bump
();
...
...
@@ -1473,7 +1492,7 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
}
else
if
self
.token
==
token
::
OpenDelim
(
token
::
Bracket
)
{
// VECTOR
self
.expect
(
&
token
::
OpenDelim
(
token
::
Bracket
));
let
t
=
self
.parse_ty
(
true
);
let
t
=
self
.parse_ty
_sum
(
);
// Parse the `, ..e` in `[ int, ..e ]`
// where `e` is a const expression
...
...
@@ -1514,7 +1533,7 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
}
else
if
self
.token
==
token
::
Lt
{
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
self
.bump
();
let
self_type
=
self
.parse_ty
(
true
);
let
self_type
=
self
.parse_ty
_sum
(
);
self
.expect_keyword
(
keywords
::
As
);
let
trait_ref
=
self
.parse_trait_ref
();
self
.expect
(
&
token
::
Gt
);
...
...
@@ -1529,7 +1548,7 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
self
.token
.is_ident
()
||
self
.token
.is_path
()
{
// NAMED TYPE
self
.parse_ty_path
(
plus_allowed
)
self
.parse_ty_path
()
}
else
if
self
.eat
(
&
token
::
Underscore
)
{
// TYPE TO BE INFERRED
TyInfer
...
...
@@ -1563,7 +1582,7 @@ pub fn parse_ptr(&mut self) -> MutTy {
known as `*const T`"
);
MutImmutable
};
let
t
=
self
.parse_ty
(
true
);
let
t
=
self
.parse_ty
();
MutTy
{
ty
:
t
,
mutbl
:
mutbl
}
}
...
...
@@ -1603,7 +1622,7 @@ pub fn parse_arg_general(&mut self, require_name: bool) -> Arg {
special_idents
::
invalid
)
};
let
t
=
self
.parse_ty
(
true
);
let
t
=
self
.parse_ty
_sum
(
);
Arg
{
ty
:
t
,
...
...
@@ -1621,7 +1640,7 @@ pub fn parse_arg(&mut self) -> Arg {
pub
fn
parse_fn_block_arg
(
&
mut
self
)
->
Arg
{
let
pat
=
self
.parse_pat
();
let
t
=
if
self
.eat
(
&
token
::
Colon
)
{
self
.parse_ty
(
true
)
self
.parse_ty
_sum
(
)
}
else
{
P
(
Ty
{
id
:
ast
::
DUMMY_NODE_ID
,
...
...
@@ -1739,7 +1758,7 @@ pub fn parse_literal_maybe_minus(&mut self) -> P<Expr> {
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
/// bounds are permitted and whether `::` must precede type parameter
/// groups.
pub
fn
parse_path
(
&
mut
self
,
mode
:
PathParsingMode
)
->
PathAndBounds
{
pub
fn
parse_path
(
&
mut
self
,
mode
:
PathParsingMode
)
->
ast
::
Path
{
// Check for a whole path...
let
found
=
match
self
.token
{
token
::
Interpolated
(
token
::
NtPath
(
_
))
=>
Some
(
self
.bump_and_get
()),
...
...
@@ -1747,10 +1766,7 @@ pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
};
match
found
{
Some
(
token
::
Interpolated
(
token
::
NtPath
(
box
path
)))
=>
{
return
PathAndBounds
{
path
:
path
,
bounds
:
None
}
return
path
;
}
_
=>
{}
}
...
...
@@ -1762,8 +1778,7 @@ pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
// identifier followed by an optional lifetime and a set of types.
// A bound set is a set of type parameter bounds.
let
segments
=
match
mode
{
LifetimeAndTypesWithoutColons
|
LifetimeAndTypesAndBounds
=>
{
LifetimeAndTypesWithoutColons
=>
{
self
.parse_path_segments_without_colons
()
}
LifetimeAndTypesWithColons
=>
{
...
...
@@ -1774,44 +1789,14 @@ pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
}
};
// Next, parse a plus and bounded type parameters, if
// applicable. We need to remember whether the separate was
// present for later, because in some contexts it's a parse
// error.
let
opt_bounds
=
{
if
mode
==
LifetimeAndTypesAndBounds
&&
self
.eat
(
&
token
::
BinOp
(
token
::
Plus
))
{
let
bounds
=
self
.parse_ty_param_bounds
();
// For some reason that I do not fully understand, we
// do not permit an empty list in the case where it is
// introduced by a `+`, but we do for `:` and other
// separators. -nmatsakis
if
bounds
.len
()
==
0
{
let
last_span
=
self
.last_span
;
self
.span_err
(
last_span
,
"at least one type parameter bound
\
must be specified"
);
}
Some
(
bounds
)
}
else
{
None
}
};
// Assemble the span.
let
span
=
mk_sp
(
lo
,
self
.last_span.hi
);
// Assemble the result.
PathAndBounds
{
path
:
ast
::
Path
{
span
:
span
,
global
:
is_global
,
segments
:
segments
,
},
bounds
:
opt_bounds
,
ast
::
Path
{
span
:
span
,
global
:
is_global
,
segments
:
segments
,
}
}
...
...
@@ -1837,10 +1822,10 @@ pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
let
inputs
=
self
.parse_seq_to_end
(
&
token
::
CloseDelim
(
token
::
Paren
),
seq_sep_trailing_allowed
(
token
::
Comma
),
|
p
|
p
.parse_ty
(
true
));
|
p
|
p
.parse_ty
_sum
(
));
let
output_ty
=
if
self
.eat
(
&
token
::
RArrow
)
{
Some
(
self
.parse_ty
(
true
))
Some
(
self
.parse_ty
())
}
else
{
None
};
...
...
@@ -2327,7 +2312,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
!
self
.token
.is_keyword
(
keywords
::
True
)
&&
!
self
.token
.is_keyword
(
keywords
::
False
)
{
let
pth
=
self
.parse_path
(
LifetimeAndTypesWithColons
)
.path
;
self
.parse_path
(
LifetimeAndTypesWithColons
);
// `!`, as an operator, is prefix, so we know this isn't that
if
self
.token
==
token
::
Not
{
...
...
@@ -2898,7 +2883,7 @@ pub fn parse_more_binops(&mut self, lhs: P<Expr>, min_prec: uint) -> P<Expr> {
}
None
=>
{
if
as_prec
>
min_prec
&&
self
.eat_keyword
(
keywords
::
As
)
{
let
rhs
=
self
.parse_ty
(
false
);
let
rhs
=
self
.parse_ty
();
let
_
as
=
self
.mk_expr
(
lhs
.span.lo
,
rhs
.span.hi
,
ExprCast
(
lhs
,
rhs
));
...
...
@@ -3362,8 +3347,7 @@ pub fn parse_pat(&mut self) -> P<Pat> {
})
{
self
.bump
();
let
end
=
if
self
.token
.is_ident
()
||
self
.token
.is_path
()
{
let
path
=
self
.parse_path
(
LifetimeAndTypesWithColons
)
.path
;
let
path
=
self
.parse_path
(
LifetimeAndTypesWithColons
);
let
hi
=
self
.span.hi
;
self
.mk_expr
(
lo
,
hi
,
ExprPath
(
path
))
}
else
{
...
...
@@ -3433,8 +3417,7 @@ pub fn parse_pat(&mut self) -> P<Pat> {
}
}
else
{
// parse an enum pat
let
enum_path
=
self
.parse_path
(
LifetimeAndTypesWithColons
)
.path
;
let
enum_path
=
self
.parse_path
(
LifetimeAndTypesWithColons
);
match
self
.token
{
token
::
OpenDelim
(
token
::
Brace
)
=>
{
self
.bump
();
...
...
@@ -3548,7 +3531,7 @@ fn parse_local(&mut self) -> P<Local> {
span
:
mk_sp
(
lo
,
lo
),
});
if
self
.eat
(
&
token
::
Colon
)
{
ty
=
self
.parse_ty
(
true
);
ty
=
self
.parse_ty
_sum
(
);
}
let
init
=
self
.parse_initializer
();
P
(
ast
::
Local
{
...
...
@@ -3577,7 +3560,7 @@ fn parse_name_and_ty(&mut self, pr: Visibility,
}
let
name
=
self
.parse_ident
();
self
.expect
(
&
token
::
Colon
);
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
spanned
(
lo
,
self
.last_span.hi
,
ast
::
StructField_
{
kind
:
NamedField
(
name
,
pr
),
id
:
ast
::
DUMMY_NODE_ID
,
...
...
@@ -3624,7 +3607,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) {
// Potential trouble: if we allow macros with paths instead of
// idents, we'd need to look ahead past the whole path here...
let
pth
=
self
.parse_path
(
NoTypesAllowed
)
.path
;
let
pth
=
self
.parse_path
(
NoTypesAllowed
);
self
.bump
();
let
id
=
match
self
.token
{
...
...
@@ -3976,7 +3959,7 @@ fn parse_ty_param(&mut self) -> TyParam {
let
default
=
if
self
.token
==
token
::
Eq
{
self
.bump
();
Some
(
self
.parse_ty
(
true
))
Some
(
self
.parse_ty
_sum
(
))
}
else
{
None
};
...
...
@@ -4032,7 +4015,7 @@ fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> )
Some
(
token
::
Comma
),
|
p
|
{
p
.forbid_lifetime
();
p
.parse_ty
(
true
)
p
.parse_ty
_sum
(
)
}
);
(
lifetimes
,
result
.into_vec
())
...
...
@@ -4265,7 +4248,7 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
// Determine whether this is the fully explicit form, `self:
// TYPE`.
if
self
.eat
(
&
token
::
Colon
)
{
SelfExplicit
(
self
.parse_ty
(
false
),
self_ident
)
SelfExplicit
(
self
.parse_ty
_sum
(
),
self_ident
)
}
else
{
SelfValue
(
self_ident
)
}
...
...
@@ -4277,7 +4260,7 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
// Determine whether this is the fully explicit form,
// `self: TYPE`.
if
self
.eat
(
&
token
::
Colon
)
{
SelfExplicit
(
self
.parse_ty
(
false
),
self_ident
)
SelfExplicit
(
self
.parse_ty
_sum
(
),
self_ident
)
}
else
{
SelfValue
(
self_ident
)
}
...
...
@@ -4466,7 +4449,7 @@ pub fn parse_method(&mut self,
&&
(
self
.look_ahead
(
2
,
|
t
|
*
t
==
token
::
OpenDelim
(
token
::
Paren
))
||
self
.look_ahead
(
2
,
|
t
|
*
t
==
token
::
OpenDelim
(
token
::
Brace
)))
{
// method macro.
let
pth
=
self
.parse_path
(
NoTypesAllowed
)
.path
;
let
pth
=
self
.parse_path
(
NoTypesAllowed
);
self
.expect
(
&
token
::
Not
);
// eat a matched-delimiter token tree:
...
...
@@ -4564,30 +4547,25 @@ fn parse_item_impl(&mut self) -> ItemInfo {
let
could_be_trait
=
self
.token
!=
token
::
OpenDelim
(
token
::
Paren
);
// Parse the trait.
let
mut
ty
=
self
.parse_ty
(
true
);
let
mut
ty
=
self
.parse_ty
_sum
(
);
// Parse traits, if necessary.
let
opt_trait
=
if
could_be_trait
&&
self
.eat_keyword
(
keywords
::
For
)
{
// New-style trait. Reinterpret the type as a trait.
let
opt_trait_ref
=
match
ty
.node
{
TyPath
(
ref
path
,
None
,
node_id
)
=>
{
TyPath
(
ref
path
,
node_id
)
=>
{
Some
(
TraitRef
{
path
:
(
*
path
)
.clone
(),
ref_id
:
node_id
,
})
}
TyPath
(
_
,
Some
(
_
),
_
)
=>
{
self
.span_err
(
ty
.span
,
"bounded traits are only valid in type position"
);
None
}
_
=>
{
self
.span_err
(
ty
.span
,
"not a trait"
);
None
}
};
ty
=
self
.parse_ty
(
true
);
ty
=
self
.parse_ty
_sum
(
);
opt_trait_ref
}
else
{
None
...
...
@@ -4606,7 +4584,7 @@ fn parse_item_impl(&mut self) -> ItemInfo {
/// Parse a::B<String,int>
fn
parse_trait_ref
(
&
mut
self
)
->
TraitRef
{
ast
::
TraitRef
{
path
:
self
.parse_path
(
LifetimeAndTypesWithoutColons
)
.path
,
path
:
self
.parse_path
(
LifetimeAndTypesWithoutColons
),
ref_id
:
ast
::
DUMMY_NODE_ID
,
}
}
...
...
@@ -4638,7 +4616,7 @@ fn parse_item_struct(&mut self) -> ItemInfo {
let
mut
generics
=
self
.parse_generics
();
if
self
.eat
(
&
token
::
Colon
)
{
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
self
.span_err
(
ty
.span
,
"`virtual` structs have been removed from the language"
);
}
...
...
@@ -4673,7 +4651,7 @@ fn parse_item_struct(&mut self) -> ItemInfo {
let
struct_field_
=
ast
::
StructField_
{
kind
:
UnnamedField
(
p
.parse_visibility
()),
id
:
ast
::
DUMMY_NODE_ID
,
ty
:
p
.parse_ty
(
true
),
ty
:
p
.parse_ty
_sum
(
),
attrs
:
attrs
,
};
spanned
(
lo
,
p
.span.hi
,
struct_field_
)
...
...
@@ -4830,7 +4808,7 @@ fn parse_mod_items(&mut self,
fn
parse_item_const
(
&
mut
self
,
m
:
Option
<
Mutability
>
)
->
ItemInfo
{
let
id
=
self
.parse_ident
();
self
.expect
(
&
token
::
Colon
);
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
self
.expect
(
&
token
::
Eq
);
let
e
=
self
.parse_expr
();
self
.commit_expr_expecting
(
&*
e
,
token
::
Semi
);
...
...
@@ -5023,7 +5001,7 @@ fn parse_item_foreign_static(&mut self, vis: ast::Visibility,
let
ident
=
self
.parse_ident
();
self
.expect
(
&
token
::
Colon
);
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
let
hi
=
self
.span.hi
;
self
.expect
(
&
token
::
Semi
);
P
(
ForeignItem
{
...
...
@@ -5181,7 +5159,7 @@ fn parse_item_type(&mut self) -> ItemInfo {
let
mut
tps
=
self
.parse_generics
();
self
.parse_where_clause
(
&
mut
tps
);
self
.expect
(
&
token
::
Eq
);
let
ty
=
self
.parse_ty
(
true
);
let
ty
=
self
.parse_ty
_sum
(
);
self
.expect
(
&
token
::
Semi
);
(
ident
,
ItemTy
(
ty
,
tps
),
None
)
}
...
...
@@ -5235,7 +5213,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> EnumDef {
&
token
::
OpenDelim
(
token
::
Paren
),
&
token
::
CloseDelim
(
token
::
Paren
),
seq_sep_trailing_allowed
(
token
::
Comma
),
|
p
|
p
.parse_ty
(
true
)
|
p
|
p
.parse_ty
_sum
(
)
);
for
ty
in
arg_tys
.into_iter
()
{
args
.push
(
ast
::
VariantArg
{
...
...
@@ -5593,7 +5571,7 @@ fn parse_macro_use_or_failure(
// MACRO INVOCATION ITEM
// item macro.
let
pth
=
self
.parse_path
(
NoTypesAllowed
)
.path
;
let
pth
=
self
.parse_path
(
NoTypesAllowed
);
self
.expect
(
&
token
::
Not
);
// a 'special' identifier (like what `macro_rules!` uses)
...
...
src/libsyntax/print/pprust.rs
浏览文件 @
74a1041a
...
...
@@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String {
$to_string
(|
s
|
s
.print_type
(
ty
))
}
pub
fn
bounds_to_string
(
bounds
:
&
[
ast
::
TyParamBound
])
->
String
{
$to_string
(|
s
|
s
.print_bounds
(
""
,
bounds
))
}
pub
fn
pat_to_string
(
pat
:
&
ast
::
Pat
)
->
String
{
$to_string
(|
s
|
s
.print_pat
(
pat
))
}
...
...
@@ -739,11 +743,15 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
Some
(
&
generics
),
None
));
}
ast
::
TyPath
(
ref
path
,
ref
bounds
,
_
)
=>
{
try!
(
self
.print_bounded_path
(
path
,
bounds
));
ast
::
TyPath
(
ref
path
,
_
)
=>
{
try!
(
self
.print_path
(
path
,
false
));
}
ast
::
TyObjectSum
(
ref
ty
,
ref
bounds
)
=>
{
try!
(
self
.print_type
(
&**
ty
));
try!
(
self
.print_bounds
(
"+"
,
bounds
.as_slice
()));
}
ast
::
TyPolyTraitRef
(
ref
bounds
)
=>
{
try!
(
self
.print_bounds
(
""
,
bounds
));
try!
(
self
.print_bounds
(
""
,
bounds
.as_slice
()
));
}
ast
::
TyQPath
(
ref
qpath
)
=>
{
try!
(
word
(
&
mut
self
.s
,
"<"
));
...
...
@@ -970,7 +978,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
}
_
=>
{}
}
try!
(
self
.print_bounds
(
":"
,
bounds
));
try!
(
self
.print_bounds
(
":"
,
bounds
.as_slice
()
));
try!
(
self
.print_where_clause
(
generics
));
try!
(
word
(
&
mut
self
.s
,
" "
));
try!
(
self
.bopen
());
...
...
@@ -2329,7 +2337,7 @@ pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
pub
fn
print_bounds
(
&
mut
self
,
prefix
:
&
str
,
bounds
:
&
OwnedSlice
<
ast
::
TyParamBound
>
)
bounds
:
&
[
ast
::
TyParamBound
]
)
->
IoResult
<
()
>
{
if
!
bounds
.is_empty
()
{
try!
(
word
(
&
mut
self
.s
,
prefix
));
...
...
@@ -2418,7 +2426,7 @@ pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
_
=>
{}
}
try!
(
self
.print_ident
(
param
.ident
));
try!
(
self
.print_bounds
(
":"
,
&
param
.bounds
));
try!
(
self
.print_bounds
(
":"
,
param
.bounds
.as_slice
()
));
match
param
.default
{
Some
(
ref
default
)
=>
{
try!
(
space
(
&
mut
self
.s
));
...
...
@@ -2447,7 +2455,7 @@ pub fn print_where_clause(&mut self, generics: &ast::Generics)
}
try!
(
self
.print_ident
(
predicate
.ident
));
try!
(
self
.print_bounds
(
":"
,
&
predicate
.bounds
));
try!
(
self
.print_bounds
(
":"
,
predicate
.bounds
.as_slice
()
));
}
Ok
(())
...
...
@@ -2664,7 +2672,7 @@ pub fn print_ty_fn(&mut self,
try!
(
self
.pclose
());
}
try!
(
self
.print_bounds
(
":"
,
bounds
));
try!
(
self
.print_bounds
(
":"
,
bounds
.as_slice
()
));
try!
(
self
.print_fn_output
(
decl
));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录