Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
afa74080
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
afa74080
编写于
1月 02, 2021
作者:
R
Ralf Jung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
use PlaceRef more consistently instead of loosely coupled local+projection
上级
929f66af
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
61 addition
and
111 deletion
+61
-111
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
+3
-8
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
+1
-1
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/mod.rs
+12
-9
compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
...rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+10
-28
compiler/rustc_mir/src/borrow_check/mod.rs
compiler/rustc_mir/src/borrow_check/mod.rs
+24
-50
compiler/rustc_mir/src/borrow_check/prefixes.rs
compiler/rustc_mir/src/borrow_check/prefixes.rs
+11
-15
未找到文件。
compiler/rustc_codegen_ssa/src/mir/analyze.rs
浏览文件 @
afa74080
...
...
@@ -104,7 +104,7 @@ fn process_place(
)
{
let
cx
=
self
.fx.cx
;
if
let
&
[
ref
proj_base
@
..
,
elem
]
=
place_ref
.projection
{
if
let
Some
((
place_base
,
elem
))
=
place_ref
.last_projection
()
{
let
mut
base_context
=
if
context
.is_mutating_use
()
{
PlaceContext
::
MutatingUse
(
MutatingUseContext
::
Projection
)
}
else
{
...
...
@@ -119,8 +119,7 @@ fn process_place(
)
);
if
is_consume
{
let
base_ty
=
mir
::
Place
::
ty_from
(
place_ref
.local
,
proj_base
,
self
.fx.mir
,
cx
.tcx
());
let
base_ty
=
mir
::
PlaceRef
::
ty
(
&
place_base
,
self
.fx.mir
,
cx
.tcx
());
let
base_ty
=
self
.fx
.monomorphize
(
base_ty
);
// ZSTs don't require any actual memory access.
...
...
@@ -175,11 +174,7 @@ fn process_place(
base_context
=
context
;
}
self
.process_place
(
&
mir
::
PlaceRef
{
local
:
place_ref
.local
,
projection
:
proj_base
},
base_context
,
location
,
);
self
.process_place
(
&
place_base
,
base_context
,
location
);
// HACK(eddyb) this emulates the old `visit_projection_elem`, this
// entire `visit_place`-like `process_place` method should be rewritten,
// now that we have moved to the "slice of projections" representation.
...
...
compiler/rustc_codegen_ssa/src/mir/place.rs
浏览文件 @
afa74080
...
...
@@ -514,7 +514,7 @@ pub fn codegen_place(
pub
fn
monomorphized_place_ty
(
&
self
,
place_ref
:
mir
::
PlaceRef
<
'tcx
>
)
->
Ty
<
'tcx
>
{
let
tcx
=
self
.cx
.tcx
();
let
place_ty
=
mir
::
Place
::
ty_from
(
place_ref
.local
,
place_ref
.projection
,
self
.mir
,
tcx
);
let
place_ty
=
mir
::
Place
Ref
::
ty
(
&
place_ref
,
self
.mir
,
tcx
);
self
.monomorphize
(
place_ty
.ty
)
}
}
compiler/rustc_middle/src/mir/mod.rs
浏览文件 @
afa74080
...
...
@@ -1745,18 +1745,14 @@ pub fn is_indirect(&self) -> bool {
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
/// a single deref of a local.
//
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
#[inline(always)]
pub
fn
local_or_deref_local
(
&
self
)
->
Option
<
Local
>
{
match
self
.as_ref
()
{
PlaceRef
{
local
,
projection
:
[]
}
|
PlaceRef
{
local
,
projection
:
[
ProjectionElem
::
Deref
]
}
=>
Some
(
local
),
_
=>
None
,
}
self
.as_ref
()
.local_or_deref_local
()
}
/// If this place represents a local variable like `_X` with no
/// projections, return `Some(_X)`.
#[inline(always)]
pub
fn
as_local
(
&
self
)
->
Option
<
Local
>
{
self
.as_ref
()
.as_local
()
}
...
...
@@ -1770,6 +1766,7 @@ pub fn as_ref(&self) -> PlaceRef<'tcx> {
/// As a concrete example, given the place a.b.c, this would yield:
/// - (a, .b)
/// - (a.b, .c)
///
/// Given a place without projections, the iterator is empty.
pub
fn
iter_projections
(
self
,
...
...
@@ -1790,8 +1787,6 @@ fn from(local: Local) -> Self {
impl
<
'tcx
>
PlaceRef
<
'tcx
>
{
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
/// a single deref of a local.
//
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub
fn
local_or_deref_local
(
&
self
)
->
Option
<
Local
>
{
match
*
self
{
PlaceRef
{
local
,
projection
:
[]
}
...
...
@@ -1808,6 +1803,14 @@ pub fn as_local(&self) -> Option<Local> {
_
=>
None
,
}
}
pub
fn
last_projection
(
&
self
)
->
Option
<
(
PlaceRef
<
'tcx
>
,
PlaceElem
<
'tcx
>
)
>
{
if
let
&
[
ref
proj_base
@
..
,
elem
]
=
self
.projection
{
Some
((
PlaceRef
{
local
:
self
.local
,
projection
:
proj_base
},
elem
))
}
else
{
None
}
}
}
impl
Debug
for
Place
<
'_
>
{
...
...
compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
浏览文件 @
afa74080
...
...
@@ -293,9 +293,7 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
);
}
let
ty
=
Place
::
ty_from
(
used_place
.local
,
used_place
.projection
,
self
.body
,
self
.infcx.tcx
)
.ty
;
let
ty
=
PlaceRef
::
ty
(
&
used_place
,
self
.body
,
self
.infcx.tcx
)
.ty
;
let
needs_note
=
match
ty
.kind
()
{
ty
::
Closure
(
id
,
_
)
=>
{
let
tables
=
self
.infcx.tcx
.typeck
(
id
.expect_local
());
...
...
@@ -732,8 +730,8 @@ pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
)
->
(
String
,
String
,
String
,
String
)
{
// Define a small closure that we can use to check if the type of a place
// is a union.
let
union_ty
=
|
place_base
,
place_projection
|
{
let
ty
=
Place
::
ty_from
(
place_base
,
place_projection
,
self
.body
,
self
.infcx.tcx
)
.ty
;
let
union_ty
=
|
place_base
|
{
let
ty
=
Place
Ref
::
ty
(
&
place_base
,
self
.body
,
self
.infcx.tcx
)
.ty
;
ty
.ty_adt_def
()
.filter
(|
adt
|
adt
.is_union
())
.map
(|
_
|
ty
)
};
...
...
@@ -751,15 +749,10 @@ pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
// field access to a union. If we find that, then we will keep the place of the
// union being accessed and the field that was being accessed so we can check the
// second borrowed place for the same union and a access to a different field.
let
Place
{
local
,
projection
}
=
first_borrowed_place
;
let
mut
cursor
=
projection
.as_ref
();
while
let
[
proj_base
@
..
,
elem
]
=
cursor
{
cursor
=
proj_base
;
for
(
place_base
,
elem
)
in
first_borrowed_place
.iter_projections
()
.rev
()
{
match
elem
{
ProjectionElem
::
Field
(
field
,
_
)
if
union_ty
(
local
,
proj
_base
)
.is_some
()
=>
{
return
Some
((
PlaceRef
{
local
,
projection
:
proj_base
}
,
field
));
ProjectionElem
::
Field
(
field
,
_
)
if
union_ty
(
place
_base
)
.is_some
()
=>
{
return
Some
((
place_base
,
field
));
}
_
=>
{}
}
...
...
@@ -769,23 +762,12 @@ pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
.and_then
(|(
target_base
,
target_field
)|
{
// With the place of a union and a field access into it, we traverse the second
// borrowed place and look for a access to a different field of the same union.
let
Place
{
local
,
ref
projection
}
=
second_borrowed_place
;
let
mut
cursor
=
&
projection
[
..
];
while
let
[
proj_base
@
..
,
elem
]
=
cursor
{
cursor
=
proj_base
;
for
(
place_base
,
elem
)
in
second_borrowed_place
.iter_projections
()
.rev
()
{
if
let
ProjectionElem
::
Field
(
field
,
_
)
=
elem
{
if
let
Some
(
union_ty
)
=
union_ty
(
local
,
proj_base
)
{
if
field
!=
target_field
&&
local
==
target_base
.local
&&
proj_base
==
target_base
.projection
{
if
let
Some
(
union_ty
)
=
union_ty
(
place_base
)
{
if
field
!=
target_field
&&
place_base
==
target_base
{
return
Some
((
self
.describe_any_place
(
PlaceRef
{
local
,
projection
:
proj_base
,
}),
self
.describe_any_place
(
place_base
),
self
.describe_any_place
(
first_borrowed_place
.as_ref
()),
self
.describe_any_place
(
second_borrowed_place
.as_ref
()),
union_ty
.to_string
(),
...
...
compiler/rustc_mir/src/borrow_check/mod.rs
浏览文件 @
afa74080
...
...
@@ -1740,20 +1740,18 @@ fn check_if_path_or_subpath_is_moved(
self
.check_if_full_path_is_moved
(
location
,
desired_action
,
place_span
,
flow_state
);
if
let
[
base_proj
@
..
,
ProjectionElem
::
Subslice
{
from
,
to
,
from_end
:
false
}]
=
place_span
.0
.
projection
if
let
Some
((
place_base
,
ProjectionElem
::
Subslice
{
from
,
to
,
from_end
:
false
}))
=
place_span
.0
.
last_projection
()
{
let
place_ty
=
Place
::
ty_from
(
place_span
.0
.local
,
base_proj
,
self
.body
(),
self
.infcx.tcx
);
let
place_ty
=
PlaceRef
::
ty
(
&
place_base
,
self
.body
(),
self
.infcx.tcx
);
if
let
ty
::
Array
(
..
)
=
place_ty
.ty
.kind
()
{
let
array_place
=
PlaceRef
{
local
:
place_span
.0
.local
,
projection
:
base_proj
};
self
.check_if_subslice_element_is_moved
(
location
,
desired_action
,
(
array_plac
e
,
place_span
.1
),
(
place_bas
e
,
place_span
.1
),
maybe_uninits
,
*
from
,
*
to
,
from
,
to
,
);
return
;
}
...
...
@@ -1825,10 +1823,7 @@ fn check_if_assigned_path_is_moved(
debug!
(
"check_if_assigned_path_is_moved place: {:?}"
,
place
);
// None case => assigning to `x` does not require `x` be initialized.
let
mut
cursor
=
&*
place
.projection
.as_ref
();
while
let
[
proj_base
@
..
,
elem
]
=
cursor
{
cursor
=
proj_base
;
for
(
place_base
,
elem
)
in
place
.iter_projections
()
.rev
()
{
match
elem
{
ProjectionElem
::
Index
(
_
/*operand*/
)
|
ProjectionElem
::
ConstantIndex
{
..
}
|
...
...
@@ -1843,10 +1838,7 @@ fn check_if_assigned_path_is_moved(
ProjectionElem
::
Deref
=>
{
self
.check_if_full_path_is_moved
(
location
,
InitializationRequiringAction
::
Use
,
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
,
},
span
),
flow_state
);
(
place_base
,
span
),
flow_state
);
// (base initialized; no need to
// recur further)
break
;
...
...
@@ -1862,15 +1854,12 @@ fn check_if_assigned_path_is_moved(
// assigning to `P.f` requires `P` itself
// be already initialized
let
tcx
=
self
.infcx.tcx
;
let
base_ty
=
Place
::
ty_from
(
place
.local
,
proj
_base
,
self
.body
(),
tcx
)
.ty
;
let
base_ty
=
Place
Ref
::
ty
(
&
place
_base
,
self
.body
(),
tcx
)
.ty
;
match
base_ty
.kind
()
{
ty
::
Adt
(
def
,
_
)
if
def
.has_dtor
(
tcx
)
=>
{
self
.check_if_path_or_subpath_is_moved
(
location
,
InitializationRequiringAction
::
Assignment
,
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
,
},
span
),
flow_state
);
(
place_base
,
span
),
flow_state
);
// (base initialized; no need to
// recur further)
...
...
@@ -1880,10 +1869,7 @@ fn check_if_assigned_path_is_moved(
// Once `let s; s.x = V; read(s.x);`,
// is allowed, remove this match arm.
ty
::
Adt
(
..
)
|
ty
::
Tuple
(
..
)
=>
{
check_parent_of_field
(
self
,
location
,
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
,
},
span
,
flow_state
);
check_parent_of_field
(
self
,
location
,
place_base
,
span
,
flow_state
);
// rust-lang/rust#21232, #54499, #54986: during period where we reject
// partial initialization, do not complain about unnecessary `mut` on
...
...
@@ -1965,9 +1951,7 @@ fn check_parent_of_field<'cx, 'tcx>(
// no move out from an earlier location) then this is an attempt at initialization
// of the union - we should error in that case.
let
tcx
=
this
.infcx.tcx
;
if
let
ty
::
Adt
(
def
,
_
)
=
Place
::
ty_from
(
base
.local
,
base
.projection
,
this
.body
(),
tcx
)
.ty
.kind
()
{
if
let
ty
::
Adt
(
def
,
_
)
=
PlaceRef
::
ty
(
&
base
,
this
.body
(),
tcx
)
.ty
.kind
()
{
if
def
.is_union
()
{
if
this
.move_data.path_map
[
mpi
]
.iter
()
.any
(|
moi
|
{
this
.move_data.moves
[
*
moi
]
.source
.is_predecessor_of
(
location
,
this
.body
)
...
...
@@ -2162,9 +2146,9 @@ fn is_mutable(
place
:
PlaceRef
<
'tcx
>
,
is_local_mutation_allowed
:
LocalMutationIsAllowed
,
)
->
Result
<
RootPlace
<
'tcx
>
,
PlaceRef
<
'tcx
>>
{
match
place
{
PlaceRef
{
local
,
projection
:
[]
}
=>
{
let
local
=
&
self
.body.local_decls
[
local
];
match
place
.last_projection
()
{
None
=>
{
let
local
=
&
self
.body.local_decls
[
place
.
local
];
match
local
.mutability
{
Mutability
::
Not
=>
match
is_local_mutation_allowed
{
LocalMutationIsAllowed
::
Yes
=>
Ok
(
RootPlace
{
...
...
@@ -2186,11 +2170,10 @@ fn is_mutable(
}),
}
}
PlaceRef
{
local
:
_
,
projection
:
[
proj_base
@
..
,
elem
]
}
=>
{
Some
((
place_base
,
elem
))
=>
{
match
elem
{
ProjectionElem
::
Deref
=>
{
let
base_ty
=
Place
::
ty_from
(
place
.local
,
proj_base
,
self
.body
(),
self
.infcx.tcx
)
.ty
;
let
base_ty
=
PlaceRef
::
ty
(
&
place_base
,
self
.body
(),
self
.infcx.tcx
)
.ty
;
// Check the kind of deref to decide
match
base_ty
.kind
()
{
...
...
@@ -2208,10 +2191,7 @@ fn is_mutable(
_
=>
LocalMutationIsAllowed
::
Yes
,
};
self
.is_mutable
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
},
mode
,
)
self
.is_mutable
(
place_base
,
mode
)
}
}
}
...
...
@@ -2229,10 +2209,9 @@ fn is_mutable(
}
}
// `Box<T>` owns its content, so mutable if its location is mutable
_
if
base_ty
.is_box
()
=>
self
.is_mutable
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
},
is_local_mutation_allowed
,
),
_
if
base_ty
.is_box
()
=>
{
self
.is_mutable
(
place_base
,
is_local_mutation_allowed
)
}
// Deref should only be for reference, pointers or boxes
_
=>
bug!
(
"Deref of unexpected type: {:?}"
,
base_ty
),
}
...
...
@@ -2286,10 +2265,8 @@ fn is_mutable(
// });
// }
// ```
let
_
=
self
.is_mutable
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
},
is_local_mutation_allowed
,
)
?
;
let
_
=
self
.is_mutable
(
place_base
,
is_local_mutation_allowed
)
?
;
Ok
(
RootPlace
{
place_local
:
place
.local
,
place_projection
:
place
.projection
,
...
...
@@ -2298,10 +2275,7 @@ fn is_mutable(
}
}
}
else
{
self
.is_mutable
(
PlaceRef
{
local
:
place
.local
,
projection
:
proj_base
},
is_local_mutation_allowed
,
)
self
.is_mutable
(
place_base
,
is_local_mutation_allowed
)
}
}
}
...
...
compiler/rustc_mir/src/borrow_check/prefixes.rs
浏览文件 @
afa74080
...
...
@@ -10,7 +10,7 @@
use
super
::
MirBorrowckCtxt
;
use
rustc_hir
as
hir
;
use
rustc_middle
::
mir
::{
Body
,
Place
,
Place
Ref
,
ProjectionElem
};
use
rustc_middle
::
mir
::{
Body
,
PlaceRef
,
ProjectionElem
};
use
rustc_middle
::
ty
::{
self
,
TyCtxt
};
pub
trait
IsPrefixOf
<
'tcx
>
{
...
...
@@ -67,24 +67,23 @@ fn next(&mut self) -> Option<Self::Item> {
// downcasts here, but may return a base of a downcast).
'cursor
:
loop
{
match
&
cursor
{
PlaceRef
{
local
:
_
,
projection
:
[]
}
=>
{
match
cursor
.last_projection
()
{
None
=>
{
self
.next
=
None
;
return
Some
(
cursor
);
}
PlaceRef
{
local
:
_
,
projection
:
[
proj_base
@
..
,
elem
]
}
=>
{
Some
((
cursor_base
,
elem
))
=>
{
match
elem
{
ProjectionElem
::
Field
(
_
/*field*/
,
_
/*ty*/
)
=>
{
// FIXME: add union handling
self
.next
=
Some
(
PlaceRef
{
local
:
cursor
.local
,
projection
:
proj_base
});
self
.next
=
Some
(
cursor_base
);
return
Some
(
cursor
);
}
ProjectionElem
::
Downcast
(
..
)
|
ProjectionElem
::
Subslice
{
..
}
|
ProjectionElem
::
ConstantIndex
{
..
}
|
ProjectionElem
::
Index
(
_
)
=>
{
cursor
=
PlaceRef
{
local
:
cursor
.local
,
projection
:
proj_base
}
;
cursor
=
cursor_base
;
continue
'cursor
;
}
ProjectionElem
::
Deref
=>
{
...
...
@@ -92,7 +91,7 @@ fn next(&mut self) -> Option<Self::Item> {
}
}
assert_eq!
(
*
elem
,
ProjectionElem
::
Deref
);
assert_eq!
(
elem
,
ProjectionElem
::
Deref
);
match
self
.kind
{
PrefixSet
::
Shallow
=>
{
...
...
@@ -105,8 +104,7 @@ fn next(&mut self) -> Option<Self::Item> {
PrefixSet
::
All
=>
{
// All prefixes: just blindly enqueue the base
// of the projection.
self
.next
=
Some
(
PlaceRef
{
local
:
cursor
.local
,
projection
:
proj_base
});
self
.next
=
Some
(
cursor_base
);
return
Some
(
cursor
);
}
PrefixSet
::
Supporting
=>
{
...
...
@@ -119,7 +117,7 @@ fn next(&mut self) -> Option<Self::Item> {
// derefs, except we stop at the deref of a shared
// reference.
let
ty
=
Place
::
ty_from
(
cursor
.local
,
proj
_base
,
self
.body
,
self
.tcx
)
.ty
;
let
ty
=
Place
Ref
::
ty
(
&
cursor
_base
,
self
.body
,
self
.tcx
)
.ty
;
match
ty
.kind
()
{
ty
::
RawPtr
(
_
)
|
ty
::
Ref
(
_
/*rgn*/
,
_
/*ty*/
,
hir
::
Mutability
::
Not
)
=>
{
// don't continue traversing over derefs of raw pointers or shared
...
...
@@ -129,14 +127,12 @@ fn next(&mut self) -> Option<Self::Item> {
}
ty
::
Ref
(
_
/*rgn*/
,
_
/*ty*/
,
hir
::
Mutability
::
Mut
)
=>
{
self
.next
=
Some
(
PlaceRef
{
local
:
cursor
.local
,
projection
:
proj_base
});
self
.next
=
Some
(
cursor_base
);
return
Some
(
cursor
);
}
ty
::
Adt
(
..
)
if
ty
.is_box
()
=>
{
self
.next
=
Some
(
PlaceRef
{
local
:
cursor
.local
,
projection
:
proj_base
});
self
.next
=
Some
(
cursor_base
);
return
Some
(
cursor
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录