Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
736348ac
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,发现更多精彩内容 >>
提交
736348ac
编写于
12月 20, 2019
作者:
M
mark
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move a bunch of methods to inherent impl MirBorrowckCtxt
上级
c3e74f34
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
130 addition
and
145 deletion
+130
-145
src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+2
-4
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
...rustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
+1
-3
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+73
-71
src/librustc_mir/borrow_check/diagnostics/region_name.rs
src/librustc_mir/borrow_check/diagnostics/region_name.rs
+51
-60
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/mod.rs
+3
-7
未找到文件。
src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
浏览文件 @
736348ac
...
...
@@ -274,9 +274,7 @@ fn free_region_constraint_info(
);
let
mut
renctx
=
RegionErrorNamingCtx
::
new
();
let
outlived_fr_name
=
self
.nonlexical_regioncx
.give_region_a_name
(
self
,
&
mut
renctx
,
outlived_region
);
// TODO(mark-i-m): just return the region and let the caller name it
let
outlived_fr_name
=
self
.give_region_a_name
(
&
mut
renctx
,
outlived_region
);
(
category
,
from_closure
,
span
,
outlived_fr_name
)
}
...
...
@@ -357,7 +355,7 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
}
None
=>
{
if
let
Some
(
region
)
=
regioncx
.to_error_region_vid
(
borrow_region_vid
)
{
if
let
Some
(
region
)
=
self
.to_error_region_vid
(
borrow_region_vid
)
{
let
(
category
,
from_closure
,
span
,
region_name
)
=
self
.free_region_constraint_info
(
borrow_region_vid
,
region
);
if
let
Some
(
region_name
)
=
region_name
{
...
...
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
浏览文件 @
736348ac
...
...
@@ -80,9 +80,7 @@ fn region_vid_to_name(
renctx
:
&
mut
RegionErrorNamingCtx
,
region
:
RegionVid
,
)
->
Option
<
RegionName
>
{
mbcx
.nonlexical_regioncx
.give_region_a_name
(
mbcx
,
renctx
,
region
)
.filter
(
Self
::
region_name_is_suggestable
)
mbcx
.give_region_a_name
(
renctx
,
region
)
.filter
(
Self
::
region_name_is_suggestable
)
}
/// Compiles a list of all suggestions to be printed in the final big suggestion.
...
...
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
浏览文件 @
736348ac
//! Error reporting machinery for lifetime errors.
use
rustc
::
infer
::{
error_reporting
::
nice_region_error
::
NiceRegionError
,
InferCtxt
,
NLLRegionVariableOrigin
,
};
use
rustc
::
infer
::{
error_reporting
::
nice_region_error
::
NiceRegionError
,
NLLRegionVariableOrigin
};
use
rustc
::
mir
::
ConstraintCategory
;
use
rustc
::
ty
::{
self
,
RegionVid
,
Ty
};
use
rustc_errors
::{
Applicability
,
DiagnosticBuilder
};
...
...
@@ -14,7 +12,7 @@
use
crate
::
borrow_check
::{
nll
::
ConstraintDescription
,
region_infer
::{
values
::
RegionElement
,
RegionInferenceContext
,
TypeTest
},
region_infer
::{
values
::
RegionElement
,
TypeTest
},
universal_regions
::
DefiningTy
,
MirBorrowckCtxt
,
};
...
...
@@ -104,26 +102,28 @@ pub struct ErrorConstraintInfo {
pub
(
super
)
span
:
Span
,
}
impl
<
'
tcx
>
RegionInferenceContext
<
'tcx
>
{
impl
<
'
a
,
'tcx
>
MirBorrowckCtxt
<
'a
,
'tcx
>
{
/// Converts a region inference variable into a `ty::Region` that
/// we can use for error reporting. If `r` is universally bound,
/// then we use the name that we have on record for it. If `r` is
/// existentially bound, then we check its inferred value and try
/// to find a good name from that. Returns `None` if we can't find
/// one (e.g., this is just some random part of the CFG).
pub
fn
to_error_region
(
&
self
,
r
:
RegionVid
)
->
Option
<
ty
::
Region
<
'tcx
>>
{
self
.to_error_region_vid
(
r
)
.and_then
(|
r
|
self
.definitions
[
r
]
.external_name
)
// TODO(mark-i-m): make this private when we move report_region_errors here...
crate
fn
to_error_region
(
&
self
,
r
:
RegionVid
)
->
Option
<
ty
::
Region
<
'tcx
>>
{
self
.to_error_region_vid
(
r
)
.and_then
(|
r
|
self
.nonlexical_regioncx.definitions
[
r
]
.external_name
)
}
/// Returns the
[RegionVid]
corresponding to the region returned by
/// Returns the
`RegionVid`
corresponding to the region returned by
/// `to_error_region`.
pub
fn
to_error_region_vid
(
&
self
,
r
:
RegionVid
)
->
Option
<
RegionVid
>
{
if
self
.universal_regions
.is_universal_region
(
r
)
{
pub
(
super
)
fn
to_error_region_vid
(
&
self
,
r
:
RegionVid
)
->
Option
<
RegionVid
>
{
if
self
.
nonlexical_regioncx.
universal_regions
.is_universal_region
(
r
)
{
Some
(
r
)
}
else
{
let
r_scc
=
self
.constraint_sccs
.scc
(
r
);
let
upper_bound
=
self
.universal_upper_bound
(
r
);
if
self
.scc_values
.contains
(
r_scc
,
upper_bound
)
{
let
r_scc
=
self
.
nonlexical_regioncx.
constraint_sccs
.scc
(
r
);
let
upper_bound
=
self
.
nonlexical_regioncx
.
universal_upper_bound
(
r
);
if
self
.
nonlexical_regioncx.
scc_values
.contains
(
r_scc
,
upper_bound
)
{
self
.to_error_region_vid
(
upper_bound
)
}
else
{
None
...
...
@@ -132,11 +132,13 @@ pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
}
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
crate
fn
is_closure_fn_mut
(
&
self
,
infcx
:
&
InferCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
)
->
bool
{
fn
is_closure_fn_mut
(
&
self
,
fr
:
RegionVid
)
->
bool
{
if
let
Some
(
ty
::
ReFree
(
free_region
))
=
self
.to_error_region
(
fr
)
{
if
let
ty
::
BoundRegion
::
BrEnv
=
free_region
.bound_region
{
if
let
DefiningTy
::
Closure
(
def_id
,
substs
)
=
self
.universal_regions.defining_ty
{
let
closure_kind_ty
=
substs
.as_closure
()
.kind_ty
(
def_id
,
infcx
.tcx
);
if
let
DefiningTy
::
Closure
(
def_id
,
substs
)
=
self
.nonlexical_regioncx.universal_regions.defining_ty
{
let
closure_kind_ty
=
substs
.as_closure
()
.kind_ty
(
def_id
,
self
.infcx.tcx
);
return
Some
(
ty
::
ClosureKind
::
FnMut
)
==
closure_kind_ty
.to_opt_closure_kind
();
}
}
...
...
@@ -153,34 +155,35 @@ pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
pub
(
in
crate
::
borrow_check
)
fn
report_error
<
'a
>
(
&
'a
self
,
mbcx
:
&
MirBorrowckCtxt
<
'a
,
'tcx
>
,
pub
(
in
crate
::
borrow_check
)
fn
report_error
(
&
mut
self
,
fr
:
RegionVid
,
fr_origin
:
NLLRegionVariableOrigin
,
outlived_fr
:
RegionVid
,
outlives_suggestion
:
&
mut
OutlivesSuggestionBuilder
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
DiagnosticBuilder
<
'a
>
{
)
{
debug!
(
"report_error(fr={:?}, outlived_fr={:?})"
,
fr
,
outlived_fr
);
let
(
category
,
_
,
span
)
=
self
.best_blame_constraint
(
&
mbcx
.body
,
fr
,
fr_origin
,
|
r
|
{
self
.provides_universal_region
(
r
,
fr
,
outlived_fr
)
});
let
(
category
,
_
,
span
)
=
self
.nonlexical_regioncx
.best_blame_constraint
(
&
self
.body
,
fr
,
fr_origin
,
|
r
|
{
self
.nonlexical_regioncx
.provides_universal_region
(
r
,
fr
,
outlived_fr
)
});
debug!
(
"report_error: category={:?} {:?}"
,
category
,
span
);
// Check if we can use one of the "nice region errors".
if
let
(
Some
(
f
),
Some
(
o
))
=
(
self
.to_error_region
(
fr
),
self
.to_error_region
(
outlived_fr
))
{
let
tables
=
mbcx
.infcx.tcx
.typeck_tables_of
(
mbcx
.mir_def_id
);
let
nice
=
NiceRegionError
::
new_from_span
(
mbcx
.infcx
,
span
,
o
,
f
,
Some
(
tables
));
let
tables
=
self
.infcx.tcx
.typeck_tables_of
(
self
.mir_def_id
);
let
nice
=
NiceRegionError
::
new_from_span
(
self
.infcx
,
span
,
o
,
f
,
Some
(
tables
));
if
let
Some
(
diag
)
=
nice
.try_report_from_nll
()
{
return
diag
;
diag
.buffer
(
&
mut
self
.errors_buffer
);
return
;
}
}
let
(
fr_is_local
,
outlived_fr_is_local
):
(
bool
,
bool
)
=
(
self
.universal_regions
.is_local_free_region
(
fr
),
self
.universal_regions
.is_local_free_region
(
outlived_fr
),
self
.
nonlexical_regioncx.
universal_regions
.is_local_free_region
(
fr
),
self
.
nonlexical_regioncx.
universal_regions
.is_local_free_region
(
outlived_fr
),
);
debug!
(
...
...
@@ -197,28 +200,30 @@ pub(in crate::borrow_check) fn report_error<'a>(
span
,
};
match
(
category
,
fr_is_local
,
outlived_fr_is_local
)
{
(
ConstraintCategory
::
Return
,
true
,
false
)
if
self
.is_closure_fn_mut
(
mbcx
.infcx
,
fr
)
=>
{
self
.report_fnmut_error
(
mbcx
,
&
errci
,
renctx
)
let
diag
=
match
(
category
,
fr_is_local
,
outlived_fr_is_local
)
{
(
ConstraintCategory
::
Return
,
true
,
false
)
if
self
.is_closure_fn_mut
(
fr
)
=>
{
self
.report_fnmut_error
(
&
errci
,
renctx
)
}
(
ConstraintCategory
::
Assignment
,
true
,
false
)
|
(
ConstraintCategory
::
CallArgument
,
true
,
false
)
=>
{
let
mut
db
=
self
.report_escaping_data_error
(
mbcx
,
&
errci
,
renctx
);
let
mut
db
=
self
.report_escaping_data_error
(
&
errci
,
renctx
);
outlives_suggestion
.intermediate_suggestion
(
mbcx
,
&
errci
,
renctx
,
&
mut
db
);
outlives_suggestion
.intermediate_suggestion
(
self
,
&
errci
,
renctx
,
&
mut
db
);
outlives_suggestion
.collect_constraint
(
fr
,
outlived_fr
);
db
}
_
=>
{
let
mut
db
=
self
.report_general_error
(
mbcx
,
&
errci
,
renctx
);
let
mut
db
=
self
.report_general_error
(
&
errci
,
renctx
);
outlives_suggestion
.intermediate_suggestion
(
mbcx
,
&
errci
,
renctx
,
&
mut
db
);
outlives_suggestion
.intermediate_suggestion
(
self
,
&
errci
,
renctx
,
&
mut
db
);
outlives_suggestion
.collect_constraint
(
fr
,
outlived_fr
);
db
}
}
};
diag
.buffer
(
&
mut
self
.errors_buffer
);
}
/// Report a specialized error when `FnMut` closures return a reference to a captured variable.
...
...
@@ -239,13 +244,12 @@ pub(in crate::borrow_check) fn report_error<'a>(
/// ```
fn
report_fnmut_error
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
errci
:
&
ErrorConstraintInfo
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
DiagnosticBuilder
<
'
_
>
{
)
->
DiagnosticBuilder
<
'
tcx
>
{
let
ErrorConstraintInfo
{
outlived_fr
,
span
,
..
}
=
errci
;
let
mut
diag
=
mbcx
let
mut
diag
=
self
.infcx
.tcx
.sess
...
...
@@ -253,7 +257,8 @@ fn report_fnmut_error(
// We should check if the return type of this closure is in fact a closure - in that
// case, we can special case the error further.
let
return_type_is_closure
=
self
.universal_regions.unnormalized_output_ty
.is_closure
();
let
return_type_is_closure
=
self
.nonlexical_regioncx.universal_regions.unnormalized_output_ty
.is_closure
();
let
message
=
if
return_type_is_closure
{
"returns a closure that contains a reference to a captured variable, which then
\
escapes the closure body"
...
...
@@ -263,7 +268,7 @@ fn report_fnmut_error(
diag
.span_label
(
*
span
,
message
);
match
self
.give_region_a_name
(
mbcx
,
renctx
,
*
outlived_fr
)
.unwrap
()
.source
{
match
self
.give_region_a_name
(
renctx
,
*
outlived_fr
)
.unwrap
()
.source
{
RegionNameSource
::
NamedEarlyBoundRegion
(
fr_span
)
|
RegionNameSource
::
NamedFreeRegion
(
fr_span
)
|
RegionNameSource
::
SynthesizedFreeEnvRegion
(
fr_span
,
_
)
...
...
@@ -300,28 +305,27 @@ fn report_fnmut_error(
/// ```
fn
report_escaping_data_error
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
errci
:
&
ErrorConstraintInfo
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
DiagnosticBuilder
<
'
_
>
{
)
->
DiagnosticBuilder
<
'
tcx
>
{
let
ErrorConstraintInfo
{
span
,
category
,
..
}
=
errci
;
let
fr_name_and_span
=
self
.get_var_name_and_span_for_region
(
mbcx
.infcx.tcx
,
&
mbcx
.body
,
&
mbcx
.local_names
,
&
mbcx
.upvars
,
let
fr_name_and_span
=
self
.
nonlexical_regioncx
.
get_var_name_and_span_for_region
(
self
.infcx.tcx
,
&
self
.body
,
&
self
.local_names
,
&
self
.upvars
,
errci
.fr
,
);
let
outlived_fr_name_and_span
=
self
.get_var_name_and_span_for_region
(
mbcx
.infcx.tcx
,
&
mbcx
.body
,
&
mbcx
.local_names
,
&
mbcx
.upvars
,
let
outlived_fr_name_and_span
=
self
.
nonlexical_regioncx
.
get_var_name_and_span_for_region
(
self
.infcx.tcx
,
&
self
.body
,
&
self
.local_names
,
&
self
.upvars
,
errci
.outlived_fr
,
);
let
escapes_from
=
match
self
.universal_regions.defining_ty
{
let
escapes_from
=
match
self
.
nonlexical_regioncx.
universal_regions.defining_ty
{
DefiningTy
::
Closure
(
..
)
=>
"closure"
,
DefiningTy
::
Generator
(
..
)
=>
"generator"
,
DefiningTy
::
FnDef
(
..
)
=>
"function"
,
...
...
@@ -335,14 +339,13 @@ fn report_escaping_data_error(
||
escapes_from
==
"const"
{
return
self
.report_general_error
(
mbcx
,
&
ErrorConstraintInfo
{
fr_is_local
:
true
,
outlived_fr_is_local
:
false
,
..*
errci
},
renctx
,
);
}
let
mut
diag
=
borrowck_errors
::
borrowed_data_escapes_closure
(
mbcx
.infcx.tcx
,
*
span
,
escapes_from
);
borrowck_errors
::
borrowed_data_escapes_closure
(
self
.infcx.tcx
,
*
span
,
escapes_from
);
if
let
Some
((
Some
(
outlived_fr_name
),
outlived_fr_span
))
=
outlived_fr_name_and_span
{
diag
.span_label
(
...
...
@@ -386,10 +389,9 @@ fn report_escaping_data_error(
/// ```
fn
report_general_error
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
errci
:
&
ErrorConstraintInfo
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
DiagnosticBuilder
<
'
_
>
{
)
->
DiagnosticBuilder
<
'
tcx
>
{
let
ErrorConstraintInfo
{
fr
,
fr_is_local
,
...
...
@@ -401,14 +403,14 @@ fn report_general_error(
}
=
errci
;
let
mut
diag
=
mbcx
.infcx.tcx.sess
.struct_span_err
(
*
span
,
"lifetime may not live long enough"
);
self
.infcx.tcx.sess
.struct_span_err
(
*
span
,
"lifetime may not live long enough"
);
let
mir_def_name
=
if
mbcx
.infcx.tcx
.is_closure
(
mbcx
.mir_def_id
)
{
"closure"
}
else
{
"function"
};
if
self
.infcx.tcx
.is_closure
(
self
.mir_def_id
)
{
"closure"
}
else
{
"function"
};
let
fr_name
=
self
.give_region_a_name
(
mbcx
,
renctx
,
*
fr
)
.unwrap
();
let
fr_name
=
self
.give_region_a_name
(
renctx
,
*
fr
)
.unwrap
();
fr_name
.highlight_region_name
(
&
mut
diag
);
let
outlived_fr_name
=
self
.give_region_a_name
(
mbcx
,
renctx
,
*
outlived_fr
)
.unwrap
();
let
outlived_fr_name
=
self
.give_region_a_name
(
renctx
,
*
outlived_fr
)
.unwrap
();
outlived_fr_name
.highlight_region_name
(
&
mut
diag
);
match
(
category
,
outlived_fr_is_local
,
fr_is_local
)
{
...
...
@@ -435,7 +437,7 @@ fn report_general_error(
}
}
self
.add_static_impl_trait_suggestion
(
mbcx
.infcx
,
&
mut
diag
,
*
fr
,
fr_name
,
*
outlived_fr
);
self
.add_static_impl_trait_suggestion
(
&
mut
diag
,
*
fr
,
fr_name
,
*
outlived_fr
);
diag
}
...
...
@@ -451,8 +453,7 @@ fn report_general_error(
/// ```
fn
add_static_impl_trait_suggestion
(
&
self
,
infcx
:
&
InferCtxt
<
'_
,
'tcx
>
,
diag
:
&
mut
DiagnosticBuilder
<
'_
>
,
diag
:
&
mut
DiagnosticBuilder
<
'tcx
>
,
fr
:
RegionVid
,
// We need to pass `fr_name` - computing it again will label it twice.
fr_name
:
RegionName
,
...
...
@@ -461,11 +462,12 @@ fn add_static_impl_trait_suggestion(
if
let
(
Some
(
f
),
Some
(
ty
::
RegionKind
::
ReStatic
))
=
(
self
.to_error_region
(
fr
),
self
.to_error_region
(
outlived_fr
))
{
if
let
Some
((
ty
::
TyS
{
kind
:
ty
::
Opaque
(
did
,
substs
),
..
},
_
))
=
infcx
if
let
Some
((
ty
::
TyS
{
kind
:
ty
::
Opaque
(
did
,
substs
),
..
},
_
))
=
self
.infcx
.tcx
.is_suitable_region
(
f
)
.map
(|
r
|
r
.def_id
)
.map
(|
id
|
infcx
.tcx
.return_type_impl_trait
(
id
))
.map
(|
id
|
self
.
infcx.tcx
.return_type_impl_trait
(
id
))
.unwrap_or
(
None
)
{
// Check whether or not the impl trait return type is intended to capture
...
...
@@ -473,8 +475,8 @@ fn add_static_impl_trait_suggestion(
//
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
let
has_static_predicate
=
{
let
predicates_of
=
infcx
.tcx
.predicates_of
(
*
did
);
let
bounds
=
predicates_of
.instantiate
(
infcx
.tcx
,
substs
);
let
predicates_of
=
self
.
infcx.tcx
.predicates_of
(
*
did
);
let
bounds
=
predicates_of
.instantiate
(
self
.
infcx.tcx
,
substs
);
let
mut
found
=
false
;
for
predicate
in
bounds
.predicates
{
...
...
@@ -502,8 +504,8 @@ fn add_static_impl_trait_suggestion(
diag
.help
(
&
format!
(
"consider replacing `{}` with `{}`"
,
fr_name
,
static_str
));
}
else
{
// Otherwise, we should suggest adding a constraint on the return type.
let
span
=
infcx
.tcx
.def_span
(
*
did
);
if
let
Ok
(
snippet
)
=
infcx
.tcx.sess
.source_map
()
.span_to_snippet
(
span
)
{
let
span
=
self
.
infcx.tcx
.def_span
(
*
did
);
if
let
Ok
(
snippet
)
=
self
.
infcx.tcx.sess
.source_map
()
.span_to_snippet
(
span
)
{
let
suggestable_fr_name
=
if
fr_name
.was_named
()
{
fr_name
.to_string
()
}
else
{
...
...
src/librustc_mir/borrow_check/diagnostics/region_name.rs
浏览文件 @
736348ac
...
...
@@ -2,7 +2,7 @@
use
rustc
::
ty
::
print
::
RegionHighlightMode
;
use
rustc
::
ty
::
subst
::{
GenericArgKind
,
SubstsRef
};
use
rustc
::
ty
::{
self
,
RegionVid
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::{
self
,
RegionVid
,
Ty
};
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
rustc_errors
::
DiagnosticBuilder
;
use
rustc_hir
as
hir
;
...
...
@@ -10,10 +10,7 @@
use
rustc_span
::
symbol
::
kw
;
use
rustc_span
::{
symbol
::
Symbol
,
Span
,
DUMMY_SP
};
use
crate
::
borrow_check
::{
nll
::
ToRegionVid
,
region_infer
::
RegionInferenceContext
,
universal_regions
::
DefiningTy
,
MirBorrowckCtxt
,
};
use
crate
::
borrow_check
::{
nll
::
ToRegionVid
,
universal_regions
::
DefiningTy
,
MirBorrowckCtxt
};
/// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
...
...
@@ -161,7 +158,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
impl
<
'tcx
>
RegionInferenceContext
<
'tcx
>
{
impl
<
'tcx
>
MirBorrowckCtxt
<
'_
,
'tcx
>
{
/// Maps from an internal MIR region vid to something that we can
/// report to the user. In some cases, the region vids will map
/// directly to lifetimes that the user has a name for (e.g.,
...
...
@@ -189,24 +186,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// and then return the name `'1` for us to use.
crate
fn
give_region_a_name
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
renctx
:
&
mut
RegionErrorNamingCtx
,
fr
:
RegionVid
,
)
->
Option
<
RegionName
>
{
debug!
(
"give_region_a_name(fr={:?}, counter={:?})"
,
fr
,
renctx
.counter
);
assert
!
(
self
.universal_regions
.is_universal_region
(
fr
));
assert
!
(
self
.
nonlexical_regioncx.
universal_regions
.is_universal_region
(
fr
));
if
let
Some
(
value
)
=
renctx
.get
(
&
fr
)
{
return
Some
(
value
.clone
());
}
let
value
=
self
.give_name_from_error_region
(
mbcx
,
fr
,
renctx
)
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_arguments
(
mbcx
,
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_upvars
(
mbcx
,
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_output
(
mbcx
,
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_yield_ty
(
mbcx
,
fr
,
renctx
));
.give_name_from_error_region
(
fr
,
renctx
)
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_arguments
(
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_upvars
(
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_output
(
fr
,
renctx
))
.or_else
(||
self
.give_name_if_anonymous_region_appears_in_yield_ty
(
fr
,
renctx
));
if
let
Some
(
ref
value
)
=
value
{
renctx
.insert
(
fr
,
value
.clone
());
...
...
@@ -222,13 +218,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// named variants.
fn
give_name_from_error_region
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
let
error_region
=
self
.to_error_region
(
fr
)
?
;
let
tcx
=
mbcx
.infcx.tcx
;
let
tcx
=
self
.infcx.tcx
;
debug!
(
"give_region_a_name: error_region = {:?}"
,
error_region
);
match
error_region
{
...
...
@@ -276,13 +271,13 @@ fn give_name_from_error_region(
}
ty
::
BoundRegion
::
BrEnv
=>
{
let
mir_hir_id
=
mbcx
let
mir_hir_id
=
self
.infcx
.tcx
.hir
()
.as_local_hir_id
(
mbcx
.mir_def_id
)
.as_local_hir_id
(
self
.mir_def_id
)
.expect
(
"non-local mir"
);
let
def_ty
=
self
.universal_regions.defining_ty
;
let
def_ty
=
self
.
nonlexical_regioncx.
universal_regions.defining_ty
;
if
let
DefiningTy
::
Closure
(
def_id
,
substs
)
=
def_ty
{
let
args_span
=
if
let
hir
::
ExprKind
::
Closure
(
_
,
_
,
_
,
span
,
_
)
=
...
...
@@ -346,38 +341,34 @@ fn give_name_from_error_region(
/// ```
fn
give_name_if_anonymous_region_appears_in_arguments
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
let
implicit_inputs
=
self
.universal_regions.defining_ty
.implicit_inputs
();
let
argument_index
=
self
.get_argument_index_for_region
(
mbcx
.infcx.tcx
,
fr
)
?
;
let
arg_ty
=
self
.universal_regions.unnormalized_input_tys
[
implicit_inputs
+
argument_index
];
if
let
Some
(
region_name
)
=
self
.give_name_if_we_can_match_hir_ty_from_argument
(
mbcx
,
fr
,
arg_ty
,
argument_index
,
renctx
,
)
{
let
implicit_inputs
=
self
.nonlexical_regioncx.universal_regions.defining_ty
.implicit_inputs
();
let
argument_index
=
self
.nonlexical_regioncx
.get_argument_index_for_region
(
self
.infcx.tcx
,
fr
)
?
;
let
arg_ty
=
self
.nonlexical_regioncx.universal_regions.unnormalized_input_tys
[
implicit_inputs
+
argument_index
];
if
let
Some
(
region_name
)
=
self
.give_name_if_we_can_match_hir_ty_from_argument
(
fr
,
arg_ty
,
argument_index
,
renctx
)
{
return
Some
(
region_name
);
}
self
.give_name_if_we_cannot_match_hir_ty
(
mbcx
,
fr
,
arg_ty
,
renctx
)
self
.give_name_if_we_cannot_match_hir_ty
(
fr
,
arg_ty
,
renctx
)
}
fn
give_name_if_we_can_match_hir_ty_from_argument
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
needle_fr
:
RegionVid
,
argument_ty
:
Ty
<
'tcx
>
,
argument_index
:
usize
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
let
mir_hir_id
=
mbcx
.infcx.tcx
.hir
()
.as_local_hir_id
(
mbcx
.mir_def_id
)
?
;
let
fn_decl
=
mbcx
.infcx.tcx
.hir
()
.fn_decl_by_hir_id
(
mir_hir_id
)
?
;
let
mir_hir_id
=
self
.infcx.tcx
.hir
()
.as_local_hir_id
(
self
.mir_def_id
)
?
;
let
fn_decl
=
self
.infcx.tcx
.hir
()
.fn_decl_by_hir_id
(
mir_hir_id
)
?
;
let
argument_hir_ty
:
&
hir
::
Ty
<
'_
>
=
fn_decl
.inputs
.get
(
argument_index
)
?
;
match
argument_hir_ty
.kind
{
// This indicates a variable with no type annotation, like
...
...
@@ -388,7 +379,6 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
hir
::
TyKind
::
Infer
=>
None
,
_
=>
self
.give_name_if_we_can_match_hir_ty
(
mbcx
.infcx.tcx
,
needle_fr
,
argument_ty
,
argument_hir_ty
,
...
...
@@ -410,7 +400,6 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
/// ```
fn
give_name_if_we_cannot_match_hir_ty
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
needle_fr
:
RegionVid
,
argument_ty
:
Ty
<
'tcx
>
,
renctx
:
&
mut
RegionErrorNamingCtx
,
...
...
@@ -418,7 +407,7 @@ fn give_name_if_we_cannot_match_hir_ty(
let
counter
=
renctx
.counter
;
let
mut
highlight
=
RegionHighlightMode
::
default
();
highlight
.highlighting_region_vid
(
needle_fr
,
counter
);
let
type_name
=
mbcx
.infcx
.extract_type_name
(
&
argument_ty
,
Some
(
highlight
))
.0
;
let
type_name
=
self
.infcx
.extract_type_name
(
&
argument_ty
,
Some
(
highlight
))
.0
;
debug!
(
"give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}"
,
...
...
@@ -426,10 +415,12 @@ fn give_name_if_we_cannot_match_hir_ty(
);
let
assigned_region_name
=
if
type_name
.find
(
&
format!
(
"'{}"
,
counter
))
.is_some
()
{
// Only add a label if we can confirm that a region was labelled.
let
argument_index
=
self
.get_argument_index_for_region
(
mbcx
.infcx.tcx
,
needle_fr
)
?
;
let
(
_
,
span
)
=
self
.get_argument_name_and_span_for_region
(
&
mbcx
.body
,
&
mbcx
.local_names
,
let
argument_index
=
self
.nonlexical_regioncx
.get_argument_index_for_region
(
self
.infcx.tcx
,
needle_fr
)
?
;
let
(
_
,
span
)
=
self
.nonlexical_regioncx
.get_argument_name_and_span_for_region
(
&
self
.body
,
&
self
.local_names
,
argument_index
,
);
...
...
@@ -470,7 +461,6 @@ fn give_name_if_we_cannot_match_hir_ty(
/// to highlighting that closest type instead.
fn
give_name_if_we_can_match_hir_ty
(
&
self
,
tcx
:
TyCtxt
<
'tcx
>
,
needle_fr
:
RegionVid
,
argument_ty
:
Ty
<
'tcx
>
,
argument_hir_ty
:
&
hir
::
Ty
<
'_
>
,
...
...
@@ -495,7 +485,7 @@ fn give_name_if_we_can_match_hir_ty(
let
region_name
=
renctx
.synthesize_region_name
();
// Just grab the first character, the `&`.
let
source_map
=
tcx
.sess
.source_map
();
let
source_map
=
self
.infcx.
tcx.sess
.source_map
();
let
ampersand_span
=
source_map
.start_point
(
hir_ty
.span
);
return
Some
(
RegionName
{
...
...
@@ -665,13 +655,16 @@ fn try_match_adt_and_generic_args<'hir>(
/// ```
fn
give_name_if_anonymous_region_appears_in_upvars
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
let
upvar_index
=
self
.get_upvar_index_for_region
(
mbcx
.infcx.tcx
,
fr
)
?
;
let
(
upvar_name
,
upvar_span
)
=
self
.get_upvar_name_and_span_for_region
(
mbcx
.infcx.tcx
,
&
mbcx
.upvars
,
upvar_index
);
let
upvar_index
=
self
.nonlexical_regioncx
.get_upvar_index_for_region
(
self
.infcx.tcx
,
fr
)
?
;
let
(
upvar_name
,
upvar_span
)
=
self
.nonlexical_regioncx
.get_upvar_name_and_span_for_region
(
self
.infcx.tcx
,
&
self
.upvars
,
upvar_index
,
);
let
region_name
=
renctx
.synthesize_region_name
();
Some
(
RegionName
{
...
...
@@ -686,13 +679,12 @@ fn give_name_if_anonymous_region_appears_in_upvars(
/// or be early bound (named, not in argument).
fn
give_name_if_anonymous_region_appears_in_output
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
let
tcx
=
mbcx
.infcx.tcx
;
let
tcx
=
self
.infcx.tcx
;
let
return_ty
=
self
.universal_regions.unnormalized_output_ty
;
let
return_ty
=
self
.
nonlexical_regioncx.
universal_regions.unnormalized_output_ty
;
debug!
(
"give_name_if_anonymous_region_appears_in_output: return_ty = {:?}"
,
return_ty
);
if
!
tcx
.any_free_region_meets
(
&
return_ty
,
|
r
|
r
.to_region_vid
()
==
fr
)
{
return
None
;
...
...
@@ -700,9 +692,9 @@ fn give_name_if_anonymous_region_appears_in_output(
let
mut
highlight
=
RegionHighlightMode
::
default
();
highlight
.highlighting_region_vid
(
fr
,
renctx
.counter
);
let
type_name
=
mbcx
.infcx
.extract_type_name
(
&
return_ty
,
Some
(
highlight
))
.0
;
let
type_name
=
self
.infcx
.extract_type_name
(
&
return_ty
,
Some
(
highlight
))
.0
;
let
mir_hir_id
=
tcx
.hir
()
.as_local_hir_id
(
mbcx
.mir_def_id
)
.expect
(
"non-local mir"
);
let
mir_hir_id
=
tcx
.hir
()
.as_local_hir_id
(
self
.mir_def_id
)
.expect
(
"non-local mir"
);
let
(
return_span
,
mir_description
)
=
match
tcx
.hir
()
.get
(
mir_hir_id
)
{
hir
::
Node
::
Expr
(
hir
::
Expr
{
...
...
@@ -719,7 +711,7 @@ fn give_name_if_anonymous_region_appears_in_output(
kind
:
hir
::
ImplItemKind
::
Method
(
method_sig
,
_
),
..
})
=>
(
method_sig
.decl.output
.span
(),
""
),
_
=>
(
mbcx
.body.span
,
""
),
_
=>
(
self
.body.span
,
""
),
};
Some
(
RegionName
{
...
...
@@ -737,16 +729,15 @@ fn give_name_if_anonymous_region_appears_in_output(
fn
give_name_if_anonymous_region_appears_in_yield_ty
(
&
self
,
mbcx
:
&
MirBorrowckCtxt
<
'_
,
'tcx
>
,
fr
:
RegionVid
,
renctx
:
&
mut
RegionErrorNamingCtx
,
)
->
Option
<
RegionName
>
{
// Note: generators from `async fn` yield `()`, so we don't have to
// worry about them here.
let
yield_ty
=
self
.universal_regions.yield_ty
?
;
let
yield_ty
=
self
.
nonlexical_regioncx.
universal_regions.yield_ty
?
;
debug!
(
"give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}"
,
yield_ty
,);
let
tcx
=
mbcx
.infcx.tcx
;
let
tcx
=
self
.infcx.tcx
;
if
!
tcx
.any_free_region_meets
(
&
yield_ty
,
|
r
|
r
.to_region_vid
()
==
fr
)
{
return
None
;
...
...
@@ -754,15 +745,15 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
let
mut
highlight
=
RegionHighlightMode
::
default
();
highlight
.highlighting_region_vid
(
fr
,
renctx
.counter
);
let
type_name
=
mbcx
.infcx
.extract_type_name
(
&
yield_ty
,
Some
(
highlight
))
.0
;
let
type_name
=
self
.infcx
.extract_type_name
(
&
yield_ty
,
Some
(
highlight
))
.0
;
let
mir_hir_id
=
tcx
.hir
()
.as_local_hir_id
(
mbcx
.mir_def_id
)
.expect
(
"non-local mir"
);
let
mir_hir_id
=
tcx
.hir
()
.as_local_hir_id
(
self
.mir_def_id
)
.expect
(
"non-local mir"
);
let
yield_span
=
match
tcx
.hir
()
.get
(
mir_hir_id
)
{
hir
::
Node
::
Expr
(
hir
::
Expr
{
kind
:
hir
::
ExprKind
::
Closure
(
_
,
_
,
_
,
span
,
_
),
..
})
=>
(
tcx
.sess
.source_map
()
.end_point
(
*
span
)),
_
=>
mbcx
.body.span
,
_
=>
self
.body.span
,
};
debug!
(
...
...
src/librustc_mir/borrow_check/mod.rs
浏览文件 @
736348ac
...
...
@@ -1471,7 +1471,7 @@ fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
// buffered in the `MirBorrowckCtxt`.
//
FIXME
(mark-i-m): Would be great to get rid of the naming context.
//
TODO
(mark-i-m): Would be great to get rid of the naming context.
let
mut
region_naming
=
RegionErrorNamingCtx
::
new
();
let
mut
outlives_suggestion
=
OutlivesSuggestionBuilder
::
default
();
...
...
@@ -1479,8 +1479,7 @@ fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
match
nll_error
{
RegionErrorKind
::
TypeTestError
{
type_test
}
=>
{
// Try to convert the lower-bound region into something named we can print for the user.
let
lower_bound_region
=
self
.nonlexical_regioncx
.to_error_region
(
type_test
.lower_bound
);
let
lower_bound_region
=
self
.to_error_region
(
type_test
.lower_bound
);
// Skip duplicate-ish errors.
let
type_test_span
=
type_test
.locations
.span
(
&
self
.body
);
...
...
@@ -1557,16 +1556,13 @@ fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
RegionErrorKind
::
RegionError
{
fr_origin
,
longer_fr
,
shorter_fr
,
is_reported
}
=>
{
if
is_reported
{
let
db
=
self
.nonlexical_regioncx
.report_error
(
self
,
self
.report_error
(
longer_fr
,
fr_origin
,
shorter_fr
,
&
mut
outlives_suggestion
,
&
mut
region_naming
,
);
db
.buffer
(
&
mut
self
.errors_buffer
);
}
else
{
// We only report the first error, so as not to overwhelm the user. See
// `RegRegionErrorKind` docs.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录