Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
4e8e6414
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,发现更多精彩内容 >>
提交
4e8e6414
编写于
3月 16, 2015
作者:
E
Eduard Burtescu
提交者:
Nick Cameron
4月 14, 2015
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
eddyb's refactoring of coercions/adjustments
上级
a4eb5a66
变更
25
展开全部
隐藏空白更改
内联
并排
Showing
25 changed file
with
815 addition
and
1490 deletion
+815
-1490
src/librustc/middle/astencode.rs
src/librustc/middle/astencode.rs
+59
-215
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+29
-59
src/librustc/middle/mem_categorization.rs
src/librustc/middle/mem_categorization.rs
+11
-27
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+85
-241
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_fold.rs
+4
-27
src/librustc_lint/builtin.rs
src/librustc_lint/builtin.rs
+2
-2
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/common.rs
+0
-27
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/consts.rs
+49
-66
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/expr.rs
+98
-221
src/librustc_trans/trans/type_of.rs
src/librustc_trans/trans/type_of.rs
+2
-2
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+48
-2
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/callee.rs
+17
-20
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/coercion.rs
+194
-201
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/confirm.rs
+60
-73
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/mod.rs
+15
-17
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/probe.rs
+75
-92
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+39
-127
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+14
-15
src/librustc_typeck/check/vtable.rs
src/librustc_typeck/check/vtable.rs
+0
-38
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+3
-10
src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs
...l/associated-type-projection-from-multiple-supertraits.rs
+2
-0
src/test/compile-fail/issue-18819.rs
src/test/compile-fail/issue-18819.rs
+1
-1
src/test/compile-fail/issue-19482.rs
src/test/compile-fail/issue-19482.rs
+3
-4
src/test/compile-fail/retslot-cast.rs
src/test/compile-fail/retslot-cast.rs
+4
-2
src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
...test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
+1
-1
未找到文件。
src/librustc/middle/astencode.rs
浏览文件 @
4e8e6414
此差异已折叠。
点击以展开。
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
4e8e6414
...
...
@@ -787,23 +787,30 @@ fn contains_field_named(field: &ty::field,
// process.
fn
walk_adjustment
(
&
mut
self
,
expr
:
&
ast
::
Expr
)
{
let
typer
=
self
.typer
;
match
typer
.adjustments
()
.borrow
()
.get
(
&
expr
.id
)
{
None
=>
{
}
Some
(
adjustment
)
=>
{
match
*
adjustment
{
ty
::
AdjustReifyFnPointer
(
..
)
|
ty
::
AdjustUnsafeFnPointer
(
..
)
=>
{
// Creating a closure/fn-pointer consumes the
// input and stores it into the resulting
// rvalue.
debug!
(
"walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)"
);
if
let
Some
(
adjustment
)
=
typer
.adjustments
()
.borrow
()
.get
(
&
expr
.id
)
{
match
*
adjustment
{
ty
::
AdjustReifyFnPointer
|
ty
::
AdjustUnsafeFnPointer
=>
{
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
debug!
(
"walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)"
);
let
cmt_unadjusted
=
return_if_err!
(
self
.mc
.cat_expr_unadjusted
(
expr
));
self
.delegate_consume
(
expr
.id
,
expr
.span
,
cmt_unadjusted
);
}
ty
::
AdjustDerefRef
(
ref
adj
)
=>
{
self
.walk_autoderefs
(
expr
,
adj
.autoderefs
);
if
let
Some
(
ref
r
)
=
adj
.autoref
{
self
.walk_autoref
(
expr
,
r
,
adj
.autoderefs
);
}
else
if
adj
.unsize
.is_some
()
{
assert
!
(
adj
.autoderefs
==
0
,
format!
(
"Expected no derefs with
\
unsize AutoRefs, found: {}"
,
adj
.repr
(
self
.tcx
())));
let
cmt_unadjusted
=
return_if_err!
(
self
.mc
.cat_expr_unadjusted
(
expr
));
self
.delegate_consume
(
expr
.id
,
expr
.span
,
cmt_unadjusted
);
}
ty
::
AdjustDerefRef
(
ref
adj
)
=>
{
self
.walk_autoderefref
(
expr
,
adj
);
}
}
}
}
...
...
@@ -818,7 +825,7 @@ fn walk_autoderefs(&mut self,
debug!
(
"walk_autoderefs expr={} autoderefs={}"
,
expr
.repr
(
self
.tcx
()),
autoderefs
);
for
i
in
0
..
autoderefs
{
let
deref_id
=
ty
::
MethodCall
::
autoderef
(
expr
.id
,
i
);
let
deref_id
=
ty
::
MethodCall
::
autoderef
(
expr
.id
,
i
as
u32
);
match
self
.typer
.node_method_ty
(
deref_id
)
{
None
=>
{}
Some
(
method_ty
)
=>
{
...
...
@@ -903,59 +910,22 @@ fn walk_autoref(&mut self,
}
};
match
*
autoref
{
ty
::
AutoPtr
(
r
,
m
,
ref
baseref
)
=>
{
let
cmt_base
=
self
.walk_autoref_recursively
(
expr
,
cmt_derefd
,
baseref
);
let
cmt_base
=
self
.walk_autoref_recursively
(
expr
,
cmt_derefd
,
baseref
);
debug!
(
"walk_autoref: expr.id={} cmt_base={}"
,
expr
.id
,
cmt_base
.repr
(
self
.tcx
()));
debug!
(
"walk_autoref: expr.id={} cmt_base={}"
,
expr
.id
,
cmt_base
.repr
(
self
.tcx
()));
match
*
autoref
{
ty
::
AutoPtr
(
r
,
m
)
=>
{
self
.delegate
.borrow
(
expr
.id
,
expr
.span
,
cmt_
base
,
r
,
cmt_
derefd
,
*
r
,
ty
::
BorrowKind
::
from_mutbl
(
m
),
AutoRef
);
}
ty
::
AutoUnsize
(
_
)
=>
{
// Converting a `[T; N]` to `[T]` or `T` to `Trait`
// isn't really a borrow, move, etc, in and of itself.
// Also, no recursive step here, this is a base case.
// It may seem a bit odd to return the cmt_derefd
// unmodified here, but in fact I think it's the right
// thing to do. Essentially the unsize transformation
// isn't really relevant to the borrowing rules --
// it's best thought of as a kind of side-modifier to
// the autoref, adding additional data that is
// attached to the pointer that is produced, but not
// affecting the data being borrowed in any other
// way. To see what I mean, consider this example:
//
// fn foo<'a>(&'a self) -> &'a Trait { self }
//
// This is valid because the underlying `self` value
// lives for the lifetime 'a. If we were to treat the
// "unsizing" as e.g. producing an rvalue, that would
// only be valid for the temporary scope, which isn't
// enough to justify the return value, which have the
// lifetime 'a.
//
// Another option would be to add a variant for
// categorization (like downcast) that wraps
// cmt_derefd and represents the unsizing operation.
// But I don't think there is any particular use for
// this (yet). -nmatsakis
return
cmt_derefd
.clone
();
}
ty
::
AutoUnsizeUniq
(
_
)
=>
{
// these are handled via special case above
self
.tcx
()
.sess
.span_bug
(
expr
.span
,
"nexpected AutoUnsizeUniq"
);
}
ty
::
AutoUnsafe
(
m
,
ref
baseref
)
=>
{
let
cmt_base
=
self
.walk_autoref_recursively
(
expr
,
cmt_derefd
,
baseref
);
...
...
src/librustc/middle/mem_categorization.rs
浏览文件 @
4e8e6414
...
...
@@ -451,33 +451,23 @@ pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
Some
(
adjustment
)
=>
{
match
*
adjustment
{
ty
::
AdjustReifyFnPointer
(
..
)
|
ty
::
AdjustUnsafeFnPointer
(
..
)
=>
{
debug!
(
"cat_expr(AdjustReifyFnPointer): {}"
,
expr
.repr
(
self
.tcx
()));
// Convert a bare fn to a closure by adding NULL env.
// Result is an rvalue.
let
expr_ty
=
try!
(
self
.expr_ty_adjusted
(
expr
));
Ok
(
self
.cat_rvalue_node
(
expr
.id
(),
expr
.span
(),
expr_ty
))
}
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoref
:
Some
(
_
),
..
})
=>
{
debug!
(
"cat_expr(AdjustDerefRef): {}"
,
autoref
:
None
,
unsize
:
None
,
autoderefs
,
..
})
=>
{
// Equivalent to *expr or something similar.
self
.cat_expr_autoderefd
(
expr
,
autoderefs
)
}
ty
::
AdjustReifyFnPointer
|
ty
::
AdjustUnsafeFnPointer
|
ty
::
AdjustDerefRef
(
_
)
=>
{
debug!
(
"cat_expr({}): {}"
,
adjustment
.repr
(
self
.tcx
()),
expr
.repr
(
self
.tcx
()));
// Equivalent to &*expr or something similar.
// Result is an rvalue.
let
expr_ty
=
try!
(
self
.expr_ty_adjusted
(
expr
));
Ok
(
self
.cat_rvalue_node
(
expr
.id
(),
expr
.span
(),
expr_ty
))
}
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoref
:
None
,
autoderefs
})
=>
{
// Equivalent to *expr or something similar.
self
.cat_expr_autoderefd
(
expr
,
autoderefs
)
}
}
}
}
...
...
@@ -928,15 +918,9 @@ fn cat_deref<N:ast_node>(&self,
deref_cnt
:
usize
,
deref_context
:
DerefKindContext
)
->
McResult
<
cmt
<
'tcx
>>
{
let
adjustment
=
match
self
.typer
.adjustments
()
.borrow
()
.get
(
&
node
.id
())
{
Some
(
adj
)
if
ty
::
adjust_is_object
(
adj
)
=>
ty
::
AutoObject
,
_
if
deref_cnt
!=
0
=>
ty
::
AutoDeref
(
deref_cnt
),
_
=>
ty
::
NoAdjustment
};
let
method_call
=
ty
::
MethodCall
{
expr_id
:
node
.id
(),
a
djustment
:
adjustment
a
utoderef
:
deref_cnt
as
u32
};
let
method_ty
=
self
.typer
.node_method_ty
(
method_call
);
...
...
src/librustc/middle/ty.rs
浏览文件 @
4e8e6414
...
...
@@ -20,7 +20,6 @@
pub
use
self
::
Variance
::
*
;
pub
use
self
::
AutoAdjustment
::
*
;
pub
use
self
::
Representability
::
*
;
pub
use
self
::
UnsizeKind
::
*
;
pub
use
self
::
AutoRef
::
*
;
pub
use
self
::
ExprKind
::
*
;
pub
use
self
::
DtorKind
::
*
;
...
...
@@ -33,7 +32,6 @@
pub
use
self
::
BoundRegion
::
*
;
pub
use
self
::
sty
::
*
;
pub
use
self
::
IntVarValue
::
*
;
pub
use
self
::
ExprAdjustment
::
*
;
pub
use
self
::
vtable_origin
::
*
;
pub
use
self
::
MethodOrigin
::
*
;
pub
use
self
::
CopyImplementationError
::
*
;
...
...
@@ -283,145 +281,34 @@ pub enum Variance {
Bivariant
,
// T<A> <: T<B> -- e.g., unused type parameter
}
#[derive(Clone,
Debug)]
#[derive(C
opy,
C
lone,
Debug)]
pub
enum
AutoAdjustment
<
'tcx
>
{
AdjustReifyFnPointer
(
ast
::
DefId
)
,
// go from a fn-item type to a fn-pointer type
AdjustReifyFnPointer
,
// go from a fn-item type to a fn-pointer type
AdjustUnsafeFnPointer
,
// go from a safe fn pointer to an unsafe fn pointer
AdjustDerefRef
(
AutoDerefRef
<
'tcx
>
)
}
#[derive(Clone,
PartialEq,
Debug)]
pub
enum
UnsizeKind
<
'tcx
>
{
// [T, ..n] -> [T], the usize field is n.
UnsizeLength
(
usize
),
// An unsize coercion applied to the tail field of a struct.
// The usize is the index of the type parameter which is unsized.
UnsizeStruct
(
Box
<
UnsizeKind
<
'tcx
>>
,
usize
),
UnsizeVtable
(
TyTrait
<
'tcx
>
,
/* the self type of the trait */
Ty
<
'tcx
>
),
UnsizeUpcast
(
Ty
<
'tcx
>
),
AdjustDerefRef
(
AutoDerefRef
<
'tcx
>
),
}
#[derive(Clone,
Debug)]
#[derive(C
opy,
C
lone,
Debug)]
pub
struct
AutoDerefRef
<
'tcx
>
{
/// Apply a number of dereferences, producing an lvalue.
pub
autoderefs
:
usize
,
pub
autoref
:
Option
<
AutoRef
<
'tcx
>>
/// Produce a pointer/reference from the value.
pub
autoref
:
Option
<
AutoRef
<
'tcx
>>
,
/// Unsize a pointer/reference value, e.g. &[T; n] to &[T].
/// The stored type is the target pointer type.
pub
unsize
:
Option
<
Ty
<
'tcx
>>
,
}
#[derive(Clone,
PartialEq,
Debug)]
#[derive(C
opy,
C
lone,
PartialEq,
Debug)]
pub
enum
AutoRef
<
'tcx
>
{
/// Convert from T to &T
/// The third field allows us to wrap other AutoRef adjustments.
AutoPtr
(
Region
,
ast
::
Mutability
,
Option
<
Box
<
AutoRef
<
'tcx
>>>
),
/// Convert [T, ..n] to [T] (or similar, depending on the kind)
AutoUnsize
(
UnsizeKind
<
'tcx
>
),
/// Convert Box<[T, ..n]> to Box<[T]> or something similar in a Box.
/// With DST and Box a library type, this should be replaced by UnsizeStruct.
AutoUnsizeUniq
(
UnsizeKind
<
'tcx
>
),
AutoPtr
(
&
'tcx
Region
,
ast
::
Mutability
),
/// Convert from T to *T
/// Value to thin pointer
/// The second field allows us to wrap other AutoRef adjustments.
AutoUnsafe
(
ast
::
Mutability
,
Option
<
Box
<
AutoRef
<
'tcx
>>>
),
}
// Ugly little helper function. The first bool in the returned tuple is true if
// there is an 'unsize to trait object' adjustment at the bottom of the
// adjustment. If that is surrounded by an AutoPtr, then we also return the
// region of the AutoPtr (in the third argument). The second bool is true if the
// adjustment is unique.
fn
autoref_object_region
(
autoref
:
&
AutoRef
)
->
(
bool
,
bool
,
Option
<
Region
>
)
{
fn
unsize_kind_is_object
(
k
:
&
UnsizeKind
)
->
bool
{
match
k
{
&
UnsizeVtable
(
..
)
=>
true
,
&
UnsizeStruct
(
box
ref
k
,
_
)
=>
unsize_kind_is_object
(
k
),
_
=>
false
}
}
match
autoref
{
&
AutoUnsize
(
ref
k
)
=>
(
unsize_kind_is_object
(
k
),
false
,
None
),
&
AutoUnsizeUniq
(
ref
k
)
=>
(
unsize_kind_is_object
(
k
),
true
,
None
),
&
AutoPtr
(
adj_r
,
_
,
Some
(
box
ref
autoref
))
=>
{
let
(
b
,
u
,
r
)
=
autoref_object_region
(
autoref
);
if
r
.is_some
()
||
u
{
(
b
,
u
,
r
)
}
else
{
(
b
,
u
,
Some
(
adj_r
))
}
}
&
AutoUnsafe
(
_
,
Some
(
box
ref
autoref
))
=>
autoref_object_region
(
autoref
),
_
=>
(
false
,
false
,
None
)
}
}
// If the adjustment introduces a borrowed reference to a trait object, then
// returns the region of the borrowed reference.
pub
fn
adjusted_object_region
(
adj
:
&
AutoAdjustment
)
->
Option
<
Region
>
{
match
adj
{
&
AdjustDerefRef
(
AutoDerefRef
{
autoref
:
Some
(
ref
autoref
),
..
})
=>
{
let
(
b
,
_
,
r
)
=
autoref_object_region
(
autoref
);
if
b
{
r
}
else
{
None
}
}
_
=>
None
}
}
// Returns true if there is a trait cast at the bottom of the adjustment.
pub
fn
adjust_is_object
(
adj
:
&
AutoAdjustment
)
->
bool
{
match
adj
{
&
AdjustDerefRef
(
AutoDerefRef
{
autoref
:
Some
(
ref
autoref
),
..
})
=>
{
let
(
b
,
_
,
_
)
=
autoref_object_region
(
autoref
);
b
}
_
=>
false
}
}
// If possible, returns the type expected from the given adjustment. This is not
// possible if the adjustment depends on the type of the adjusted expression.
pub
fn
type_of_adjust
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
adj
:
&
AutoAdjustment
<
'tcx
>
)
->
Option
<
Ty
<
'tcx
>>
{
fn
type_of_autoref
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
autoref
:
&
AutoRef
<
'tcx
>
)
->
Option
<
Ty
<
'tcx
>>
{
match
autoref
{
&
AutoUnsize
(
ref
k
)
=>
match
k
{
&
UnsizeVtable
(
TyTrait
{
ref
principal
,
ref
bounds
},
_
)
=>
{
Some
(
mk_trait
(
cx
,
principal
.clone
(),
bounds
.clone
()))
}
_
=>
None
},
&
AutoUnsizeUniq
(
ref
k
)
=>
match
k
{
&
UnsizeVtable
(
TyTrait
{
ref
principal
,
ref
bounds
},
_
)
=>
{
Some
(
mk_uniq
(
cx
,
mk_trait
(
cx
,
principal
.clone
(),
bounds
.clone
())))
}
_
=>
None
},
&
AutoPtr
(
r
,
m
,
Some
(
box
ref
autoref
))
=>
{
match
type_of_autoref
(
cx
,
autoref
)
{
Some
(
ty
)
=>
Some
(
mk_rptr
(
cx
,
cx
.mk_region
(
r
),
mt
{
mutbl
:
m
,
ty
:
ty
})),
None
=>
None
}
}
&
AutoUnsafe
(
m
,
Some
(
box
ref
autoref
))
=>
{
match
type_of_autoref
(
cx
,
autoref
)
{
Some
(
ty
)
=>
Some
(
mk_ptr
(
cx
,
mt
{
mutbl
:
m
,
ty
:
ty
})),
None
=>
None
}
}
_
=>
None
}
}
match
adj
{
&
AdjustDerefRef
(
AutoDerefRef
{
autoref
:
Some
(
ref
autoref
),
..
})
=>
{
type_of_autoref
(
cx
,
autoref
)
}
_
=>
None
}
AutoUnsafe
(
ast
::
Mutability
),
}
#[derive(Clone,
Copy,
RustcEncodable,
RustcDecodable,
PartialEq,
PartialOrd,
Debug)]
...
...
@@ -509,35 +396,21 @@ pub struct MethodCallee<'tcx> {
#[derive(Clone,
Copy,
PartialEq,
Eq,
Hash,
Debug)]
pub
struct
MethodCall
{
pub
expr_id
:
ast
::
NodeId
,
pub
adjustment
:
ExprAdjustment
}
#[derive(Clone,
PartialEq,
Eq,
Hash,
Debug,
RustcEncodable,
RustcDecodable,
Copy)]
pub
enum
ExprAdjustment
{
NoAdjustment
,
AutoDeref
(
usize
),
AutoObject
pub
autoderef
:
u32
}
impl
MethodCall
{
pub
fn
expr
(
id
:
ast
::
NodeId
)
->
MethodCall
{
MethodCall
{
expr_id
:
id
,
adjustment
:
NoAdjustment
}
}
pub
fn
autoobject
(
id
:
ast
::
NodeId
)
->
MethodCall
{
MethodCall
{
expr_id
:
id
,
adjustment
:
AutoObject
autoderef
:
0
}
}
pub
fn
autoderef
(
expr_id
:
ast
::
NodeId
,
autoderef
:
usize
)
->
MethodCall
{
MethodCall
{
expr_id
:
expr_id
,
a
djustment
:
AutoDeref
(
1
+
autoderef
)
a
utoderef
:
1
+
autoderef
}
}
}
...
...
@@ -4581,16 +4454,15 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
return
match
adjustment
{
Some
(
adjustment
)
=>
{
match
*
adjustment
{
AdjustReifyFnPointer
(
_
)
=>
{
AdjustReifyFnPointer
=>
{
match
unadjusted_ty
.sty
{
ty
::
ty_bare_fn
(
Some
(
_
),
b
)
=>
{
ty
::
mk_bare_fn
(
cx
,
None
,
b
)
}
ref
b
=>
{
_
=>
{
cx
.sess
.bug
(
&
format!
(
"AdjustReifyFnPointer adjustment on non-fn-item:
\
{:?}"
,
b
));
{}"
,
unadjusted_ty
.repr
(
cx
)));
}
}
}
...
...
@@ -4612,7 +4484,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
if
!
ty
::
type_is_error
(
adjusted_ty
)
{
for
i
in
0
..
adj
.autoderefs
{
let
method_call
=
MethodCall
::
autoderef
(
expr_id
,
i
);
let
method_call
=
MethodCall
::
autoderef
(
expr_id
,
i
as
u32
);
match
method_type
(
method_call
)
{
Some
(
method_ty
)
=>
{
// overloaded deref operators have all late-bound
...
...
@@ -4639,7 +4511,11 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
}
}
adjust_ty_for_autoref
(
cx
,
span
,
adjusted_ty
,
adj
.autoref
.as_ref
())
if
let
Some
(
target
)
=
adj
.unsize
{
target
}
else
{
adjust_ty_for_autoref
(
cx
,
adjusted_ty
,
adj
.autoref
)
}
}
}
}
...
...
@@ -4648,73 +4524,16 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
}
pub
fn
adjust_ty_for_autoref
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
,
autoref
:
Option
<&
AutoRef
<
'tcx
>>
)
->
Ty
<
'tcx
>
{
autoref
:
Option
<
AutoRef
<
'tcx
>>
)
->
Ty
<
'tcx
>
{
match
autoref
{
None
=>
ty
,
Some
(
&
AutoPtr
(
r
,
m
,
ref
a
))
=>
{
let
adjusted_ty
=
match
a
{
&
Some
(
box
ref
a
)
=>
adjust_ty_for_autoref
(
cx
,
span
,
ty
,
Some
(
a
)),
&
None
=>
ty
};
mk_rptr
(
cx
,
cx
.mk_region
(
r
),
mt
{
ty
:
adjusted_ty
,
mutbl
:
m
})
Some
(
AutoPtr
(
r
,
m
))
=>
{
mk_rptr
(
cx
,
r
,
mt
{
ty
:
ty
,
mutbl
:
m
})
}
Some
(
&
AutoUnsafe
(
m
,
ref
a
))
=>
{
let
adjusted_ty
=
match
a
{
&
Some
(
box
ref
a
)
=>
adjust_ty_for_autoref
(
cx
,
span
,
ty
,
Some
(
a
)),
&
None
=>
ty
};
mk_ptr
(
cx
,
mt
{
ty
:
adjusted_ty
,
mutbl
:
m
})
}
Some
(
&
AutoUnsize
(
ref
k
))
=>
unsize_ty
(
cx
,
ty
,
k
,
span
),
Some
(
&
AutoUnsizeUniq
(
ref
k
))
=>
ty
::
mk_uniq
(
cx
,
unsize_ty
(
cx
,
ty
,
k
,
span
)),
}
}
// Take a sized type and a sizing adjustment and produce an unsized version of
// the type.
pub
fn
unsize_ty
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
kind
:
&
UnsizeKind
<
'tcx
>
,
span
:
Span
)
->
Ty
<
'tcx
>
{
match
kind
{
&
UnsizeLength
(
len
)
=>
match
ty
.sty
{
ty_vec
(
ty
,
Some
(
n
))
=>
{
assert
!
(
len
==
n
);
mk_vec
(
cx
,
ty
,
None
)
}
_
=>
cx
.sess
.span_bug
(
span
,
&
format!
(
"UnsizeLength with bad sty: {:?}"
,
ty_to_string
(
cx
,
ty
)))
},
&
UnsizeStruct
(
box
ref
k
,
tp_index
)
=>
match
ty
.sty
{
ty_struct
(
did
,
substs
)
=>
{
let
ty_substs
=
substs
.types
.get_slice
(
subst
::
TypeSpace
);
let
new_ty
=
unsize_ty
(
cx
,
ty_substs
[
tp_index
],
k
,
span
);
let
mut
unsized_substs
=
substs
.clone
();
unsized_substs
.types
.get_mut_slice
(
subst
::
TypeSpace
)[
tp_index
]
=
new_ty
;
mk_struct
(
cx
,
did
,
cx
.mk_substs
(
unsized_substs
))
}
_
=>
cx
.sess
.span_bug
(
span
,
&
format!
(
"UnsizeStruct with bad sty: {:?}"
,
ty_to_string
(
cx
,
ty
)))
},
&
UnsizeVtable
(
TyTrait
{
ref
principal
,
ref
bounds
},
_
)
=>
{
mk_trait
(
cx
,
principal
.clone
(),
bounds
.clone
())
}
&
UnsizeUpcast
(
target_ty
)
=>
{
target_ty
Some
(
AutoUnsafe
(
m
))
=>
{
mk_ptr
(
cx
,
mt
{
ty
:
ty
,
mutbl
:
m
})
}
}
}
...
...
@@ -5971,6 +5790,47 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
})
.collect
()
}
/// Returns the deeply last field of nested structures, or the same type,
/// if not a structure at all. Corresponds to the only possible unsized
/// field, and its type can be used to determine unsizing strategy.
pub
fn
struct_tail
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
mut
ty
:
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
{
while
let
ty_struct
(
def_id
,
substs
)
=
ty
.sty
{
match
struct_fields
(
cx
,
def_id
,
substs
)
.last
()
{
Some
(
f
)
=>
ty
=
f
.mt.ty
,
None
=>
break
}
}
ty
}
/// Same as applying struct_tail on `source` and `target`, but only
/// keeps going as long as the two types are instances of the same
/// structure definitions.
/// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
/// whereas struct_tail produces `T`, and `Trait`, respectively.
pub
fn
struct_lockstep_tails
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
source
:
Ty
<
'tcx
>
,
target
:
Ty
<
'tcx
>
)
->
(
Ty
<
'tcx
>
,
Ty
<
'tcx
>
)
{
let
(
mut
a
,
mut
b
)
=
(
source
,
target
);
while
let
(
&
ty_struct
(
a_did
,
a_substs
),
&
ty_struct
(
b_did
,
b_substs
))
=
(
&
a
.sty
,
&
b
.sty
)
{
if
a_did
!=
b_did
{
continue
;
}
if
let
Some
(
a_f
)
=
struct_fields
(
cx
,
a_did
,
a_substs
)
.last
()
{
if
let
Some
(
b_f
)
=
struct_fields
(
cx
,
b_did
,
b_substs
)
.last
()
{
a
=
a_f
.mt.ty
;
b
=
b_f
.mt.ty
;
}
else
{
break
;
}
}
else
{
break
;
}
}
(
a
,
b
)
}
#[derive(Copy,
Clone)]
pub
struct
ClosureUpvar
<
'tcx
>
{
pub
def
:
def
::
Def
,
...
...
@@ -6881,8 +6741,8 @@ pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
impl
<
'tcx
>
AutoAdjustment
<
'tcx
>
{
pub
fn
is_identity
(
&
self
)
->
bool
{
match
*
self
{
AdjustReifyFnPointer
(
..
)
=>
false
,
AdjustUnsafeFnPointer
(
..
)
=>
false
,
AdjustReifyFnPointer
|
AdjustUnsafeFnPointer
=>
false
,
AdjustDerefRef
(
ref
r
)
=>
r
.is_identity
(),
}
}
...
...
@@ -6890,7 +6750,7 @@ pub fn is_identity(&self) -> bool {
impl
<
'tcx
>
AutoDerefRef
<
'tcx
>
{
pub
fn
is_identity
(
&
self
)
->
bool
{
self
.autoderefs
==
0
&&
self
.autoref
.is_none
()
self
.autoderefs
==
0
&&
self
.
unsize
.is_none
()
&&
self
.
autoref
.is_none
()
}
}
...
...
@@ -7051,8 +6911,8 @@ pub fn shifted(&self, amount: u32) -> DebruijnIndex {
impl
<
'tcx
>
Repr
<
'tcx
>
for
AutoAdjustment
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
<
'tcx
>
)
->
String
{
match
*
self
{
AdjustReifyFnPointer
(
def_id
)
=>
{
format!
(
"AdjustReifyFnPointer
({})"
,
def_id
.repr
(
tcx
)
)
AdjustReifyFnPointer
=>
{
format!
(
"AdjustReifyFnPointer
"
)
}
AdjustUnsafeFnPointer
=>
{
format!
(
"AdjustUnsafeFnPointer"
)
...
...
@@ -7064,37 +6924,21 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
UnsizeKind
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
<
'tcx
>
)
->
String
{
match
*
self
{
UnsizeLength
(
n
)
=>
format!
(
"UnsizeLength({})"
,
n
),
UnsizeStruct
(
ref
k
,
n
)
=>
format!
(
"UnsizeStruct({},{})"
,
k
.repr
(
tcx
),
n
),
UnsizeVtable
(
ref
a
,
ref
b
)
=>
format!
(
"UnsizeVtable({},{})"
,
a
.repr
(
tcx
),
b
.repr
(
tcx
)),
UnsizeUpcast
(
ref
a
)
=>
format!
(
"UnsizeUpcast({})"
,
a
.repr
(
tcx
)),
}
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
AutoDerefRef
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
<
'tcx
>
)
->
String
{
format!
(
"AutoDerefRef({}, {})"
,
self
.autoderefs
,
self
.autoref
.repr
(
tcx
))
format!
(
"AutoDerefRef({}, unsize={}, {})"
,
self
.autoderefs
,
self
.unsize
.repr
(
tcx
),
self
.autoref
.repr
(
tcx
))
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
AutoRef
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
<
'tcx
>
)
->
String
{
match
*
self
{
AutoPtr
(
a
,
b
,
ref
c
)
=>
{
format!
(
"AutoPtr({},{:?},{})"
,
a
.repr
(
tcx
),
b
,
c
.repr
(
tcx
))
}
AutoUnsize
(
ref
a
)
=>
{
format!
(
"AutoUnsize({})"
,
a
.repr
(
tcx
))
}
AutoUnsizeUniq
(
ref
a
)
=>
{
format!
(
"AutoUnsizeUniq({})"
,
a
.repr
(
tcx
))
AutoPtr
(
a
,
b
)
=>
{
format!
(
"AutoPtr({},{:?})"
,
a
.repr
(
tcx
),
b
)
}
AutoUnsafe
(
ref
a
,
ref
b
)
=>
{
format!
(
"AutoUnsafe({:?}
,{})"
,
a
,
b
.repr
(
tcx
)
)
AutoUnsafe
(
ref
a
)
=>
{
format!
(
"AutoUnsafe({:?}
)"
,
a
)
}
}
}
...
...
src/librustc/middle/ty_fold.rs
浏览文件 @
4e8e6414
...
...
@@ -477,24 +477,6 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::InstantiatedPred
}
}
impl
<
'tcx
>
TypeFoldable
<
'tcx
>
for
ty
::
UnsizeKind
<
'tcx
>
{
fn
fold_with
<
F
:
TypeFolder
<
'tcx
>>
(
&
self
,
folder
:
&
mut
F
)
->
ty
::
UnsizeKind
<
'tcx
>
{
match
*
self
{
ty
::
UnsizeLength
(
len
)
=>
ty
::
UnsizeLength
(
len
),
ty
::
UnsizeStruct
(
box
ref
k
,
n
)
=>
ty
::
UnsizeStruct
(
box
k
.fold_with
(
folder
),
n
),
ty
::
UnsizeVtable
(
ty
::
TyTrait
{
ref
principal
,
ref
bounds
},
self_ty
)
=>
{
ty
::
UnsizeVtable
(
ty
::
TyTrait
{
principal
:
principal
.fold_with
(
folder
),
bounds
:
bounds
.fold_with
(
folder
),
},
self_ty
.fold_with
(
folder
))
}
ty
::
UnsizeUpcast
(
t
)
=>
ty
::
UnsizeUpcast
(
t
.fold_with
(
folder
)),
}
}
}
impl
<
'tcx
,
O
>
TypeFoldable
<
'tcx
>
for
traits
::
Obligation
<
'tcx
,
O
>
where
O
:
TypeFoldable
<
'tcx
>
{
...
...
@@ -768,16 +750,11 @@ pub fn super_fold_autoref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
->
ty
::
AutoRef
<
'tcx
>
{
match
*
autoref
{
ty
::
AutoPtr
(
r
,
m
,
None
)
=>
ty
::
AutoPtr
(
this
.fold_region
(
r
),
m
,
None
),
ty
::
AutoPtr
(
r
,
m
,
Some
(
ref
a
))
=>
{
ty
::
AutoPtr
(
this
.fold_region
(
r
),
m
,
Some
(
box
super_fold_autoref
(
this
,
&**
a
)))
}
ty
::
AutoUnsafe
(
m
,
None
)
=>
ty
::
AutoUnsafe
(
m
,
None
),
ty
::
AutoUnsafe
(
m
,
Some
(
ref
a
))
=>
{
ty
::
AutoUnsafe
(
m
,
Some
(
box
super_fold_autoref
(
this
,
&**
a
)))
ty
::
AutoPtr
(
r
,
m
)
=>
{
let
r
=
r
.fold_with
(
this
);
ty
::
AutoPtr
(
this
.tcx
()
.mk_region
(
r
),
m
)
}
ty
::
AutoUnsize
(
ref
k
)
=>
ty
::
AutoUnsize
(
k
.fold_with
(
this
)),
ty
::
AutoUnsizeUniq
(
ref
k
)
=>
ty
::
AutoUnsizeUniq
(
k
.fold_with
(
this
)),
ty
::
AutoUnsafe
(
m
)
=>
ty
::
AutoUnsafe
(
m
)
}
}
...
...
src/librustc_lint/builtin.rs
浏览文件 @
4e8e6414
...
...
@@ -1405,11 +1405,11 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
if
let
Some
(
adjustment
)
=
cx
.tcx.adjustments
.borrow
()
.get
(
&
e
.id
)
{
if
let
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
ref
autoref
,
..
})
=
*
adjustment
{
match
autoref
{
&
Some
(
ty
::
AutoPtr
(
_
,
ast
::
MutImmutable
,
None
))
=>
{
&
Some
(
ty
::
AutoPtr
(
_
,
ast
::
MutImmutable
))
=>
{
cx
.span_lint
(
UNUSED_ALLOCATION
,
e
.span
,
"unnecessary allocation, use & instead"
);
}
&
Some
(
ty
::
AutoPtr
(
_
,
ast
::
MutMutable
,
None
))
=>
{
&
Some
(
ty
::
AutoPtr
(
_
,
ast
::
MutMutable
))
=>
{
cx
.span_lint
(
UNUSED_ALLOCATION
,
e
.span
,
"unnecessary allocation, use &mut instead"
);
}
...
...
src/librustc_trans/trans/common.rs
浏览文件 @
4e8e6414
...
...
@@ -146,33 +146,6 @@ pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
}
}
// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
// 'Smallest' here means component of the static representation of the type; not
// the size of an object at runtime.
pub
fn
unsized_part_of_type
<
'tcx
>
(
cx
:
&
ty
::
ctxt
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
{
match
ty
.sty
{
ty
::
ty_str
|
ty
::
ty_trait
(
..
)
|
ty
::
ty_vec
(
..
)
=>
ty
,
ty
::
ty_struct
(
def_id
,
substs
)
=>
{
let
unsized_fields
:
Vec
<
_
>
=
ty
::
struct_fields
(
cx
,
def_id
,
substs
)
.iter
()
.map
(|
f
|
f
.mt.ty
)
.filter
(|
ty
|
!
type_is_sized
(
cx
,
*
ty
))
.collect
();
// Exactly one of the fields must be unsized.
assert
!
(
unsized_fields
.len
()
==
1
);
unsized_part_of_type
(
cx
,
unsized_fields
[
0
])
}
_
=>
{
assert
!
(
type_is_sized
(
cx
,
ty
),
"unsized_part_of_type failed even though ty is unsized"
);
panic!
(
"called unsized_part_of_type with sized ty"
);
}
}
}
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
...
...
src/librustc_trans/trans/consts.rs
浏览文件 @
4e8e6414
...
...
@@ -254,7 +254,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
&
ty
::
expr_ty_adjusted
(
cx
.tcx
(),
e
));
let
opt_adj
=
cx
.tcx
()
.adjustments
.borrow
()
.get
(
&
e
.id
)
.cloned
();
match
opt_adj
{
Some
(
ty
::
AdjustReifyFnPointer
(
_
def_id
)
)
=>
{
Some
(
ty
::
AdjustReifyFnPointer
)
=>
{
// FIXME(#19925) once fn item types are
// zero-sized, we'll need to do something here
}
...
...
@@ -272,73 +272,56 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}
let
second_autoref
=
match
adj
.autoref
{
None
=>
{
let
(
dv
,
dt
)
=
const_deref
(
cx
,
llconst
,
ty
);
llconst
=
dv
;
// If we derefed a fat pointer then we will have an
// open type here. So we need to update the type with
// the one returned from const_deref.
ety_adjusted
=
dt
;
None
}
Some
(
ty
::
AutoUnsafe
(
_
,
opt_autoref
))
|
Some
(
ty
::
AutoPtr
(
_
,
_
,
opt_autoref
))
=>
{
if
adj
.autoderefs
==
0
{
// Don't copy data to do a deref+ref
// (i.e., skip the last auto-deref).
llconst
=
addr_of
(
cx
,
llconst
,
"autoref"
);
}
else
{
// Seeing as we are deref'ing here and take a reference
// again to make the pointer part of the far pointer below,
// we just skip the whole thing. We still need the type
// though. This works even if we don't need to deref
// because of byref semantics. Note that this is not just
// an optimisation, it is necessary for mutable vectors to
// work properly.
ty
=
match
ty
::
deref
(
ty
,
true
)
{
Some
(
mt
)
=>
mt
.ty
,
None
=>
{
cx
.sess
()
.bug
(
&
format!
(
"unexpected dereferenceable type {}"
,
ty_to_string
(
cx
.tcx
(),
ty
)))
}
}
}
opt_autoref
}
Some
(
autoref
)
=>
{
cx
.sess
()
.span_bug
(
e
.span
,
&
format!
(
"unimplemented const first autoref {:?}"
,
autoref
))
}
};
match
second_autoref
{
None
=>
{}
Some
(
box
ty
::
AutoUnsafe
(
_
,
None
))
|
Some
(
box
ty
::
AutoPtr
(
_
,
_
,
None
))
=>
{
if
adj
.autoref
.is_some
()
{
if
adj
.autoderefs
==
0
{
// Don't copy data to do a deref+ref
// (i.e., skip the last auto-deref).
llconst
=
addr_of
(
cx
,
llconst
,
"autoref"
);
ty
=
ty
::
mk_imm_rptr
(
cx
.tcx
(),
cx
.tcx
()
.mk_region
(
ty
::
ReStatic
),
ty
);
}
Some
(
box
ty
::
AutoUnsize
(
ref
k
))
=>
{
let
info
=
expr
::
unsized_info
(
cx
,
k
,
e
.id
,
ty
,
param_substs
,
||
const_get_elt
(
cx
,
llconst
,
&
[
abi
::
FAT_PTR_EXTRA
as
u32
]));
let
unsized_ty
=
ty
::
unsize_ty
(
cx
.tcx
(),
ty
,
k
,
e
.span
);
let
ptr_ty
=
type_of
::
in_memory_type_of
(
cx
,
unsized_ty
)
.ptr_to
();
let
base
=
ptrcast
(
llconst
,
ptr_ty
);
let
prev_const
=
cx
.const_unsized
()
.borrow_mut
()
.insert
(
base
,
llconst
);
assert
!
(
prev_const
.is_none
()
||
prev_const
==
Some
(
llconst
));
assert_eq!
(
abi
::
FAT_PTR_ADDR
,
0
);
assert_eq!
(
abi
::
FAT_PTR_EXTRA
,
1
);
llconst
=
C_struct
(
cx
,
&
[
base
,
info
],
false
);
}
Some
(
autoref
)
=>
{
cx
.sess
()
.span_bug
(
e
.span
,
&
format!
(
"unimplemented const second autoref {:?}"
,
autoref
))
}
}
else
{
let
(
dv
,
dt
)
=
const_deref
(
cx
,
llconst
,
ty
);
llconst
=
dv
;
// If we derefed a fat pointer then we will have an
// open type here. So we need to update the type with
// the one returned from const_deref.
ety_adjusted
=
dt
;
}
if
let
Some
(
target
)
=
adj
.unsize
{
let
target
=
monomorphize
::
apply_param_substs
(
cx
.tcx
(),
param_substs
,
&
target
);
let
pointee_ty
=
ty
::
deref
(
ty
,
true
)
.expect
(
"consts: unsizing got non-pointer type"
)
.ty
;
let
(
base
,
old_info
)
=
if
!
type_is_sized
(
cx
.tcx
(),
pointee_ty
)
{
// Normally, the source is a thin pointer and we are
// adding extra info to make a fat pointer. The exception
// is when we are upcasting an existing object fat pointer
// to use a different vtable. In that case, we want to
// load out the original data pointer so we can repackage
// it.
(
const_get_elt
(
cx
,
llconst
,
&
[
abi
::
FAT_PTR_ADDR
as
u32
]),
Some
(
const_get_elt
(
cx
,
llconst
,
&
[
abi
::
FAT_PTR_EXTRA
as
u32
])))
}
else
{
(
llconst
,
None
)
};
let
unsized_ty
=
ty
::
deref
(
target
,
true
)
.expect
(
"consts: unsizing got non-pointer target type"
)
.ty
;
let
ptr_ty
=
type_of
::
in_memory_type_of
(
cx
,
unsized_ty
)
.ptr_to
();
let
base
=
ptrcast
(
base
,
ptr_ty
);
let
info
=
expr
::
unsized_info
(
cx
,
pointee_ty
,
unsized_ty
,
old_info
,
param_substs
);
let
prev_const
=
cx
.const_unsized
()
.borrow_mut
()
.insert
(
base
,
llconst
);
assert
!
(
prev_const
.is_none
()
||
prev_const
==
Some
(
llconst
));
assert_eq!
(
abi
::
FAT_PTR_ADDR
,
0
);
assert_eq!
(
abi
::
FAT_PTR_EXTRA
,
1
);
llconst
=
C_struct
(
cx
,
&
[
base
,
info
],
false
);
}
}
None
=>
{}
...
...
src/librustc_trans/trans/expr.rs
浏览文件 @
4e8e6414
...
...
@@ -72,8 +72,7 @@
use
trans
::
tvec
;
use
trans
::
type_of
;
use
middle
::
ty
::{
struct_fields
,
tup_fields
};
use
middle
::
ty
::{
AdjustDerefRef
,
AdjustReifyFnPointer
,
AdjustUnsafeFnPointer
,
AutoUnsafe
};
use
middle
::
ty
::
AutoPtr
;
use
middle
::
ty
::{
AdjustDerefRef
,
AdjustReifyFnPointer
,
AdjustUnsafeFnPointer
};
use
middle
::
ty
::{
self
,
Ty
};
use
middle
::
ty
::
MethodCall
;
use
util
::
common
::
indenter
;
...
...
@@ -290,72 +289,39 @@ pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
Store
(
bcx
,
Load
(
bcx
,
get_len
(
bcx
,
src_ptr
)),
get_len
(
bcx
,
dst_ptr
));
}
// Retrieve the information we are losing (making dynamic) in an unsizing
// adjustment.
//
// The `unadjusted_val` argument is a bit funny. It is intended
// for use in an upcast, where the new vtable for an object will
// be drived from the old one. Hence it is a pointer to the fat
// pointer.
pub
fn
unsized_info_bcx
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
kind
:
&
ty
::
UnsizeKind
<
'tcx
>
,
id
:
ast
::
NodeId
,
unadjusted_ty
:
Ty
<
'tcx
>
,
unadjusted_val
:
ValueRef
,
// see above (*)
param_substs
:
&
'tcx
subst
::
Substs
<
'tcx
>
)
->
ValueRef
{
unsized_info
(
bcx
.ccx
(),
kind
,
id
,
unadjusted_ty
,
param_substs
,
||
Load
(
bcx
,
GEPi
(
bcx
,
unadjusted_val
,
&
[
0
,
abi
::
FAT_PTR_EXTRA
])))
}
// Same as `unsize_info_bcx`, but does not require a bcx -- instead it
// takes an extra closure to compute the upcast vtable.
pub
fn
unsized_info
<
'ccx
,
'tcx
,
MK_UPCAST_VTABLE
>
(
ccx
:
&
CrateContext
<
'ccx
,
'tcx
>
,
kind
:
&
ty
::
UnsizeKind
<
'tcx
>
,
id
:
ast
::
NodeId
,
unadjusted_ty
:
Ty
<
'tcx
>
,
param_substs
:
&
'tcx
subst
::
Substs
<
'tcx
>
,
mk_upcast_vtable
:
MK_UPCAST_VTABLE
)
// see notes above
->
ValueRef
where
MK_UPCAST_VTABLE
:
FnOnce
()
->
ValueRef
{
debug!
(
"unsized_info(kind={:?}, id={}, unadjusted_ty={})"
,
kind
,
id
,
unadjusted_ty
.repr
(
ccx
.tcx
()));
match
kind
{
&
ty
::
UnsizeLength
(
len
)
=>
C_uint
(
ccx
,
len
),
&
ty
::
UnsizeStruct
(
box
ref
k
,
tp_index
)
=>
match
unadjusted_ty
.sty
{
ty
::
ty_struct
(
_
,
ref
substs
)
=>
{
let
ty_substs
=
substs
.types
.get_slice
(
subst
::
TypeSpace
);
unsized_info
(
ccx
,
k
,
id
,
ty_substs
[
tp_index
],
param_substs
,
mk_upcast_vtable
)
}
_
=>
ccx
.sess
()
.bug
(
&
format!
(
"UnsizeStruct with bad sty: {}"
,
unadjusted_ty
.repr
(
ccx
.tcx
())))
},
&
ty
::
UnsizeVtable
(
ty
::
TyTrait
{
ref
principal
,
..
},
_
)
=>
{
/// Retrieve the information we are losing (making dynamic) in an unsizing
/// adjustment.
///
/// The `old_info` argument is a bit funny. It is intended for use
/// in an upcast, where the new vtable for an object will be drived
/// from the old one.
pub
fn
unsized_info
<
'ccx
,
'tcx
>
(
ccx
:
&
CrateContext
<
'ccx
,
'tcx
>
,
source
:
Ty
<
'tcx
>
,
target
:
Ty
<
'tcx
>
,
old_info
:
Option
<
ValueRef
>
,
param_substs
:
&
'tcx
subst
::
Substs
<
'tcx
>
)
->
ValueRef
{
let
(
source
,
target
)
=
ty
::
struct_lockstep_tails
(
ccx
.tcx
(),
source
,
target
);
match
(
&
source
.sty
,
&
target
.sty
)
{
(
&
ty
::
ty_vec
(
_
,
Some
(
len
)),
&
ty
::
ty_vec
(
_
,
None
))
=>
C_uint
(
ccx
,
len
),
(
&
ty
::
ty_trait
(
_
),
&
ty
::
ty_trait
(
_
))
=>
{
// For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual
// change to the vtable.
old_info
.expect
(
"unsized_info: missing old info for trait upcast"
)
}
(
_
,
&
ty
::
ty_trait
(
box
ty
::
TyTrait
{
ref
principal
,
..
}))
=>
{
// Note that we preserve binding levels here:
let
substs
=
principal
.0
.substs
.with_self_ty
(
unadjusted_ty
)
.erase_regions
();
let
substs
=
principal
.0
.substs
.with_self_ty
(
source
)
.erase_regions
();
let
substs
=
ccx
.tcx
()
.mk_substs
(
substs
);
let
trait_ref
=
ty
::
Binder
(
Rc
::
new
(
ty
::
TraitRef
{
def_id
:
principal
.def_id
(),
substs
:
substs
}));
let
trait_ref
=
monomorphize
::
apply_param_substs
(
ccx
.tcx
(),
param_substs
,
&
trait_ref
);
substs
:
substs
}));
consts
::
ptrcast
(
meth
::
get_vtable
(
ccx
,
trait_ref
,
param_substs
),
Type
::
vtable_ptr
(
ccx
))
}
&
ty
::
UnsizeUpcast
(
_
)
=>
{
// For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual
// change to the vtable.
mk_upcast_vtable
()
}
_
=>
ccx
.sess
()
.bug
(
&
format!
(
"unsized_info: invalid unsizing {} -> {}"
,
source
.repr
(
ccx
.tcx
()),
target
.repr
(
ccx
.tcx
())))
}
}
...
...
@@ -379,7 +345,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
datum
.to_string
(
bcx
.ccx
()),
adjustment
);
match
adjustment
{
AdjustReifyFnPointer
(
_
def_id
)
=>
{
AdjustReifyFnPointer
=>
{
// FIXME(#19925) once fn item types are
// zero-sized, we'll need to do something here
}
...
...
@@ -387,202 +353,112 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// purely a type-level thing
}
AdjustDerefRef
(
ref
adj
)
=>
{
let
(
autoderefs
,
use_autoref
)
=
match
adj
.autoref
{
// Extracting a value from a box counts as a deref, but if we are
// just converting Box<[T, ..n]> to Box<[T]> we aren't really doing
// a deref (and wouldn't if we could treat Box like a normal struct).
Some
(
ty
::
AutoUnsizeUniq
(
..
))
=>
(
adj
.autoderefs
-
1
,
true
),
let
skip_reborrows
=
if
adj
.autoderefs
==
1
&&
adj
.autoref
.is_some
()
{
// We are a bit paranoid about adjustments and thus might have a re-
// borrow here which merely derefs and then refs again (it might have
// a different region or mutability, but we don't care here. It might
// also be just in case we need to unsize. But if there are no nested
// adjustments then it should be a no-op).
Some
(
ty
::
AutoPtr
(
_
,
_
,
None
))
|
Some
(
ty
::
AutoUnsafe
(
_
,
None
))
if
adj
.autoderefs
==
1
=>
{
match
datum
.ty.sty
{
// Don't skip a conversion from Box<T> to &T, etc.
ty
::
ty_rptr
(
..
)
=>
{
let
method_call
=
MethodCall
::
autoderef
(
expr
.id
,
adj
.autoderefs
-
1
);
let
method
=
bcx
.tcx
()
.method_map
.borrow
()
.get
(
&
method_call
)
.is_some
();
if
method
{
// Don't skip an overloaded deref.
(
adj
.autoderefs
,
true
)
}
else
{
(
adj
.autoderefs
-
1
,
false
)
}
// a different region or mutability, but we don't care here).
match
datum
.ty.sty
{
// Don't skip a conversion from Box<T> to &T, etc.
ty
::
ty_rptr
(
..
)
=>
{
let
method_call
=
MethodCall
::
autoderef
(
expr
.id
,
0
);
if
bcx
.tcx
()
.method_map
.borrow
()
.contains_key
(
&
method_call
)
{
// Don't skip an overloaded deref.
0
}
else
{
1
}
_
=>
(
adj
.autoderefs
,
true
),
}
_
=>
0
}
_
=>
(
adj
.autoderefs
,
true
)
}
else
{
0
};
if
a
utoderefs
>
0
{
if
a
dj
.autoderefs
>
skip_reborrows
{
// Schedule cleanup.
let
lval
=
unpack_datum!
(
bcx
,
datum
.to_lvalue_datum
(
bcx
,
"auto_deref"
,
expr
.id
));
datum
=
unpack_datum!
(
bcx
,
deref_multiple
(
bcx
,
expr
,
lval
.to_expr_datum
(),
autoderefs
));
datum
=
unpack_datum!
(
bcx
,
deref_multiple
(
bcx
,
expr
,
lval
.to_expr_datum
(),
adj
.autoderefs
-
skip_reborrows
));
}
// (You might think there is a more elegant way to do this than a
// use_autoref bool, but then you remember that the borrow checker exists).
if
let
(
true
,
&
Some
(
ref
a
))
=
(
use_autoref
,
&
adj
.autoref
)
{
datum
=
unpack_datum!
(
bcx
,
apply_autoref
(
a
,
bcx
,
expr
,
datum
));
// skip_reborrows bool, but then you remember that the borrow checker exists).
if
skip_reborrows
==
0
&&
adj
.autoref
.is_some
()
{
datum
=
unpack_datum!
(
bcx
,
apply_autoref
(
bcx
,
expr
,
datum
));
}
if
let
Some
(
target
)
=
adj
.unsize
{
datum
=
unpack_datum!
(
bcx
,
unsize_pointer
(
bcx
,
datum
,
bcx
.monomorphize
(
&
target
)));
}
}
}
debug!
(
"after adjustments, datum={}"
,
datum
.to_string
(
bcx
.ccx
()));
return
DatumBlock
::
new
(
bcx
,
datum
);
fn
apply_autoref
<
'blk
,
'tcx
>
(
autoref
:
&
ty
::
AutoRef
<
'tcx
>
,
bcx
:
Block
<
'blk
,
'tcx
>
,
fn
apply_autoref
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
expr
:
&
ast
::
Expr
,
datum
:
Datum
<
'tcx
,
Expr
>
)
->
DatumBlock
<
'blk
,
'tcx
,
Expr
>
{
let
mut
bcx
=
bcx
;
let
mut
datum
=
datum
;
let
datum
=
match
autoref
{
&
AutoPtr
(
_
,
_
,
ref
a
)
|
&
AutoUnsafe
(
_
,
ref
a
)
=>
{
debug!
(
" AutoPtr"
);
if
let
&
Some
(
box
ref
a
)
=
a
{
datum
=
unpack_datum!
(
bcx
,
apply_autoref
(
a
,
bcx
,
expr
,
datum
));
}
if
!
type_is_sized
(
bcx
.tcx
(),
datum
.ty
)
{
// Arrange cleanup
let
lval
=
unpack_datum!
(
bcx
,
datum
.to_lvalue_datum
(
bcx
,
"ref_fat_ptr"
,
expr
.id
));
unpack_datum!
(
bcx
,
ref_fat_ptr
(
bcx
,
lval
))
}
else
{
unpack_datum!
(
bcx
,
auto_ref
(
bcx
,
datum
,
expr
))
}
}
&
ty
::
AutoUnsize
(
ref
k
)
=>
{
debug!
(
" AutoUnsize"
);
unpack_datum!
(
bcx
,
unsize_expr
(
bcx
,
expr
,
datum
,
k
))
}
&
ty
::
AutoUnsizeUniq
(
ty
::
UnsizeLength
(
len
))
=>
{
debug!
(
" AutoUnsizeUniq(UnsizeLength)"
);
unpack_datum!
(
bcx
,
unsize_unique_vec
(
bcx
,
expr
,
datum
,
len
))
}
&
ty
::
AutoUnsizeUniq
(
ref
k
)
=>
{
debug!
(
" AutoUnsizeUniq"
);
unpack_datum!
(
bcx
,
unsize_unique_expr
(
bcx
,
expr
,
datum
,
k
))
}
};
DatumBlock
::
new
(
bcx
,
datum
)
if
!
type_is_sized
(
bcx
.tcx
(),
datum
.ty
)
{
// Arrange cleanup
let
lval
=
unpack_datum!
(
bcx
,
datum
.to_lvalue_datum
(
bcx
,
"ref_fat_ptr"
,
expr
.id
));
ref_fat_ptr
(
bcx
,
lval
)
}
else
{
auto_ref
(
bcx
,
datum
,
expr
)
}
}
fn
unsize_expr
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
expr
:
&
ast
::
Expr
,
datum
:
Datum
<
'tcx
,
Expr
>
,
k
:
&
ty
::
UnsizeKind
<
'tcx
>
)
->
DatumBlock
<
'blk
,
'tcx
,
Expr
>
{
fn
unsize_pointer
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
datum
:
Datum
<
'tcx
,
Expr
>
,
target
:
Ty
<
'tcx
>
)
->
DatumBlock
<
'blk
,
'tcx
,
Expr
>
{
let
mut
bcx
=
bcx
;
let
tcx
=
bcx
.tcx
();
let
datum_ty
=
datum
.ty
;
let
unsized_ty
=
ty
::
unsize_ty
(
tcx
,
datum_ty
,
k
,
expr
.span
);
debug!
(
"unsized_ty={}"
,
unsized_ty
.repr
(
bcx
.tcx
()));
let
info
=
unsized_info_bcx
(
bcx
,
k
,
expr
.id
,
datum_ty
,
datum
.val
,
bcx
.fcx.param_substs
);
// Arrange cleanup
let
lval
=
unpack_datum!
(
bcx
,
datum
.to_lvalue_datum
(
bcx
,
"into_fat_ptr"
,
expr
.id
));
let
unsized_ty
=
ty
::
deref
(
target
,
true
)
.expect
(
"expr::unsize got non-pointer target type"
)
.ty
;
debug!
(
"unsize_lvalue(unsized_ty={})"
,
unsized_ty
.repr
(
bcx
.tcx
()));
// Compute the base pointer. This doesn't change the pointer value,
// but merely its type.
let
ptr_ty
=
type_of
::
in_memory_type_of
(
bcx
.ccx
(),
unsized_ty
)
.ptr_to
();
let
base
=
if
!
type_is_sized
(
bcx
.tcx
(),
lval
.ty
)
{
// We do not arrange cleanup ourselves; if we already are an
// L-value, then cleanup will have already been scheduled (and
// the `datum.to_rvalue_datum` call below will emit code to zero
// the drop flag when moving out of the L-value). If we are an
// R-value, then we do not need to schedule cleanup.
let
datum
=
unpack_datum!
(
bcx
,
datum
.to_rvalue_datum
(
bcx
,
"__unsize_ref"
));
let
pointee_ty
=
ty
::
deref
(
datum
.ty
,
true
)
.expect
(
"expr::unsize got non-pointer datum type"
)
.ty
;
let
(
base
,
old_info
)
=
if
!
type_is_sized
(
bcx
.tcx
(),
pointee_ty
)
{
// Normally, the source is a thin pointer and we are
// adding extra info to make a fat pointer. The exception
// is when we are upcasting an existing object fat pointer
// to use a different vtable. In that case, we want to
// load out the original data pointer so we can repackage
// it.
Load
(
bcx
,
get_dataptr
(
bcx
,
lval
.val
))
(
Load
(
bcx
,
get_dataptr
(
bcx
,
datum
.val
)),
Some
(
Load
(
bcx
,
get_len
(
bcx
,
datum
.val
))))
}
else
{
lval
.val
(
datum
.val
,
None
)
};
let
info
=
unsized_info
(
bcx
.ccx
(),
pointee_ty
,
unsized_ty
,
old_info
,
bcx
.fcx.param_substs
);
// Compute the base pointer. This doesn't change the pointer value,
// but merely its type.
let
ptr_ty
=
type_of
::
in_memory_type_of
(
bcx
.ccx
(),
unsized_ty
)
.ptr_to
();
let
base
=
PointerCast
(
bcx
,
base
,
ptr_ty
);
let
llty
=
type_of
::
type_of
(
bcx
.ccx
(),
unsized_ty
);
let
llty
=
type_of
::
type_of
(
bcx
.ccx
(),
target
);
// HACK(eddyb) get around issues with lifetime intrinsics.
let
scratch
=
alloca_no_lifetime
(
bcx
,
llty
,
"__fat_ptr"
);
Store
(
bcx
,
base
,
get_dataptr
(
bcx
,
scratch
));
Store
(
bcx
,
info
,
get_len
(
bcx
,
scratch
));
DatumBlock
::
new
(
bcx
,
Datum
::
new
(
scratch
,
unsized_ty
,
LvalueExpr
))
}
fn
unsize_unique_vec
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
expr
:
&
ast
::
Expr
,
datum
:
Datum
<
'tcx
,
Expr
>
,
len
:
usize
)
->
DatumBlock
<
'blk
,
'tcx
,
Expr
>
{
let
mut
bcx
=
bcx
;
let
tcx
=
bcx
.tcx
();
let
datum_ty
=
datum
.ty
;
debug!
(
"unsize_unique_vec expr.id={} datum_ty={} len={}"
,
expr
.id
,
datum_ty
.repr
(
tcx
),
len
);
// We do not arrange cleanup ourselves; if we already are an
// L-value, then cleanup will have already been scheduled (and
// the `datum.store_to` call below will emit code to zero the
// drop flag when moving out of the L-value). If we are an R-value,
// then we do not need to schedule cleanup.
let
ll_len
=
C_uint
(
bcx
.ccx
(),
len
);
let
unit_ty
=
ty
::
sequence_element_type
(
tcx
,
ty
::
type_content
(
datum_ty
));
let
vec_ty
=
ty
::
mk_uniq
(
tcx
,
ty
::
mk_vec
(
tcx
,
unit_ty
,
None
));
let
scratch
=
rvalue_scratch_datum
(
bcx
,
vec_ty
,
"__unsize_unique"
);
let
base
=
get_dataptr
(
bcx
,
scratch
.val
);
let
base
=
PointerCast
(
bcx
,
base
,
type_of
::
type_of
(
bcx
.ccx
(),
datum_ty
)
.ptr_to
());
bcx
=
datum
.store_to
(
bcx
,
base
);
Store
(
bcx
,
ll_len
,
get_len
(
bcx
,
scratch
.val
));
DatumBlock
::
new
(
bcx
,
scratch
.to_expr_datum
())
}
fn
unsize_unique_expr
<
'blk
,
'tcx
>
(
bcx
:
Block
<
'blk
,
'tcx
>
,
expr
:
&
ast
::
Expr
,
datum
:
Datum
<
'tcx
,
Expr
>
,
k
:
&
ty
::
UnsizeKind
<
'tcx
>
)
->
DatumBlock
<
'blk
,
'tcx
,
Expr
>
{
let
mut
bcx
=
bcx
;
let
tcx
=
bcx
.tcx
();
let
datum_ty
=
datum
.ty
;
let
unboxed_ty
=
match
datum_ty
.sty
{
ty
::
ty_uniq
(
t
)
=>
t
,
_
=>
bcx
.sess
()
.bug
(
&
format!
(
"Expected ty_uniq, found {}"
,
bcx
.ty_to_string
(
datum_ty
)))
};
let
result_ty
=
ty
::
mk_uniq
(
tcx
,
ty
::
unsize_ty
(
tcx
,
unboxed_ty
,
k
,
expr
.span
));
// We do not arrange cleanup ourselves; if we already are an
// L-value, then cleanup will have already been scheduled (and
// the `datum.store_to` call below will emit code to zero the
// drop flag when moving out of the L-value). If we are an R-value,
// then we do not need to schedule cleanup.
let
scratch
=
rvalue_scratch_datum
(
bcx
,
result_ty
,
"__uniq_fat_ptr"
);
let
llbox_ty
=
type_of
::
type_of
(
bcx
.ccx
(),
datum_ty
);
let
base
=
PointerCast
(
bcx
,
get_dataptr
(
bcx
,
scratch
.val
),
llbox_ty
.ptr_to
());
bcx
=
datum
.store_to
(
bcx
,
base
);
let
info
=
unsized_info_bcx
(
bcx
,
k
,
expr
.id
,
unboxed_ty
,
base
,
bcx
.fcx.param_substs
);
Store
(
bcx
,
info
,
get_len
(
bcx
,
scratch
.val
));
DatumBlock
::
new
(
bcx
,
scratch
.to_expr_datum
())
DatumBlock
::
new
(
bcx
,
Datum
::
new
(
scratch
,
target
,
RvalueExpr
(
Rvalue
::
new
(
ByRef
))))
}
}
...
...
@@ -2233,7 +2109,7 @@ fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let
mut
bcx
=
bcx
;
let
mut
datum
=
datum
;
for
i
in
0
..
times
{
let
method_call
=
MethodCall
::
autoderef
(
expr
.id
,
i
);
let
method_call
=
MethodCall
::
autoderef
(
expr
.id
,
i
as
u32
);
datum
=
unpack_datum!
(
bcx
,
deref_once
(
bcx
,
expr
,
datum
,
method_call
));
}
DatumBlock
{
bcx
:
bcx
,
datum
:
datum
}
...
...
@@ -2265,10 +2141,11 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// converts from the `Smaht<T>` pointer that we have into
// a `&T` pointer. We can then proceed down the normal
// path (below) to dereference that `&T`.
let
datum
=
match
method_call
.adjustment
{
let
datum
=
if
method_call
.autoderef
==
0
{
datum
}
else
{
// Always perform an AutoPtr when applying an overloaded auto-deref
ty
::
AutoDeref
(
_
)
=>
unpack_datum!
(
bcx
,
auto_ref
(
bcx
,
datum
,
expr
)),
_
=>
datum
unpack_datum!
(
bcx
,
auto_ref
(
bcx
,
datum
,
expr
))
};
let
ref_ty
=
// invoked methods have their LB regions instantiated
...
...
src/librustc_trans/trans/type_of.rs
浏览文件 @
4e8e6414
...
...
@@ -359,14 +359,14 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
cx
.tn
()
.find_type
(
"str_slice"
)
.unwrap
()
}
else
{
let
ptr_ty
=
in_memory_type_of
(
cx
,
ty
)
.ptr_to
();
let
unsized_part
=
unsized_part_of_type
(
cx
.tcx
(),
ty
);
let
unsized_part
=
ty
::
struct_tail
(
cx
.tcx
(),
ty
);
let
info_ty
=
match
unsized_part
.sty
{
ty
::
ty_str
|
ty
::
ty_vec
(
..
)
=>
{
Type
::
uint_from_ty
(
cx
,
ast
::
TyUs
)
}
ty
::
ty_trait
(
_
)
=>
Type
::
vtable_ptr
(
cx
),
_
=>
panic!
(
"Unexpected type returned from
\
unsized_part_of_type
: {} for ty={}"
,
struct_tail
: {} for ty={}"
,
unsized_part
.repr
(
cx
.tcx
()),
ty
.repr
(
cx
.tcx
()))
};
Type
::
struct_
(
cx
,
&
[
ptr_ty
,
info_ty
],
false
)
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
4e8e6414
...
...
@@ -59,6 +59,7 @@
use
rscope
::{
self
,
UnelidableRscope
,
RegionScope
,
ElidableRscope
,
ExplicitRscope
,
ObjectLifetimeDefaultRscope
,
ShiftedRscope
,
BindingRscope
};
use
util
::
common
::{
ErrorReported
,
FN_OUTPUT_NAME
};
use
util
::
nodemap
::
FnvHashSet
;
use
util
::
ppaux
::{
self
,
Repr
,
UserString
};
use
std
::
iter
::
repeat
;
...
...
@@ -1011,13 +1012,58 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
projection_bounds
,
bounds
);
let
result
=
ty
::
mk_trait
(
this
.tcx
()
,
trait_ref
,
existential_bounds
);
let
result
=
make_object_type
(
this
,
span
,
trait_ref
,
existential_bounds
);
debug!
(
"trait_ref_to_object_type: result={}"
,
result
.repr
(
this
.tcx
()));
result
}
fn
make_object_type
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
span
:
Span
,
principal
:
ty
::
PolyTraitRef
<
'tcx
>
,
bounds
:
ty
::
ExistentialBounds
<
'tcx
>
)
->
Ty
<
'tcx
>
{
let
tcx
=
this
.tcx
();
let
object
=
ty
::
TyTrait
{
principal
:
principal
,
bounds
:
bounds
};
let
object_trait_ref
=
object
.principal_trait_ref_with_self_ty
(
tcx
,
tcx
.types.err
);
// ensure the super predicates and stop if we encountered an error
if
this
.ensure_super_predicates
(
span
,
object
.principal_def_id
())
.is_err
()
{
return
tcx
.types.err
;
}
let
mut
associated_types
:
FnvHashSet
<
(
ast
::
DefId
,
ast
::
Name
)
>
=
traits
::
supertraits
(
tcx
,
object_trait_ref
)
.flat_map
(|
tr
|
{
let
trait_def
=
ty
::
lookup_trait_def
(
tcx
,
tr
.def_id
());
trait_def
.associated_type_names
.clone
()
.into_iter
()
.map
(
move
|
associated_type_name
|
(
tr
.def_id
(),
associated_type_name
))
})
.collect
();
for
projection_bound
in
&
object
.bounds.projection_bounds
{
let
pair
=
(
projection_bound
.0
.projection_ty.trait_ref.def_id
,
projection_bound
.0
.projection_ty.item_name
);
associated_types
.remove
(
&
pair
);
}
for
(
trait_def_id
,
name
)
in
associated_types
{
span_err!
(
tcx
.sess
,
span
,
E0191
,
"the value of the associated type `{}` (from the trait `{}`) must be specified"
,
name
.user_string
(
tcx
),
ty
::
item_path_str
(
tcx
,
trait_def_id
));
}
ty
::
mk_trait
(
tcx
,
object
.principal
,
object
.bounds
)
}
fn
report_ambiguous_associated_type
(
tcx
:
&
ty
::
ctxt
,
span
:
Span
,
type_str
:
&
str
,
...
...
@@ -1914,7 +1960,7 @@ fn conv_ty_poly_trait_ref<'tcx>(
projection_bounds
,
partitioned_bounds
);
ty
::
mk_trait
(
this
.tcx
()
,
main_trait_bound
,
bounds
)
make_object_type
(
this
,
span
,
main_trait_bound
,
bounds
)
}
pub
fn
conv_existential_bounds_from_partitioned_bounds
<
'tcx
>
(
...
...
src/librustc_typeck/check/callee.rs
浏览文件 @
4e8e6414
...
...
@@ -125,14 +125,10 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
adjusted_ty
.repr
(
fcx
.tcx
()),
autoderefs
);
let
autoderefref
=
ty
::
AutoDerefRef
{
autoderefs
:
autoderefs
,
autoref
:
None
};
// If the callee is a bare function or a closure, then we're all set.
match
structurally_resolved_type
(
fcx
,
callee_expr
.span
,
adjusted_ty
)
.sty
{
ty
::
ty_bare_fn
(
..
)
=>
{
fcx
.write_adjustment
(
callee_expr
.id
,
callee_expr
.span
,
ty
::
AdjustDerefRef
(
autoderefref
));
fcx
.write_autoderef_adjustment
(
callee_expr
.id
,
autoderefs
);
return
Some
(
CallStep
::
Builtin
);
}
...
...
@@ -149,14 +145,14 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
call_expr
.span
,
infer
::
FnCall
,
&
closure_ty
.sig
)
.0
;
fcx
.record_deferred_call_resolution
(
def_id
,
Box
::
new
(
CallResolution
{
call_expr
:
call
_expr
,
callee_expr
:
callee_expr
,
adjusted_ty
:
adjusted_ty
,
autoderefref
:
autoderefref
,
fn_sig
:
fn_sig
.clone
(),
closure_def_id
:
def_id
}));
fcx
.record_deferred_call_resolution
(
def_id
,
Box
::
new
(
CallResolution
{
call_expr
:
call_expr
,
callee_expr
:
callee
_expr
,
adjusted_ty
:
adjusted_ty
,
autoderefs
:
autoderefs
,
fn_sig
:
fn_sig
.clone
()
,
closure_def_id
:
def_id
}));
return
Some
(
CallStep
::
DeferredClosure
(
fn_sig
));
}
}
...
...
@@ -176,7 +172,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
_
=>
{}
}
try_overloaded_call_traits
(
fcx
,
call_expr
,
callee_expr
,
adjusted_ty
,
autoderef
ref
)
try_overloaded_call_traits
(
fcx
,
call_expr
,
callee_expr
,
adjusted_ty
,
autoderef
s
)
.map
(|
method_callee
|
CallStep
::
Overloaded
(
method_callee
))
}
...
...
@@ -184,7 +180,7 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr
:
&
ast
::
Expr
,
callee_expr
:
&
ast
::
Expr
,
adjusted_ty
:
Ty
<
'tcx
>
,
autoderef
ref
:
ty
::
AutoDerefRef
<
'tcx
>
)
autoderef
s
:
usize
)
->
Option
<
ty
::
MethodCallee
<
'tcx
>>
{
// Try the options that are least restrictive on the caller first.
...
...
@@ -203,7 +199,8 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some
(
&*
callee_expr
),
method_name
,
trait_def_id
,
autoderefref
.clone
(),
autoderefs
,
false
,
adjusted_ty
,
None
)
{
None
=>
continue
,
...
...
@@ -335,7 +332,7 @@ struct CallResolution<'tcx> {
call_expr
:
&
'tcx
ast
::
Expr
,
callee_expr
:
&
'tcx
ast
::
Expr
,
adjusted_ty
:
Ty
<
'tcx
>
,
autoderef
ref
:
ty
::
AutoDerefRef
<
'tcx
>
,
autoderef
s
:
usize
,
fn_sig
:
ty
::
FnSig
<
'tcx
>
,
closure_def_id
:
ast
::
DefId
,
}
...
...
@@ -343,11 +340,11 @@ struct CallResolution<'tcx> {
impl
<
'tcx
>
Repr
<
'tcx
>
for
CallResolution
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ty
::
ctxt
<
'tcx
>
)
->
String
{
format!
(
"CallResolution(call_expr={}, callee_expr={}, adjusted_ty={},
\
autoderef
ref
={}, fn_sig={}, closure_def_id={})"
,
autoderef
s
={}, fn_sig={}, closure_def_id={})"
,
self
.call_expr
.repr
(
tcx
),
self
.callee_expr
.repr
(
tcx
),
self
.adjusted_ty
.repr
(
tcx
),
self
.autoderef
ref
.repr
(
tcx
)
,
self
.autoderef
s
,
self
.fn_sig
.repr
(
tcx
),
self
.closure_def_id
.repr
(
tcx
))
}
...
...
@@ -364,7 +361,7 @@ fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
// We may now know enough to figure out fn vs fnmut etc.
match
try_overloaded_call_traits
(
fcx
,
self
.call_expr
,
self
.callee_expr
,
self
.adjusted_ty
,
self
.autoderef
ref
.clone
()
)
{
self
.adjusted_ty
,
self
.autoderef
s
)
{
Some
(
method_callee
)
=>
{
// One problem is that when we get here, we are going
// to have a newly instantiated function signature
...
...
src/librustc_typeck/check/coercion.rs
浏览文件 @
4e8e6414
此差异已折叠。
点击以展开。
src/librustc_typeck/check/method/confirm.rs
浏览文件 @
4e8e6414
...
...
@@ -24,7 +24,6 @@
use
syntax
::
ast
;
use
syntax
::
codemap
::
Span
;
use
std
::
rc
::
Rc
;
use
std
::
mem
;
use
std
::
iter
::
repeat
;
use
util
::
ppaux
::
Repr
;
...
...
@@ -84,7 +83,7 @@ fn confirm(&mut self,
->
MethodCallee
<
'tcx
>
{
// Adjust the self expression the user provided and obtain the adjusted type.
let
self_ty
=
self
.adjust_self_ty
(
unadjusted_self_ty
,
&
pick
.adjustment
);
let
self_ty
=
self
.adjust_self_ty
(
unadjusted_self_ty
,
&
pick
);
// Make sure nobody calls `drop()` explicitly.
self
.enforce_illegal_method_limitations
(
&
pick
);
...
...
@@ -134,11 +133,20 @@ fn confirm(&mut self,
fn
adjust_self_ty
(
&
mut
self
,
unadjusted_self_ty
:
Ty
<
'tcx
>
,
adjustment
:
&
probe
::
PickAdjustment
)
pick
:
&
probe
::
Pick
<
'tcx
>
)
->
Ty
<
'tcx
>
{
// Construct the actual adjustment and write it into the table
let
auto_deref_ref
=
self
.create_ty_adjustment
(
adjustment
);
let
(
autoref
,
unsize
)
=
if
let
Some
(
mutbl
)
=
pick
.autoref
{
let
region
=
self
.infcx
()
.next_region_var
(
infer
::
Autoref
(
self
.span
));
let
autoref
=
ty
::
AutoPtr
(
self
.tcx
()
.mk_region
(
region
),
mutbl
);
(
Some
(
autoref
),
pick
.unsize
.map
(|
target
|
{
ty
::
adjust_ty_for_autoref
(
self
.tcx
(),
target
,
Some
(
autoref
))
}))
}
else
{
// No unsizing should be performed without autoref.
assert
!
(
pick
.unsize
.is_none
());
(
None
,
None
)
};
// Commit the autoderefs by calling `autoderef again, but this
// time writing the results into the various tables.
...
...
@@ -149,47 +157,27 @@ fn adjust_self_ty(&mut self,
UnresolvedTypeAction
::
Error
,
NoPreference
,
|
_
,
n
|
{
if
n
==
auto_deref_ref
.autoderefs
{
if
n
==
pick
.autoderefs
{
Some
(())
}
else
{
None
}
});
assert_eq!
(
n
,
auto_deref_ref
.autoderefs
);
assert_eq!
(
n
,
pick
.autoderefs
);
assert_eq!
(
result
,
Some
(()));
let
final_ty
=
ty
::
adjust_ty_for_autoref
(
self
.tcx
(),
self
.span
,
autoderefd_ty
,
auto_deref_ref
.autoref
.as_ref
());
// Write out the final adjustment.
self
.fcx
.write_adjustment
(
self
.self_expr.id
,
self
.span
,
ty
::
AdjustDerefRef
(
auto_deref_ref
));
final_ty
}
self
.fcx
.write_adjustment
(
self
.self_expr.id
,
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
pick
.autoderefs
,
autoref
:
autoref
,
unsize
:
unsize
}));
fn
create_ty_adjustment
(
&
mut
self
,
adjustment
:
&
probe
::
PickAdjustment
)
->
ty
::
AutoDerefRef
<
'tcx
>
{
match
*
adjustment
{
probe
::
AutoDeref
(
num
)
=>
{
ty
::
AutoDerefRef
{
autoderefs
:
num
,
autoref
:
None
,
}
}
probe
::
AutoUnsizeLength
(
autoderefs
,
len
)
=>
{
ty
::
AutoDerefRef
{
autoderefs
:
autoderefs
,
autoref
:
Some
(
ty
::
AutoUnsize
(
ty
::
UnsizeLength
(
len
))),
}
}
probe
::
AutoRef
(
mutability
,
ref
sub_adjustment
)
=>
{
let
deref
=
self
.create_ty_adjustment
(
&**
sub_adjustment
);
let
region
=
self
.infcx
()
.next_region_var
(
infer
::
Autoref
(
self
.span
));
wrap_autoref
(
deref
,
|
base
|
ty
::
AutoPtr
(
region
,
mutability
,
base
))
}
if
let
Some
(
target
)
=
unsize
{
target
}
else
{
ty
::
adjust_ty_for_autoref
(
self
.tcx
(),
autoderefd_ty
,
autoref
)
}
}
...
...
@@ -499,10 +487,7 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
.adjustments
.borrow
()
.get
(
&
expr
.id
)
{
Some
(
&
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
autoderef_count
,
autoref
:
_
}))
=>
autoderef_count
,
Some
(
&
ty
::
AdjustDerefRef
(
ref
adj
))
=>
adj
.autoderefs
,
Some
(
_
)
|
None
=>
0
,
};
...
...
@@ -529,17 +514,6 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
if
i
!=
0
{
match
expr
.node
{
ast
::
ExprIndex
(
ref
base_expr
,
ref
index_expr
)
=>
{
let
mut
base_adjustment
=
match
self
.fcx.inh.adjustments
.borrow
()
.get
(
&
base_expr
.id
)
{
Some
(
&
ty
::
AdjustDerefRef
(
ref
adr
))
=>
(
*
adr
)
.clone
(),
None
=>
ty
::
AutoDerefRef
{
autoderefs
:
0
,
autoref
:
None
},
Some
(
_
)
=>
{
self
.tcx
()
.sess
.span_bug
(
base_expr
.span
,
"unexpected adjustment type"
);
}
};
// If this is an overloaded index, the
// adjustment will include an extra layer of
// autoref because the method is an &self/&mut
...
...
@@ -548,21 +522,44 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
// expects. This is annoying and horrible. We
// ought to recode this routine so it doesn't
// (ab)use the normal type checking paths.
base_adjustment
.autoref
=
match
base_adjustment
.autoref
{
None
=>
{
None
}
Some
(
ty
::
AutoPtr
(
_
,
_
,
None
))
=>
{
None
}
Some
(
ty
::
AutoPtr
(
_
,
_
,
Some
(
box
r
)))
=>
{
Some
(
r
)
}
let
adj
=
self
.fcx.inh.adjustments
.borrow
()
.get
(
&
base_expr
.id
)
.cloned
();
let
(
autoderefs
,
unsize
)
=
match
adj
{
Some
(
ty
::
AdjustDerefRef
(
adr
))
=>
match
adr
.autoref
{
None
=>
{
assert
!
(
adr
.unsize
.is_none
());
(
adr
.autoderefs
,
None
)
}
Some
(
ty
::
AutoPtr
(
_
,
_
))
=>
{
(
adr
.autoderefs
,
adr
.unsize
.map
(|
target
|
{
ty
::
deref
(
target
,
false
)
.expect
(
"fixup: AutoPtr is not &T"
)
.ty
}))
}
Some
(
_
)
=>
{
self
.tcx
()
.sess
.span_bug
(
base_expr
.span
,
&
format!
(
"unexpected adjustment autoref {}"
,
adr
.repr
(
self
.tcx
())));
}
},
None
=>
(
0
,
None
),
Some
(
_
)
=>
{
self
.tcx
()
.sess
.span_bug
(
base_expr
.span
,
"unexpected adjustment
autoref
"
);
"unexpected adjustment
type
"
);
}
};
let
adjusted_base_ty
=
self
.fcx
.adjust_expr_ty
(
&**
base_expr
,
Some
(
&
ty
::
AdjustDerefRef
(
base_adjustment
.clone
())));
let
(
adjusted_base_ty
,
unsize
)
=
if
let
Some
(
target
)
=
unsize
{
(
target
,
true
)
}
else
{
(
self
.fcx
.adjust_expr_ty
(
base_expr
,
Some
(
&
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
autoderefs
,
autoref
:
None
,
unsize
:
None
}))),
false
)
};
let
index_expr_ty
=
self
.fcx
.expr_ty
(
&**
index_expr
);
let
result
=
check
::
try_index_step
(
...
...
@@ -571,7 +568,8 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
expr
,
&**
base_expr
,
adjusted_base_ty
,
base_adjustment
,
autoderefs
,
unsize
,
PreferMutLvalue
,
index_expr_ty
);
...
...
@@ -658,14 +656,3 @@ fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) ->
self
.span
,
infer
::
FnCall
,
value
)
.0
}
}
fn
wrap_autoref
<
'tcx
,
F
>
(
mut
deref
:
ty
::
AutoDerefRef
<
'tcx
>
,
base_fn
:
F
)
->
ty
::
AutoDerefRef
<
'tcx
>
where
F
:
FnOnce
(
Option
<
Box
<
ty
::
AutoRef
<
'tcx
>>>
)
->
ty
::
AutoRef
<
'tcx
>
,
{
let
autoref
=
mem
::
replace
(
&
mut
deref
.autoref
,
None
);
let
autoref
=
autoref
.map
(|
r
|
box
r
);
deref
.autoref
=
Some
(
base_fn
(
autoref
));
deref
}
src/librustc_typeck/check/method/mod.rs
浏览文件 @
4e8e6414
...
...
@@ -122,8 +122,7 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
->
Option
<
MethodCallee
<
'tcx
>>
{
lookup_in_trait_adjusted
(
fcx
,
span
,
self_expr
,
m_name
,
trait_def_id
,
ty
::
AutoDerefRef
{
autoderefs
:
0
,
autoref
:
None
},
self_ty
,
opt_input_types
)
0
,
false
,
self_ty
,
opt_input_types
)
}
/// `lookup_in_trait_adjusted` is used for overloaded operators. It does a very narrow slice of
...
...
@@ -140,7 +139,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
self_expr
:
Option
<&
ast
::
Expr
>
,
m_name
:
ast
::
Name
,
trait_def_id
:
DefId
,
autoderefref
:
ty
::
AutoDerefRef
<
'tcx
>
,
autoderefs
:
usize
,
unsize
:
bool
,
self_ty
:
Ty
<
'tcx
>
,
opt_input_types
:
Option
<
Vec
<
Ty
<
'tcx
>>>
)
->
Option
<
MethodCallee
<
'tcx
>>
...
...
@@ -241,18 +241,15 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some
(
self_expr
)
=>
{
debug!
(
"lookup_in_trait_adjusted: inserting adjustment if needed
\
(self-id={}, base adjustment={:?}, explicit_self={:?})"
,
self_expr
.id
,
autoderefref
,
method_ty
.explicit_self
);
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})"
,
self_expr
.id
,
autoderefs
,
unsize
,
method_ty
.explicit_self
);
match
method_ty
.explicit_self
{
ty
::
ByValueExplicitSelfCategory
=>
{
// Trait method is fn(self), no transformation needed.
if
!
autoderefref
.is_identity
()
{
fcx
.write_adjustment
(
self_expr
.id
,
span
,
ty
::
AdjustDerefRef
(
autoderefref
));
}
assert
!
(
!
unsize
);
fcx
.write_autoderef_adjustment
(
self_expr
.id
,
autoderefs
);
}
ty
::
ByReferenceExplicitSelfCategory
(
..
)
=>
{
...
...
@@ -260,14 +257,15 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// autoref. Pull the region etc out of the type of first argument.
match
transformed_self_ty
.sty
{
ty
::
ty_rptr
(
region
,
ty
::
mt
{
mutbl
,
ty
:
_
})
=>
{
let
ty
::
AutoDerefRef
{
autoderefs
,
autoref
}
=
autoderefref
;
let
autoref
=
autoref
.map
(|
r
|
box
r
);
fcx
.write_adjustment
(
self_expr
.id
,
span
,
fcx
.write_adjustment
(
self_expr
.id
,
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
autoderefs
,
autoref
:
Some
(
ty
::
AutoPtr
(
*
region
,
mutbl
,
autoref
))
autoref
:
Some
(
ty
::
AutoPtr
(
region
,
mutbl
)),
unsize
:
if
unsize
{
Some
(
transformed_self_ty
)
}
else
{
None
}
}));
}
...
...
src/librustc_typeck/check/method/probe.rs
浏览文件 @
4e8e6414
...
...
@@ -31,7 +31,6 @@
use
util
::
ppaux
::
Repr
;
use
self
::
CandidateKind
::
*
;
pub
use
self
::
PickAdjustment
::
*
;
pub
use
self
::
PickKind
::
*
;
struct
ProbeContext
<
'a
,
'tcx
:
'a
>
{
...
...
@@ -49,7 +48,8 @@ struct ProbeContext<'a, 'tcx:'a> {
struct
CandidateStep
<
'tcx
>
{
self_ty
:
Ty
<
'tcx
>
,
adjustment
:
PickAdjustment
,
autoderefs
:
usize
,
unsize
:
bool
}
struct
Candidate
<
'tcx
>
{
...
...
@@ -70,8 +70,24 @@ enum CandidateKind<'tcx> {
pub
struct
Pick
<
'tcx
>
{
pub
method_ty
:
Rc
<
ty
::
Method
<
'tcx
>>
,
pub
adjustment
:
PickAdjustment
,
pub
kind
:
PickKind
<
'tcx
>
,
// Indicates that the source expression should be autoderef'd N times
//
// A = expr | *expr | **expr | ...
pub
autoderefs
:
usize
,
// Indicates that an autoref is applied after the optional autoderefs
//
// B = A | &A | &mut A
pub
autoref
:
Option
<
ast
::
Mutability
>
,
// Indicates that the source expression should be "unsized" to a
// target type. This should probably eventually go away in favor
// of just coercing method receivers.
//
// C = B | unsize(B)
pub
unsize
:
Option
<
Ty
<
'tcx
>>
,
}
#[derive(Clone,Debug)]
...
...
@@ -85,30 +101,6 @@ pub enum PickKind<'tcx> {
pub
type
PickResult
<
'tcx
>
=
Result
<
Pick
<
'tcx
>
,
MethodError
>
;
// This is a kind of "abstracted" version of ty::AutoAdjustment. The
// difference is that it doesn't embed any regions or other
// specifics. The "confirmation" step recreates those details as
// needed.
#[derive(Clone,Debug)]
pub
enum
PickAdjustment
{
// Indicates that the source expression should be autoderef'd N times
//
// A = expr | *expr | **expr
AutoDeref
(
usize
),
// Indicates that the source expression should be autoderef'd N
// times and then "unsized". This should probably eventually go
// away in favor of just coercing method receivers.
//
// A = unsize(expr | *expr | **expr)
AutoUnsizeLength
(
/* number of autoderefs */
usize
,
/* length*/
usize
),
// Indicates that an autoref is applied after some number of other adjustments
//
// A = &A | &mut A
AutoRef
(
ast
::
Mutability
,
Box
<
PickAdjustment
>
),
}
#[derive(PartialEq,
Eq,
Copy,
Clone)]
pub
enum
Mode
{
// An expression of the form `receiver.method_name(...)`.
...
...
@@ -149,7 +141,8 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
else
{
vec!
[
CandidateStep
{
self_ty
:
self_ty
,
adjustment
:
AutoDeref
(
0
)
autoderefs
:
0
,
unsize
:
false
}]
};
...
...
@@ -200,16 +193,21 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
UnresolvedTypeAction
::
Error
,
NoPreference
,
|
t
,
d
|
{
let
adjustment
=
AutoDeref
(
d
);
steps
.push
(
CandidateStep
{
self_ty
:
t
,
adjustment
:
adjustment
});
steps
.push
(
CandidateStep
{
self_ty
:
t
,
autoderefs
:
d
,
unsize
:
false
});
None
::
<
()
>
// keep iterating until we can't anymore
});
match
final_ty
.sty
{
ty
::
ty_vec
(
elem_ty
,
Some
(
len
))
=>
{
ty
::
ty_vec
(
elem_ty
,
Some
(
_
))
=>
{
let
slice_ty
=
ty
::
mk_vec
(
fcx
.tcx
(),
elem_ty
,
None
);
steps
.push
(
CandidateStep
{
self_ty
:
ty
::
mk_vec
(
fcx
.tcx
(),
elem_ty
,
None
),
adjustment
:
AutoUnsizeLength
(
dereferences
,
len
),
self_ty
:
slice_ty
,
autoderefs
:
dereferences
,
unsize
:
true
});
}
ty
::
ty_err
=>
return
None
,
...
...
@@ -926,20 +924,21 @@ fn pick_by_value_method(&mut self,
* consuming them for their entire lifetime.
*/
let
adjustment
=
match
step
.adjustment
{
AutoDeref
(
d
)
=>
consider_reborrow
(
step
.self_ty
,
d
),
AutoUnsizeLength
(
..
)
|
AutoRef
(
..
)
=>
step
.adjustment
.clone
(),
};
if
step
.unsize
{
return
None
;
}
return
self
.pick_method
(
step
.self_ty
)
.map
(|
r
|
self
.adjust
(
r
,
adjustment
.clone
()));
self
.pick_method
(
step
.self_ty
)
.map
(|
r
|
r
.map
(|
mut
pick
|
{
pick
.autoderefs
=
step
.autoderefs
;
fn
consider_reborrow
<
'tcx
>
(
ty
:
Ty
<
'tcx
>
,
d
:
usize
)
->
PickAdjustment
{
// Insert a `&*` or `&mut *` if this is a reference type:
match
ty
.sty
{
ty
::
ty_rptr
(
_
,
ref
mt
)
=>
AutoRef
(
mt
.mutbl
,
box
AutoDeref
(
d
+
1
)),
_
=>
AutoDeref
(
d
),
if
let
ty
::
ty_rptr
(
_
,
mt
)
=
step
.self_
ty.sty
{
pick
.autoderefs
+=
1
;
pick
.autoref
=
Some
(
mt
.mutbl
);
}
}
pick
}))
}
fn
pick_autorefd_method
(
&
mut
self
,
...
...
@@ -947,46 +946,28 @@ fn pick_autorefd_method(&mut self,
->
Option
<
PickResult
<
'tcx
>>
{
let
tcx
=
self
.tcx
();
self
.search_mutabilities
(
|
m
|
AutoRef
(
m
,
box
step
.adjustment
.clone
()),
|
m
,
r
|
ty
::
mk_rptr
(
tcx
,
tcx
.mk_region
(
r
),
ty
::
mt
{
ty
:
step
.self_ty
,
mutbl
:
m
}))
}
fn
search_mutabilities
<
F
,
G
>
(
&
mut
self
,
mut
mk_adjustment
:
F
,
mut
mk_autoref_ty
:
G
)
->
Option
<
PickResult
<
'tcx
>>
where
F
:
FnMut
(
ast
::
Mutability
)
->
PickAdjustment
,
G
:
FnMut
(
ast
::
Mutability
,
ty
::
Region
)
->
Ty
<
'tcx
>
,
{
// In general, during probing we erase regions. See
// `impl_self_ty()` for an explanation.
let
region
=
t
y
::
ReStatic
;
let
region
=
t
cx
.mk_region
(
ty
::
ReStatic
)
;
// Search through mutabilities in order to find one where pick works:
[
ast
::
MutImmutable
,
ast
::
MutMutable
]
.iter
()
.flat_map
(|
&
m
|
{
let
autoref_ty
=
mk_autoref_ty
(
m
,
region
);
self
.pick_method
(
autoref_ty
)
.map
(|
r
|
self
.adjust
(
r
,
mk_adjustment
(
m
)))
.into_iter
()
})
.nth
(
0
)
}
fn
adjust
(
&
mut
self
,
result
:
PickResult
<
'tcx
>
,
adjustment
:
PickAdjustment
)
->
PickResult
<
'tcx
>
{
match
result
{
Err
(
e
)
=>
Err
(
e
),
Ok
(
mut
pick
)
=>
{
pick
.adjustment
=
adjustment
;
Ok
(
pick
)
}
}
[
ast
::
MutImmutable
,
ast
::
MutMutable
]
.iter
()
.filter_map
(|
&
m
|
{
let
autoref_ty
=
ty
::
mk_rptr
(
tcx
,
region
,
ty
::
mt
{
ty
:
step
.self_ty
,
mutbl
:
m
});
self
.pick_method
(
autoref_ty
)
.map
(|
r
|
r
.map
(|
mut
pick
|
{
pick
.autoderefs
=
step
.autoderefs
;
pick
.autoref
=
Some
(
m
);
pick
.unsize
=
if
step
.unsize
{
Some
(
step
.self_ty
)
}
else
{
None
};
pick
}))
})
.nth
(
0
)
}
fn
pick_method
(
&
mut
self
,
self_ty
:
Ty
<
'tcx
>
)
->
Option
<
PickResult
<
'tcx
>>
{
...
...
@@ -1122,8 +1103,10 @@ fn collapse_candidates_to_trait_pick(&self,
let
method_ty
=
probes
[
0
]
.method_ty
.clone
();
Some
(
Pick
{
method_ty
:
method_ty
,
adjustment
:
AutoDeref
(
0
),
kind
:
TraitPick
(
trait_def_id
,
method_num
)
kind
:
TraitPick
(
trait_def_id
,
method_num
),
autoderefs
:
0
,
autoref
:
None
,
unsize
:
None
})
}
...
...
@@ -1296,7 +1279,6 @@ impl<'tcx> Candidate<'tcx> {
fn
to_unadjusted_pick
(
&
self
)
->
Pick
<
'tcx
>
{
Pick
{
method_ty
:
self
.method_ty
.clone
(),
adjustment
:
AutoDeref
(
0
),
kind
:
match
self
.kind
{
InherentImplCandidate
(
def_id
,
_
)
=>
{
InherentImplPick
(
def_id
)
...
...
@@ -1323,7 +1305,10 @@ fn to_unadjusted_pick(&self) -> Pick<'tcx> {
ProjectionCandidate
(
def_id
,
index
)
=>
{
TraitPick
(
def_id
,
index
)
}
}
},
autoderefs
:
0
,
autoref
:
None
,
unsize
:
None
}
}
...
...
@@ -1392,15 +1377,10 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
impl
<
'tcx
>
Repr
<
'tcx
>
for
CandidateStep
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ty
::
ctxt
<
'tcx
>
)
->
String
{
format!
(
"CandidateStep({},
{:?
})"
,
format!
(
"CandidateStep({},
autoderefs={}, unsize={
})"
,
self
.self_ty
.repr
(
tcx
),
self
.adjustment
)
}
}
impl
<
'tcx
>
Repr
<
'tcx
>
for
PickAdjustment
{
fn
repr
(
&
self
,
_
tcx
:
&
ty
::
ctxt
)
->
String
{
format!
(
"{:?}"
,
self
)
self
.autoderefs
,
self
.unsize
)
}
}
...
...
@@ -1412,9 +1392,12 @@ fn repr(&self, _tcx: &ty::ctxt) -> String {
impl
<
'tcx
>
Repr
<
'tcx
>
for
Pick
<
'tcx
>
{
fn
repr
(
&
self
,
tcx
:
&
ty
::
ctxt
<
'tcx
>
)
->
String
{
format!
(
"Pick(method_ty={}, adjustment={:?}, kind={:?})"
,
format!
(
"Pick(method_ty={}, autoderefs={},
autoref={}, unsize={}, kind={:?})"
,
self
.method_ty
.repr
(
tcx
),
self
.adjustment
,
self
.autoderefs
,
self
.autoref
.repr
(
tcx
),
self
.unsize
.repr
(
tcx
),
self
.kind
)
}
}
src/librustc_typeck/check/mod.rs
浏览文件 @
4e8e6414
...
...
@@ -1292,21 +1292,19 @@ pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
pub
fn
write_autoderef_adjustment
(
&
self
,
node_id
:
ast
::
NodeId
,
span
:
Span
,
derefs
:
usize
)
{
if
derefs
==
0
{
return
;
}
self
.write_adjustment
(
node_id
,
span
,
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
derefs
,
autoref
:
None
})
autoref
:
None
,
unsize
:
None
})
);
}
pub
fn
write_adjustment
(
&
self
,
node_id
:
ast
::
NodeId
,
span
:
Span
,
adj
:
ty
::
AutoAdjustment
<
'tcx
>
)
{
debug!
(
"write_adjustment(node_id={}, adj={})"
,
node_id
,
adj
.repr
(
self
.tcx
()));
...
...
@@ -1314,13 +1312,6 @@ pub fn write_adjustment(&self,
return
;
}
// Careful: adjustments can imply trait obligations if we are
// casting from a concrete type to an object type. I think
// it'd probably be nicer to move the logic that creates the
// obligation into the code that creates the adjustment, but
// that's a bit awkward, so instead we go digging and pull the
// obligation out here.
self
.register_adjustment_obligations
(
span
,
&
adj
);
self
.inh.adjustments
.borrow_mut
()
.insert
(
node_id
,
adj
);
}
...
...
@@ -1383,74 +1374,6 @@ fn normalize_associated_type(&self,
cause
)
}
fn
register_adjustment_obligations
(
&
self
,
span
:
Span
,
adj
:
&
ty
::
AutoAdjustment
<
'tcx
>
)
{
match
*
adj
{
ty
::
AdjustReifyFnPointer
(
..
)
=>
{
}
ty
::
AdjustUnsafeFnPointer
=>
{
}
ty
::
AdjustDerefRef
(
ref
d_r
)
=>
{
match
d_r
.autoref
{
Some
(
ref
a_r
)
=>
{
self
.register_autoref_obligations
(
span
,
a_r
);
}
None
=>
{}
}
}
}
}
fn
register_autoref_obligations
(
&
self
,
span
:
Span
,
autoref
:
&
ty
::
AutoRef
<
'tcx
>
)
{
match
*
autoref
{
ty
::
AutoUnsize
(
ref
unsize
)
=>
{
self
.register_unsize_obligations
(
span
,
unsize
);
}
ty
::
AutoPtr
(
_
,
_
,
None
)
|
ty
::
AutoUnsafe
(
_
,
None
)
=>
{
}
ty
::
AutoPtr
(
_
,
_
,
Some
(
ref
a_r
))
|
ty
::
AutoUnsafe
(
_
,
Some
(
ref
a_r
))
=>
{
self
.register_autoref_obligations
(
span
,
&**
a_r
)
}
ty
::
AutoUnsizeUniq
(
ref
unsize
)
=>
{
self
.register_unsize_obligations
(
span
,
unsize
);
}
}
}
fn
register_unsize_obligations
(
&
self
,
span
:
Span
,
unsize
:
&
ty
::
UnsizeKind
<
'tcx
>
)
{
debug!
(
"register_unsize_obligations: unsize={:?}"
,
unsize
);
match
*
unsize
{
ty
::
UnsizeLength
(
..
)
=>
{}
ty
::
UnsizeStruct
(
ref
u
,
_
)
=>
{
self
.register_unsize_obligations
(
span
,
&**
u
)
}
ty
::
UnsizeVtable
(
ref
ty_trait
,
self_ty
)
=>
{
vtable
::
check_object_safety
(
self
.tcx
(),
ty_trait
,
span
);
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` implements `Foo`:
vtable
::
register_object_cast_obligations
(
self
,
span
,
ty_trait
,
self_ty
);
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`:
let
cause
=
traits
::
ObligationCause
{
span
:
span
,
body_id
:
self
.body_id
,
code
:
traits
::
ObjectCastObligation
(
self_ty
)
};
self
.register_region_obligation
(
self_ty
,
ty_trait
.bounds.region_bound
,
cause
);
}
ty
::
UnsizeUpcast
(
_
)
=>
{
}
}
}
/// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
/// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
/// Registers any trait obligations specified on `def_id` at the same time.
...
...
@@ -1881,7 +1804,8 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
let
mt
=
match
ty
::
deref
(
resolved_t
,
false
)
{
Some
(
mt
)
=>
Some
(
mt
),
None
=>
{
let
method_call
=
opt_expr
.map
(|
expr
|
MethodCall
::
autoderef
(
expr
.id
,
autoderefs
));
let
method_call
=
opt_expr
.map
(|
expr
|
MethodCall
::
autoderef
(
expr
.id
,
autoderefs
as
u32
));
// Super subtle: it might seem as though we should
// pass `opt_expr` to `try_overloaded_deref`, so that
...
...
@@ -1972,13 +1896,13 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
fn
autoderef_for_index
<
'a
,
'tcx
,
T
,
F
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
base_
expr
:
&
ast
::
Expr
,
base_ty
:
Ty
<
'tcx
>
,
lvalue_pref
:
LvaluePreference
,
mut
step
:
F
)
->
Option
<
T
>
where
F
:
FnMut
(
Ty
<
'tcx
>
,
ty
::
AutoDerefRef
<
'tcx
>
)
->
Option
<
T
>
,
fn
lookup_indexing
<
'a
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
expr
:
&
ast
::
Expr
,
base_expr
:
&
'tcx
ast
::
Expr
,
base_ty
:
Ty
<
'tcx
>
,
idx_ty
:
Ty
<
'tcx
>
,
lvalue_pref
:
LvaluePreference
)
->
Option
<
(
/*index type*/
Ty
<
'tcx
>
,
/*element type*/
Ty
<
'tcx
>
)
>
{
// FIXME(#18741) -- this is almost but not quite the same as the
// autoderef that normal method probing does. They could likely be
...
...
@@ -1991,9 +1915,9 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
UnresolvedTypeAction
::
Error
,
lvalue_pref
,
|
adj_ty
,
idx
|
{
let
autoderefref
=
ty
::
AutoDerefRef
{
autoderefs
:
idx
,
autoref
:
None
};
step
(
adj_ty
,
autoderefref
)
});
try_index_step
(
fcx
,
MethodCall
::
expr
(
expr
.id
),
expr
,
base_expr
,
adj_ty
,
idx
,
false
,
lvalue_pref
,
idx_ty
)
});
if
final_mt
.is_some
()
{
return
final_mt
;
...
...
@@ -2001,41 +1925,38 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
// After we have fully autoderef'd, if the resulting type is [T, ..n], then
// do a final unsized coercion to yield [T].
match
ty
.sty
{
ty
::
ty_vec
(
element_ty
,
Some
(
n
))
=>
{
let
adjusted_ty
=
ty
::
mk_vec
(
fcx
.tcx
(),
element_ty
,
None
);
let
autoderefref
=
ty
::
AutoDerefRef
{
autoderefs
:
autoderefs
,
autoref
:
Some
(
ty
::
AutoUnsize
(
ty
::
UnsizeLength
(
n
)))
};
step
(
adjusted_ty
,
autoderefref
)
}
_
=>
{
None
}
if
let
ty
::
ty_vec
(
element_ty
,
Some
(
_
))
=
ty
.sty
{
let
adjusted_ty
=
ty
::
mk_vec
(
fcx
.tcx
(),
element_ty
,
None
);
try_index_step
(
fcx
,
MethodCall
::
expr
(
expr
.id
),
expr
,
base_expr
,
adjusted_ty
,
autoderefs
,
true
,
lvalue_pref
,
idx_ty
)
}
else
{
None
}
}
/// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
/// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
/// This loop implements one step in that search; the autoderef loop is implemented by
/// `
autoderef_for_index
`.
/// `
lookup_indexing
`.
fn
try_index_step
<
'a
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
method_call
:
MethodCall
,
expr
:
&
ast
::
Expr
,
base_expr
:
&
'tcx
ast
::
Expr
,
adjusted_ty
:
Ty
<
'tcx
>
,
adjustment
:
ty
::
AutoDerefRef
<
'tcx
>
,
autoderefs
:
usize
,
unsize
:
bool
,
lvalue_pref
:
LvaluePreference
,
index_ty
:
Ty
<
'tcx
>
)
->
Option
<
(
/*index type*/
Ty
<
'tcx
>
,
/*element type*/
Ty
<
'tcx
>
)
>
{
let
tcx
=
fcx
.tcx
();
debug!
(
"try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})"
,
debug!
(
"try_index_step(expr={}, base_expr.id={}, adjusted_ty={},
\
autoderefs={}, unsize={}, index_ty={})"
,
expr
.repr
(
tcx
),
base_expr
.repr
(
tcx
),
adjusted_ty
.repr
(
tcx
),
adjustment
,
autoderefs
,
unsize
,
index_ty
.repr
(
tcx
));
let
input_ty
=
fcx
.infcx
()
.next_ty_var
();
...
...
@@ -2044,7 +1965,9 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
match
(
ty
::
index
(
adjusted_ty
),
&
index_ty
.sty
)
{
(
Some
(
ty
),
&
ty
::
ty_uint
(
ast
::
TyUs
))
|
(
Some
(
ty
),
&
ty
::
ty_infer
(
ty
::
IntVar
(
_
)))
=>
{
debug!
(
"try_index_step: success, using built-in indexing"
);
fcx
.write_adjustment
(
base_expr
.id
,
base_expr
.span
,
ty
::
AdjustDerefRef
(
adjustment
));
// If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
assert
!
(
!
unsize
);
fcx
.write_autoderef_adjustment
(
base_expr
.id
,
autoderefs
);
return
Some
((
tcx
.types.usize
,
ty
));
}
_
=>
{}
...
...
@@ -2058,7 +1981,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some
(
&*
base_expr
),
token
::
intern
(
"index_mut"
),
trait_did
,
adjustment
.clone
(),
autoderefs
,
unsize
,
adjusted_ty
,
Some
(
vec!
[
input_ty
]))
}
...
...
@@ -2073,7 +1997,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some
(
&*
base_expr
),
token
::
intern
(
"index"
),
trait_did
,
adjustment
.clone
(),
autoderefs
,
unsize
,
adjusted_ty
,
Some
(
vec!
[
input_ty
]))
}
...
...
@@ -2662,7 +2587,7 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
match
field_ty
{
Some
(
field_ty
)
=>
{
fcx
.write_ty
(
expr
.id
,
field_ty
);
fcx
.write_autoderef_adjustment
(
base
.id
,
base
.span
,
autoderefs
);
fcx
.write_autoderef_adjustment
(
base
.id
,
autoderefs
);
return
;
}
None
=>
{}
...
...
@@ -2773,7 +2698,7 @@ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
match
field_ty
{
Some
(
field_ty
)
=>
{
fcx
.write_ty
(
expr
.id
,
field_ty
);
fcx
.write_autoderef_adjustment
(
base
.id
,
base
.span
,
autoderefs
);
fcx
.write_autoderef_adjustment
(
base
.id
,
autoderefs
);
return
;
}
None
=>
{}
...
...
@@ -3600,26 +3525,13 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
fcx
.write_ty
(
id
,
idx_t
);
}
else
{
let
base_t
=
structurally_resolved_type
(
fcx
,
expr
.span
,
base_t
);
let
result
=
autoderef_for_index
(
fcx
,
&**
base
,
base_t
,
lvalue_pref
,
|
adj_ty
,
adj
|
{
try_index_step
(
fcx
,
MethodCall
::
expr
(
expr
.id
),
expr
,
&**
base
,
adj_ty
,
adj
,
lvalue_pref
,
idx_t
)
});
match
result
{
match
lookup_indexing
(
fcx
,
expr
,
base
,
base_t
,
idx_t
,
lvalue_pref
)
{
Some
((
index_ty
,
element_ty
))
=>
{
let
idx_expr_ty
=
fcx
.expr_ty
(
idx
);
demand
::
eqtype
(
fcx
,
expr
.span
,
index_ty
,
idx_expr_ty
);
fcx
.write_ty
(
id
,
element_ty
);
}
_
=>
{
None
=>
{
check_expr_has_type
(
fcx
,
&**
idx
,
fcx
.tcx
()
.types.err
);
fcx
.type_error_message
(
expr
.span
,
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
4e8e6414
...
...
@@ -499,10 +499,10 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
if
let
Some
(
adjustment
)
=
rcx
.fcx.inh.adjustments
.borrow
()
.get
(
&
expr
.id
)
{
debug!
(
"adjustment={:?}"
,
adjustment
);
match
*
adjustment
{
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
,
autoref
:
ref
opt_autoref
})
=>
{
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
,
ref
autoref
,
..
})
=>
{
let
expr_ty
=
rcx
.resolve_node_type
(
expr
.id
);
constrain_autoderefs
(
rcx
,
expr
,
autoderefs
,
expr_ty
);
if
let
Some
(
ref
autoref
)
=
*
opt_
autoref
{
if
let
Some
(
ref
autoref
)
=
*
autoref
{
link_autoref
(
rcx
,
expr
,
autoderefs
,
autoref
);
// Require that the resulting region encompasses
...
...
@@ -872,7 +872,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
let
r_deref_expr
=
ty
::
ReScope
(
CodeExtent
::
from_node_id
(
deref_expr
.id
));
for
i
in
0
..
derefs
{
let
method_call
=
MethodCall
::
autoderef
(
deref_expr
.id
,
i
);
let
method_call
=
MethodCall
::
autoderef
(
deref_expr
.id
,
i
as
u32
);
debug!
(
"constrain_autoderefs: method_call={:?} (of {:?} total)"
,
method_call
,
derefs
);
derefd_ty
=
match
rcx
.fcx.inh.method_map
.borrow
()
.get
(
&
method_call
)
{
...
...
@@ -904,7 +904,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
let
self_cmt
=
ignore_err!
(
mc
.cat_expr_autoderefd
(
deref_expr
,
i
));
debug!
(
"constrain_autoderefs: self_cmt={:?}"
,
self_cmt
.repr
(
rcx
.tcx
()));
link_region
(
rcx
,
deref_expr
.span
,
*
r
,
link_region
(
rcx
,
deref_expr
.span
,
r
,
ty
::
BorrowKind
::
from_mutbl
(
m
),
self_cmt
);
}
...
...
@@ -1102,7 +1102,7 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
ast
::
PatVec
(
_
,
Some
(
ref
slice_pat
),
_
)
=>
{
match
mc
.cat_slice_pattern
(
sub_cmt
,
&**
slice_pat
)
{
Ok
((
slice_cmt
,
slice_mutbl
,
slice_r
))
=>
{
link_region
(
rcx
,
sub_pat
.span
,
slice_r
,
link_region
(
rcx
,
sub_pat
.span
,
&
slice_r
,
ty
::
BorrowKind
::
from_mutbl
(
slice_mutbl
),
slice_cmt
);
}
...
...
@@ -1127,16 +1127,15 @@ fn link_autoref(rcx: &Rcx,
debug!
(
"expr_cmt={}"
,
expr_cmt
.repr
(
rcx
.tcx
()));
match
*
autoref
{
ty
::
AutoPtr
(
r
,
m
,
_
)
=>
{
link_region
(
rcx
,
expr
.span
,
r
,
ty
::
BorrowKind
::
from_mutbl
(
m
),
expr_cmt
);
ty
::
AutoPtr
(
r
,
m
)
=>
{
link_region
(
rcx
,
expr
.span
,
r
,
ty
::
BorrowKind
::
from_mutbl
(
m
),
expr_cmt
);
}
ty
::
AutoUnsafe
(
m
,
_
)
=>
{
ty
::
AutoUnsafe
(
m
)
=>
{
let
r
=
ty
::
ReScope
(
CodeExtent
::
from_node_id
(
expr
.id
));
link_region
(
rcx
,
expr
.span
,
r
,
ty
::
BorrowKind
::
from_mutbl
(
m
),
expr_cmt
);
}
ty
::
AutoUnsizeUniq
(
_
)
|
ty
::
AutoUnsize
(
_
)
=>
{}
}
}
...
...
@@ -1151,7 +1150,7 @@ fn link_by_ref(rcx: &Rcx,
let
mc
=
mc
::
MemCategorizationContext
::
new
(
rcx
.fcx
);
let
expr_cmt
=
ignore_err!
(
mc
.cat_expr
(
expr
));
let
borrow_region
=
ty
::
ReScope
(
callee_scope
);
link_region
(
rcx
,
expr
.span
,
borrow_region
,
ty
::
ImmBorrow
,
expr_cmt
);
link_region
(
rcx
,
expr
.span
,
&
borrow_region
,
ty
::
ImmBorrow
,
expr_cmt
);
}
/// Like `link_region()`, except that the region is extracted from the type of `id`, which must be
...
...
@@ -1169,7 +1168,7 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
let
tcx
=
rcx
.fcx.ccx.tcx
;
debug!
(
"rptr_ty={}"
,
ty_to_string
(
tcx
,
rptr_ty
));
let
r
=
ty
::
ty_region
(
tcx
,
span
,
rptr_ty
);
link_region
(
rcx
,
span
,
r
,
ty
::
BorrowKind
::
from_mutbl
(
mutbl
),
link_region
(
rcx
,
span
,
&
r
,
ty
::
BorrowKind
::
from_mutbl
(
mutbl
),
cmt_borrowed
);
}
}
...
...
@@ -1179,7 +1178,7 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
/// between regions, as explained in `link_reborrowed_region()`.
fn
link_region
<
'a
,
'tcx
>
(
rcx
:
&
Rcx
<
'a
,
'tcx
>
,
span
:
Span
,
borrow_region
:
ty
::
Region
,
borrow_region
:
&
ty
::
Region
,
borrow_kind
:
ty
::
BorrowKind
,
borrow_cmt
:
mc
::
cmt
<
'tcx
>
)
{
let
mut
borrow_cmt
=
borrow_cmt
;
...
...
@@ -1273,7 +1272,7 @@ fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
/// recurse and process `ref_cmt` (see case 2 above).
fn
link_reborrowed_region
<
'a
,
'tcx
>
(
rcx
:
&
Rcx
<
'a
,
'tcx
>
,
span
:
Span
,
borrow_region
:
ty
::
Region
,
borrow_region
:
&
ty
::
Region
,
borrow_kind
:
ty
::
BorrowKind
,
ref_cmt
:
mc
::
cmt
<
'tcx
>
,
ref_region
:
ty
::
Region
,
...
...
@@ -1318,7 +1317,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
debug!
(
"link_reborrowed_region: {} <= {}"
,
borrow_region
.repr
(
rcx
.tcx
()),
ref_region
.repr
(
rcx
.tcx
()));
rcx
.fcx
.mk_subr
(
cause
,
borrow_region
,
ref_region
);
rcx
.fcx
.mk_subr
(
cause
,
*
borrow_region
,
ref_region
);
// If we end up needing to recurse and establish a region link
// with `ref_cmt`, calculate what borrow kind we will end up
...
...
src/librustc_typeck/check/vtable.rs
浏览文件 @
4e8e6414
...
...
@@ -15,7 +15,6 @@
use
middle
::
ty
::{
self
,
Ty
,
AsPredicate
};
use
syntax
::
ast
;
use
syntax
::
codemap
::
Span
;
use
util
::
nodemap
::
FnvHashSet
;
use
util
::
ppaux
::{
Repr
,
UserString
};
...
...
@@ -133,46 +132,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fcx
.register_predicate
(
projection_obligation
);
}
// Finally, check that there IS a projection predicate for every associated type.
check_object_type_binds_all_associated_types
(
fcx
.tcx
(),
span
,
object_trait
);
object_trait_ref
}
fn
check_object_type_binds_all_associated_types
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
span
:
Span
,
object_trait
:
&
ty
::
TyTrait
<
'tcx
>
)
{
let
object_trait_ref
=
object_trait
.principal_trait_ref_with_self_ty
(
tcx
,
tcx
.types.err
);
let
mut
associated_types
:
FnvHashSet
<
(
ast
::
DefId
,
ast
::
Name
)
>
=
traits
::
supertraits
(
tcx
,
object_trait_ref
.clone
())
.flat_map
(|
tr
|
{
let
trait_def
=
ty
::
lookup_trait_def
(
tcx
,
tr
.def_id
());
trait_def
.associated_type_names
.clone
()
.into_iter
()
.map
(
move
|
associated_type_name
|
(
tr
.def_id
(),
associated_type_name
))
})
.collect
();
for
projection_bound
in
&
object_trait
.bounds.projection_bounds
{
let
pair
=
(
projection_bound
.0
.projection_ty.trait_ref.def_id
,
projection_bound
.0
.projection_ty.item_name
);
associated_types
.remove
(
&
pair
);
}
for
(
trait_def_id
,
name
)
in
associated_types
{
span_err!
(
tcx
.sess
,
span
,
E0191
,
"the value of the associated type `{}` (from the trait `{}`) must be specified"
,
name
.user_string
(
tcx
),
ty
::
item_path_str
(
tcx
,
trait_def_id
));
}
}
pub
fn
select_all_fcx_obligations_and_apply_defaults
(
fcx
:
&
FnCtxt
)
{
debug!
(
"select_all_fcx_obligations_and_apply_defaults"
);
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
4e8e6414
...
...
@@ -285,11 +285,8 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
}
Some
(
adjustment
)
=>
{
let
adj_object
=
ty
::
adjust_is_object
(
&
adjustment
);
let
resolved_adjustment
=
match
adjustment
{
ty
::
AdjustReifyFnPointer
(
def_id
)
=>
{
ty
::
AdjustReifyFnPointer
(
def_id
)
}
ty
::
AdjustReifyFnPointer
=>
ty
::
AdjustReifyFnPointer
,
ty
::
AdjustUnsafeFnPointer
=>
{
ty
::
AdjustUnsafeFnPointer
...
...
@@ -297,18 +294,14 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
ty
::
AdjustDerefRef
(
adj
)
=>
{
for
autoderef
in
0
..
adj
.autoderefs
{
let
method_call
=
MethodCall
::
autoderef
(
id
,
autoderef
);
self
.visit_method_map_entry
(
reason
,
method_call
);
}
if
adj_object
{
let
method_call
=
MethodCall
::
autoobject
(
id
);
let
method_call
=
MethodCall
::
autoderef
(
id
,
autoderef
as
u32
);
self
.visit_method_map_entry
(
reason
,
method_call
);
}
ty
::
AdjustDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
adj
.autoderefs
,
autoref
:
self
.resolve
(
&
adj
.autoref
,
reason
),
unsize
:
self
.resolve
(
&
adj
.unsize
,
reason
),
})
}
};
...
...
src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs
浏览文件 @
4e8e6414
...
...
@@ -34,6 +34,8 @@ fn dent<C:BoxCar>(c: C, color: C::Color) {
fn
dent_object
<
COLOR
>
(
c
:
BoxCar
<
Color
=
COLOR
>
)
{
//~^ ERROR ambiguous associated type
//~| ERROR the associated type `Color` (from the trait `Box`) must be specified
//~| ERROR the associated type `Color` (from the trait `Vehicle`) must be specified
}
fn
paint
<
C
:
BoxCar
>
(
c
:
C
,
d
:
C
::
Color
)
{
...
...
src/test/compile-fail/issue-18819.rs
浏览文件 @
4e8e6414
...
...
@@ -20,7 +20,7 @@ impl Foo for X {
type
Item
=
bool
;
}
fn
print_x
(
_
:
&
Foo
,
extra
:
&
str
)
{
fn
print_x
(
_
:
&
Foo
<
Item
=
bool
>
,
extra
:
&
str
)
{
println!
(
"{}"
,
extra
);
}
...
...
src/test/
run-pass/issue-19121
.rs
→
src/test/
compile-fail/issue-19482
.rs
浏览文件 @
4e8e6414
// Copyright 201
4
The Rust Project Developers. See the COPYRIGHT
// Copyright 201
5
The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
...
...
@@ -9,7 +9,7 @@
// except according to those terms.
// Test that a partially specified trait object with unspecified associated
// type does not
ICE
.
// type does not
type-check
.
// pretty-expanded FIXME #23616
...
...
@@ -20,7 +20,6 @@ fn dummy(&self) { }
}
fn
bar
(
x
:
&
Foo
)
{}
// FIXME(#19482) -- `Foo` should specify `A`, but this is not
// currently enforced except at object creation
//~^ ERROR the associated type `A` (from the trait `Foo`) must be specified
pub
fn
main
()
{}
src/test/compile-fail/retslot-cast.rs
浏览文件 @
4e8e6414
...
...
@@ -11,7 +11,8 @@
#![feature(rustc_attrs)]
#![allow(warnings)]
pub
fn
fail
(
x
:
Option
<&
(
Iterator
+
Send
)
>
)
->
Option
<&
Iterator
>
{
pub
fn
fail
(
x
:
Option
<&
(
Iterator
<
Item
=
()
>+
Send
)
>
)
->
Option
<&
Iterator
<
Item
=
()
>>
{
// This call used to trigger an LLVM assertion because the return
// slot had type "Option<&Iterator>"* instead of
// "Option<&(Iterator+Send)>"* -- but this now yields a
...
...
@@ -23,7 +24,8 @@ pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> {
inner
(
x
)
//~ ERROR mismatched types
}
pub
fn
inner
(
x
:
Option
<&
(
Iterator
+
Send
)
>
)
->
Option
<&
(
Iterator
+
Send
)
>
{
pub
fn
inner
(
x
:
Option
<&
(
Iterator
<
Item
=
()
>+
Send
)
>
)
->
Option
<&
(
Iterator
<
Item
=
()
>+
Send
)
>
{
x
}
...
...
src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
浏览文件 @
4e8e6414
...
...
@@ -11,7 +11,7 @@
// Test that the `Fn` traits require `()` form without a feature gate.
fn
bar1
(
x
:
&
Fn
<
()
>
)
{
fn
bar1
(
x
:
&
Fn
<
()
,
Output
=
()
>
)
{
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录