Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1baac866
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
1baac866
编写于
7月 15, 2021
作者:
C
Camille GILLOT
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Simplify lifetimes_from_impl_trait_bounds.
上级
4878034c
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
181 addition
and
200 deletion
+181
-200
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/lib.rs
+181
-200
未找到文件。
compiler/rustc_ast_lowering/src/lib.rs
浏览文件 @
1baac866
...
...
@@ -1497,20 +1497,50 @@ fn lower_opaque_impl_trait(
self
.allocate_hir_id_counter
(
opaque_ty_node_id
);
let
hir_bounds
=
self
.with_hir_id_owner
(
opaque_ty_node_id
,
lower_bounds
);
let
collected_lifetimes
=
self
.with_hir_id_owner
(
opaque_ty_node_id
,
move
|
lctx
|
{
let
hir_bounds
=
lower_bounds
(
lctx
);
let
(
lifetimes
,
lifetime_defs
)
=
self
.
lifetimes_from_impl_trait_bounds
(
let
collected_lifetimes
=
lifetimes_from_impl_trait_bounds
(
opaque_ty_node_id
,
opaque_ty_def_id
,
&
hir_bounds
,
capturable_lifetimes
,
);
debug!
(
"lower_opaque_impl_trait: lifetimes={:#?}"
,
lifetimes
);
let
lifetime_defs
=
lctx
.arena
.alloc_from_iter
(
collected_lifetimes
.iter
()
.map
(|
&
(
name
,
span
)|
{
let
def_node_id
=
lctx
.resolver
.next_node_id
();
let
hir_id
=
lctx
.lower_node_id
(
def_node_id
);
lctx
.resolver
.create_def
(
opaque_ty_def_id
,
def_node_id
,
DefPathData
::
LifetimeNs
(
name
.ident
()
.name
),
ExpnId
::
root
(),
span
,
);
let
(
name
,
kind
)
=
match
name
{
hir
::
LifetimeName
::
Underscore
=>
(
hir
::
ParamName
::
Plain
(
Ident
::
with_dummy_span
(
kw
::
UnderscoreLifetime
)),
hir
::
LifetimeParamKind
::
Elided
,
),
hir
::
LifetimeName
::
Param
(
param_name
)
=>
{
(
param_name
,
hir
::
LifetimeParamKind
::
Explicit
)
}
_
=>
panic!
(
"expected `LifetimeName::Param` or `ParamName::Plain`"
),
};
hir
::
GenericParam
{
hir_id
,
name
,
span
,
pure_wrt_drop
:
false
,
bounds
:
&
[],
kind
:
hir
::
GenericParamKind
::
Lifetime
{
kind
},
}
}));
debug!
(
"lower_opaque_impl_trait: lifetime_defs={:#?}"
,
lifetime_defs
);
self
.with_hir_id_owner
(
opaque_ty_node_id
,
move
|
lctx
|
{
let
opaque_ty_item
=
hir
::
OpaqueTy
{
generics
:
hir
::
Generics
{
params
:
lifetime_defs
,
...
...
@@ -1525,9 +1555,18 @@ fn lower_opaque_impl_trait(
trace!
(
"lower_opaque_impl_trait: {:#?}"
,
opaque_ty_def_id
);
lctx
.generate_opaque_type
(
opaque_ty_def_id
,
opaque_ty_item
,
span
,
opaque_ty_span
);
collected_lifetimes
});
let
lifetimes
=
self
.arena
.alloc_from_iter
(
collected_lifetimes
.into_iter
()
.map
(|(
name
,
span
)|
{
hir
::
GenericArg
::
Lifetime
(
hir
::
Lifetime
{
hir_id
:
self
.next_id
(),
span
,
name
})
}));
debug!
(
"lower_opaque_impl_trait: lifetimes={:#?}"
,
lifetimes
);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir
::
TyKind
::
OpaqueDef
(
hir
::
ItemId
{
def_id
:
opaque_ty_def_id
},
lifetimes
)
})
}
/// Registers a new opaque type with the proper `NodeId`s and
...
...
@@ -1556,193 +1595,6 @@ fn generate_opaque_type(
self
.insert_item
(
opaque_ty_item
);
}
fn
lifetimes_from_impl_trait_bounds
(
&
mut
self
,
opaque_ty_id
:
NodeId
,
parent_def_id
:
LocalDefId
,
bounds
:
hir
::
GenericBounds
<
'hir
>
,
lifetimes_to_include
:
Option
<&
FxHashSet
<
hir
::
LifetimeName
>>
,
)
->
(
&
'hir
[
hir
::
GenericArg
<
'hir
>
],
&
'hir
[
hir
::
GenericParam
<
'hir
>
])
{
debug!
(
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?},
\
parent_def_id={:?},
\
bounds={:#?})"
,
opaque_ty_id
,
parent_def_id
,
bounds
,
);
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
// appear in the bounds, excluding lifetimes that are created within the bounds.
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
struct
ImplTraitLifetimeCollector
<
'r
,
'a
,
'hir
>
{
context
:
&
'r
mut
LoweringContext
<
'a
,
'hir
>
,
parent
:
LocalDefId
,
opaque_ty_id
:
NodeId
,
collect_elided_lifetimes
:
bool
,
currently_bound_lifetimes
:
Vec
<
hir
::
LifetimeName
>
,
already_defined_lifetimes
:
FxHashSet
<
hir
::
LifetimeName
>
,
output_lifetimes
:
Vec
<
hir
::
GenericArg
<
'hir
>>
,
output_lifetime_params
:
Vec
<
hir
::
GenericParam
<
'hir
>>
,
lifetimes_to_include
:
Option
<&
'r
FxHashSet
<
hir
::
LifetimeName
>>
,
}
impl
<
'r
,
'a
,
'v
,
'hir
>
intravisit
::
Visitor
<
'v
>
for
ImplTraitLifetimeCollector
<
'r
,
'a
,
'hir
>
{
type
Map
=
intravisit
::
ErasedMap
<
'v
>
;
fn
nested_visit_map
(
&
mut
self
)
->
intravisit
::
NestedVisitorMap
<
Self
::
Map
>
{
intravisit
::
NestedVisitorMap
::
None
}
fn
visit_generic_args
(
&
mut
self
,
span
:
Span
,
parameters
:
&
'v
hir
::
GenericArgs
<
'v
>
)
{
// Don't collect elided lifetimes used inside of `Fn()` syntax.
if
parameters
.parenthesized
{
let
old_collect_elided_lifetimes
=
self
.collect_elided_lifetimes
;
self
.collect_elided_lifetimes
=
false
;
intravisit
::
walk_generic_args
(
self
,
span
,
parameters
);
self
.collect_elided_lifetimes
=
old_collect_elided_lifetimes
;
}
else
{
intravisit
::
walk_generic_args
(
self
,
span
,
parameters
);
}
}
fn
visit_ty
(
&
mut
self
,
t
:
&
'v
hir
::
Ty
<
'v
>
)
{
// Don't collect elided lifetimes used inside of `fn()` syntax.
if
let
hir
::
TyKind
::
BareFn
(
_
)
=
t
.kind
{
let
old_collect_elided_lifetimes
=
self
.collect_elided_lifetimes
;
self
.collect_elided_lifetimes
=
false
;
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let
old_len
=
self
.currently_bound_lifetimes
.len
();
intravisit
::
walk_ty
(
self
,
t
);
self
.currently_bound_lifetimes
.truncate
(
old_len
);
self
.collect_elided_lifetimes
=
old_collect_elided_lifetimes
;
}
else
{
intravisit
::
walk_ty
(
self
,
t
)
}
}
fn
visit_poly_trait_ref
(
&
mut
self
,
trait_ref
:
&
'v
hir
::
PolyTraitRef
<
'v
>
,
modifier
:
hir
::
TraitBoundModifier
,
)
{
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let
old_len
=
self
.currently_bound_lifetimes
.len
();
intravisit
::
walk_poly_trait_ref
(
self
,
trait_ref
,
modifier
);
self
.currently_bound_lifetimes
.truncate
(
old_len
);
}
fn
visit_generic_param
(
&
mut
self
,
param
:
&
'v
hir
::
GenericParam
<
'v
>
)
{
// Record the introduction of 'a in `for<'a> ...`.
if
let
hir
::
GenericParamKind
::
Lifetime
{
..
}
=
param
.kind
{
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
let
lt_name
=
hir
::
LifetimeName
::
Param
(
param
.name
);
self
.currently_bound_lifetimes
.push
(
lt_name
);
}
intravisit
::
walk_generic_param
(
self
,
param
);
}
fn
visit_lifetime
(
&
mut
self
,
lifetime
:
&
'v
hir
::
Lifetime
)
{
let
name
=
match
lifetime
.name
{
hir
::
LifetimeName
::
Implicit
|
hir
::
LifetimeName
::
Underscore
=>
{
if
self
.collect_elided_lifetimes
{
// Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`.
hir
::
LifetimeName
::
Underscore
}
else
{
return
;
}
}
hir
::
LifetimeName
::
Param
(
_
)
=>
lifetime
.name
,
// Refers to some other lifetime that is "in
// scope" within the type.
hir
::
LifetimeName
::
ImplicitObjectLifetimeDefault
=>
return
,
hir
::
LifetimeName
::
Error
|
hir
::
LifetimeName
::
Static
=>
return
,
};
if
!
self
.currently_bound_lifetimes
.contains
(
&
name
)
&&
!
self
.already_defined_lifetimes
.contains
(
&
name
)
&&
self
.lifetimes_to_include
.map_or
(
true
,
|
lifetimes
|
lifetimes
.contains
(
&
name
))
{
self
.already_defined_lifetimes
.insert
(
name
);
self
.output_lifetimes
.push
(
hir
::
GenericArg
::
Lifetime
(
hir
::
Lifetime
{
hir_id
:
self
.context
.next_id
(),
span
:
self
.context
.lower_span
(
lifetime
.span
),
name
,
}));
let
def_node_id
=
self
.context.resolver
.next_node_id
();
let
hir_id
=
self
.context
.lower_node_id_with_owner
(
def_node_id
,
self
.opaque_ty_id
);
self
.context.resolver
.create_def
(
self
.parent
,
def_node_id
,
DefPathData
::
LifetimeNs
(
name
.ident
()
.name
),
ExpnId
::
root
(),
lifetime
.span
,
);
let
(
name
,
kind
)
=
match
name
{
hir
::
LifetimeName
::
Underscore
=>
(
hir
::
ParamName
::
Plain
(
Ident
::
with_dummy_span
(
kw
::
UnderscoreLifetime
)),
hir
::
LifetimeParamKind
::
Elided
,
),
hir
::
LifetimeName
::
Param
(
param_name
)
=>
{
(
param_name
,
hir
::
LifetimeParamKind
::
Explicit
)
}
_
=>
panic!
(
"expected `LifetimeName::Param` or `ParamName::Plain`"
),
};
let
name
=
match
name
{
hir
::
ParamName
::
Plain
(
ident
)
=>
{
hir
::
ParamName
::
Plain
(
self
.context
.lower_ident
(
ident
))
}
name
=>
name
,
};
self
.output_lifetime_params
.push
(
hir
::
GenericParam
{
hir_id
,
name
,
span
:
self
.context
.lower_span
(
lifetime
.span
),
pure_wrt_drop
:
false
,
bounds
:
&
[],
kind
:
hir
::
GenericParamKind
::
Lifetime
{
kind
},
});
}
}
}
let
mut
lifetime_collector
=
ImplTraitLifetimeCollector
{
context
:
self
,
parent
:
parent_def_id
,
opaque_ty_id
,
collect_elided_lifetimes
:
true
,
currently_bound_lifetimes
:
Vec
::
new
(),
already_defined_lifetimes
:
FxHashSet
::
default
(),
output_lifetimes
:
Vec
::
new
(),
output_lifetime_params
:
Vec
::
new
(),
lifetimes_to_include
,
};
for
bound
in
bounds
{
intravisit
::
walk_param_bound
(
&
mut
lifetime_collector
,
&
bound
);
}
let
ImplTraitLifetimeCollector
{
output_lifetimes
,
output_lifetime_params
,
..
}
=
lifetime_collector
;
(
self
.arena
.alloc_from_iter
(
output_lifetimes
),
self
.arena
.alloc_from_iter
(
output_lifetime_params
),
)
}
fn
lower_fn_params_to_names
(
&
mut
self
,
decl
:
&
FnDecl
)
->
&
'hir
[
Ident
]
{
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
// as they are not explicit in HIR/Ty function signatures.
...
...
@@ -2723,3 +2575,132 @@ fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::Gener
this
.arena
.alloc
(
ga
)
}
}
fn
lifetimes_from_impl_trait_bounds
(
opaque_ty_id
:
NodeId
,
bounds
:
hir
::
GenericBounds
<
'_
>
,
lifetimes_to_include
:
Option
<&
FxHashSet
<
hir
::
LifetimeName
>>
,
)
->
Vec
<
(
hir
::
LifetimeName
,
Span
)
>
{
debug!
(
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?},
\
bounds={:#?})"
,
opaque_ty_id
,
bounds
,
);
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
// appear in the bounds, excluding lifetimes that are created within the bounds.
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
struct
ImplTraitLifetimeCollector
<
'r
>
{
collect_elided_lifetimes
:
bool
,
currently_bound_lifetimes
:
Vec
<
hir
::
LifetimeName
>
,
already_defined_lifetimes
:
FxHashSet
<
hir
::
LifetimeName
>
,
lifetimes
:
Vec
<
(
hir
::
LifetimeName
,
Span
)
>
,
lifetimes_to_include
:
Option
<&
'r
FxHashSet
<
hir
::
LifetimeName
>>
,
}
impl
<
'r
,
'v
>
intravisit
::
Visitor
<
'v
>
for
ImplTraitLifetimeCollector
<
'r
>
{
type
Map
=
intravisit
::
ErasedMap
<
'v
>
;
fn
nested_visit_map
(
&
mut
self
)
->
intravisit
::
NestedVisitorMap
<
Self
::
Map
>
{
intravisit
::
NestedVisitorMap
::
None
}
fn
visit_generic_args
(
&
mut
self
,
span
:
Span
,
parameters
:
&
'v
hir
::
GenericArgs
<
'v
>
)
{
// Don't collect elided lifetimes used inside of `Fn()` syntax.
if
parameters
.parenthesized
{
let
old_collect_elided_lifetimes
=
self
.collect_elided_lifetimes
;
self
.collect_elided_lifetimes
=
false
;
intravisit
::
walk_generic_args
(
self
,
span
,
parameters
);
self
.collect_elided_lifetimes
=
old_collect_elided_lifetimes
;
}
else
{
intravisit
::
walk_generic_args
(
self
,
span
,
parameters
);
}
}
fn
visit_ty
(
&
mut
self
,
t
:
&
'v
hir
::
Ty
<
'v
>
)
{
// Don't collect elided lifetimes used inside of `fn()` syntax.
if
let
hir
::
TyKind
::
BareFn
(
_
)
=
t
.kind
{
let
old_collect_elided_lifetimes
=
self
.collect_elided_lifetimes
;
self
.collect_elided_lifetimes
=
false
;
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let
old_len
=
self
.currently_bound_lifetimes
.len
();
intravisit
::
walk_ty
(
self
,
t
);
self
.currently_bound_lifetimes
.truncate
(
old_len
);
self
.collect_elided_lifetimes
=
old_collect_elided_lifetimes
;
}
else
{
intravisit
::
walk_ty
(
self
,
t
)
}
}
fn
visit_poly_trait_ref
(
&
mut
self
,
trait_ref
:
&
'v
hir
::
PolyTraitRef
<
'v
>
,
modifier
:
hir
::
TraitBoundModifier
,
)
{
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let
old_len
=
self
.currently_bound_lifetimes
.len
();
intravisit
::
walk_poly_trait_ref
(
self
,
trait_ref
,
modifier
);
self
.currently_bound_lifetimes
.truncate
(
old_len
);
}
fn
visit_generic_param
(
&
mut
self
,
param
:
&
'v
hir
::
GenericParam
<
'v
>
)
{
// Record the introduction of 'a in `for<'a> ...`.
if
let
hir
::
GenericParamKind
::
Lifetime
{
..
}
=
param
.kind
{
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
let
lt_name
=
hir
::
LifetimeName
::
Param
(
param
.name
);
self
.currently_bound_lifetimes
.push
(
lt_name
);
}
intravisit
::
walk_generic_param
(
self
,
param
);
}
fn
visit_lifetime
(
&
mut
self
,
lifetime
:
&
'v
hir
::
Lifetime
)
{
let
name
=
match
lifetime
.name
{
hir
::
LifetimeName
::
Implicit
|
hir
::
LifetimeName
::
Underscore
=>
{
if
self
.collect_elided_lifetimes
{
// Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`.
hir
::
LifetimeName
::
Underscore
}
else
{
return
;
}
}
hir
::
LifetimeName
::
Param
(
_
)
=>
lifetime
.name
,
// Refers to some other lifetime that is "in
// scope" within the type.
hir
::
LifetimeName
::
ImplicitObjectLifetimeDefault
=>
return
,
hir
::
LifetimeName
::
Error
|
hir
::
LifetimeName
::
Static
=>
return
,
};
if
!
self
.currently_bound_lifetimes
.contains
(
&
name
)
&&
!
self
.already_defined_lifetimes
.contains
(
&
name
)
&&
self
.lifetimes_to_include
.map_or
(
true
,
|
lifetimes
|
lifetimes
.contains
(
&
name
))
{
self
.already_defined_lifetimes
.insert
(
name
);
self
.lifetimes
.push
((
name
,
lifetime
.span
));
}
}
}
let
mut
lifetime_collector
=
ImplTraitLifetimeCollector
{
collect_elided_lifetimes
:
true
,
currently_bound_lifetimes
:
Vec
::
new
(),
already_defined_lifetimes
:
FxHashSet
::
default
(),
lifetimes
:
Vec
::
new
(),
lifetimes_to_include
,
};
for
bound
in
bounds
{
intravisit
::
walk_param_bound
(
&
mut
lifetime_collector
,
&
bound
);
}
lifetime_collector
.lifetimes
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录