Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
cf468206
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,发现更多精彩内容 >>
提交
cf468206
编写于
3月 06, 2016
作者:
V
Vadim Petrochenkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor away some functions from hir::pat_util
上级
216f5fba
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
168 addition
and
255 deletion
+168
-255
src/librustc/cfg/construct.rs
src/librustc/cfg/construct.rs
+1
-2
src/librustc/hir/mod.rs
src/librustc/hir/mod.rs
+3
-12
src/librustc/hir/pat_util.rs
src/librustc/hir/pat_util.rs
+27
-48
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+70
-87
src/librustc/middle/liveness.rs
src/librustc/middle/liveness.rs
+5
-9
src/librustc/ty/util.rs
src/librustc/ty/util.rs
+2
-2
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/check_match.rs
+20
-26
src/librustc_lint/unused.rs
src/librustc_lint/unused.rs
+1
-1
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+1
-1
src/librustc_trans/_match.rs
src/librustc_trans/_match.rs
+10
-12
src/librustc_trans/debuginfo/create_scope_map.rs
src/librustc_trans/debuginfo/create_scope_map.rs
+1
-4
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/metadata.rs
+2
-6
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/_match.rs
+9
-13
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+6
-14
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+1
-1
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+3
-5
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+6
-12
未找到文件。
src/librustc/cfg/construct.rs
浏览文件 @
cf468206
...
...
@@ -456,8 +456,7 @@ fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
// Visit the guard expression
let
guard_exit
=
self
.expr
(
&
guard
,
guard_start
);
let
this_has_bindings
=
pat_util
::
pat_contains_bindings_or_wild
(
&
self
.tcx.def_map
.borrow
(),
&
pat
);
let
this_has_bindings
=
pat_util
::
pat_contains_bindings_or_wild
(
&
pat
);
// If both this pattern and the previous pattern
// were free of bindings, they must consist only
...
...
src/librustc/hir/mod.rs
浏览文件 @
cf468206
...
...
@@ -524,14 +524,7 @@ pub enum PatKind {
/// Represents a wildcard pattern (`_`)
Wild
,
/// A `PatKind::Ident` may either be a new bound variable,
/// or a unit struct/variant pattern, or a const pattern (in the last two cases
/// the third field must be `None`).
///
/// In the unit or const pattern case, the parser can't determine
/// which it is. The resolver determines this, and
/// records this pattern's `NodeId` in an auxiliary
/// set (of "PatIdents that refer to unit patterns or constants").
/// A fresh binding `ref mut binding @ OPT_SUBPATTERN`.
Binding
(
BindingMode
,
Spanned
<
Name
>
,
Option
<
P
<
Pat
>>
),
/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
...
...
@@ -547,10 +540,8 @@ pub enum PatKind {
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path
(
Path
),
/// An associated const named using the qualified path `<T>::CONST` or
/// `<T as Trait>::CONST`. Associated consts from inherent impls can be
/// referred to as simply `T::CONST`, in which case they will end up as
/// PatKind::Path, and the resolver will have to sort that out.
/// A path pattern written in qualified form, i.e. `<T as Trait>::CONST` or `<T>::CONST`.
/// Such patterns can only refer to associated constants at the moment.
QPath
(
QSelf
,
Path
),
/// A tuple pattern `(a, b)`.
...
...
src/librustc/hir/pat_util.rs
浏览文件 @
cf468206
...
...
@@ -10,14 +10,12 @@
use
hir
::
def
::
*
;
use
hir
::
def_id
::
DefId
;
use
hir
::{
self
,
PatKind
};
use
ty
::
TyCtxt
;
use
util
::
nodemap
::
FnvHashMap
;
use
syntax
::
ast
;
use
hir
::{
self
,
PatKind
};
use
syntax
::
codemap
::{
respan
,
Span
,
Spanned
,
DUMMY_SP
};
use
syntax
::
codemap
::{
Span
,
Spanned
,
DUMMY_SP
};
use
std
::
cell
::
RefCell
;
use
std
::
iter
::{
Enumerate
,
ExactSizeIterator
};
pub
type
PatIdMap
=
FnvHashMap
<
ast
::
Name
,
ast
::
NodeId
>
;
...
...
@@ -57,9 +55,9 @@ fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
// This is used because same-named variables in alternative patterns need to
// use the NodeId of their namesake in the first pattern.
pub
fn
pat_id_map
(
dm
:
&
RefCell
<
DefMap
>
,
pat
:
&
hir
::
Pat
)
->
PatIdMap
{
pub
fn
pat_id_map
(
pat
:
&
hir
::
Pat
)
->
PatIdMap
{
let
mut
map
=
FnvHashMap
();
pat_bindings
(
dm
,
pat
,
|
_
bm
,
p_id
,
_
s
,
path1
|
{
pat_bindings
(
pat
,
|
_
bm
,
p_id
,
_
s
,
path1
|
{
map
.insert
(
path1
.node
,
p_id
);
});
map
...
...
@@ -123,31 +121,14 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
}
}
pub
fn
pat_is_binding
(
_
:
&
DefMap
,
pat
:
&
hir
::
Pat
)
->
bool
{
match
pat
.node
{
PatKind
::
Binding
(
..
)
=>
true
,
_
=>
false
}
}
pub
fn
pat_is_binding_or_wild
(
_
:
&
DefMap
,
pat
:
&
hir
::
Pat
)
->
bool
{
match
pat
.node
{
PatKind
::
Binding
(
..
)
|
PatKind
::
Wild
=>
true
,
_
=>
false
}
}
/// Call `it` on every "binding" in a pattern, e.g., on `a` in
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub
fn
pat_bindings
<
I
>
(
_
:
&
RefCell
<
DefMap
>
,
pat
:
&
hir
::
Pat
,
mut
it
:
I
)
where
I
:
FnMut
(
hir
::
BindingMode
,
ast
::
NodeId
,
Span
,
&
Spanned
<
ast
::
Name
>
),
pub
fn
pat_bindings
<
F
>
(
pat
:
&
hir
::
Pat
,
mut
f
:
F
)
where
F
:
FnMut
(
hir
::
BindingMode
,
ast
::
NodeId
,
Span
,
&
Spanned
<
ast
::
Name
>
),
{
pat
.walk
(|
p
|
{
match
p
.node
{
PatKind
::
Binding
(
binding_mode
,
ref
pth
,
_
)
=>
{
it
(
binding_mode
,
p
.id
,
p
.span
,
&
respan
(
pth
.span
,
pth
.node
));
}
_
=>
{}
if
let
PatKind
::
Binding
(
binding_mode
,
ref
pth
,
_
)
=
p
.node
{
f
(
binding_mode
,
p
.id
,
p
.span
,
pth
);
}
true
});
...
...
@@ -155,10 +136,10 @@ pub fn pat_bindings<I>(_: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
/// Checks if the pattern contains any patterns that bind something to
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
pub
fn
pat_contains_bindings
(
dm
:
&
DefMap
,
pat
:
&
hir
::
Pat
)
->
bool
{
pub
fn
pat_contains_bindings
(
pat
:
&
hir
::
Pat
)
->
bool
{
let
mut
contains_bindings
=
false
;
pat
.walk
(|
p
|
{
if
pat_is_binding
(
dm
,
p
)
{
if
let
PatKind
::
Binding
(
..
)
=
p
.node
{
contains_bindings
=
true
;
false
// there's at least one binding, can short circuit now.
}
else
{
...
...
@@ -170,18 +151,15 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool {
/// Checks if the pattern contains any `ref` or `ref mut` bindings,
/// and if yes whether its containing mutable ones or just immutables ones.
pub
fn
pat_contains_ref_binding
(
dm
:
&
RefCell
<
DefMap
>
,
pat
:
&
hir
::
Pat
)
->
Option
<
hir
::
Mutability
>
{
pub
fn
pat_contains_ref_binding
(
pat
:
&
hir
::
Pat
)
->
Option
<
hir
::
Mutability
>
{
let
mut
result
=
None
;
pat_bindings
(
dm
,
pat
,
|
mode
,
_
,
_
,
_
|
{
match
mode
{
hir
::
BindingMode
::
BindByRef
(
m
)
=>
{
// Pick Mutable as maximum
match
result
{
None
|
Some
(
hir
::
MutImmutable
)
=>
result
=
Some
(
m
),
_
=>
(),
}
pat_bindings
(
pat
,
|
mode
,
_
,
_
,
_
|
{
if
let
hir
::
BindingMode
::
BindByRef
(
m
)
=
mode
{
// Pick Mutable as maximum
match
result
{
None
|
Some
(
hir
::
MutImmutable
)
=>
result
=
Some
(
m
),
_
=>
(),
}
hir
::
BindingMode
::
BindByValue
(
_
)
=>
{
}
}
});
result
...
...
@@ -189,9 +167,9 @@ pub fn pat_contains_ref_binding(dm: &RefCell<DefMap>, pat: &hir::Pat) -> Option<
/// Checks if the patterns for this arm contain any `ref` or `ref mut`
/// bindings, and if yes whether its containing mutable ones or just immutables ones.
pub
fn
arm_contains_ref_binding
(
dm
:
&
RefCell
<
DefMap
>
,
arm
:
&
hir
::
Arm
)
->
Option
<
hir
::
Mutability
>
{
pub
fn
arm_contains_ref_binding
(
arm
:
&
hir
::
Arm
)
->
Option
<
hir
::
Mutability
>
{
arm
.pats
.iter
()
.filter_map
(|
pat
|
pat_contains_ref_binding
(
dm
,
pat
))
.filter_map
(|
pat
|
pat_contains_ref_binding
(
pat
))
.max_by_key
(|
m
|
match
*
m
{
hir
::
MutMutable
=>
1
,
hir
::
MutImmutable
=>
0
,
...
...
@@ -200,14 +178,15 @@ pub fn arm_contains_ref_binding(dm: &RefCell<DefMap>, arm: &hir::Arm) -> Option<
/// Checks if the pattern contains any patterns that bind something to
/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
pub
fn
pat_contains_bindings_or_wild
(
dm
:
&
DefMap
,
pat
:
&
hir
::
Pat
)
->
bool
{
pub
fn
pat_contains_bindings_or_wild
(
pat
:
&
hir
::
Pat
)
->
bool
{
let
mut
contains_bindings
=
false
;
pat
.walk
(|
p
|
{
if
pat_is_binding_or_wild
(
dm
,
p
)
{
contains_bindings
=
true
;
false
// there's at least one binding/wildcard, can short circuit now.
}
else
{
true
match
p
.node
{
PatKind
::
Binding
(
..
)
|
PatKind
::
Wild
=>
{
contains_bindings
=
true
;
false
// there's at least one binding/wildcard, can short circuit now.
}
_
=>
true
}
});
contains_bindings
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
cf468206
...
...
@@ -612,8 +612,7 @@ fn walk_local(&mut self, local: &hir::Local) {
match
local
.init
{
None
=>
{
let
delegate
=
&
mut
self
.delegate
;
pat_util
::
pat_bindings
(
&
self
.mc.infcx.tcx.def_map
,
&
local
.pat
,
|
_
,
id
,
span
,
_
|
{
pat_util
::
pat_bindings
(
&
local
.pat
,
|
_
,
id
,
span
,
_
|
{
delegate
.decl_without_init
(
id
,
span
);
})
}
...
...
@@ -932,23 +931,16 @@ fn determine_pat_move_mode(&mut self,
debug!
(
"determine_pat_move_mode cmt_discr={:?} pat={:?}"
,
cmt_discr
,
pat
);
return_if_err!
(
self
.mc
.cat_pattern
(
cmt_discr
,
pat
,
|
_
mc
,
cmt_pat
,
pat
|
{
let
def_map
=
&
self
.tcx
()
.def_map
;
if
pat_util
::
pat_is_binding
(
&
def_map
.borrow
(),
pat
)
{
match
pat
.node
{
PatKind
::
Binding
(
hir
::
BindByRef
(
_
),
_
,
_
)
=>
mode
.lub
(
BorrowingMatch
),
PatKind
::
Binding
(
hir
::
BindByValue
(
_
),
_
,
_
)
=>
{
match
copy_or_move
(
self
.mc.infcx
,
&
cmt_pat
,
PatBindingMove
)
{
Copy
=>
mode
.lub
(
CopyingMatch
),
Move
(
_
)
=>
mode
.lub
(
MovingMatch
),
}
}
_
=>
{
span_bug!
(
pat
.span
,
"binding pattern not an identifier"
);
match
pat
.node
{
PatKind
::
Binding
(
hir
::
BindByRef
(
..
),
_
,
_
)
=>
mode
.lub
(
BorrowingMatch
),
PatKind
::
Binding
(
hir
::
BindByValue
(
..
),
_
,
_
)
=>
{
match
copy_or_move
(
self
.mc.infcx
,
&
cmt_pat
,
PatBindingMove
)
{
Copy
=>
mode
.lub
(
CopyingMatch
),
Move
(
..
)
=>
mode
.lub
(
MovingMatch
),
}
}
_
=>
{}
}
}));
}
...
...
@@ -968,83 +960,74 @@ fn walk_pat(&mut self,
let
def_map
=
&
self
.tcx
()
.def_map
;
let
delegate
=
&
mut
self
.delegate
;
return_if_err!
(
mc
.cat_pattern
(
cmt_discr
.clone
(),
pat
,
|
mc
,
cmt_pat
,
pat
|
{
if
pat_util
::
pat_is_binding
(
&
def_map
.borrow
(),
pat
)
{
debug!
(
"binding cmt_pat={:?} pat={:?} match_mode={:?}"
,
cmt_pat
,
pat
,
match_mode
);
// pat_ty: the type of the binding being produced.
let
pat_ty
=
return_if_err!
(
infcx
.node_ty
(
pat
.id
));
// Each match binding is effectively an assignment to the
// binding being produced.
let
def
=
def_map
.borrow
()
.get
(
&
pat
.id
)
.unwrap
()
.full_def
();
match
mc
.cat_def
(
pat
.id
,
pat
.span
,
pat_ty
,
def
)
{
Ok
(
binding_cmt
)
=>
{
match
pat
.node
{
PatKind
::
Binding
(
bmode
,
_
,
_
)
=>
{
debug!
(
"binding cmt_pat={:?} pat={:?} match_mode={:?}"
,
cmt_
pat
,
pat
,
match_mode
);
// pat_ty: the type of the binding being produced.
let
pat_ty
=
return_if_err!
(
infcx
.node_ty
(
pat
.id
));
// Each match binding is effectively an assignment to the
// binding being produced.
let
def
=
def_map
.borrow
()
.get
(
&
pat
.id
)
.unwrap
()
.full_def
();
if
let
Ok
(
binding_cmt
)
=
mc
.cat_def
(
pat
.id
,
pat
.span
,
pat_ty
,
def
)
{
delegate
.mutate
(
pat
.id
,
pat
.span
,
binding_cmt
,
MutateMode
::
Init
);
}
Err
(
_
)
=>
{
}
}
// It is also a borrow or copy/move of the value being matched.
match
pat
.node
{
PatKind
::
Binding
(
hir
::
BindByRef
(
m
),
_
,
_
)
=>
{
if
let
ty
::
TyRef
(
&
r
,
_
)
=
pat_ty
.sty
{
let
bk
=
ty
::
BorrowKind
::
from_mutbl
(
m
);
delegate
.borrow
(
pat
.id
,
pat
.span
,
cmt_pat
,
r
,
bk
,
RefBinding
);
// It is also a borrow or copy/move of the value being matched.
match
bmode
{
hir
::
BindByRef
(
m
)
=>
{
if
let
ty
::
TyRef
(
&
r
,
_
)
=
pat_ty
.sty
{
let
bk
=
ty
::
BorrowKind
::
from_mutbl
(
m
);
delegate
.borrow
(
pat
.id
,
pat
.span
,
cmt_pat
,
r
,
bk
,
RefBinding
);
}
}
hir
::
BindByValue
(
..
)
=>
{
let
mode
=
copy_or_move
(
infcx
,
&
cmt_pat
,
PatBindingMove
);
debug!
(
"walk_pat binding consuming pat"
);
delegate
.consume_pat
(
pat
,
cmt_pat
,
mode
);
}
}
PatKind
::
Binding
(
hir
::
BindByValue
(
_
),
_
,
_
)
=>
{
let
mode
=
copy_or_move
(
infcx
,
&
cmt_pat
,
PatBindingMove
);
debug!
(
"walk_pat binding consuming pat"
);
delegate
.consume_pat
(
pat
,
cmt_pat
,
mode
);
}
_
=>
{
span_bug!
(
pat
.span
,
"binding pattern not an identifier"
);
}
}
}
else
{
match
pat
.node
{
PatKind
::
Vec
(
_
,
Some
(
ref
slice_pat
),
_
)
=>
{
// The `slice_pat` here creates a slice into
// the original vector. This is effectively a
// borrow of the elements of the vector being
// matched.
let
(
slice_cmt
,
slice_mutbl
,
slice_r
)
=
return_if_err!
(
mc
.cat_slice_pattern
(
cmt_pat
,
&
slice_pat
));
// Note: We declare here that the borrow
// occurs upon entering the `[...]`
// pattern. This implies that something like
// `[a; b]` where `a` is a move is illegal,
// because the borrow is already in effect.
// In fact such a move would be safe-ish, but
// it effectively *requires* that we use the
// nulling out semantics to indicate when a
// value has been moved, which we are trying
// to move away from. Otherwise, how can we
// indicate that the first element in the
// vector has been moved? Eventually, we
// could perhaps modify this rule to permit
// `[..a, b]` where `b` is a move, because in
// that case we can adjust the length of the
// original vec accordingly, but we'd have to
// make trans do the right thing, and it would
// only work for `Box<[T]>`s. It seems simpler
// to just require that people call
// `vec.pop()` or `vec.unshift()`.
let
slice_bk
=
ty
::
BorrowKind
::
from_mutbl
(
slice_mutbl
);
delegate
.borrow
(
pat
.id
,
pat
.span
,
slice_cmt
,
slice_r
,
slice_bk
,
RefBinding
);
}
_
=>
{
}
PatKind
::
Vec
(
_
,
Some
(
ref
slice_pat
),
_
)
=>
{
// The `slice_pat` here creates a slice into
// the original vector. This is effectively a
// borrow of the elements of the vector being
// matched.
let
(
slice_cmt
,
slice_mutbl
,
slice_r
)
=
return_if_err!
(
mc
.cat_slice_pattern
(
cmt_pat
,
&
slice_pat
));
// Note: We declare here that the borrow
// occurs upon entering the `[...]`
// pattern. This implies that something like
// `[a; b]` where `a` is a move is illegal,
// because the borrow is already in effect.
// In fact such a move would be safe-ish, but
// it effectively *requires* that we use the
// nulling out semantics to indicate when a
// value has been moved, which we are trying
// to move away from. Otherwise, how can we
// indicate that the first element in the
// vector has been moved? Eventually, we
// could perhaps modify this rule to permit
// `[..a, b]` where `b` is a move, because in
// that case we can adjust the length of the
// original vec accordingly, but we'd have to
// make trans do the right thing, and it would
// only work for `Box<[T]>`s. It seems simpler
// to just require that people call
// `vec.pop()` or `vec.unshift()`.
let
slice_bk
=
ty
::
BorrowKind
::
from_mutbl
(
slice_mutbl
);
delegate
.borrow
(
pat
.id
,
pat
.span
,
slice_cmt
,
slice_r
,
slice_bk
,
RefBinding
);
}
_
=>
{}
}
}));
...
...
src/librustc/middle/liveness.rs
浏览文件 @
cf468206
...
...
@@ -380,9 +380,7 @@ fn visit_fn(ir: &mut IrMaps,
debug!
(
"creating fn_maps: {:?}"
,
&
fn_maps
as
*
const
IrMaps
);
for
arg
in
&
decl
.inputs
{
pat_util
::
pat_bindings
(
&
ir
.tcx.def_map
,
&
arg
.pat
,
|
_
bm
,
arg_id
,
_
x
,
path1
|
{
pat_util
::
pat_bindings
(
&
arg
.pat
,
|
_
bm
,
arg_id
,
_
x
,
path1
|
{
debug!
(
"adding argument {}"
,
arg_id
);
let
name
=
path1
.node
;
fn_maps
.add_variable
(
Arg
(
arg_id
,
name
));
...
...
@@ -415,7 +413,7 @@ fn visit_fn(ir: &mut IrMaps,
}
fn
visit_local
(
ir
:
&
mut
IrMaps
,
local
:
&
hir
::
Local
)
{
pat_util
::
pat_bindings
(
&
ir
.tcx.def_map
,
&
local
.pat
,
|
_
,
p_id
,
sp
,
path1
|
{
pat_util
::
pat_bindings
(
&
local
.pat
,
|
_
,
p_id
,
sp
,
path1
|
{
debug!
(
"adding local variable {}"
,
p_id
);
let
name
=
path1
.node
;
ir
.add_live_node_for_node
(
p_id
,
VarDefNode
(
sp
));
...
...
@@ -429,7 +427,7 @@ fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
fn
visit_arm
(
ir
:
&
mut
IrMaps
,
arm
:
&
hir
::
Arm
)
{
for
pat
in
&
arm
.pats
{
pat_util
::
pat_bindings
(
&
ir
.tcx.def_map
,
&
pat
,
|
bm
,
p_id
,
sp
,
path1
|
{
pat_util
::
pat_bindings
(
&
pat
,
|
bm
,
p_id
,
sp
,
path1
|
{
debug!
(
"adding local variable {} from match with bm {:?}"
,
p_id
,
bm
);
let
name
=
path1
.node
;
...
...
@@ -589,7 +587,7 @@ fn variable(&self, node_id: NodeId, span: Span) -> Variable {
fn
pat_bindings
<
F
>
(
&
mut
self
,
pat
:
&
hir
::
Pat
,
mut
f
:
F
)
where
F
:
FnMut
(
&
mut
Liveness
<
'a
,
'tcx
>
,
LiveNode
,
Variable
,
Span
,
NodeId
),
{
pat_util
::
pat_bindings
(
&
self
.ir.tcx.def_map
,
pat
,
|
_
bm
,
p_id
,
sp
,
_
n
|
{
pat_util
::
pat_bindings
(
pat
,
|
_
bm
,
p_id
,
sp
,
_
n
|
{
let
ln
=
self
.live_node
(
p_id
,
sp
);
let
var
=
self
.variable
(
p_id
,
sp
);
f
(
self
,
ln
,
var
,
sp
,
p_id
);
...
...
@@ -1567,9 +1565,7 @@ fn should_warn(&self, var: Variable) -> Option<String> {
fn
warn_about_unused_args
(
&
self
,
decl
:
&
hir
::
FnDecl
,
entry_ln
:
LiveNode
)
{
for
arg
in
&
decl
.inputs
{
pat_util
::
pat_bindings
(
&
self
.ir.tcx.def_map
,
&
arg
.pat
,
|
_
bm
,
p_id
,
sp
,
path1
|
{
pat_util
::
pat_bindings
(
&
arg
.pat
,
|
_
bm
,
p_id
,
sp
,
path1
|
{
let
var
=
self
.variable
(
p_id
,
sp
);
// Ignore unused self.
let
name
=
path1
.node
;
...
...
src/librustc/ty/util.rs
浏览文件 @
cf468206
...
...
@@ -173,11 +173,11 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl
<
'a
,
'gcx
,
'tcx
>
TyCtxt
<
'a
,
'gcx
,
'tcx
>
{
pub
fn
pat_contains_ref_binding
(
self
,
pat
:
&
hir
::
Pat
)
->
Option
<
hir
::
Mutability
>
{
pat_util
::
pat_contains_ref_binding
(
&
self
.def_map
,
pat
)
pat_util
::
pat_contains_ref_binding
(
pat
)
}
pub
fn
arm_contains_ref_binding
(
self
,
arm
:
&
hir
::
Arm
)
->
Option
<
hir
::
Mutability
>
{
pat_util
::
arm_contains_ref_binding
(
&
self
.def_map
,
arm
)
pat_util
::
arm_contains_ref_binding
(
arm
)
}
/// Returns the type of element at index `i` in tuple or tuple-like type `t`.
...
...
src/librustc_const_eval/check_match.rs
浏览文件 @
cf468206
...
...
@@ -748,10 +748,9 @@ fn is_useful(cx: &MatchCheckCtxt,
})
.find
(|
result
|
result
!=
&
NotUseful
)
.unwrap_or
(
NotUseful
)
}
else
{
let
matrix
=
rows
.iter
()
.filter_map
(|
r
|
{
if
pat_is_binding_or_wild
(
&
cx
.tcx.def_map
.borrow
(),
raw_pat
(
r
[
0
]))
{
Some
(
r
[
1
..
]
.to_vec
())
}
else
{
None
match
raw_pat
(
r
[
0
])
.node
{
PatKind
::
Binding
(
..
)
|
PatKind
::
Wild
=>
Some
(
r
[
1
..
]
.to_vec
()),
_
=>
None
,
}
})
.collect
();
match
is_useful
(
cx
,
&
matrix
,
&
v
[
1
..
],
witness
)
{
...
...
@@ -1089,17 +1088,11 @@ fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option<A>
fn
check_legality_of_move_bindings
(
cx
:
&
MatchCheckCtxt
,
has_guard
:
bool
,
pats
:
&
[
P
<
Pat
>
])
{
let
tcx
=
cx
.tcx
;
let
def_map
=
&
tcx
.def_map
;
let
mut
by_ref_span
=
None
;
for
pat
in
pats
{
pat_bindings
(
def_map
,
&
pat
,
|
bm
,
_
,
span
,
_
path
|
{
match
bm
{
hir
::
BindByRef
(
_
)
=>
{
by_ref_span
=
Some
(
span
);
}
hir
::
BindByValue
(
_
)
=>
{
}
pat_bindings
(
&
pat
,
|
bm
,
_
,
span
,
_
path
|
{
if
let
hir
::
BindByRef
(
..
)
=
bm
{
by_ref_span
=
Some
(
span
);
}
})
}
...
...
@@ -1108,7 +1101,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
// check legality of moving out of the enum
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
if
sub
.map_or
(
false
,
|
p
|
pat_contains_bindings
(
&
def_map
.borrow
(),
&
p
))
{
if
sub
.map_or
(
false
,
|
p
|
pat_contains_bindings
(
&
p
))
{
span_err!
(
cx
.tcx.sess
,
p
.span
,
E0007
,
"cannot bind by-move with sub-bindings"
);
}
else
if
has_guard
{
span_err!
(
cx
.tcx.sess
,
p
.span
,
E0008
,
"cannot bind by-move into a pattern guard"
);
...
...
@@ -1123,7 +1116,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
for
pat
in
pats
{
pat
.walk
(|
p
|
{
if
let
PatKind
::
Binding
(
hir
::
BindByValue
(
..
),
_
,
ref
sub
)
=
p
.node
{
let
pat_ty
=
tcx
.node_id_to_type
(
p
.id
);
let
pat_ty
=
cx
.
tcx
.node_id_to_type
(
p
.id
);
//FIXME: (@jroesch) this code should be floated up as well
cx
.tcx
.infer_ctxt
(
None
,
Some
(
cx
.param_env
.clone
()),
ProjectionMode
::
AnyFinal
)
.enter
(|
infcx
|
{
...
...
@@ -1199,18 +1192,19 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> {
impl
<
'a
,
'b
,
'tcx
,
'v
>
Visitor
<
'v
>
for
AtBindingPatternVisitor
<
'a
,
'b
,
'tcx
>
{
fn
visit_pat
(
&
mut
self
,
pat
:
&
Pat
)
{
if
!
self
.bindings_allowed
&&
pat_is_binding
(
&
self
.cx.tcx.def_map
.borrow
(),
pat
)
{
span_err!
(
self
.cx.tcx.sess
,
pat
.span
,
E0303
,
"pattern bindings are not allowed
\
after an `@`"
);
}
match
pat
.node
{
PatKind
::
Binding
(
_
,
_
,
Some
(
_
))
=>
{
let
bindings_were_allowed
=
self
.bindings_allowed
;
self
.bindings_allowed
=
false
;
intravisit
::
walk_pat
(
self
,
pat
);
self
.bindings_allowed
=
bindings_were_allowed
;
PatKind
::
Binding
(
_
,
_
,
ref
subpat
)
=>
{
if
!
self
.bindings_allowed
{
span_err!
(
self
.cx.tcx.sess
,
pat
.span
,
E0303
,
"pattern bindings are not allowed after an `@`"
);
}
if
subpat
.is_some
()
{
let
bindings_were_allowed
=
self
.bindings_allowed
;
self
.bindings_allowed
=
false
;
intravisit
::
walk_pat
(
self
,
pat
);
self
.bindings_allowed
=
bindings_were_allowed
;
}
}
_
=>
intravisit
::
walk_pat
(
self
,
pat
),
}
...
...
src/librustc_lint/unused.rs
浏览文件 @
cf468206
...
...
@@ -43,7 +43,7 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
let
mut
mutables
=
FnvHashMap
();
for
p
in
pats
{
pat_util
::
pat_bindings
(
&
cx
.tcx.def_map
,
p
,
|
mode
,
id
,
_
,
path1
|
{
pat_util
::
pat_bindings
(
p
,
|
mode
,
id
,
_
,
path1
|
{
let
name
=
path1
.node
;
if
let
hir
::
BindByValue
(
hir
::
MutMutable
)
=
mode
{
if
!
name
.as_str
()
.starts_with
(
"_"
)
{
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
cf468206
...
...
@@ -656,7 +656,7 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
None
}
else
{
map
=
FnvHashMap
();
pat_util
::
pat_bindings
(
&
cx
.tcx.def_map
,
&
arm
.pats
[
0
],
|
_
,
p_id
,
_
,
path
|
{
pat_util
::
pat_bindings
(
&
arm
.pats
[
0
],
|
_
,
p_id
,
_
,
path
|
{
map
.insert
(
path
.node
,
p_id
);
});
Some
(
&
map
)
...
...
src/librustc_trans/_match.rs
浏览文件 @
cf468206
...
...
@@ -540,7 +540,6 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}
fn
enter_default
<
'a
,
'p
,
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
dm
:
&
RefCell
<
DefMap
>
,
m
:
&
[
Match
<
'a
,
'p
,
'blk
,
'tcx
>
],
col
:
usize
,
val
:
MatchInput
)
...
...
@@ -551,12 +550,13 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Collect all of the matches that can match against anything.
enter_match
(
bcx
,
m
,
col
,
val
,
|
pats
|
{
if
pat_is_binding_or_wild
(
&
dm
.borrow
(),
&
pats
[
col
])
{
let
mut
r
=
pats
[
..
col
]
.to_vec
();
r
.extend_from_slice
(
&
pats
[
col
+
1
..
]);
Some
(
r
)
}
else
{
None
match
pats
[
col
]
.node
{
PatKind
::
Binding
(
..
)
|
PatKind
::
Wild
=>
{
let
mut
r
=
pats
[
..
col
]
.to_vec
();
r
.extend_from_slice
(
&
pats
[
col
+
1
..
]);
Some
(
r
)
}
_
=>
None
}
})
}
...
...
@@ -1145,7 +1145,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
has_genuine_default
:
bool
)
{
let
fcx
=
bcx
.fcx
;
let
tcx
=
bcx
.tcx
();
let
dm
=
&
tcx
.def_map
;
let
mut
vals_left
=
vals
[
0
..
col
]
.to_vec
();
vals_left
.extend_from_slice
(
&
vals
[
col
+
1
..
]);
...
...
@@ -1279,7 +1278,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
C_int
(
ccx
,
0
)
// Placeholder for when not using a switch
};
let
defaults
=
enter_default
(
else_cx
,
dm
,
m
,
col
,
val
);
let
defaults
=
enter_default
(
else_cx
,
m
,
col
,
val
);
let
exhaustive
=
chk
.is_infallible
()
&&
defaults
.is_empty
();
let
len
=
opts
.len
();
...
...
@@ -1509,10 +1508,9 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
// Note that we use the names because each binding will have many ids
// from the various alternatives.
let
ccx
=
bcx
.ccx
();
let
tcx
=
bcx
.tcx
();
let
reassigned
=
is_discr_reassigned
(
bcx
,
discr
,
body
);
let
mut
bindings_map
=
FnvHashMap
();
pat_bindings
(
&
tcx
.def_map
,
&
pat
,
|
bm
,
p_id
,
span
,
path1
|
{
pat_bindings
(
&
pat
,
|
bm
,
p_id
,
span
,
path1
|
{
let
name
=
path1
.node
;
let
variable_ty
=
node_id_type
(
bcx
,
p_id
);
let
llvariable_ty
=
type_of
::
type_of
(
ccx
,
variable_ty
);
...
...
@@ -1655,7 +1653,7 @@ fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// create dummy memory for the variables if we have no
// value to store into them immediately
let
tcx
=
bcx
.tcx
();
pat_bindings
(
&
tcx
.def_map
,
pat
,
|
_
,
p_id
,
_
,
path1
|
{
pat_bindings
(
pat
,
|
_
,
p_id
,
_
,
path1
|
{
let
scope
=
cleanup
::
var_scope
(
tcx
,
p_id
);
bcx
=
mk_binding_alloca
(
bcx
,
p_id
,
path1
.node
,
scope
,
(),
...
...
src/librustc_trans/debuginfo/create_scope_map.rs
浏览文件 @
cf468206
...
...
@@ -42,16 +42,13 @@ pub fn create_scope_map(cx: &CrateContext,
fn_ast_id
:
ast
::
NodeId
)
->
NodeMap
<
DIScope
>
{
let
mut
scope_map
=
NodeMap
();
let
def_map
=
&
cx
.tcx
()
.def_map
;
let
mut
scope_stack
=
vec!
(
ScopeStackEntry
{
scope_metadata
:
fn_metadata
,
name
:
None
});
scope_map
.insert
(
fn_ast_id
,
fn_metadata
);
// Push argument identifiers onto the stack so arguments integrate nicely
// with variable shadowing.
for
arg
in
args
{
pat_util
::
pat_bindings
(
def_map
,
&
arg
.pat
,
|
_
,
node_id
,
_
,
path1
|
{
pat_util
::
pat_bindings
(
&
arg
.pat
,
|
_
,
node_id
,
_
,
path1
|
{
scope_stack
.push
(
ScopeStackEntry
{
scope_metadata
:
fn_metadata
,
name
:
Some
(
path1
.node
.unhygienize
())
});
scope_map
.insert
(
node_id
,
fn_metadata
);
...
...
src/librustc_trans/debuginfo/metadata.rs
浏览文件 @
cf468206
...
...
@@ -1889,11 +1889,8 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
return
;
}
let
cx
=
bcx
.ccx
();
let
def_map
=
&
cx
.tcx
()
.def_map
;
let
locals
=
bcx
.fcx.lllocals
.borrow
();
pat_util
::
pat_bindings
(
def_map
,
&
local
.pat
,
|
_
,
node_id
,
span
,
var_name
|
{
pat_util
::
pat_bindings
(
&
local
.pat
,
|
_
,
node_id
,
span
,
var_name
|
{
let
datum
=
match
locals
.get
(
&
node_id
)
{
Some
(
datum
)
=>
datum
,
None
=>
{
...
...
@@ -2062,7 +2059,6 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
return
;
}
let
def_map
=
&
bcx
.tcx
()
.def_map
;
let
scope_metadata
=
bcx
.fcx
.debug_context
...
...
@@ -2070,7 +2066,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
.fn_metadata
;
let
locals
=
bcx
.fcx.lllocals
.borrow
();
pat_util
::
pat_bindings
(
def_map
,
&
arg
.pat
,
|
_
,
node_id
,
span
,
var_name
|
{
pat_util
::
pat_bindings
(
&
arg
.pat
,
|
_
,
node_id
,
span
,
var_name
|
{
let
datum
=
match
locals
.get
(
&
node_id
)
{
Some
(
v
)
=>
v
,
None
=>
{
...
...
src/librustc_typeck/check/_match.rs
浏览文件 @
cf468206
...
...
@@ -10,7 +10,7 @@
use
hir
::
def
::{
self
,
Def
};
use
rustc
::
infer
::{
self
,
InferOk
,
TypeOrigin
};
use
hir
::
pat_util
::{
PatIdMap
,
pat_id_map
,
pat_is_binding
};
use
hir
::
pat_util
::{
PatIdMap
,
pat_id_map
};
use
hir
::
pat_util
::{
EnumerateAndAdjustIterator
,
pat_is_resolved_const
};
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
::{
self
,
Ty
,
TypeFoldable
,
LvaluePreference
};
...
...
@@ -436,23 +436,19 @@ fn check_assoc_item_is_const(&self, def: Def, span: Span) -> bool {
}
pub
fn
check_dereferencable
(
&
self
,
span
:
Span
,
expected
:
Ty
<
'tcx
>
,
inner
:
&
hir
::
Pat
)
->
bool
{
let
tcx
=
self
.tcx
;
if
pat_is_binding
(
&
tcx
.def_map
.borrow
(),
inner
)
{
let
expected
=
self
.shallow_resolve
(
expected
);
expected
.builtin_deref
(
true
,
ty
::
NoPreference
)
.map_or
(
true
,
|
mt
|
match
mt
.ty.sty
{
ty
::
TyTrait
(
_
)
=>
{
if
let
PatKind
::
Binding
(
..
)
=
inner
.node
{
if
let
Some
(
mt
)
=
self
.shallow_resolve
(
expected
)
.builtin_deref
(
true
,
ty
::
NoPreference
)
{
if
let
ty
::
TyTrait
(
..
)
=
mt
.ty.sty
{
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
span_err!
(
tcx
.sess
,
span
,
E0033
,
span_err!
(
self
.
tcx.sess
,
span
,
E0033
,
"type `{}` cannot be dereferenced"
,
self
.ty_to_string
(
expected
));
false
return
false
}
_
=>
true
})
}
else
{
true
}
}
true
}
}
...
...
@@ -491,7 +487,7 @@ pub fn check_match(&self,
for
arm
in
arms
{
let
pcx
=
PatCtxt
{
fcx
:
self
,
map
:
pat_id_map
(
&
tcx
.def_map
,
&
arm
.pats
[
0
]),
map
:
pat_id_map
(
&
arm
.pats
[
0
]),
};
for
p
in
&
arm
.pats
{
pcx
.check_pat
(
&
p
,
discrim_ty
);
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
cf468206
...
...
@@ -630,8 +630,6 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
body
:
&
'gcx
hir
::
Block
)
->
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
let
tcx
=
inherited
.tcx
;
let
arg_tys
=
&
fn_sig
.inputs
;
let
ret_ty
=
fn_sig
.output
;
...
...
@@ -667,19 +665,15 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fcx
.register_old_wf_obligation
(
arg_ty
,
input
.ty.span
,
traits
::
MiscObligation
);
// Create type variables for each argument.
pat_util
::
pat_bindings
(
&
tcx
.def_map
,
&
input
.pat
,
|
_
bm
,
pat_id
,
sp
,
_
path
|
{
let
var_ty
=
visit
.assign
(
sp
,
pat_id
,
None
);
fcx
.require_type_is_sized
(
var_ty
,
sp
,
traits
::
VariableType
(
pat_id
));
});
pat_util
::
pat_bindings
(
&
input
.pat
,
|
_
bm
,
pat_id
,
sp
,
_
path
|
{
let
var_ty
=
visit
.assign
(
sp
,
pat_id
,
None
);
fcx
.require_type_is_sized
(
var_ty
,
sp
,
traits
::
VariableType
(
pat_id
));
});
// Check the pattern.
let
pcx
=
PatCtxt
{
fcx
:
&
fcx
,
map
:
pat_id_map
(
&
tcx
.def_map
,
&
input
.pat
),
map
:
pat_id_map
(
&
input
.pat
),
};
pcx
.check_pat
(
&
input
.pat
,
*
arg_ty
);
}
...
...
@@ -3932,8 +3926,6 @@ pub fn check_decl_initializer(&self,
}
pub
fn
check_decl_local
(
&
self
,
local
:
&
'gcx
hir
::
Local
)
{
let
tcx
=
self
.tcx
;
let
t
=
self
.local_ty
(
local
.span
,
local
.id
);
self
.write_ty
(
local
.id
,
t
);
...
...
@@ -3947,7 +3939,7 @@ pub fn check_decl_local(&self, local: &'gcx hir::Local) {
let
pcx
=
PatCtxt
{
fcx
:
self
,
map
:
pat_id_map
(
&
tcx
.def_map
,
&
local
.pat
),
map
:
pat_id_map
(
&
local
.pat
),
};
pcx
.check_pat
(
&
local
.pat
,
t
);
let
pat_ty
=
self
.node_ty
(
local
.pat.id
);
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
cf468206
...
...
@@ -452,7 +452,7 @@ fn resolve_regions_and_report_errors(&self) {
fn
constrain_bindings_in_pat
(
&
mut
self
,
pat
:
&
hir
::
Pat
)
{
let
tcx
=
self
.tcx
;
debug!
(
"regionck::visit_pat(pat={:?})"
,
pat
);
pat_util
::
pat_bindings
(
&
tcx
.def_map
,
pat
,
|
_
,
id
,
span
,
_
|
{
pat_util
::
pat_bindings
(
pat
,
|
_
,
id
,
span
,
_
|
{
// If we have a variable that contains region'd data, that
// data will be accessible from anywhere that the variable is
// accessed. We must be wary of loops like this:
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
cf468206
...
...
@@ -15,7 +15,6 @@
use
check
::
FnCtxt
;
use
hir
::
def_id
::
DefId
;
use
hir
::
pat_util
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
,
MethodCall
,
MethodCallee
};
use
rustc
::
ty
::
adjustment
;
use
rustc
::
ty
::
fold
::{
TypeFolder
,
TypeFoldable
};
...
...
@@ -29,7 +28,7 @@
use
syntax
::
codemap
::{
DUMMY_SP
,
Span
};
use
rustc
::
hir
::
print
::
pat_to_string
;
use
rustc
::
hir
::
intravisit
::{
self
,
Visitor
};
use
rustc
::
hir
;
use
rustc
::
hir
::{
self
,
PatKind
}
;
///////////////////////////////////////////////////////////////////////////
// Entry point functions
...
...
@@ -54,9 +53,8 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
wbcx
.visit_pat
(
&
arg
.pat
);
// Privacy needs the type for the whole pattern, not just each binding
if
!
pat_util
::
pat_is_binding
(
&
self
.tcx.def_map
.borrow
(),
&
arg
.pat
)
{
wbcx
.visit_node_id
(
ResolvingPattern
(
arg
.pat.span
),
arg
.pat.id
);
if
let
PatKind
::
Binding
(
..
)
=
arg
.pat.node
{}
else
{
wbcx
.visit_node_id
(
ResolvingPattern
(
arg
.pat.span
),
arg
.pat.id
);
}
}
wbcx
.visit_upvar_borrow_map
();
...
...
src/libsyntax/ast.rs
浏览文件 @
cf468206
...
...
@@ -616,14 +616,10 @@ pub enum PatKind {
/// Represents a wildcard pattern (`_`)
Wild
,
/// A `PatKind::Ident` may either be a new bound variable,
/// or a unit struct/variant pattern, or a const pattern (in the last two cases
/// the third field must be `None`).
///
/// In the unit or const pattern case, the parser can't determine
/// which it is. The resolver determines this, and
/// records this pattern's `NodeId` in an auxiliary
/// set (of "PatIdents that refer to unit patterns or constants").
/// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
/// during name resolution.
Ident
(
BindingMode
,
SpannedIdent
,
Option
<
P
<
Pat
>>
),
/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
...
...
@@ -639,10 +635,8 @@ pub enum PatKind {
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path
(
Path
),
/// An associated const named using the qualified path `<T>::CONST` or
/// `<T as Trait>::CONST`. Associated consts from inherent impls can be
/// referred to as simply `T::CONST`, in which case they will end up as
/// PatKind::Path, and the resolver will have to sort that out.
/// A path pattern written in qualified form, i.e. `<T as Trait>::CONST` or `<T>::CONST`.
/// Such patterns can only refer to associated constants at the moment.
QPath
(
QSelf
,
Path
),
/// A tuple pattern `(a, b)`.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录