Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a8efd31f
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,发现更多精彩内容 >>
提交
a8efd31f
编写于
11月 23, 2019
作者:
M
Matthew Jasper
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add raw address of expressions to the AST and HIR
上级
9420ff4c
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
308 addition
and
139 deletion
+308
-139
src/librustc/hir/intravisit.rs
src/librustc/hir/intravisit.rs
+1
-1
src/librustc/hir/lowering/expr.rs
src/librustc/hir/lowering/expr.rs
+7
-3
src/librustc/hir/mod.rs
src/librustc/hir/mod.rs
+28
-10
src/librustc/hir/print.rs
src/librustc/hir/print.rs
+19
-16
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+1
-1
src/librustc/middle/region.rs
src/librustc/middle/region.rs
+2
-2
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes.rs
+1
-0
src/librustc_error_codes/error_codes/E0745.md
src/librustc_error_codes/error_codes/E0745.md
+20
-0
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+79
-52
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/diagnostics.rs
+1
-1
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/expr.rs
+20
-5
src/librustc_passes/liveness.rs
src/librustc_passes/liveness.rs
+1
-1
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/demand.rs
+5
-1
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/expr.rs
+61
-21
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/op.rs
+1
-1
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+1
-1
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+18
-3
src/libsyntax/mut_visit.rs
src/libsyntax/mut_visit.rs
+1
-1
src/libsyntax/print/pprust.rs
src/libsyntax/print/pprust.rs
+20
-17
src/libsyntax/visit.rs
src/libsyntax/visit.rs
+1
-1
src/libsyntax_expand/build.rs
src/libsyntax_expand/build.rs
+1
-1
src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
+19
-0
未找到文件。
src/librustc/hir/intravisit.rs
浏览文件 @
a8efd31f
...
...
@@ -1024,7 +1024,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor
.visit_expr
(
left_expression
);
visitor
.visit_expr
(
right_expression
)
}
ExprKind
::
AddrOf
(
_
,
ref
subexpression
)
|
ExprKind
::
Unary
(
_
,
ref
subexpression
)
=>
{
ExprKind
::
AddrOf
(
_
,
_
,
ref
subexpression
)
|
ExprKind
::
Unary
(
_
,
ref
subexpression
)
=>
{
visitor
.visit_expr
(
subexpression
)
}
ExprKind
::
Cast
(
ref
subexpression
,
ref
typ
)
|
ExprKind
::
Type
(
ref
subexpression
,
ref
typ
)
=>
{
...
...
src/librustc/hir/lowering/expr.rs
浏览文件 @
a8efd31f
...
...
@@ -65,9 +65,9 @@ pub(super) fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let
expr
=
P
(
self
.lower_expr
(
expr
));
hir
::
ExprKind
::
Type
(
expr
,
self
.lower_ty
(
ty
,
ImplTraitContext
::
disallowed
()))
}
ExprKind
::
AddrOf
(
m
,
ref
ohs
)
=>
{
ExprKind
::
AddrOf
(
k
,
m
,
ref
ohs
)
=>
{
let
ohs
=
P
(
self
.lower_expr
(
ohs
));
hir
::
ExprKind
::
AddrOf
(
m
,
ohs
)
hir
::
ExprKind
::
AddrOf
(
k
,
m
,
ohs
)
}
ExprKind
::
Let
(
ref
pat
,
ref
scrutinee
)
=>
self
.lower_expr_let
(
e
.span
,
pat
,
scrutinee
),
ExprKind
::
If
(
ref
cond
,
ref
then
,
ref
else_opt
)
=>
{
...
...
@@ -1339,7 +1339,11 @@ fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr>
}
fn
expr_mut_addr_of
(
&
mut
self
,
span
:
Span
,
e
:
P
<
hir
::
Expr
>
)
->
hir
::
Expr
{
self
.expr
(
span
,
hir
::
ExprKind
::
AddrOf
(
hir
::
Mutability
::
Mutable
,
e
),
ThinVec
::
new
())
self
.expr
(
span
,
hir
::
ExprKind
::
AddrOf
(
hir
::
BorrowKind
::
Ref
,
hir
::
Mutability
::
Mutable
,
e
),
ThinVec
::
new
(),
)
}
fn
expr_unit
(
&
mut
self
,
sp
:
Span
)
->
hir
::
Expr
{
...
...
src/librustc/hir/mod.rs
浏览文件 @
a8efd31f
...
...
@@ -21,7 +21,8 @@
use
syntax
::
source_map
::
Spanned
;
use
syntax
::
ast
::{
self
,
CrateSugar
,
Ident
,
Name
,
NodeId
,
AsmDialect
};
use
syntax
::
ast
::{
Attribute
,
Label
,
LitKind
,
StrStyle
,
FloatTy
,
IntTy
,
UintTy
};
pub
use
syntax
::
ast
::{
Mutability
,
Constness
,
Unsafety
,
Movability
,
CaptureBy
,
IsAuto
,
ImplPolarity
};
pub
use
syntax
::
ast
::{
Mutability
,
Constness
,
Unsafety
,
Movability
,
CaptureBy
};
pub
use
syntax
::
ast
::{
IsAuto
,
ImplPolarity
,
BorrowKind
};
use
syntax
::
attr
::{
InlineAttr
,
OptimizeAttr
};
use
syntax
::
symbol
::{
Symbol
,
kw
};
use
syntax
::
tokenstream
::
TokenStream
;
...
...
@@ -1493,8 +1494,20 @@ pub fn precedence(&self) -> ExprPrecedence {
}
}
pub
fn
is_place_expr
(
&
self
)
->
bool
{
match
self
.kind
{
// Whether this looks like a place expr, without checking for deref
// adjustments.
// This will return `true` in some potentially surprising cases such as
// `CONSTANT.field`.
pub
fn
is_syntactic_place_expr
(
&
self
)
->
bool
{
self
.is_place_expr
(|
_
|
true
)
}
// Whether this is a place expression.
// `allow_projections_from` should return `true` if indexing a field or
// index expression based on the given expression should be considered a
// place expression.
pub
fn
is_place_expr
(
&
self
,
mut
allow_projections_from
:
impl
FnMut
(
&
Self
)
->
bool
)
->
bool
{
match
self
.kind
{
ExprKind
::
Path
(
QPath
::
Resolved
(
_
,
ref
path
))
=>
{
match
path
.res
{
Res
::
Local
(
..
)
...
...
@@ -1504,14 +1517,19 @@ pub fn is_place_expr(&self) -> bool {
}
}
// Type ascription inherits its place expression kind from its
// operand. See:
// https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
ExprKind
::
Type
(
ref
e
,
_
)
=>
{
e
.is_place_expr
()
e
.is_place_expr
(
allow_projections_from
)
}
ExprKind
::
Unary
(
UnDeref
,
_
)
|
ExprKind
::
Field
(
..
)
|
ExprKind
::
Index
(
..
)
=>
{
true
ExprKind
::
Unary
(
UnDeref
,
_
)
=>
true
,
ExprKind
::
Field
(
ref
base
,
_
)
|
ExprKind
::
Index
(
ref
base
,
_
)
=>
{
allow_projections_from
(
base
)
||
base
.is_place_expr
(
allow_projections_from
)
}
// Partially qualified paths in expressions can only legally
...
...
@@ -1646,8 +1664,8 @@ pub enum ExprKind {
/// Path to a definition, possibly containing lifetime or type parameters.
Path
(
QPath
),
/// A referencing operation (i.e., `&a`
or `&
mut a`).
AddrOf
(
Mutability
,
P
<
Expr
>
),
/// A referencing operation (i.e., `&a`
, `&mut a`, `&raw const a`, or `&raw
mut a`).
AddrOf
(
BorrowKind
,
Mutability
,
P
<
Expr
>
),
/// A `break`, with an optional label to break.
Break
(
Destination
,
Option
<
P
<
Expr
>>
),
/// A `continue`, with an optional label.
...
...
src/librustc/hir/print.rs
浏览文件 @
a8efd31f
...
...
@@ -294,16 +294,12 @@ pub fn print_type(&mut self, ty: &hir::Ty) {
}
hir
::
TyKind
::
Ptr
(
ref
mt
)
=>
{
self
.s
.word
(
"*"
);
match
mt
.mutbl
{
hir
::
Mutability
::
Mutable
=>
self
.word_nbsp
(
"mut"
),
hir
::
Mutability
::
Immutable
=>
self
.word_nbsp
(
"const"
),
}
self
.print_type
(
&
mt
.ty
);
self
.print_mt
(
mt
,
true
);
}
hir
::
TyKind
::
Rptr
(
ref
lifetime
,
ref
mt
)
=>
{
self
.s
.word
(
"&"
);
self
.print_opt_lifetime
(
lifetime
);
self
.print_mt
(
mt
);
self
.print_mt
(
mt
,
false
);
}
hir
::
TyKind
::
Never
=>
{
self
.s
.word
(
"!"
);
...
...
@@ -1178,11 +1174,18 @@ fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) {
}
fn
print_expr_addr_of
(
&
mut
self
,
kind
:
hir
::
BorrowKind
,
mutability
:
hir
::
Mutability
,
expr
:
&
hir
::
Expr
)
{
{
self
.s
.word
(
"&"
);
self
.print_mutability
(
mutability
);
match
kind
{
hir
::
BorrowKind
::
Ref
=>
self
.print_mutability
(
mutability
,
false
),
hir
::
BorrowKind
::
Raw
=>
{
self
.word_nbsp
(
"raw"
);
self
.print_mutability
(
mutability
,
true
);
}
}
self
.print_expr_maybe_paren
(
expr
,
parser
::
PREC_PREFIX
)
}
...
...
@@ -1225,8 +1228,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr) {
hir
::
ExprKind
::
Unary
(
op
,
ref
expr
)
=>
{
self
.print_expr_unary
(
op
,
&
expr
);
}
hir
::
ExprKind
::
AddrOf
(
m
,
ref
expr
)
=>
{
self
.print_expr_addr_of
(
m
,
&
expr
);
hir
::
ExprKind
::
AddrOf
(
k
,
m
,
ref
expr
)
=>
{
self
.print_expr_addr_of
(
k
,
m
,
&
expr
);
}
hir
::
ExprKind
::
Lit
(
ref
lit
)
=>
{
self
.print_literal
(
&
lit
);
...
...
@@ -1629,11 +1632,11 @@ pub fn print_pat(&mut self, pat: &hir::Pat) {
match
binding_mode
{
hir
::
BindingAnnotation
::
Ref
=>
{
self
.word_nbsp
(
"ref"
);
self
.print_mutability
(
hir
::
Mutability
::
Immutable
);
self
.print_mutability
(
hir
::
Mutability
::
Immutable
,
false
);
}
hir
::
BindingAnnotation
::
RefMut
=>
{
self
.word_nbsp
(
"ref"
);
self
.print_mutability
(
hir
::
Mutability
::
Mutable
);
self
.print_mutability
(
hir
::
Mutability
::
Mutable
,
false
);
}
hir
::
BindingAnnotation
::
Unannotated
=>
{}
hir
::
BindingAnnotation
::
Mutable
=>
{
...
...
@@ -2060,15 +2063,15 @@ pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) {
}
}
pub
fn
print_mutability
(
&
mut
self
,
mutbl
:
hir
::
Mutability
)
{
pub
fn
print_mutability
(
&
mut
self
,
mutbl
:
hir
::
Mutability
,
print_const
:
bool
)
{
match
mutbl
{
hir
::
Mutability
::
Mutable
=>
self
.word_nbsp
(
"mut"
),
hir
::
Mutability
::
Immutable
=>
{
},
hir
::
Mutability
::
Immutable
=>
if
print_const
{
self
.word_nbsp
(
"const"
)
},
}
}
pub
fn
print_mt
(
&
mut
self
,
mt
:
&
hir
::
MutTy
)
{
self
.print_mutability
(
mt
.mutbl
);
pub
fn
print_mt
(
&
mut
self
,
mt
:
&
hir
::
MutTy
,
print_const
:
bool
)
{
self
.print_mutability
(
mt
.mutbl
,
print_const
);
self
.print_type
(
&
mt
.ty
)
}
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
a8efd31f
...
...
@@ -276,7 +276,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
self
.consume_exprs
(
exprs
);
}
hir
::
ExprKind
::
AddrOf
(
m
,
ref
base
)
=>
{
// &base
hir
::
ExprKind
::
AddrOf
(
_
,
m
,
ref
base
)
=>
{
// &base
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
let
bk
=
ty
::
BorrowKind
::
from_mutbl
(
m
);
...
...
src/librustc/middle/region.rs
浏览文件 @
a8efd31f
...
...
@@ -1241,7 +1241,7 @@ fn record_rvalue_scope_if_borrow_expr<'tcx>(
blk_id
:
Option
<
Scope
>
,
)
{
match
expr
.kind
{
hir
::
ExprKind
::
AddrOf
(
_
,
ref
subexpr
)
=>
{
hir
::
ExprKind
::
AddrOf
(
_
,
_
,
ref
subexpr
)
=>
{
record_rvalue_scope_if_borrow_expr
(
visitor
,
&
subexpr
,
blk_id
);
record_rvalue_scope
(
visitor
,
&
subexpr
,
blk_id
);
}
...
...
@@ -1301,7 +1301,7 @@ fn record_rvalue_scope<'tcx>(
visitor
.scope_tree
.record_rvalue_scope
(
expr
.hir_id.local_id
,
blk_scope
);
match
expr
.kind
{
hir
::
ExprKind
::
AddrOf
(
_
,
ref
subexpr
)
|
hir
::
ExprKind
::
AddrOf
(
_
,
_
,
ref
subexpr
)
|
hir
::
ExprKind
::
Unary
(
hir
::
UnDeref
,
ref
subexpr
)
|
hir
::
ExprKind
::
Field
(
ref
subexpr
,
_
)
|
hir
::
ExprKind
::
Index
(
ref
subexpr
,
_
)
=>
{
...
...
src/librustc_error_codes/error_codes.rs
浏览文件 @
a8efd31f
...
...
@@ -409,6 +409,7 @@
E0742
:
include_str!
(
"./error_codes/E0742.md"
),
E0743
:
include_str!
(
"./error_codes/E0743.md"
),
E0744
:
include_str!
(
"./error_codes/E0744.md"
),
E0745
:
include_str!
(
"./error_codes/E0745.md"
),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
...
...
src/librustc_error_codes/error_codes/E0745.md
0 → 100644
浏览文件 @
a8efd31f
Cannot take address of temporary value.
Erroneous code example:
```
compile_fail,E0745
# #![feature(raw_ref_op)]
fn temp_address() {
let ptr = &raw const 2; // ERROR
}
```
To avoid the error, first bind the temporary to a named local variable.
```
ignore
# #![feature(raw_ref_op)]
fn temp_address() {
let val = 2;
let ptr = &raw const val;
}
```
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
a8efd31f
...
...
@@ -137,55 +137,8 @@ fn apply_adjustment<'a, 'tcx>(
arg
:
expr
.to_ref
(),
}
}
Adjust
::
Borrow
(
AutoBorrow
::
RawPtr
(
m
))
=>
{
// Convert this to a suitable `&foo` and
// then an unsafe coercion.
expr
=
Expr
{
temp_lifetime
,
ty
:
cx
.tcx
.mk_ref
(
cx
.tcx.lifetimes.re_erased
,
ty
::
TypeAndMut
{
ty
:
expr
.ty
,
mutbl
:
m
,
}),
span
,
kind
:
ExprKind
::
Borrow
{
borrow_kind
:
m
.to_borrow_kind
(),
arg
:
expr
.to_ref
(),
},
};
let
cast_expr
=
Expr
{
temp_lifetime
,
ty
:
adjustment
.target
,
span
,
kind
:
ExprKind
::
Cast
{
source
:
expr
.to_ref
()
}
};
// To ensure that both implicit and explicit coercions are
// handled the same way, we insert an extra layer of indirection here.
// For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
// will be an ExprKind::Hair with the appropriate cast expression. Here,
// we make our Use source the generated Cast from the original coercion.
//
// In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
// as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
// Ordinary, this is identical to using the cast directly as an rvalue. However, if the
// source of the cast was previously borrowed as mutable, storing the cast in a
// temporary gives the source a chance to expire before the cast is used. For
// structs with a self-referential *mut ptr, this allows assignment to work as
// expected.
//
// For example, consider the type 'struct Foo { field: *mut Foo }',
// The method 'fn bar(&mut self) { self.field = self }'
// triggers a coercion from '&mut self' to '*mut self'. In order
// for the assignment to be valid, the implicit borrow
// of 'self' involved in the coercion needs to end before the local
// containing the '*mut T' is assigned to 'self.field' - otherwise,
// we end up trying to assign to 'self.field' while we have another mutable borrow
// active.
//
// We only need to worry about this kind of thing for coercions from refs to ptrs,
// since they get rid of a borrow implicitly.
ExprKind
::
Use
{
source
:
cast_expr
.to_ref
()
}
Adjust
::
Borrow
(
AutoBorrow
::
RawPtr
(
mutbl
))
=>
{
raw_ref_shim
(
cx
,
expr
.to_ref
(),
adjustment
.target
,
mutbl
,
span
,
temp_lifetime
)
}
};
...
...
@@ -302,13 +255,26 @@ fn make_mirror_unadjusted<'a, 'tcx>(
}
}
hir
::
ExprKind
::
AddrOf
(
mutbl
,
ref
expr
)
=>
{
hir
::
ExprKind
::
AddrOf
(
hir
::
BorrowKind
::
Ref
,
mutbl
,
ref
arg
)
=>
{
ExprKind
::
Borrow
{
borrow_kind
:
mutbl
.to_borrow_kind
(),
arg
:
expr
.to_ref
(),
arg
:
arg
.to_ref
(),
}
}
hir
::
ExprKind
::
AddrOf
(
hir
::
BorrowKind
::
Raw
,
mutbl
,
ref
arg
)
=>
{
cx
.tcx.sess
.struct_span_err
(
expr
.span
,
"raw borrows are not yet implemented"
)
.note
(
"for more information, see https://github.com/rust-lang/rust/issues/64490"
)
.emit
();
// Lower to an approximation to avoid further errors.
raw_ref_shim
(
cx
,
arg
.to_ref
(),
expr_ty
,
mutbl
,
expr
.span
,
temp_lifetime
)
}
hir
::
ExprKind
::
Block
(
ref
blk
,
_
)
=>
ExprKind
::
Block
{
body
:
&
blk
},
hir
::
ExprKind
::
Assign
(
ref
lhs
,
ref
rhs
)
=>
{
...
...
@@ -742,7 +708,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
let
user_provided_types
=
cx
.tables
.user_provided_types
();
let
user_ty
=
user_provided_types
.get
(
ty
.hir_id
)
.map
(|
u_ty
|
*
u_ty
);
debug!
(
"make_mirror_unadjusted: (type) user_ty={:?}"
,
user_ty
);
if
source
.is_place_expr
()
{
if
source
.is_
syntactic_
place_expr
()
{
ExprKind
::
PlaceTypeAscription
{
source
:
source
.to_ref
(),
user_ty
,
...
...
@@ -1123,6 +1089,67 @@ fn convert_var(
}
/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf`
/// exists in MIR.
fn
raw_ref_shim
<
'tcx
>
(
cx
:
&
mut
Cx
<
'_
,
'tcx
>
,
arg
:
ExprRef
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
mutbl
:
hir
::
Mutability
,
span
:
Span
,
temp_lifetime
:
Option
<
region
::
Scope
>
,
)
->
ExprKind
<
'tcx
>
{
let
arg_tm
=
if
let
ty
::
RawPtr
(
type_mutbl
)
=
ty
.kind
{
type_mutbl
}
else
{
bug!
(
"raw_ref_shim called with non-raw pointer type"
);
};
// Convert this to a suitable `&foo` and
// then an unsafe coercion.
let
borrow_expr
=
Expr
{
temp_lifetime
,
ty
:
cx
.tcx
.mk_ref
(
cx
.tcx.lifetimes.re_erased
,
arg_tm
),
span
,
kind
:
ExprKind
::
Borrow
{
borrow_kind
:
mutbl
.to_borrow_kind
(),
arg
,
},
};
let
cast_expr
=
Expr
{
temp_lifetime
,
ty
,
span
,
kind
:
ExprKind
::
Cast
{
source
:
borrow_expr
.to_ref
()
}
};
// To ensure that both implicit and explicit coercions are
// handled the same way, we insert an extra layer of indirection here.
// For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
// will be an ExprKind::Hair with the appropriate cast expression. Here,
// we make our Use source the generated Cast from the original coercion.
//
// In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
// as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
// Ordinary, this is identical to using the cast directly as an rvalue. However, if the
// source of the cast was previously borrowed as mutable, storing the cast in a
// temporary gives the source a chance to expire before the cast is used. For
// structs with a self-referential *mut ptr, this allows assignment to work as
// expected.
//
// For example, consider the type 'struct Foo { field: *mut Foo }',
// The method 'fn bar(&mut self) { self.field = self }'
// triggers a coercion from '&mut self' to '*mut self'. In order
// for the assignment to be valid, the implicit borrow
// of 'self' involved in the coercion needs to end before the local
// containing the '*mut T' is assigned to 'self.field' - otherwise,
// we end up trying to assign to 'self.field' while we have another mutable borrow
// active.
//
// We only need to worry about this kind of thing for coercions from refs to ptrs,
// since they get rid of a borrow implicitly.
ExprKind
::
Use
{
source
:
cast_expr
.to_ref
()
}
}
fn
bin_op
(
op
:
hir
::
BinOpKind
)
->
BinOp
{
match
op
{
hir
::
BinOpKind
::
Add
=>
BinOp
::
Add
,
...
...
src/librustc_parse/parser/diagnostics.rs
浏览文件 @
a8efd31f
...
...
@@ -726,7 +726,7 @@ pub(super) fn maybe_recover_from_bad_type_plus(
let
sum_with_parens
=
pprust
::
to_string
(|
s
|
{
s
.s
.word
(
"&"
);
s
.print_opt_lifetime
(
lifetime
);
s
.print_mutability
(
mut_ty
.mutbl
);
s
.print_mutability
(
mut_ty
.mutbl
,
false
);
s
.popen
();
s
.print_type
(
&
mut_ty
.ty
);
s
.print_type_bounds
(
" +"
,
&
bounds
);
...
...
src/librustc_parse/parser/expr.rs
浏览文件 @
a8efd31f
...
...
@@ -442,11 +442,7 @@ fn parse_prefix_expr(
(
lo
.to
(
span
),
self
.mk_unary
(
UnOp
::
Deref
,
e
))
}
token
::
BinOp
(
token
::
And
)
|
token
::
AndAnd
=>
{
self
.expect_and
()
?
;
let
m
=
self
.parse_mutability
();
let
e
=
self
.parse_prefix_expr
(
None
);
let
(
span
,
e
)
=
self
.interpolated_or_expr_span
(
e
)
?
;
(
lo
.to
(
span
),
ExprKind
::
AddrOf
(
m
,
e
))
self
.parse_address_of
(
lo
)
?
}
token
::
Ident
(
..
)
if
self
.token
.is_keyword
(
kw
::
Box
)
=>
{
self
.bump
();
...
...
@@ -596,6 +592,25 @@ fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span,
}
}
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`
fn
parse_address_of
(
&
mut
self
,
lo
:
Span
)
->
PResult
<
'a
,
(
Span
,
ExprKind
)
>
{
self
.expect_and
()
?
;
let
(
k
,
m
)
=
if
self
.check_keyword
(
kw
::
Raw
)
&&
self
.look_ahead
(
1
,
Token
::
is_mutability
)
{
let
found_raw
=
self
.eat_keyword
(
kw
::
Raw
);
assert
!
(
found_raw
);
let
mutability
=
self
.parse_const_or_mut
()
.unwrap
();
self
.sess.gated_spans
.gate
(
sym
::
raw_ref_op
,
lo
.to
(
self
.prev_span
));
(
ast
::
BorrowKind
::
Raw
,
mutability
)
}
else
{
(
ast
::
BorrowKind
::
Ref
,
self
.parse_mutability
())
};
let
e
=
self
.parse_prefix_expr
(
None
);
let
(
span
,
e
)
=
self
.interpolated_or_expr_span
(
e
)
?
;
Ok
((
lo
.to
(
span
),
ExprKind
::
AddrOf
(
k
,
m
,
e
)))
}
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
fn
parse_dot_or_call_expr
(
&
mut
self
,
...
...
src/librustc_passes/liveness.rs
浏览文件 @
a8efd31f
...
...
@@ -1174,7 +1174,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode {
}
hir
::
ExprKind
::
Box
(
ref
e
)
|
hir
::
ExprKind
::
AddrOf
(
_
,
ref
e
)
|
hir
::
ExprKind
::
AddrOf
(
_
,
_
,
ref
e
)
|
hir
::
ExprKind
::
Cast
(
ref
e
,
_
)
|
hir
::
ExprKind
::
Type
(
ref
e
,
_
)
|
hir
::
ExprKind
::
DropTemps
(
ref
e
)
|
...
...
src/librustc_typeck/check/demand.rs
浏览文件 @
a8efd31f
...
...
@@ -484,7 +484,11 @@ pub fn check_ref(
}
}
},
(
hir
::
ExprKind
::
AddrOf
(
_
,
ref
expr
),
_
,
&
ty
::
Ref
(
_
,
checked
,
_
))
if
{
(
hir
::
ExprKind
::
AddrOf
(
hir
::
BorrowKind
::
Ref
,
_
,
ref
expr
),
_
,
&
ty
::
Ref
(
_
,
checked
,
_
)
)
if
{
self
.infcx
.can_sub
(
self
.param_env
,
checked
,
&
expected
)
.is_ok
()
&&
!
is_macro
}
=>
{
// We have `&T`, check if what was expected was `T`. If so,
...
...
src/librustc_typeck/check/expr.rs
浏览文件 @
a8efd31f
...
...
@@ -238,8 +238,8 @@ fn check_expr_kind(
ExprKind
::
Unary
(
unop
,
ref
oprnd
)
=>
{
self
.check_expr_unary
(
unop
,
oprnd
,
expected
,
needs
,
expr
)
}
ExprKind
::
AddrOf
(
mutbl
,
ref
oprnd
)
=>
{
self
.check_expr_addr_of
(
mutbl
,
oprnd
,
expected
,
expr
)
ExprKind
::
AddrOf
(
kind
,
mutbl
,
ref
oprnd
)
=>
{
self
.check_expr_addr_of
(
kind
,
mutbl
,
oprnd
,
expected
,
expr
)
}
ExprKind
::
Path
(
ref
qpath
)
=>
{
self
.check_expr_path
(
qpath
,
expr
)
...
...
@@ -424,6 +424,7 @@ fn check_expr_unary(
fn
check_expr_addr_of
(
&
self
,
kind
:
hir
::
BorrowKind
,
mutbl
:
hir
::
Mutability
,
oprnd
:
&
'tcx
hir
::
Expr
,
expected
:
Expectation
<
'tcx
>
,
...
...
@@ -432,7 +433,7 @@ fn check_expr_addr_of(
let
hint
=
expected
.only_has_type
(
self
)
.map_or
(
NoExpectation
,
|
ty
|
{
match
ty
.kind
{
ty
::
Ref
(
_
,
ty
,
_
)
|
ty
::
RawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
{
if
oprnd
.is_place_expr
()
{
if
oprnd
.is_
syntactic_
place_expr
()
{
// Places may legitimately have unsized types.
// For example, dereferences of a fat pointer and
// the last field of a struct can be unsized.
...
...
@@ -448,24 +449,63 @@ fn check_expr_addr_of(
let
ty
=
self
.check_expr_with_expectation_and_needs
(
&
oprnd
,
hint
,
needs
);
let
tm
=
ty
::
TypeAndMut
{
ty
:
ty
,
mutbl
:
mutbl
};
if
tm
.ty
.references_error
()
{
self
.tcx.types.err
}
else
{
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
// errors. Moreover, the longest lifetime will depend on the
// precise details of the value whose address is being taken
// (and how long it is valid), which we don't know yet until type
// inference is complete.
match
kind
{
_
if
tm
.ty
.references_error
()
=>
self
.tcx.types.err
,
hir
::
BorrowKind
::
Raw
=>
{
self
.check_named_place_expr
(
oprnd
);
self
.tcx
.mk_ptr
(
tm
)
}
hir
::
BorrowKind
::
Ref
=>
{
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
// errors. Moreover, the longest lifetime will depend on the
// precise details of the value whose address is being taken
// (and how long it is valid), which we don't know yet until
// type inference is complete.
//
// Therefore, here we simply generate a region variable. The
// region inferencer will then select a suitable value.
// Finally, borrowck will infer the value of the region again,
// this time with enough precision to check that the value
// whose address was taken can actually be made to live as long
// as it needs to live.
let
region
=
self
.next_region_var
(
infer
::
AddrOfRegion
(
expr
.span
));
self
.tcx
.mk_ref
(
region
,
tm
)
}
}
}
/// Does this expression refer to a place that either:
/// * Is based on a local or static.
/// * Contains a dereference
/// Note that the adjustments for the children of `expr` should already
/// have been resolved.
fn
check_named_place_expr
(
&
self
,
oprnd
:
&
'tcx
hir
::
Expr
)
{
let
is_named
=
oprnd
.is_place_expr
(|
base
|
{
// Allow raw borrows if there are any deref adjustments.
//
// Therefore, here we simply generate a region variable. The
// region inferencer will then select the ultimate value.
// Finally, borrowck is charged with guaranteeing that the
// value whose address was taken can actually be made to live
// as long as it needs to live.
let
region
=
self
.next_region_var
(
infer
::
AddrOfRegion
(
expr
.span
));
self
.tcx
.mk_ref
(
region
,
tm
)
// const VAL: (i32,) = (0,);
// const REF: &(i32,) = &(0,);
//
// &raw const VAL.0; // ERROR
// &raw const REF.0; // OK, same as &raw const (*REF).0;
//
// This is maybe too permissive, since it allows
// `let u = &raw const Box::new((1,)).0`, which creates an
// immediately dangling raw pointer.
self
.tables
.borrow
()
.adjustments
()
.get
(
base
.hir_id
)
.map_or
(
false
,
|
x
|
{
x
.iter
()
.any
(|
adj
|
if
let
Adjust
::
Deref
(
_
)
=
adj
.kind
{
true
}
else
{
false
})
})
});
if
!
is_named
{
struct_span_err!
(
self
.tcx.sess
,
oprnd
.span
,
E0745
,
"cannot take address of a temporary"
)
.span_label
(
oprnd
.span
,
"temporary value"
)
.emit
();
}
}
...
...
@@ -740,7 +780,7 @@ fn check_expr_assign(
err
.help
(
msg
);
}
err
.emit
();
}
else
if
!
lhs
.is_place_expr
()
{
}
else
if
!
lhs
.is_
syntactic_
place_expr
()
{
struct_span_err!
(
self
.tcx.sess
,
expr
.span
,
E0070
,
"invalid left-hand side expression"
)
.span_label
(
expr
.span
,
"left-hand of expression not valid"
)
...
...
src/librustc_typeck/check/op.rs
浏览文件 @
a8efd31f
...
...
@@ -33,7 +33,7 @@ pub fn check_binop_assign(
return_ty
};
if
!
lhs_expr
.is_place_expr
()
{
if
!
lhs_expr
.is_
syntactic_
place_expr
()
{
struct_span_err!
(
self
.tcx.sess
,
lhs_expr
.span
,
E0067
,
"invalid left-hand side expression"
)
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
a8efd31f
...
...
@@ -645,7 +645,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
intravisit
::
walk_expr
(
self
,
expr
);
}
hir
::
ExprKind
::
AddrOf
(
m
,
ref
base
)
=>
{
hir
::
ExprKind
::
AddrOf
(
hir
::
BorrowKind
::
Ref
,
m
,
ref
base
)
=>
{
self
.link_addr_of
(
expr
,
m
,
&
base
);
// Require that when you write a `&expr` expression, the
...
...
src/libsyntax/ast.rs
浏览文件 @
a8efd31f
...
...
@@ -754,6 +754,21 @@ pub fn prefix_str(&self) -> &'static str {
}
}
/// The kind of borrow in an `AddrOf` expression,
/// e.g., `&place` or `&raw const place`.
#[derive(Clone,
Copy,
PartialEq,
Eq,
Debug)]
#[derive(RustcEncodable,
RustcDecodable,
HashStable_Generic)]
pub
enum
BorrowKind
{
/// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
/// The resulting type is either `*const T` or `*mut T`
/// where `T = typeof($expr)`.
Ref
,
/// A normal borrow, `&$expr` or `&mut $expr`.
/// The resulting type is either `&'a T` or `&'a mut T`
/// where `T = typeof($expr)` and `'a` is some lifetime.
Raw
,
}
#[derive(Clone,
PartialEq,
RustcEncodable,
RustcDecodable,
Debug,
Copy)]
pub
enum
BinOpKind
{
/// The `+` operator (addition)
...
...
@@ -1071,7 +1086,7 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
ExprKind
::
Paren
(
expr
)
=>
expr
.to_ty
()
.map
(
TyKind
::
Paren
)
?
,
ExprKind
::
AddrOf
(
mutbl
,
expr
)
=>
expr
ExprKind
::
AddrOf
(
BorrowKind
::
Ref
,
mutbl
,
expr
)
=>
expr
.to_ty
()
.map
(|
ty
|
TyKind
::
Rptr
(
None
,
MutTy
{
ty
,
mutbl
:
*
mutbl
}))
?
,
...
...
@@ -1262,8 +1277,8 @@ pub enum ExprKind {
/// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`).
Path
(
Option
<
QSelf
>
,
Path
),
/// A referencing operation (`&a`
or `&
mut a`).
AddrOf
(
Mutability
,
P
<
Expr
>
),
/// A referencing operation (`&a`
, `&mut a`, `&raw const a` or `&raw
mut a`).
AddrOf
(
BorrowKind
,
Mutability
,
P
<
Expr
>
),
/// A `break`, with an optional label to break, and an optional expression.
Break
(
Option
<
Label
>
,
Option
<
P
<
Expr
>>
),
/// A `continue`, with an optional label.
...
...
src/libsyntax/mut_visit.rs
浏览文件 @
a8efd31f
...
...
@@ -1128,7 +1128,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
vis
.visit_expr
(
expr
);
vis
.visit_ty
(
ty
);
}
ExprKind
::
AddrOf
(
_
m
,
ohs
)
=>
vis
.visit_expr
(
ohs
),
ExprKind
::
AddrOf
(
_
,
_
,
ohs
)
=>
vis
.visit_expr
(
ohs
),
ExprKind
::
Let
(
pat
,
scrutinee
)
=>
{
vis
.visit_pat
(
pat
);
vis
.visit_expr
(
scrutinee
);
...
...
src/libsyntax/print/pprust.rs
浏览文件 @
a8efd31f
...
...
@@ -984,16 +984,12 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
}
ast
::
TyKind
::
Ptr
(
ref
mt
)
=>
{
self
.s
.word
(
"*"
);
match
mt
.mutbl
{
ast
::
Mutability
::
Mutable
=>
self
.word_nbsp
(
"mut"
),
ast
::
Mutability
::
Immutable
=>
self
.word_nbsp
(
"const"
),
}
self
.print_type
(
&
mt
.ty
);
self
.print_mt
(
mt
,
true
);
}
ast
::
TyKind
::
Rptr
(
ref
lifetime
,
ref
mt
)
=>
{
self
.s
.word
(
"&"
);
self
.print_opt_lifetime
(
lifetime
);
self
.print_mt
(
mt
);
self
.print_mt
(
mt
,
false
);
}
ast
::
TyKind
::
Never
=>
{
self
.s
.word
(
"!"
);
...
...
@@ -1974,10 +1970,17 @@ fn print_expr_unary(&mut self,
}
fn
print_expr_addr_of
(
&
mut
self
,
kind
:
ast
::
BorrowKind
,
mutability
:
ast
::
Mutability
,
expr
:
&
ast
::
Expr
)
{
self
.s
.word
(
"&"
);
self
.print_mutability
(
mutability
);
match
kind
{
ast
::
BorrowKind
::
Ref
=>
self
.print_mutability
(
mutability
,
false
),
ast
::
BorrowKind
::
Raw
=>
{
self
.word_nbsp
(
"raw"
);
self
.print_mutability
(
mutability
,
true
);
}
}
self
.print_expr_maybe_paren
(
expr
,
parser
::
PREC_PREFIX
)
}
...
...
@@ -2028,8 +2031,8 @@ fn print_expr_outer_attr_style(&mut self,
ast
::
ExprKind
::
Unary
(
op
,
ref
expr
)
=>
{
self
.print_expr_unary
(
op
,
expr
);
}
ast
::
ExprKind
::
AddrOf
(
m
,
ref
expr
)
=>
{
self
.print_expr_addr_of
(
m
,
expr
);
ast
::
ExprKind
::
AddrOf
(
k
,
m
,
ref
expr
)
=>
{
self
.print_expr_addr_of
(
k
,
m
,
expr
);
}
ast
::
ExprKind
::
Lit
(
ref
lit
)
=>
{
self
.print_literal
(
lit
);
...
...
@@ -2361,7 +2364,7 @@ fn print_qpath(&mut self,
match
binding_mode
{
ast
::
BindingMode
::
ByRef
(
mutbl
)
=>
{
self
.word_nbsp
(
"ref"
);
self
.print_mutability
(
mutbl
);
self
.print_mutability
(
mutbl
,
false
);
}
ast
::
BindingMode
::
ByValue
(
ast
::
Mutability
::
Immutable
)
=>
{}
ast
::
BindingMode
::
ByValue
(
ast
::
Mutability
::
Mutable
)
=>
{
...
...
@@ -2504,17 +2507,17 @@ fn print_arm(&mut self, arm: &ast::Arm) {
fn
print_explicit_self
(
&
mut
self
,
explicit_self
:
&
ast
::
ExplicitSelf
)
{
match
explicit_self
.node
{
SelfKind
::
Value
(
m
)
=>
{
self
.print_mutability
(
m
);
self
.print_mutability
(
m
,
false
);
self
.s
.word
(
"self"
)
}
SelfKind
::
Region
(
ref
lt
,
m
)
=>
{
self
.s
.word
(
"&"
);
self
.print_opt_lifetime
(
lt
);
self
.print_mutability
(
m
);
self
.print_mutability
(
m
,
false
);
self
.s
.word
(
"self"
)
}
SelfKind
::
Explicit
(
ref
typ
,
m
)
=>
{
self
.print_mutability
(
m
);
self
.print_mutability
(
m
,
false
);
self
.s
.word
(
"self"
);
self
.word_space
(
":"
);
self
.print_type
(
typ
)
...
...
@@ -2746,15 +2749,15 @@ pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::Generic
}
}
pub
fn
print_mutability
(
&
mut
self
,
mutbl
:
ast
::
Mutability
)
{
pub
fn
print_mutability
(
&
mut
self
,
mutbl
:
ast
::
Mutability
,
print_const
:
bool
)
{
match
mutbl
{
ast
::
Mutability
::
Mutable
=>
self
.word_nbsp
(
"mut"
),
ast
::
Mutability
::
Immutable
=>
{
},
ast
::
Mutability
::
Immutable
=>
if
print_const
{
self
.word_nbsp
(
"const"
);
},
}
}
crate
fn
print_mt
(
&
mut
self
,
mt
:
&
ast
::
MutTy
)
{
self
.print_mutability
(
mt
.mutbl
);
crate
fn
print_mt
(
&
mut
self
,
mt
:
&
ast
::
MutTy
,
print_const
:
bool
)
{
self
.print_mutability
(
mt
.mutbl
,
print_const
);
self
.print_type
(
&
mt
.ty
)
}
...
...
src/libsyntax/visit.rs
浏览文件 @
a8efd31f
...
...
@@ -708,7 +708,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor
.visit_expr
(
left_expression
);
visitor
.visit_expr
(
right_expression
)
}
ExprKind
::
AddrOf
(
_
,
ref
subexpression
)
|
ExprKind
::
Unary
(
_
,
ref
subexpression
)
=>
{
ExprKind
::
AddrOf
(
_
,
_
,
ref
subexpression
)
|
ExprKind
::
Unary
(
_
,
ref
subexpression
)
=>
{
visitor
.visit_expr
(
subexpression
)
}
ExprKind
::
Cast
(
ref
subexpression
,
ref
typ
)
|
ExprKind
::
Type
(
ref
subexpression
,
ref
typ
)
=>
{
...
...
src/libsyntax_expand/build.rs
浏览文件 @
a8efd31f
...
...
@@ -270,7 +270,7 @@ pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
}
pub
fn
expr_addr_of
(
&
self
,
sp
:
Span
,
e
:
P
<
ast
::
Expr
>
)
->
P
<
ast
::
Expr
>
{
self
.expr
(
sp
,
ast
::
ExprKind
::
AddrOf
(
ast
::
Mutability
::
Immutable
,
e
))
self
.expr
(
sp
,
ast
::
ExprKind
::
AddrOf
(
ast
::
BorrowKind
::
Ref
,
ast
::
Mutability
::
Immutable
,
e
))
}
pub
fn
expr_call
(
...
...
src/test/ui/raw-ref-op/raw-ref-temp-deref.rs
0 → 100644
浏览文件 @
a8efd31f
// Ensure that we don't allow taking the address of temporary values
#![feature(raw_ref_op)]
const
PAIR
:
(
i32
,
i64
)
=
(
1
,
2
);
const
PAIR_REF
:
&
(
i32
,
i64
)
=
&
(
1
,
2
);
const
ARRAY
:
[
i32
;
2
]
=
[
1
,
2
];
const
ARRAY_REF
:
&
[
i32
;
2
]
=
&
[
3
,
4
];
const
SLICE_REF
:
&
[
i32
]
=
&
[
5
,
6
];
fn
main
()
{
// These are all OK, we're not taking the address of the temporary
let
deref_ref
=
&
raw
const
*
PAIR_REF
;
//~ ERROR not yet implemented
let
field_deref_ref
=
&
raw
const
PAIR_REF
.0
;
//~ ERROR not yet implemented
let
deref_ref
=
&
raw
const
*
ARRAY_REF
;
//~ ERROR not yet implemented
let
field_deref_ref
=
&
raw
const
ARRAY_REF
[
0
];
//~ ERROR not yet implemented
let
deref_ref
=
&
raw
const
*
SLICE_REF
;
//~ ERROR not yet implemented
let
field_deref_ref
=
&
raw
const
SLICE_REF
[
1
];
//~ ERROR not yet implemented
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录