Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
cafd83d1
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,发现更多精彩内容 >>
提交
cafd83d1
编写于
1月 11, 2019
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: don't keep RegionHighlightMode in a thread-local.
上级
7c4eecef
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
334 addition
and
306 deletion
+334
-306
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/need_type_info.rs
+18
-7
src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
...er/error_reporting/nice_region_error/placeholder_error.rs
+124
-106
src/librustc/ty/print.rs
src/librustc/ty/print.rs
+106
-0
src/librustc/util/ppaux.rs
src/librustc/util/ppaux.rs
+32
-161
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/error_reporting.rs
+47
-25
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
...row_check/nll/region_infer/error_reporting/region_name.rs
+7
-7
未找到文件。
src/librustc/infer/error_reporting/need_type_info.rs
浏览文件 @
cafd83d1
...
...
@@ -3,6 +3,7 @@
use
crate
::
infer
::
InferCtxt
;
use
crate
::
infer
::
type_variable
::
TypeVariableOrigin
;
use
crate
::
ty
::{
self
,
Ty
,
Infer
,
TyVar
};
use
ty
::
print
::
Print
;
use
syntax
::
source_map
::
CompilerDesugaringKind
;
use
syntax_pos
::
Span
;
use
errors
::
DiagnosticBuilder
;
...
...
@@ -64,18 +65,28 @@ fn visit_body(&mut self, body: &'gcx Body) {
impl
<
'a
,
'gcx
,
'tcx
>
InferCtxt
<
'a
,
'gcx
,
'tcx
>
{
pub
fn
extract_type_name
(
&
self
,
ty
:
&
'a
Ty
<
'tcx
>
)
->
String
{
pub
fn
extract_type_name
(
&
self
,
ty
:
&
'a
Ty
<
'tcx
>
,
highlight
:
Option
<
ty
::
print
::
RegionHighlightMode
>
,
)
->
String
{
if
let
ty
::
Infer
(
ty
::
TyVar
(
ty_vid
))
=
(
*
ty
)
.sty
{
let
ty_vars
=
self
.type_variables
.borrow
();
if
let
TypeVariableOrigin
::
TypeParameterDefinition
(
_
,
name
)
=
*
ty_vars
.var_origin
(
ty_vid
)
{
name
.to_string
()
}
else
{
ty
.to_string
()
return
name
.to_string
();
}
}
else
{
ty
.to_string
()
}
let
mut
s
=
String
::
new
();
let
mut
printer
=
ty
::
print
::
FmtPrinter
::
new
(
&
mut
s
);
if
let
Some
(
highlight
)
=
highlight
{
printer
.region_highlight_mode
=
highlight
;
}
let
_
=
ty
::
print
::
PrintCx
::
with
(
self
.tcx
,
printer
,
|
cx
|
{
ty
.print
(
cx
)
});
s
}
pub
fn
need_type_info_err
(
&
self
,
...
...
@@ -84,7 +95,7 @@ pub fn need_type_info_err(&self,
ty
:
Ty
<
'tcx
>
)
->
DiagnosticBuilder
<
'gcx
>
{
let
ty
=
self
.resolve_type_vars_if_possible
(
&
ty
);
let
name
=
self
.extract_type_name
(
&
ty
);
let
name
=
self
.extract_type_name
(
&
ty
,
None
);
let
mut
err_span
=
span
;
let
mut
labels
=
vec!
[(
...
...
src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
浏览文件 @
cafd83d1
...
...
@@ -5,10 +5,12 @@
use
crate
::
infer
::
ValuePairs
;
use
crate
::
infer
::{
SubregionOrigin
,
TypeTrace
};
use
crate
::
traits
::{
ObligationCause
,
ObligationCauseCode
};
use
crate
::
ty
;
use
crate
::
ty
::{
self
,
TyCtxt
}
;
use
crate
::
ty
::
error
::
ExpectedFound
;
use
crate
::
ty
::
subst
::
SubstsRef
;
use
crate
::
util
::
ppaux
::
RegionHighlightMode
;
use
crate
::
ty
::
print
::{
Print
,
RegionHighlightMode
,
FmtPrinter
};
use
std
::
fmt
::{
self
,
Write
};
impl
NiceRegionError
<
'me
,
'gcx
,
'tcx
>
{
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
...
...
@@ -309,13 +311,48 @@ fn explain_actual_impl_that_was_found(
sup_placeholder
:
Option
<
ty
::
Region
<
'tcx
>>
,
has_sub
:
Option
<
usize
>
,
has_sup
:
Option
<
usize
>
,
expected_trait_ref
:
ty
::
TraitRef
<
'
_
>
,
actual_trait_ref
:
ty
::
TraitRef
<
'
_
>
,
expected_trait_ref
:
ty
::
TraitRef
<
'
tcx
>
,
actual_trait_ref
:
ty
::
TraitRef
<
'
tcx
>
,
vid
:
Option
<
ty
::
Region
<
'tcx
>>
,
expected_has_vid
:
Option
<
usize
>
,
actual_has_vid
:
Option
<
usize
>
,
any_self_ty_has_vid
:
bool
,
)
{
// HACK(eddyb) maybe move this in a more central location.
#[derive(Copy,
Clone)]
struct
Highlighted
<
'a
,
'gcx
,
'tcx
,
T
>
{
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
highlight
:
RegionHighlightMode
,
value
:
T
,
}
impl
<
'a
,
'gcx
,
'tcx
,
T
>
Highlighted
<
'a
,
'gcx
,
'tcx
,
T
>
{
fn
map
<
U
>
(
self
,
f
:
impl
FnOnce
(
T
)
->
U
)
->
Highlighted
<
'a
,
'gcx
,
'tcx
,
U
>
{
Highlighted
{
tcx
:
self
.tcx
,
highlight
:
self
.highlight
,
value
:
f
(
self
.value
),
}
}
}
impl
<
'tcx
,
T
>
fmt
::
Display
for
Highlighted
<
'_
,
'_
,
'tcx
,
T
>
where
T
:
for
<
'a
,
'b
>
Print
<
'tcx
,
FmtPrinter
<&
'a
mut
fmt
::
Formatter
<
'b
>>
,
Error
=
fmt
::
Error
,
>
,
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
<
'_
>
)
->
fmt
::
Result
{
let
mut
printer
=
ty
::
print
::
FmtPrinter
::
new
(
f
);
printer
.region_highlight_mode
=
self
.highlight
;
ty
::
print
::
PrintCx
::
with
(
self
.tcx
,
printer
,
|
cx
|
{
self
.value
.print
(
cx
)
?
;
Ok
(())
})
}
}
// The weird thing here with the `maybe_highlighting_region` calls and the
// the match inside is meant to be like this:
//
...
...
@@ -331,112 +368,93 @@ fn explain_actual_impl_that_was_found(
// None, an then we check again inside the closure, but this
// setup sort of minimized the number of calls and so form.
RegionHighlightMode
::
maybe_highlighting_region
(
sub_placeholder
,
has_sub
,
||
{
RegionHighlightMode
::
maybe_highlighting_region
(
sup_placeholder
,
has_sup
,
||
{
match
(
has_sub
,
has_sup
)
{
(
Some
(
n1
),
Some
(
n2
))
=>
{
if
any_self_ty_has_vid
{
err
.note
(
&
format!
(
"`{}` would have to be implemented for the type `{}`,
\
for any two lifetimes `'{}` and `'{}`"
,
expected_trait_ref
,
expected_trait_ref
.self_ty
(),
std
::
cmp
::
min
(
n1
,
n2
),
std
::
cmp
::
max
(
n1
,
n2
),
));
}
else
{
err
.note
(
&
format!
(
"`{}` must implement `{}`,
\
for any two lifetimes `'{}` and `'{}`"
,
expected_trait_ref
.self_ty
(),
expected_trait_ref
,
std
::
cmp
::
min
(
n1
,
n2
),
std
::
cmp
::
max
(
n1
,
n2
),
));
}
}
(
Some
(
n
),
_
)
|
(
_
,
Some
(
n
))
=>
{
if
any_self_ty_has_vid
{
err
.note
(
&
format!
(
"`{}` would have to be implemented for the type `{}`,
\
for any lifetime `'{}`"
,
expected_trait_ref
,
expected_trait_ref
.self_ty
(),
n
,
));
}
else
{
err
.note
(
&
format!
(
"`{}` must implement `{}`, for any lifetime `'{}`"
,
expected_trait_ref
.self_ty
(),
expected_trait_ref
,
n
,
));
}
}
(
None
,
None
)
=>
RegionHighlightMode
::
maybe_highlighting_region
(
vid
,
expected_has_vid
,
||
{
if
let
Some
(
n
)
=
expected_has_vid
{
err
.note
(
&
format!
(
"`{}` would have to be implemented for the type `{}`,
\
for some specific lifetime `'{}`"
,
expected_trait_ref
,
expected_trait_ref
.self_ty
(),
n
,
));
}
else
{
if
any_self_ty_has_vid
{
err
.note
(
&
format!
(
"`{}` would have to be implemented for the type `{}`"
,
expected_trait_ref
,
expected_trait_ref
.self_ty
(),
));
}
else
{
err
.note
(
&
format!
(
"`{}` must implement `{}`"
,
expected_trait_ref
.self_ty
(),
expected_trait_ref
,
));
}
}
},
),
}
})
});
let
highlight_trait_ref
=
|
trait_ref
|
Highlighted
{
tcx
:
self
.tcx
(),
highlight
:
RegionHighlightMode
::
default
(),
value
:
trait_ref
,
};
RegionHighlightMode
::
maybe_highlighting_region
(
vid
,
actual_has_vid
,
||
match
actual_has_vid
{
Some
(
n
)
=>
{
if
any_self_ty_has_vid
{
err
.note
(
&
format!
(
"but `{}` is actually implemented for the type `{}`,
\
for some specific lifetime `'{}`"
,
actual_trait_ref
,
actual_trait_ref
.self_ty
(),
n
));
}
else
{
err
.note
(
&
format!
(
"but `{}` actually implements `{}`, for some specific lifetime `'{}`"
,
actual_trait_ref
.self_ty
(),
actual_trait_ref
,
n
));
let
mut
expected_trait_ref
=
highlight_trait_ref
(
expected_trait_ref
);
expected_trait_ref
.highlight
.maybe_highlighting_region
(
sub_placeholder
,
has_sub
);
expected_trait_ref
.highlight
.maybe_highlighting_region
(
sup_placeholder
,
has_sup
);
err
.note
(
&
{
let
passive_voice
=
match
(
has_sub
,
has_sup
)
{
(
Some
(
_
),
_
)
|
(
_
,
Some
(
_
))
=>
any_self_ty_has_vid
,
(
None
,
None
)
=>
{
expected_trait_ref
.highlight
.maybe_highlighting_region
(
vid
,
expected_has_vid
);
match
expected_has_vid
{
Some
(
_
)
=>
true
,
None
=>
any_self_ty_has_vid
,
}
}
};
_
=>
{
err
.note
(
&
format!
(
"but `{}` is actually implemented for the type `{}`"
,
actual_trait_ref
,
actual_trait_ref
.self_ty
(),
));
let
mut
note
=
if
passive_voice
{
format!
(
"`{}` would have to be implemented for the type `{}`"
,
expected_trait_ref
,
expected_trait_ref
.map
(|
tr
|
tr
.self_ty
()),
)
}
else
{
format!
(
"`{}` must implement `{}`"
,
expected_trait_ref
.map
(|
tr
|
tr
.self_ty
()),
expected_trait_ref
,
)
};
match
(
has_sub
,
has_sup
)
{
(
Some
(
n1
),
Some
(
n2
))
=>
{
let
_
=
write!
(
note
,
", for any two lifetimes `'{}` and `'{}`"
,
std
::
cmp
::
min
(
n1
,
n2
),
std
::
cmp
::
max
(
n1
,
n2
),
);
}
},
);
(
Some
(
n
),
_
)
|
(
_
,
Some
(
n
))
=>
{
let
_
=
write!
(
note
,
", for any lifetime `'{}`"
,
n
,
);
}
(
None
,
None
)
=>
if
let
Some
(
n
)
=
expected_has_vid
{
let
_
=
write!
(
note
,
", for some specific lifetime `'{}`"
,
n
,
);
},
}
note
});
let
mut
actual_trait_ref
=
highlight_trait_ref
(
actual_trait_ref
);
actual_trait_ref
.highlight
.maybe_highlighting_region
(
vid
,
actual_has_vid
);
err
.note
(
&
{
let
passive_voice
=
match
actual_has_vid
{
Some
(
_
)
=>
any_self_ty_has_vid
,
None
=>
true
,
};
let
mut
note
=
if
passive_voice
{
format!
(
"but `{}` is actually implemented for the type `{}`"
,
actual_trait_ref
,
actual_trait_ref
.map
(|
tr
|
tr
.self_ty
()),
)
}
else
{
format!
(
"but `{}` actually implements `{}`"
,
actual_trait_ref
.map
(|
tr
|
tr
.self_ty
()),
actual_trait_ref
,
)
};
if
let
Some
(
n
)
=
actual_has_vid
{
let
_
=
write!
(
note
,
", for some specific lifetime `'{}`"
,
n
);
}
note
});
}
}
src/librustc/ty/print.rs
浏览文件 @
cafd83d1
...
...
@@ -47,6 +47,102 @@ pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
// FIXME(eddyb) this module uses `pub(crate)` for things used only
// from `ppaux` - when that is removed, they can be re-privatized.
/// The "region highlights" are used to control region printing during
/// specific error messages. When a "region highlight" is enabled, it
/// gives an alternate way to print specific regions. For now, we
/// always print those regions using a number, so something like "`'0`".
///
/// Regions not selected by the region highlight mode are presently
/// unaffected.
#[derive(Copy,
Clone,
Default)]
pub
struct
RegionHighlightMode
{
/// If enabled, when we see the selected region, use "`'N`"
/// instead of the ordinary behavior.
highlight_regions
:
[
Option
<
(
ty
::
RegionKind
,
usize
)
>
;
3
],
/// If enabled, when printing a "free region" that originated from
/// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
/// have names print as normal.
///
/// This is used when you have a signature like `fn foo(x: &u32,
/// y: &'a u32)` and we want to give a name to the region of the
/// reference `x`.
pub
(
crate
)
highlight_bound_region
:
Option
<
(
ty
::
BoundRegion
,
usize
)
>
,
}
impl
RegionHighlightMode
{
/// If `region` and `number` are both `Some`, invokes
/// `highlighting_region`.
pub
fn
maybe_highlighting_region
(
&
mut
self
,
region
:
Option
<
ty
::
Region
<
'_
>>
,
number
:
Option
<
usize
>
,
)
{
if
let
Some
(
k
)
=
region
{
if
let
Some
(
n
)
=
number
{
self
.highlighting_region
(
k
,
n
);
}
}
}
/// Highlights the region inference variable `vid` as `'N`.
pub
fn
highlighting_region
(
&
mut
self
,
region
:
ty
::
Region
<
'_
>
,
number
:
usize
,
)
{
let
num_slots
=
self
.highlight_regions
.len
();
let
first_avail_slot
=
self
.highlight_regions
.iter_mut
()
.filter
(|
s
|
s
.is_none
())
.next
()
.unwrap_or_else
(||
{
bug!
(
"can only highlight {} placeholders at a time"
,
num_slots
,
)
});
*
first_avail_slot
=
Some
((
*
region
,
number
));
}
/// Convenience wrapper for `highlighting_region`.
pub
fn
highlighting_region_vid
(
&
mut
self
,
vid
:
ty
::
RegionVid
,
number
:
usize
,
)
{
self
.highlighting_region
(
&
ty
::
ReVar
(
vid
),
number
)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
pub
(
crate
)
fn
region_highlighted
(
&
self
,
region
:
ty
::
Region
<
'_
>
)
->
Option
<
usize
>
{
self
.highlight_regions
.iter
()
.filter_map
(|
h
|
match
h
{
Some
((
r
,
n
))
if
r
==
region
=>
Some
(
*
n
),
_
=>
None
,
})
.next
()
}
/// Highlight the given bound region.
/// We can only highlight one bound region at a time. See
/// the field `highlight_bound_region` for more detailed notes.
pub
fn
highlighting_bound_region
(
&
mut
self
,
br
:
ty
::
BoundRegion
,
number
:
usize
,
)
{
assert
!
(
self
.highlight_bound_region
.is_none
());
self
.highlight_bound_region
=
Some
((
br
,
number
));
}
/// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
pub
(
crate
)
fn
placeholder_highlight
(
&
self
,
p
:
ty
::
PlaceholderRegion
)
->
Option
<
usize
>
{
self
.region_highlighted
(
&
ty
::
RePlaceholder
(
p
))
}
}
struct
LateBoundRegionNameCollector
(
FxHashSet
<
InternedString
>
);
impl
<
'tcx
>
ty
::
fold
::
TypeVisitor
<
'tcx
>
for
LateBoundRegionNameCollector
{
fn
visit_region
(
&
mut
self
,
r
:
ty
::
Region
<
'tcx
>
)
->
bool
{
...
...
@@ -237,6 +333,10 @@ fn nest<'a, 'gcx, 'tcx, E>(
config
:
self
.config
,
})
}
fn
region_highlight_mode
(
&
self
)
->
RegionHighlightMode
{
RegionHighlightMode
::
default
()
}
}
macro_rules!
nest
{
...
...
@@ -450,6 +550,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
pub
struct
FmtPrinter
<
F
:
fmt
::
Write
>
{
pub
(
crate
)
fmt
:
F
,
empty
:
bool
,
pub
region_highlight_mode
:
RegionHighlightMode
,
}
impl
<
F
:
fmt
::
Write
>
FmtPrinter
<
F
>
{
...
...
@@ -457,6 +558,7 @@ pub fn new(fmt: F) -> Self {
FmtPrinter
{
fmt
,
empty
:
true
,
region_highlight_mode
:
RegionHighlightMode
::
default
(),
}
}
}
...
...
@@ -920,4 +1022,8 @@ fn nest<'a, 'gcx, 'tcx, E>(
config
:
self
.config
,
})
}
fn
region_highlight_mode
(
&
self
)
->
RegionHighlightMode
{
self
.region_highlight_mode
}
}
src/librustc/util/ppaux.rs
浏览文件 @
cafd83d1
...
...
@@ -12,7 +12,6 @@
use
crate
::
ty
::
print
::{
FmtPrinter
,
PrettyPrinter
,
PrintCx
,
Print
,
Printer
};
use
crate
::
mir
::
interpret
::
ConstValue
;
use
std
::
cell
::
Cell
;
use
std
::
fmt
::{
self
,
Write
as
_
};
use
std
::
iter
;
use
std
::
usize
;
...
...
@@ -22,142 +21,6 @@
use
syntax
::
symbol
::{
Symbol
,
InternedString
};
use
crate
::
hir
;
/// The "region highlights" are used to control region printing during
/// specific error messages. When a "region highlight" is enabled, it
/// gives an alternate way to print specific regions. For now, we
/// always print those regions using a number, so something like "`'0`".
///
/// Regions not selected by the region highlight mode are presently
/// unaffected.
#[derive(Copy,
Clone,
Default)]
pub
struct
RegionHighlightMode
{
/// If enabled, when we see the selected region, use "`'N`"
/// instead of the ordinary behavior.
highlight_regions
:
[
Option
<
(
ty
::
RegionKind
,
usize
)
>
;
3
],
/// If enabled, when printing a "free region" that originated from
/// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
/// have names print as normal.
///
/// This is used when you have a signature like `fn foo(x: &u32,
/// y: &'a u32)` and we want to give a name to the region of the
/// reference `x`.
highlight_bound_region
:
Option
<
(
ty
::
BoundRegion
,
usize
)
>
,
}
thread_local!
{
/// Mechanism for highlighting of specific regions for display in NLL region inference errors.
/// Contains region to highlight and counter for number to use when highlighting.
static
REGION_HIGHLIGHT_MODE
:
Cell
<
RegionHighlightMode
>
=
Cell
::
new
(
RegionHighlightMode
::
default
())
}
impl
RegionHighlightMode
{
/// Reads and returns the current region highlight settings (accesses thread-local state).
pub
fn
get
()
->
Self
{
REGION_HIGHLIGHT_MODE
.with
(|
c
|
c
.get
())
}
// Internal helper to update current settings during the execution of `op`.
fn
set
<
R
>
(
old_mode
:
Self
,
new_mode
:
Self
,
op
:
impl
FnOnce
()
->
R
,
)
->
R
{
REGION_HIGHLIGHT_MODE
.with
(|
c
|
{
c
.set
(
new_mode
);
let
result
=
op
();
c
.set
(
old_mode
);
result
})
}
/// If `region` and `number` are both `Some`, invokes
/// `highlighting_region`; otherwise, just invokes `op` directly.
pub
fn
maybe_highlighting_region
<
R
>
(
region
:
Option
<
ty
::
Region
<
'_
>>
,
number
:
Option
<
usize
>
,
op
:
impl
FnOnce
()
->
R
,
)
->
R
{
if
let
Some
(
k
)
=
region
{
if
let
Some
(
n
)
=
number
{
return
Self
::
highlighting_region
(
k
,
n
,
op
);
}
}
op
()
}
/// During the execution of `op`, highlights the region inference
/// variable `vid` as `'N`. We can only highlight one region `vid`
/// at a time.
pub
fn
highlighting_region
<
R
>
(
region
:
ty
::
Region
<
'_
>
,
number
:
usize
,
op
:
impl
FnOnce
()
->
R
,
)
->
R
{
let
old_mode
=
Self
::
get
();
let
mut
new_mode
=
old_mode
;
let
first_avail_slot
=
new_mode
.highlight_regions
.iter_mut
()
.filter
(|
s
|
s
.is_none
())
.next
()
.unwrap_or_else
(||
{
panic!
(
"can only highlight {} placeholders at a time"
,
old_mode
.highlight_regions
.len
(),
)
});
*
first_avail_slot
=
Some
((
*
region
,
number
));
Self
::
set
(
old_mode
,
new_mode
,
op
)
}
/// Convenience wrapper for `highlighting_region`.
pub
fn
highlighting_region_vid
<
R
>
(
vid
:
ty
::
RegionVid
,
number
:
usize
,
op
:
impl
FnOnce
()
->
R
,
)
->
R
{
Self
::
highlighting_region
(
&
ty
::
ReVar
(
vid
),
number
,
op
)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
fn
region_highlighted
(
&
self
,
region
:
ty
::
Region
<
'_
>
)
->
Option
<
usize
>
{
Self
::
get
()
.highlight_regions
.iter
()
.filter_map
(|
h
|
match
h
{
Some
((
r
,
n
))
if
r
==
region
=>
Some
(
*
n
),
_
=>
None
,
})
.next
()
}
/// During the execution of `op`, highlight the given bound
/// region. We can only highlight one bound region at a time. See
/// the field `highlight_bound_region` for more detailed notes.
pub
fn
highlighting_bound_region
<
R
>
(
br
:
ty
::
BoundRegion
,
number
:
usize
,
op
:
impl
FnOnce
()
->
R
,
)
->
R
{
let
old_mode
=
Self
::
get
();
assert
!
(
old_mode
.highlight_bound_region
.is_none
());
Self
::
set
(
old_mode
,
Self
{
highlight_bound_region
:
Some
((
br
,
number
)),
..
old_mode
},
op
,
)
}
/// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
pub
fn
placeholder_highlight
(
&
self
,
p
:
ty
::
PlaceholderRegion
)
->
Option
<
usize
>
{
self
.region_highlighted
(
&
ty
::
RePlaceholder
(
p
))
}
}
macro_rules!
gen_display_debug_body
{
(
$with:path
)
=>
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
<
'_
>
)
->
fmt
::
Result
{
...
...
@@ -622,7 +485,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
let
Some
((
region
,
counter
))
=
highlight
.highlight_bound_region
{
if
*
self
==
region
{
p!
(
write
(
"'{}"
,
counter
));
...
...
@@ -647,7 +510,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//
// NB: this must be kept in sync with the printing logic above.
impl
ty
::
BoundRegion
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
where
P
:
PrettyPrinter
{
if
cx
.config.is_verbose
{
return
true
;
}
...
...
@@ -658,7 +523,7 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
}
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
let
Some
((
region
,
_
))
=
highlight
.highlight_bound_region
{
if
*
self
==
region
{
return
true
;
...
...
@@ -676,7 +541,7 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
return
self
.print_debug
(
cx
);
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
let
Some
(
counter
)
=
highlight
.placeholder_highlight
(
*
self
)
{
p!
(
write
(
"'{}"
,
counter
));
}
else
{
...
...
@@ -690,12 +555,14 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
//
// NB: this must be kept in sync with the printing logic above.
impl
ty
::
PlaceholderRegion
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
where
P
:
PrettyPrinter
{
if
cx
.config.is_verbose
{
return
true
;
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
highlight
.placeholder_highlight
(
*
self
)
.is_some
()
{
return
true
;
}
...
...
@@ -712,8 +579,8 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
}
// Watch out for region highlights.
if
let
Some
(
n
)
=
RegionHighlightMode
::
get
()
.region_highlighted
(
self
)
{
p!
(
write
(
"'{
:?
}"
,
n
));
if
let
Some
(
n
)
=
cx
.printer
.region_highlight_mode
()
.region_highlighted
(
self
)
{
p!
(
write
(
"'{}"
,
n
));
return
Ok
(
cx
.printer
);
}
...
...
@@ -780,12 +647,12 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
}
ty
::
ReLateBound
(
binder_id
,
ref
bound_region
)
=>
{
p!
(
write
(
"ReLateBound({:?},
{:?})"
,
binder_id
,
bound_region
))
p!
(
write
(
"ReLateBound({:?},
"
,
binder_id
)
,
print_debug
(
bound_region
)
,
write
(
")"
))
}
ty
::
ReFree
(
ref
fr
)
=>
p!
(
write
(
"{:?}"
,
fr
)),
ty
::
ReFree
(
ref
fr
)
=>
p!
(
print_debug
(
fr
)),
ty
::
ReScope
(
id
)
=>
{
p!
(
write
(
"ReScope({:?})"
,
id
))
...
...
@@ -794,11 +661,11 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
ty
::
ReStatic
=>
p!
(
write
(
"ReStatic"
)),
ty
::
ReVar
(
ref
vid
)
=>
{
p!
(
write
(
"{:?}"
,
vid
))
p!
(
print_debug
(
vid
))
}
ty
::
RePlaceholder
(
placeholder
)
=>
{
p!
(
write
(
"RePlaceholder(
{:?})"
,
placeholder
))
p!
(
write
(
"RePlaceholder(
"
),
print_debug
(
placeholder
),
write
(
")"
))
}
ty
::
ReEmpty
=>
p!
(
write
(
"ReEmpty"
)),
...
...
@@ -817,12 +684,14 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
// NB: this must be kept in sync with the printing logic above.
impl
ty
::
RegionKind
{
// HACK(eddyb) `pub(crate)` only for `ty::print`.
pub
(
crate
)
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
{
pub
(
crate
)
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
where
P
:
PrettyPrinter
{
if
cx
.config.is_verbose
{
return
true
;
}
if
RegionHighlightMode
::
get
()
.region_highlighted
(
self
)
.is_some
()
{
if
cx
.printer
.region_highlight_mode
()
.region_highlighted
(
self
)
.is_some
()
{
return
true
;
}
...
...
@@ -926,17 +795,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
return
self
.print_debug
(
cx
);
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
let
Some
(
counter
)
=
highlight
.region_highlighted
(
&
ty
::
ReVar
(
*
self
))
{
p!
(
write
(
"'{
:?
}"
,
counter
));
p!
(
write
(
"'{}"
,
counter
));
}
}
debug
{
// HACK(eddyb) this is duplicated from `display` printing,
// to keep NLL borrowck working even with `-Zverbose`.
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
let
Some
(
counter
)
=
highlight
.region_highlighted
(
&
ty
::
ReVar
(
*
self
))
{
p!
(
write
(
"'{
:?
}"
,
counter
));
p!
(
write
(
"'{}"
,
counter
));
}
else
{
p!
(
write
(
"'_#{}r"
,
self
.index
()));
}
...
...
@@ -948,12 +817,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//
// NB: this must be kept in sync with the printing logic above.
impl
ty
::
RegionVid
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
{
fn
display_outputs_anything
<
P
>
(
&
self
,
cx
:
&
PrintCx
<
'_
,
'_
,
'_
,
P
>
)
->
bool
where
P
:
PrettyPrinter
{
if
cx
.config.is_verbose
{
return
true
;
}
let
highlight
=
RegionHighlightMode
::
get
();
let
highlight
=
cx
.printer
.region_highlight_mode
();
if
highlight
.region_highlighted
(
&
ty
::
ReVar
(
*
self
))
.is_some
()
{
return
true
;
}
...
...
@@ -1165,9 +1036,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// FIXME(eddyb) print this with `print_def_path`.
if
let
Some
(
first
)
=
substs
.next
()
{
p!
(
write
(
"::<"
));
p!
(
write
(
"{}"
,
first
));
p!
(
print_display
(
first
));
for
subst
in
substs
{
p!
(
write
(
",
{}"
,
subst
));
p!
(
write
(
",
"
),
print_display
(
subst
));
}
p!
(
write
(
">"
));
}
...
...
src/librustc_mir/borrow_check/error_reporting.rs
浏览文件 @
cafd83d1
...
...
@@ -12,7 +12,7 @@
TerminatorKind
,
VarBindingForm
,
};
use
rustc
::
ty
::{
self
,
DefIdTree
};
use
rustc
::
util
::
ppaux
::
RegionHighlightMode
;
use
rustc
::
ty
::
print
::
Print
;
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
rustc_data_structures
::
sync
::
Lrc
;
...
...
@@ -831,7 +831,7 @@ fn report_local_value_does_not_live_long_enough(
);
if
let
Some
(
annotation
)
=
self
.annotate_argument_and_return_for_borrow
(
borrow
)
{
let
region_name
=
annotation
.emit
(
&
mut
err
);
let
region_name
=
annotation
.emit
(
self
,
&
mut
err
);
err
.span_label
(
borrow_span
,
...
...
@@ -1875,7 +1875,7 @@ fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'t
fn
annotate_argument_and_return_for_borrow
(
&
self
,
borrow
:
&
BorrowData
<
'tcx
>
,
)
->
Option
<
AnnotatedBorrowFnSignature
<
'
_
>>
{
)
->
Option
<
AnnotatedBorrowFnSignature
<
'
tcx
>>
{
// Define a fallback for when we can't match a closure.
let
fallback
=
||
{
let
is_closure
=
self
.infcx.tcx
.is_closure
(
self
.mir_def_id
);
...
...
@@ -2099,7 +2099,7 @@ fn annotate_fn_sig(
&
self
,
did
:
DefId
,
sig
:
ty
::
PolyFnSig
<
'tcx
>
,
)
->
Option
<
AnnotatedBorrowFnSignature
<
'
_
>>
{
)
->
Option
<
AnnotatedBorrowFnSignature
<
'
tcx
>>
{
debug!
(
"annotate_fn_sig: did={:?} sig={:?}"
,
did
,
sig
);
let
is_closure
=
self
.infcx.tcx
.is_closure
(
did
);
let
fn_hir_id
=
self
.infcx.tcx
.hir
()
.as_local_hir_id
(
did
)
?
;
...
...
@@ -2245,7 +2245,11 @@ enum AnnotatedBorrowFnSignature<'tcx> {
impl
<
'tcx
>
AnnotatedBorrowFnSignature
<
'tcx
>
{
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
fn
emit
(
&
self
,
diag
:
&
mut
DiagnosticBuilder
<
'_
>
)
->
String
{
fn
emit
(
&
self
,
cx
:
&
mut
MirBorrowckCtxt
<
'_
,
'_
,
'tcx
>
,
diag
:
&
mut
DiagnosticBuilder
<
'_
>
,
)
->
String
{
match
self
{
AnnotatedBorrowFnSignature
::
Closure
{
argument_ty
,
...
...
@@ -2253,10 +2257,10 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
}
=>
{
diag
.span_label
(
*
argument_span
,
format!
(
"has type `{}`"
,
self
.get_name_for_ty
(
argument_ty
,
0
)),
format!
(
"has type `{}`"
,
cx
.get_name_for_ty
(
argument_ty
,
0
)),
);
self
.get_region_name_for_ty
(
argument_ty
,
0
)
cx
.get_region_name_for_ty
(
argument_ty
,
0
)
}
AnnotatedBorrowFnSignature
::
AnonymousFunction
{
argument_ty
,
...
...
@@ -2264,10 +2268,10 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
return_ty
,
return_span
,
}
=>
{
let
argument_ty_name
=
self
.get_name_for_ty
(
argument_ty
,
0
);
let
argument_ty_name
=
cx
.get_name_for_ty
(
argument_ty
,
0
);
diag
.span_label
(
*
argument_span
,
format!
(
"has type `{}`"
,
argument_ty_name
));
let
return_ty_name
=
self
.get_name_for_ty
(
return_ty
,
0
);
let
return_ty_name
=
cx
.get_name_for_ty
(
return_ty
,
0
);
let
types_equal
=
return_ty_name
==
argument_ty_name
;
diag
.span_label
(
*
return_span
,
...
...
@@ -2286,7 +2290,7 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
lifetime-syntax.html#lifetime-elision>"
,
);
self
.get_region_name_for_ty
(
return_ty
,
0
)
cx
.get_region_name_for_ty
(
return_ty
,
0
)
}
AnnotatedBorrowFnSignature
::
NamedFunction
{
arguments
,
...
...
@@ -2294,7 +2298,7 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
return_span
,
}
=>
{
// Region of return type and arguments checked to be the same earlier.
let
region_name
=
self
.get_region_name_for_ty
(
return_ty
,
0
);
let
region_name
=
cx
.get_region_name_for_ty
(
return_ty
,
0
);
for
(
_
,
argument_span
)
in
arguments
{
diag
.span_label
(
*
argument_span
,
format!
(
"has lifetime `{}`"
,
region_name
));
}
...
...
@@ -2314,10 +2318,15 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
}
}
}
}
impl
<
'cx
,
'gcx
,
'tcx
>
MirBorrowckCtxt
<
'cx
,
'gcx
,
'tcx
>
{
/// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
/// name where required.
fn
get_name_for_ty
(
&
self
,
ty
:
ty
::
Ty
<
'tcx
>
,
counter
:
usize
)
->
String
{
let
mut
s
=
String
::
new
();
let
mut
printer
=
ty
::
print
::
FmtPrinter
::
new
(
&
mut
s
);
// We need to add synthesized lifetimes where appropriate. We do
// this by hooking into the pretty printer and telling it to label the
// lifetimes without names with the value `'0`.
...
...
@@ -2327,28 +2336,41 @@ fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
ty
::
RegionKind
::
RePlaceholder
(
ty
::
PlaceholderRegion
{
name
:
br
,
..
}),
_
,
_
,
)
=>
RegionHighlightMode
::
highlighting_bound_region
(
*
br
,
counter
,
||
ty
.to_string
()
),
_
=>
ty
.to_string
(),
)
=>
printer
.region_highlight_mode
.highlighting_bound_region
(
*
br
,
counter
),
_
=>
{}
}
let
_
=
ty
::
print
::
PrintCx
::
with
(
self
.infcx.tcx
,
printer
,
|
cx
|
{
ty
.print
(
cx
)
});
s
}
/// Returns the name of the provided `Ty` (that must be a reference)'s region with a
/// synthesized lifetime name where required.
fn
get_region_name_for_ty
(
&
self
,
ty
:
ty
::
Ty
<
'tcx
>
,
counter
:
usize
)
->
String
{
match
ty
.sty
{
ty
::
TyKind
::
Ref
(
region
,
_
,
_
)
=>
match
region
{
ty
::
RegionKind
::
ReLateBound
(
_
,
br
)
|
ty
::
RegionKind
::
RePlaceholder
(
ty
::
PlaceholderRegion
{
name
:
br
,
..
})
=>
{
RegionHighlightMode
::
highlighting_bound_region
(
*
br
,
counter
,
||
region
.to_string
(),
)
let
mut
s
=
String
::
new
();
let
mut
printer
=
ty
::
print
::
FmtPrinter
::
new
(
&
mut
s
);
let
region
=
match
ty
.sty
{
ty
::
TyKind
::
Ref
(
region
,
_
,
_
)
=>
{
match
region
{
ty
::
RegionKind
::
ReLateBound
(
_
,
br
)
|
ty
::
RegionKind
::
RePlaceholder
(
ty
::
PlaceholderRegion
{
name
:
br
,
..
})
=>
{
printer
.region_highlight_mode
.highlighting_bound_region
(
*
br
,
counter
)
}
_
=>
{}
}
_
=>
region
.to_string
(),
},
region
}
_
=>
bug!
(
"ty for annotation of borrow region is not a reference"
),
}
};
let
_
=
ty
::
print
::
PrintCx
::
with
(
self
.infcx.tcx
,
printer
,
|
cx
|
{
region
.print
(
cx
)
});
s
}
}
...
...
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
浏览文件 @
cafd83d1
...
...
@@ -8,7 +8,7 @@
use
rustc
::
mir
::
Mir
;
use
rustc
::
ty
::
subst
::{
SubstsRef
,
UnpackedKind
};
use
rustc
::
ty
::{
self
,
RegionKind
,
RegionVid
,
Ty
,
TyCtxt
};
use
rustc
::
util
::
ppaux
::
RegionHighlightMode
;
use
rustc
::
ty
::
print
::
RegionHighlightMode
;
use
rustc_errors
::
DiagnosticBuilder
;
use
syntax
::
ast
::
Name
;
use
syntax
::
symbol
::
keywords
;
...
...
@@ -396,9 +396,9 @@ fn give_name_if_we_cannot_match_hir_ty(
argument_ty
:
Ty
<
'tcx
>
,
counter
:
&
mut
usize
,
)
->
Option
<
RegionName
>
{
let
type_name
=
RegionHighlightMode
::
highlighting_region_vid
(
needle_fr
,
*
counter
,
||
{
infcx
.extract_type_name
(
&
argument_ty
)
}
);
let
mut
highlight
=
RegionHighlightMode
::
default
();
highlight
.highlighting_region_vid
(
needle_fr
,
*
counter
);
let
type_name
=
infcx
.extract_type_name
(
&
argument_ty
,
Some
(
highlight
)
);
debug!
(
"give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}"
,
...
...
@@ -680,9 +680,9 @@ fn give_name_if_anonymous_region_appears_in_output(
return
None
;
}
let
type_name
=
RegionHighlightMode
::
highlighting_region_vid
(
fr
,
*
counter
,
||
infcx
.extract_type_name
(
&
return_ty
),
);
let
mut
highlight
=
RegionHighlightMode
::
default
();
highlight
.highlighting_region_vid
(
fr
,
*
counter
);
let
type_name
=
infcx
.extract_type_name
(
&
return_ty
,
Some
(
highlight
)
);
let
mir_node_id
=
tcx
.hir
()
.as_local_node_id
(
mir_def_id
)
.expect
(
"non-local mir"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录