Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
e9ac7489
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,发现更多精彩内容 >>
提交
e9ac7489
编写于
8月 28, 2012
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor representation of borrowing so that it is tracked by fn_ctxt and not infer
上级
e398a72c
变更
10
展开全部
隐藏空白更改
内联
并排
Showing
10 changed file
with
514 addition
and
486 deletion
+514
-486
src/libstd/test.rs
src/libstd/test.rs
+1
-0
src/rustc/middle/typeck/check.rs
src/rustc/middle/typeck/check.rs
+220
-192
src/rustc/middle/typeck/check/alt.rs
src/rustc/middle/typeck/check/alt.rs
+15
-14
src/rustc/middle/typeck/check/demand.rs
src/rustc/middle/typeck/check/demand.rs
+6
-6
src/rustc/middle/typeck/check/method.rs
src/rustc/middle/typeck/check/method.rs
+38
-50
src/rustc/middle/typeck/check/regionck.rs
src/rustc/middle/typeck/check/regionck.rs
+3
-3
src/rustc/middle/typeck/check/vtable.rs
src/rustc/middle/typeck/check/vtable.rs
+16
-15
src/rustc/middle/typeck/check/writeback.rs
src/rustc/middle/typeck/check/writeback.rs
+63
-39
src/rustc/middle/typeck/infer.rs
src/rustc/middle/typeck/infer.rs
+37
-56
src/rustc/middle/typeck/infer/assignment.rs
src/rustc/middle/typeck/infer/assignment.rs
+115
-111
未找到文件。
src/libstd/test.rs
浏览文件 @
e9ac7489
...
...
@@ -106,6 +106,7 @@ fn run_tests_console(opts: test_opts,
tests
:
~
[
test_desc
])
->
bool
{
fn
callback
(
event
:
testevent
,
st
:
console_test_state
)
{
debug!
(
"callback(event=%?)"
,
event
);
match
event
{
te_filtered
(
filtered_tests
)
=>
{
st
.total
=
vec
::
len
(
filtered_tests
);
...
...
src/rustc/middle/typeck/check.rs
浏览文件 @
e9ac7489
此差异已折叠。
点击以展开。
src/rustc/middle/typeck/check/alt.rs
浏览文件 @
e9ac7489
...
...
@@ -7,7 +7,7 @@ fn check_alt(fcx: @fn_ctxt,
let
tcx
=
fcx
.ccx.tcx
;
let
mut
bot
;
let
pattern_ty
=
fcx
.infcx
.next_ty_var
();
let
pattern_ty
=
fcx
.infcx
()
.next_ty_var
();
bot
=
check_expr_with
(
fcx
,
discrim
,
pattern_ty
);
let
is_lvalue
=
ty
::
expr_is_lval
(
fcx
.ccx.method_map
,
discrim
);
...
...
@@ -30,7 +30,7 @@ fn check_alt(fcx: @fn_ctxt,
for
arm
.pats.each
|
p
|
{
check_pat
(
pcx
,
p
,
pattern_ty
);}
}
// Now typecheck the blocks.
let
mut
result_ty
=
fcx
.infcx
.next_ty_var
();
let
mut
result_ty
=
fcx
.infcx
()
.next_ty_var
();
let
mut
arm_non_bot
=
false
;
for
arms
.each
|
arm
|
{
match
arm
.guard
{
...
...
@@ -128,7 +128,7 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
tcx
.sess
.span_fatal
(
pat
.span
,
fmt!
(
"mismatched types: expected enum but found `%s`"
,
fcx
.infcx
.ty_to_str
(
expected
)));
fcx
.infcx
()
.ty_to_str
(
expected
)));
}
}
}
...
...
@@ -151,14 +151,15 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
check_expr_with
(
fcx
,
begin
,
expected
);
check_expr_with
(
fcx
,
end
,
expected
);
let
b_ty
=
fcx
.infcx
.resolve_type_vars_if_possible
(
fcx
.expr_ty
(
begin
));
fcx
.infcx
()
.resolve_type_vars_if_possible
(
fcx
.expr_ty
(
begin
));
let
e_ty
=
fcx
.infcx
.resolve_type_vars_if_possible
(
fcx
.expr_ty
(
end
));
fcx
.infcx
()
.resolve_type_vars_if_possible
(
fcx
.expr_ty
(
end
));
debug!
(
"pat_range beginning type: %?"
,
b_ty
);
debug!
(
"pat_range ending type: %?"
,
e_ty
);
if
!
require_same_types
(
tcx
,
Some
(
fcx
.infcx
),
false
,
pat
.span
,
b_ty
,
e_ty
,
||
~
"mismatched types in range"
)
{
tcx
,
Some
(
fcx
.infcx
()),
false
,
pat
.span
,
b_ty
,
e_ty
,
||
~
"mismatched types in range"
)
{
// no-op
}
else
if
!
ty
::
type_is_numeric
(
b_ty
)
{
tcx
.sess
.span_err
(
pat
.span
,
~
"non-numeric type used in range"
);
...
...
@@ -180,7 +181,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
// then the type of x is &M T where M is the mutability
// and T is the expected type
let
region_var
=
fcx
.infcx
.next_region_var_with_lb
(
fcx
.infcx
()
.next_region_var_with_lb
(
pat
.span
,
pcx
.block_region
);
let
mt
=
{
ty
:
expected
,
mutbl
:
mutbl
};
let
region_ty
=
ty
::
mk_rptr
(
tcx
,
region_var
,
mt
);
...
...
@@ -241,7 +242,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_fatal
(
pat
.span
,
fmt!
(
"mismatched types: expected `%s` but found record"
,
fcx
.infcx
.ty_to_str
(
expected
)));
fcx
.infcx
()
.ty_to_str
(
expected
)));
}
};
let
f_count
=
vec
::
len
(
fields
);
...
...
@@ -284,7 +285,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_fatal
(
pat
.span
,
fmt!
(
"mismatched types: expected `%s`
\
but found struct"
,
fcx
.infcx
.ty_to_str
(
expected
)));
fcx
.infcx
()
.ty_to_str
(
expected
)));
}
}
...
...
@@ -299,7 +300,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_err
(
pat
.span
,
fmt!
(
"mismatched types: expected `%s` but
\
found `%s`"
,
fcx
.infcx
.ty_to_str
(
expected
),
fcx
.infcx
()
.ty_to_str
(
expected
),
name
));
}
_
=>
{
...
...
@@ -364,7 +365,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_fatal
(
pat
.span
,
fmt!
(
"mismatched types: expected `%s`, found tuple"
,
fcx
.infcx
.ty_to_str
(
expected
)));
fcx
.infcx
()
.ty_to_str
(
expected
)));
}
};
let
e_count
=
vec
::
len
(
elts
);
...
...
@@ -392,7 +393,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_fatal
(
pat
.span
,
~
"mismatched types: expected `"
+
fcx
.infcx
.ty_to_str
(
expected
)
+
fcx
.infcx
()
.ty_to_str
(
expected
)
+
~
"` found box"
);
}
}
...
...
@@ -407,7 +408,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx
.sess
.span_fatal
(
pat
.span
,
~
"mismatched types: expected `"
+
fcx
.infcx
.ty_to_str
(
expected
)
+
fcx
.infcx
()
.ty_to_str
(
expected
)
+
~
"` found uniq"
);
}
}
...
...
src/rustc/middle/typeck/check/demand.rs
浏览文件 @
e9ac7489
...
...
@@ -6,7 +6,7 @@ fn suptype(fcx: @fn_ctxt, sp: span,
expected
:
ty
::
t
,
actual
:
ty
::
t
)
{
// n.b.: order of actual, expected is reversed
match
infer
::
mk_subty
(
fcx
.infcx
,
false
,
sp
,
match
infer
::
mk_subty
(
fcx
.infcx
()
,
false
,
sp
,
actual
,
expected
)
{
result
::
Ok
(())
=>
{
/* ok */
}
result
::
Err
(
ref
err
)
=>
{
...
...
@@ -18,11 +18,11 @@ fn suptype(fcx: @fn_ctxt, sp: span,
fn
eqtype
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
expected
:
ty
::
t
,
actual
:
ty
::
t
)
{
match
infer
::
mk_eqty
(
fcx
.infcx
,
false
,
sp
,
actual
,
expected
)
{
result
::
Ok
(())
=>
{
/* ok */
}
result
::
Err
(
ref
err
)
=>
{
fcx
.report_mismatched_types
(
sp
,
expected
,
actual
,
err
);
}
match
infer
::
mk_eqty
(
fcx
.infcx
()
,
false
,
sp
,
actual
,
expected
)
{
Ok
(())
=>
{
/* ok */
}
Err
(
ref
err
)
=>
{
fcx
.report_mismatched_types
(
sp
,
expected
,
actual
,
err
);
}
}
}
...
...
src/rustc/middle/typeck/check/method.rs
浏览文件 @
e9ac7489
...
...
@@ -108,14 +108,14 @@ struct lookup {
fn
method
()
->
Option
<
method_map_entry
>
{
debug!
(
"method lookup(m_name=%s, self_ty=%s, %?)"
,
self
.fcx
.tcx
()
.sess
.str_of
(
self
.m_name
),
self
.fcx.infcx
.ty_to_str
(
self
.self_ty
),
self
.fcx
.infcx
()
.ty_to_str
(
self
.self_ty
),
ty
::
get
(
self
.self_ty
)
.struct
);
// Determine if there are any inherent methods we can call.
// (An inherent method is one that belongs to no trait, but is
// inherent to a class or impl.)
let
optional_inherent_methods
;
match
get_base_type_def_id
(
self
.fcx.infcx
,
match
get_base_type_def_id
(
self
.fcx
.infcx
()
,
self
.self_expr.span
,
self
.self_ty
)
{
None
=>
{
...
...
@@ -438,35 +438,27 @@ fn check_type_match(impl_ty: ty::t,
// Depending on our argument, we find potential matches by
// checking subtypability, type assignability, or reference
// subtypability. Collect the matches.
let
matches
;
match
mode
{
subtyping_mode
=>
{
matches
=
self
.fcx
.can_mk_subty
(
self
.self_ty
,
impl_ty
);
}
assignability_mode
=>
{
matches
=
self
.fcx
.can_mk_assignty
(
self
.self_expr
,
self
.borrow_lb
,
self
.self_ty
,
impl_ty
);
}
immutable_reference_mode
=>
{
let
region
=
self
.fcx.infcx
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
let
tm
=
{
ty
:
self
.self_ty
,
mutbl
:
ast
::
m_imm
};
let
ref_ty
=
ty
::
mk_rptr
(
self
.tcx
(),
region
,
tm
);
matches
=
self
.fcx
.can_mk_subty
(
ref_ty
,
impl_ty
);
}
mutable_reference_mode
=>
{
let
region
=
self
.fcx.infcx
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
let
tm
=
{
ty
:
self
.self_ty
,
mutbl
:
ast
::
m_mutbl
};
let
ref_ty
=
ty
::
mk_rptr
(
self
.tcx
(),
region
,
tm
);
matches
=
self
.fcx
.can_mk_subty
(
ref_ty
,
impl_ty
);
}
subtyping_mode
=>
self
.fcx
.can_mk_subty
(
self
.self_ty
,
impl_ty
),
assignability_mode
=>
self
.fcx
.can_mk_assignty
(
self
.self_ty
,
impl_ty
),
immutable_reference_mode
=>
{
let
region
=
self
.fcx
.infcx
()
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
let
tm
=
{
ty
:
self
.self_ty
,
mutbl
:
ast
::
m_imm
};
let
ref_ty
=
ty
::
mk_rptr
(
self
.tcx
(),
region
,
tm
);
self
.fcx
.can_mk_subty
(
ref_ty
,
impl_ty
)
}
mutable_reference_mode
=>
{
let
region
=
self
.fcx
.infcx
()
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
let
tm
=
{
ty
:
self
.self_ty
,
mutbl
:
ast
::
m_mutbl
};
let
ref_ty
=
ty
::
mk_rptr
(
self
.tcx
(),
region
,
tm
);
self
.fcx
.can_mk_subty
(
ref_ty
,
impl_ty
)
}
}
matches
}
// Returns true if any were added and false otherwise.
...
...
@@ -530,7 +522,7 @@ fn add_candidates_from_m(inner_ty: ty::t,
None
=>
{
match
m
.self_ty
{
ast
::
sty_region
(
_
)
=>
Some
(
self
.fcx.infcx
.next_region_var
(
Some
(
self
.fcx
.infcx
()
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
)),
_
=>
None
...
...
@@ -640,7 +632,7 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
debug!
(
"write_mty_from_candidate(n_tps_m=%u, fty=%s, entry=%?)"
,
cand
.n_tps_m
,
self
.fcx.infcx
.ty_to_str
(
cand
.fty
),
self
.fcx
.infcx
()
.ty_to_str
(
cand
.fty
),
cand
.entry
);
match
cand
.mode
{
...
...
@@ -655,30 +647,18 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
self
.tcx
()
.sess
.span_bug
(
self
.expr.span
,
fmt!
(
"%s was assignable to %s but now is not?"
,
self
.fcx.infcx
.ty_to_str
(
cand
.self_ty
),
self
.fcx.infcx
.ty_to_str
(
cand
.rcvr_ty
)));
self
.fcx
.infcx
()
.ty_to_str
(
cand
.self_ty
),
self
.fcx
.infcx
()
.ty_to_str
(
cand
.rcvr_ty
)));
}
}
}
immutable_reference_mode
=>
{
// Borrow as an immutable reference.
let
region_var
=
self
.fcx.infcx
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
self
.fcx.infcx.borrowings
.push
({
expr_id
:
self
.self_expr.id
,
span
:
self
.self_expr.span
,
scope
:
region_var
,
mutbl
:
ast
::
m_imm
});
self
.add_borrow
(
ast
::
m_imm
);
}
mutable_reference_mode
=>
{
// Borrow as a mutable reference.
let
region_var
=
self
.fcx.infcx
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
self
.fcx.infcx.borrowings
.push
({
expr_id
:
self
.self_expr.id
,
span
:
self
.self_expr.span
,
scope
:
region_var
,
mutbl
:
ast
::
m_mutbl
});
self
.add_borrow
(
ast
::
m_mutbl
);
}
}
...
...
@@ -688,18 +668,18 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
let
n_tps_m
=
cand
.n_tps_m
;
let
m_substs
=
{
if
n_tps_supplied
==
0u
{
self
.fcx.infcx
.next_ty_vars
(
n_tps_m
)
self
.fcx
.infcx
()
.next_ty_vars
(
n_tps_m
)
}
else
if
n_tps_m
==
0u
{
tcx
.sess
.span_err
(
self
.expr.span
,
~
"this method does not take type parameters"
);
self
.fcx.infcx
.next_ty_vars
(
n_tps_m
)
self
.fcx
.infcx
()
.next_ty_vars
(
n_tps_m
)
}
else
if
n_tps_supplied
!=
n_tps_m
{
tcx
.sess
.span_err
(
self
.expr.span
,
~
"incorrect number of type
\
parameters given for this method"
);
self
.fcx.infcx
.next_ty_vars
(
n_tps_m
)
self
.fcx
.infcx
()
.next_ty_vars
(
n_tps_m
)
}
else
{
self
.supplied_tps
}
...
...
@@ -712,5 +692,13 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
return
cand
.entry
;
}
fn
add_borrow
(
mutbl
:
ast
::
mutability
)
{
let
region_var
=
self
.fcx
.infcx
()
.next_region_var
(
self
.self_expr.span
,
self
.self_expr.id
);
self
.fcx.inh.borrowings
.insert
(
self
.self_expr.id
,
{
region
:
region_var
,
mutbl
:
mutbl
});
}
}
src/rustc/middle/typeck/check/regionck.rs
浏览文件 @
e9ac7489
...
...
@@ -81,7 +81,7 @@ impl @rcx {
/// that `<R0>` be bigger than the let and the `*b` expression, so we
/// will effectively resolve `<R0>` to be the block B.
fn
resolve_type
(
unresolved_ty
:
ty
::
t
)
->
fres
<
ty
::
t
>
{
resolve_type
(
self
.fcx.infcx
,
unresolved_ty
,
resolve_type
(
self
.fcx
.infcx
()
,
unresolved_ty
,
resolve_and_force_all_but_regions
)
}
...
...
@@ -95,7 +95,7 @@ fn regionck_expr(fcx: @fn_ctxt, e: @ast::expr) {
let
rcx
=
rcx_
({
fcx
:
fcx
,
mut
errors_reported
:
0u
});
let
v
=
regionck_visitor
();
v
.visit_expr
(
e
,
@
rcx
,
v
);
fcx
.infcx
.resolve_regions
();
fcx
.infcx
()
.resolve_regions
();
}
fn
regionck_fn
(
fcx
:
@
fn_ctxt
,
...
...
@@ -104,7 +104,7 @@ fn regionck_fn(fcx: @fn_ctxt,
let
rcx
=
rcx_
({
fcx
:
fcx
,
mut
errors_reported
:
0u
});
let
v
=
regionck_visitor
();
v
.visit_block
(
blk
,
@
rcx
,
v
);
fcx
.infcx
.resolve_regions
();
fcx
.infcx
()
.resolve_regions
();
}
fn
regionck_visitor
()
->
rvt
{
...
...
src/rustc/middle/typeck/check/vtable.rs
浏览文件 @
e9ac7489
...
...
@@ -3,6 +3,7 @@
fixup_err_to_str
};
import
ast_util
::
new_def_hash
;
import
syntax
::
print
::
pprust
;
import
result
::{
Result
,
Ok
,
Err
};
// vtable resolution looks for places where trait bounds are
// subsituted in and figures out which vtable is used. There is some
...
...
@@ -85,7 +86,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
{
debug!
(
"lookup_vtable(ty=%s, trait_ty=%s)"
,
fcx
.infcx
.ty_to_str
(
ty
),
fcx
.infcx
.ty_to_str
(
trait_ty
));
fcx
.infcx
()
.ty_to_str
(
ty
),
fcx
.inh
.infcx
.ty_to_str
(
trait_ty
));
let
_
i
=
indenter
();
let
tcx
=
fcx
.ccx.tcx
;
...
...
@@ -253,8 +254,8 @@ impl<T> self_ty<T>: some_trait<T> { ... }
debug!
(
"(checking vtable) @2 relating trait ty %s to
\
of_ty %s"
,
fcx
.infcx
.ty_to_str
(
trait_ty
),
fcx
.infcx
.ty_to_str
(
of_ty
));
fcx
.infcx
()
.ty_to_str
(
trait_ty
),
fcx
.infcx
()
.ty_to_str
(
of_ty
));
let
of_ty
=
ty
::
subst
(
tcx
,
&
substs
,
of_ty
);
relate_trait_tys
(
fcx
,
expr
,
trait_ty
,
of_ty
);
...
...
@@ -347,18 +348,18 @@ fn fixup_ty(fcx: @fn_ctxt,
is_early
:
bool
)
->
Option
<
ty
::
t
>
{
let
tcx
=
fcx
.ccx.tcx
;
match
resolve_type
(
fcx
.infcx
,
ty
,
resolve_and_force_all_but_regions
)
{
result
::
Ok
(
new_type
)
=>
Some
(
new_type
),
result
::
Err
(
e
)
if
!
is_early
=>
{
tcx
.sess
.span_fatal
(
expr
.span
,
fmt!
(
"cannot determine a type
\
for this bounded type parameter: %s"
,
fixup_err_to_str
(
e
)))
}
result
::
Err
(
_
)
=>
{
None
}
match
resolve_type
(
fcx
.infcx
()
,
ty
,
resolve_and_force_all_but_regions
)
{
Ok
(
new_type
)
=>
Some
(
new_type
),
Err
(
e
)
if
!
is_early
=>
{
tcx
.sess
.span_fatal
(
expr
.span
,
fmt!
(
"cannot determine a type
\
for this bounded type parameter: %s"
,
fixup_err_to_str
(
e
)))
}
Err
(
_
)
=>
{
None
}
}
}
...
...
src/rustc/middle/typeck/check/writeback.rs
浏览文件 @
e9ac7489
...
...
@@ -3,30 +3,58 @@
// substitutions.
import
check
::{
fn_ctxt
,
lookup_local
};
import
infer
::{
resolve_type
,
resolve_all
,
force_all
};
import
infer
::{
resolve_type
,
resolve_
region
,
resolve_
all
,
force_all
};
export
resolve_type_vars_in_fn
;
export
resolve_type_vars_in_expr
;
import
result
::{
Result
,
Ok
,
Err
};
fn
resolve_type_vars_in_type
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
typ
:
ty
::
t
)
->
Option
<
ty
::
t
>
{
fn
resolve_type_vars_in_type
(
fcx
:
@
fn_ctxt
,
sp
:
span
,
typ
:
ty
::
t
)
->
Option
<
ty
::
t
>
{
if
!
ty
::
type_needs_infer
(
typ
)
{
return
Some
(
typ
);
}
match
resolve_type
(
fcx
.infcx
,
typ
,
resolve_all
|
force_all
)
{
result
::
Ok
(
new_type
)
=>
return
Some
(
new_type
),
result
::
Err
(
e
)
=>
{
if
!
fcx
.ccx.tcx.sess
.has_errors
()
{
fcx
.ccx.tcx.sess
.span_err
(
sp
,
fmt!
(
"cannot determine a type
\
for this expression: %s"
,
infer
::
fixup_err_to_str
(
e
)))
match
resolve_type
(
fcx
.infcx
(),
typ
,
resolve_all
|
force_all
)
{
Ok
(
new_type
)
=>
return
Some
(
new_type
),
Err
(
e
)
=>
{
if
!
fcx
.ccx.tcx.sess
.has_errors
()
{
fcx
.ccx.tcx.sess
.span_err
(
sp
,
fmt!
(
"cannot determine a type
\
for this expression: %s"
,
infer
::
fixup_err_to_str
(
e
)))
}
return
None
;
}
return
None
;
}
}
}
fn
resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
->
Option
<
ty
::
t
>
{
->
Option
<
ty
::
t
>
{
let
fcx
=
wbcx
.fcx
,
tcx
=
fcx
.ccx.tcx
;
// Resolve any borrowings for the node with id `id`
match
fcx
.inh.borrowings
.find
(
id
)
{
None
=>
(),
Some
(
borrow
)
=>
{
match
resolve_region
(
fcx
.infcx
(),
borrow
.region
,
resolve_all
|
force_all
)
{
Err
(
e
)
=>
{
// This should not, I think, happen.
fcx
.ccx.tcx.sess
.span_err
(
sp
,
fmt!
(
"cannot resolve scope of borrow: %s"
,
infer
::
fixup_err_to_str
(
e
)));
}
Ok
(
r
)
=>
{
debug!
(
"Borrowing node %d -> region %?, mutbl %?"
,
id
,
r
,
borrow
.mutbl
);
fcx
.tcx
()
.borrowings
.insert
(
id
,
{
region
:
r
,
mutbl
:
borrow
.mutbl
});
}
}
}
}
// Resolve the type of the node with id `id`
let
n_ty
=
fcx
.node_ty
(
id
);
match
resolve_type_vars_in_type
(
fcx
,
sp
,
n_ty
)
{
None
=>
{
...
...
@@ -58,8 +86,9 @@ fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id)
fn
maybe_resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
->
Option
<
ty
::
t
>
{
if
wbcx
.fcx.node_types
.contains_key
(
id
)
{
->
Option
<
ty
::
t
>
{
if
wbcx
.fcx.inh.node_types
.contains_key
(
id
)
{
resolve_type_vars_for_node
(
wbcx
,
sp
,
id
)
}
else
{
None
...
...
@@ -118,7 +147,7 @@ fn visit_pat(p: @ast::pat, wbcx: wb_ctxt, v: wb_vt) {
resolve_type_vars_for_node
(
wbcx
,
p
.span
,
p
.id
);
debug!
(
"Type for pattern binding %s (id %d) resolved to %s"
,
pat_to_str
(
p
,
wbcx
.fcx.ccx.tcx.sess
.intr
()),
p
.id
,
wbcx
.fcx.infcx
.ty_to_str
(
wbcx
.fcx
.infcx
()
.ty_to_str
(
ty
::
node_id_to_type
(
wbcx
.fcx.ccx.tcx
,
p
.id
)));
visit
::
visit_pat
(
p
,
wbcx
,
v
);
...
...
@@ -127,21 +156,22 @@ fn visit_local(l: @ast::local, wbcx: wb_ctxt, v: wb_vt) {
if
!
wbcx
.success
{
return
;
}
let
var_id
=
lookup_local
(
wbcx
.fcx
,
l
.span
,
l
.node.id
);
let
var_ty
=
ty
::
mk_var
(
wbcx
.fcx
.tcx
(),
var_id
);
match
resolve_type
(
wbcx
.fcx.infcx
,
var_ty
,
resolve_all
|
force_all
)
{
result
::
Ok
(
lty
)
=>
{
debug!
(
"Type for local %s (id %d) resolved to %s"
,
pat_to_str
(
l
.node.pat
,
wbcx
.fcx.ccx.tcx.sess
.intr
()),
l
.node.id
,
wbcx
.fcx.infcx
.ty_to_str
(
lty
));
write_ty_to_tcx
(
wbcx
.fcx.ccx.tcx
,
l
.node.id
,
lty
);
}
result
::
Err
(
e
)
=>
{
wbcx
.fcx.ccx.tcx.sess
.span_err
(
l
.span
,
fmt!
(
"cannot determine a type
\
for this local variable: %s"
,
infer
::
fixup_err_to_str
(
e
)));
wbcx
.success
=
false
;
}
match
resolve_type
(
wbcx
.fcx
.infcx
(),
var_ty
,
resolve_all
|
force_all
)
{
Ok
(
lty
)
=>
{
debug!
(
"Type for local %s (id %d) resolved to %s"
,
pat_to_str
(
l
.node.pat
,
wbcx
.fcx
.tcx
()
.sess
.intr
()),
l
.node.id
,
wbcx
.fcx
.infcx
()
.ty_to_str
(
lty
));
write_ty_to_tcx
(
wbcx
.fcx.ccx.tcx
,
l
.node.id
,
lty
);
}
Err
(
e
)
=>
{
wbcx
.fcx.ccx.tcx.sess
.span_err
(
l
.span
,
fmt!
(
"cannot determine a type
\
for this local variable: %s"
,
infer
::
fixup_err_to_str
(
e
)));
wbcx
.success
=
false
;
}
}
visit
::
visit_local
(
l
,
wbcx
,
v
);
}
...
...
@@ -163,9 +193,6 @@ fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool {
let
wbcx
=
{
fcx
:
fcx
,
mut
success
:
true
};
let
visit
=
mk_visitor
();
visit
.visit_expr
(
e
,
wbcx
,
visit
);
if
wbcx
.success
{
infer
::
resolve_borrowings
(
fcx
.infcx
);
}
return
wbcx
.success
;
}
...
...
@@ -184,8 +211,5 @@ fn resolve_type_vars_in_fn(fcx: @fn_ctxt,
for
decl
.inputs.each
|
arg
|
{
resolve_type_vars_for_node
(
wbcx
,
arg
.ty.span
,
arg
.id
);
}
if
wbcx
.success
{
infer
::
resolve_borrowings
(
fcx
.infcx
);
}
return
wbcx
.success
;
}
src/rustc/middle/typeck/infer.rs
浏览文件 @
e9ac7489
...
...
@@ -273,6 +273,7 @@ fn bar() {
import
unify
::{
vals_and_bindings
,
root
};
import
integral
::{
int_ty_set
,
int_ty_set_all
};
import
combine
::{
combine_fields
,
eq_tys
};
import
assignment
::
Assign
;
import
sub
::
Sub
;
import
lub
::
Lub
;
...
...
@@ -296,20 +297,13 @@ fn bar() {
export
root
,
to_str
;
export
int_ty_set_all
;
// Extra information needed to perform an assignment that may borrow.
// The `expr_id` and `span` are the id/span of the expression
// whose type is being assigned, and `borrow_scope` is the region
// scope to use if the value should be borrowed.
type
assignment
=
{
expr_id
:
ast
::
node_id
,
span
:
span
,
borrow_lb
:
ast
::
node_id
,
};
type
bound
<
T
:
copy
>
=
Option
<
T
>
;
type
bounds
<
T
:
copy
>
=
{
lb
:
bound
<
T
>
,
ub
:
bound
<
T
>
};
type
cres
<
T
>
=
Result
<
T
,
ty
::
type_err
>
;
type
cres
<
T
>
=
Result
<
T
,
ty
::
type_err
>
;
// "combine result"
type
ures
=
cres
<
()
>
;
// "unify result"
type
fres
<
T
>
=
Result
<
T
,
fixup_err
>
;
// "fixup result"
type
ares
=
cres
<
Option
<
ty
::
borrow
>>
;
// "assignment result"
enum
infer_ctxt
=
@
{
tcx
:
ty
::
ctxt
,
...
...
@@ -329,12 +323,7 @@ enum infer_ctxt = @{
// For keeping track of existing type and region variables.
ty_var_counter
:
@
mut
uint
,
ty_var_integral_counter
:
@
mut
uint
,
region_var_counter
:
@
mut
uint
,
borrowings
:
DVec
<
{
expr_id
:
ast
::
node_id
,
span
:
span
,
scope
:
ty
::
region
,
mutbl
:
ast
::
mutability
}
>
region_var_counter
:
@
mut
uint
};
enum
fixup_err
{
...
...
@@ -358,9 +347,6 @@ fn fixup_err_to_str(f: fixup_err) -> ~str {
}
}
type
ures
=
result
::
Result
<
(),
ty
::
type_err
>
;
type
fres
<
T
>
=
result
::
Result
<
T
,
fixup_err
>
;
fn
new_vals_and_bindings
<
V
:
copy
,
T
:
copy
>
()
->
vals_and_bindings
<
V
,
T
>
{
vals_and_bindings
{
vals
:
smallintmap
::
mk
(),
...
...
@@ -375,19 +361,14 @@ fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
region_vars
:
RegionVarBindings
(
tcx
),
ty_var_counter
:
@
mut
0u
,
ty_var_integral_counter
:
@
mut
0u
,
region_var_counter
:
@
mut
0u
,
borrowings
:
DVec
()})}
fn
mk_sub
(
cx
:
infer_ctxt
,
a_is_expected
:
bool
,
span
:
span
)
->
Sub
{
Sub
(
combine_fields
{
infcx
:
cx
,
a_is_expected
:
a_is_expected
,
span
:
span
})
}
region_var_counter
:
@
mut
0u
})}
fn
mk_subty
(
cx
:
infer_ctxt
,
a_is_expected
:
bool
,
span
:
span
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ures
{
debug!
(
"mk_subty(%s <: %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.commit
{
mk_sub
(
cx
,
a_is_expected
,
span
)
.tys
(
a
,
b
)
cx
.sub
(
a_is_expected
,
span
)
.tys
(
a
,
b
)
}
}
.to_ures
()
}
...
...
@@ -396,7 +377,7 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
debug!
(
"can_mk_subty(%s <: %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.probe
{
mk_sub
(
cx
,
true
,
ast_util
::
dummy_sp
())
.tys
(
a
,
b
)
cx
.sub
(
true
,
ast_util
::
dummy_sp
())
.tys
(
a
,
b
)
}
}
.to_ures
()
}
...
...
@@ -406,7 +387,7 @@ fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span,
debug!
(
"mk_subr(%s <: %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.commit
{
mk_sub
(
cx
,
a_is_expected
,
span
)
.regions
(
a
,
b
)
cx
.sub
(
a_is_expected
,
span
)
.regions
(
a
,
b
)
}
}
.to_ures
()
}
...
...
@@ -416,37 +397,30 @@ fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span,
debug!
(
"mk_eqty(%s <: %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.commit
{
let
suber
=
mk_sub
(
cx
,
a_is_expected
,
span
);
let
suber
=
cx
.sub
(
a_is_expected
,
span
);
eq_tys
(
&
suber
,
a
,
b
)
}
}
.to_ures
()
}
fn
mk_assignty
(
cx
:
infer_ctxt
,
anmnt
:
&
assignment
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ures
{
debug!
(
"mk_assignty(%? / %s <: %s)"
,
anmnt
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
fn
mk_assignty
(
cx
:
infer_ctxt
,
a_is_expected
:
bool
,
span
:
span
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ares
{
debug!
(
"mk_assignty(%s -> %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.commit
{
cx
.assign_tys
(
anmnt
,
a
,
b
)
Assign
(
cx
.combine_fields
(
a_is_expected
,
span
))
.tys
(
a
,
b
)
}
}
.to_ures
()
}
}
fn
can_mk_assignty
(
cx
:
infer_ctxt
,
anmnt
:
&
assignment
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ures
{
debug!
(
"can_mk_assignty(%? / %s <: %s)"
,
anmnt
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
// FIXME(#2593)---this will not unroll any entries we make in the
// borrowings table. But this is OK for the moment because this
// is only used in method lookup, and there must be exactly one
// match or an error is reported. Still, it should be fixed. (#2593)
// NDM OUTDATED
indent
(||
cx
.probe
(||
cx
.assign_tys
(
anmnt
,
a
,
b
)
)
)
.to_ures
()
fn
can_mk_assignty
(
cx
:
infer_ctxt
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ures
{
debug!
(
"can_mk_assignty(%s -> %s)"
,
a
.to_str
(
cx
),
b
.to_str
(
cx
));
do
indent
{
do
cx
.probe
{
let
span
=
ast_util
::
dummy_sp
();
Assign
(
cx
.combine_fields
(
true
,
span
))
.tys
(
a
,
b
)
}
}
.to_ures
()
}
// See comment on the type `resolve_state` below
...
...
@@ -460,6 +434,7 @@ fn resolve_region(cx: infer_ctxt, r: ty::region, modes: uint)
resolver
(
cx
,
modes
)
.resolve_region_chk
(
r
)
}
/*
fn resolve_borrowings(cx: infer_ctxt) {
for cx.borrowings.each |item| {
match resolve_region(cx, item.scope, resolve_all|force_all) {
...
...
@@ -479,6 +454,7 @@ fn resolve_borrowings(cx: infer_ctxt) {
}
}
}
*/
trait
then
{
fn
then
<
T
:
copy
>
(
f
:
fn
()
->
Result
<
T
,
ty
::
type_err
>
)
...
...
@@ -533,10 +509,20 @@ struct Snapshot {
ty_var_bindings_len
:
uint
;
ty_var_integral_bindings_len
:
uint
;
region_vars_snapshot
:
uint
;
borrowings_len
:
uint
;
}
impl
infer_ctxt
{
fn
combine_fields
(
a_is_expected
:
bool
,
span
:
span
)
->
combine_fields
{
combine_fields
{
infcx
:
self
,
a_is_expected
:
a_is_expected
,
span
:
span
}
}
fn
sub
(
a_is_expected
:
bool
,
span
:
span
)
->
Sub
{
Sub
(
self
.combine_fields
(
a_is_expected
,
span
))
}
fn
in_snapshot
()
->
bool
{
self
.region_vars
.in_snapshot
()
}
...
...
@@ -549,8 +535,6 @@ fn start_snapshot() -> Snapshot {
self
.ty_var_integral_bindings.bindings
.len
(),
region_vars_snapshot
:
self
.region_vars
.start_snapshot
(),
borrowings_len
:
self
.borrowings
.len
()
}
}
...
...
@@ -564,9 +548,6 @@ fn rollback_to(snapshot: &Snapshot) {
self
.region_vars
.rollback_to
(
snapshot
.region_vars_snapshot
);
while
self
.borrowings
.len
()
!=
snapshot
.borrowings_len
{
self
.borrowings
.pop
();
}
}
/// Execute `f` and commit the bindings if successful
...
...
src/rustc/middle/typeck/infer/assignment.rs
浏览文件 @
e9ac7489
...
...
@@ -49,70 +49,74 @@
// needed.
import
to_str
::
to_str
;
import
combine
::
combine_fields
;
impl
infer_ctxt
{
fn
assign_tys
(
anmnt
:
&
assignment
,
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ures
{
fn
to_ares
(
+
c
:
cres
<
ty
::
t
>
)
->
ares
{
match
c
{
Ok
(
_
)
=>
Ok
(
None
),
Err
(
e
)
=>
Err
(
e
)
}
}
fn
select
(
fst
:
Option
<
ty
::
t
>
,
snd
:
Option
<
ty
::
t
>
)
->
Option
<
ty
::
t
>
{
match
fst
{
Some
(
t
)
=>
Some
(
t
),
None
=>
match
snd
{
Some
(
t
)
=>
Some
(
t
),
None
=>
None
}
}
}
// Note: Assign is not actually a combiner, in that it does not
// conform to the same interface, though it performs a similar
// function.
enum
Assign
=
combine_fields
;
debug!
(
"assign_tys(anmnt=%?, %s -> %s)"
,
anmnt
,
a
.to_str
(
self
),
b
.to_str
(
self
));
impl
Assign
{
fn
tys
(
a
:
ty
::
t
,
b
:
ty
::
t
)
->
ares
{
debug!
(
"Assign.tys(%s -> %s)"
,
a
.to_str
(
self
.infcx
),
b
.to_str
(
self
.infcx
));
let
_
r
=
indenter
();
match
(
ty
::
get
(
a
)
.struct
,
ty
::
get
(
b
)
.struct
)
{
(
ty
::
ty_bot
,
_
)
=>
{
uok
(
)
}
(
ty
::
ty_var
(
a_id
),
ty
::
ty_var
(
b_id
))
=>
{
let
nde_a
=
self
.get
(
&
self
.ty_var_bindings
,
a_id
);
let
nde_b
=
self
.get
(
&
self
.ty_var_bindings
,
b_id
);
let
a_bounds
=
nde_a
.possible_types
;
let
b_bounds
=
nde_b
.possible_types
;
let
a_bnd
=
select
(
a_bounds
.ub
,
a_bounds
.lb
);
let
b_bnd
=
select
(
b_bounds
.lb
,
b_bounds
.ub
);
self
.assign_tys_or_sub
(
anmnt
,
a
,
b
,
a_bnd
,
b_bnd
)
}
(
ty
::
ty_var
(
a_id
),
_
)
=>
{
let
nde_a
=
self
.get
(
&
self
.ty_var_bindings
,
a_id
);
let
a_bounds
=
nde_a
.possible_types
;
let
a_bnd
=
select
(
a_bounds
.ub
,
a_bounds
.lb
);
self
.assign_tys_or_sub
(
anmnt
,
a
,
b
,
a_bnd
,
Some
(
b
))
}
(
_
,
ty
::
ty_var
(
b_id
))
=>
{
let
nde_b
=
self
.get
(
&
self
.ty_var_bindings
,
b_id
);
let
b_bounds
=
nde_b
.possible_types
;
let
b_bnd
=
select
(
b_bounds
.lb
,
b_bounds
.ub
);
self
.assign_tys_or_sub
(
anmnt
,
a
,
b
,
Some
(
a
),
b_bnd
)
}
(
_
,
_
)
=>
{
self
.assign_tys_or_sub
(
anmnt
,
a
,
b
,
Some
(
a
),
Some
(
b
))
}
(
ty
::
ty_bot
,
_
)
=>
{
Ok
(
None
)
}
(
ty
::
ty_var
(
a_id
),
ty
::
ty_var
(
b_id
))
=>
{
let
nde_a
=
self
.infcx
.get
(
&
self
.infcx
.ty_var_bindings
,
a_id
);
let
nde_b
=
self
.infcx
.get
(
&
self
.infcx
.ty_var_bindings
,
b_id
);
let
a_bounds
=
nde_a
.possible_types
;
let
b_bounds
=
nde_b
.possible_types
;
let
a_bnd
=
option
::
or
(
a_bounds
.ub
,
a_bounds
.lb
);
let
b_bnd
=
option
::
or
(
b_bounds
.lb
,
b_bounds
.ub
);
self
.assign_tys_or_sub
(
a
,
b
,
a_bnd
,
b_bnd
)
}
(
ty
::
ty_var
(
a_id
),
_
)
=>
{
let
nde_a
=
self
.infcx
.get
(
&
self
.infcx
.ty_var_bindings
,
a_id
);
let
a_bounds
=
nde_a
.possible_types
;
let
a_bnd
=
option
::
or
(
a_bounds
.ub
,
a_bounds
.lb
);
self
.assign_tys_or_sub
(
a
,
b
,
a_bnd
,
Some
(
b
))
}
(
_
,
ty
::
ty_var
(
b_id
))
=>
{
let
nde_b
=
self
.infcx
.get
(
&
self
.infcx
.ty_var_bindings
,
b_id
);
let
b_bounds
=
nde_b
.possible_types
;
let
b_bnd
=
option
::
or
(
b_bounds
.lb
,
b_bounds
.ub
);
self
.assign_tys_or_sub
(
a
,
b
,
Some
(
a
),
b_bnd
)
}
(
_
,
_
)
=>
{
self
.assign_tys_or_sub
(
a
,
b
,
Some
(
a
),
Some
(
b
))
}
}
}
}
priv
impl
Assign
{
fn
assign_tys_or_sub
(
anmnt
:
&
assignment
,
a
:
ty
::
t
,
b
:
ty
::
t
,
+
a_bnd
:
Option
<
ty
::
t
>
,
+
b_bnd
:
Option
<
ty
::
t
>
)
->
u
res
{
+
a_bnd
:
Option
<
ty
::
t
>
,
+
b_bnd
:
Option
<
ty
::
t
>
)
->
a
res
{
debug!
(
"
assign_tys_or_sub(anmnt=%?,
%s -> %s, %s -> %s)"
,
a
nmnt
,
a
.to_str
(
self
),
b
.to_str
(
self
),
a_bnd
.to_str
(
self
),
b_bnd
.to_str
(
self
));
debug!
(
"
Assign.assign_tys_or_sub(
%s -> %s, %s -> %s)"
,
a
.to_str
(
self
.infcx
),
b
.to_str
(
self
.infcx
),
a_bnd
.to_str
(
self
.infcx
),
b_bnd
.to_str
(
self
.infcx
));
let
_
r
=
indenter
();
fn
is_borrowable
(
v
:
ty
::
vstore
)
->
bool
{
...
...
@@ -123,73 +127,73 @@ fn is_borrowable(v: ty::vstore) -> bool {
}
match
(
a_bnd
,
b_bnd
)
{
(
Some
(
a_bnd
),
Some
(
b_bnd
))
=>
{
match
(
ty
::
get
(
a_bnd
)
.struct
,
ty
::
get
(
b_bnd
)
.struct
)
{
(
ty
::
ty_box
(
*
),
ty
::
ty_rptr
(
r_b
,
mt_b
))
=>
{
let
nr_b
=
ty
::
mk_box
(
self
.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
});
self
.crosspollinate
(
anmnt
,
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
(
ty
::
ty_uniq
(
*
),
ty
::
ty_rptr
(
r_b
,
mt_b
))
=>
{
let
nr_b
=
ty
::
mk_uniq
(
self
.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
});
self
.crosspollinate
(
anmnt
,
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
(
ty
::
ty_estr
(
vs_a
),
ty
::
ty_estr
(
ty
::
vstore_slice
(
r_b
)))
if
is_borrowable
(
vs_a
)
=>
{
let
nr_b
=
ty
::
mk_estr
(
self
.tcx
,
vs_a
);
self
.crosspollinate
(
anmnt
,
a
,
nr_b
,
m_imm
,
r_b
)
}
(
ty
::
ty_evec
(
_
,
vs_a
),
ty
::
ty_evec
(
mt_b
,
ty
::
vstore_slice
(
r_b
)))
if
is_borrowable
(
vs_a
)
=>
{
let
nr_b
=
ty
::
mk_evec
(
self
.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
},
vs_a
);
self
.crosspollinate
(
anmnt
,
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
_
=>
{
mk_sub
(
self
,
false
,
anmnt
.span
)
.tys
(
a
,
b
)
.to_ures
()
}
(
Some
(
a_bnd
),
Some
(
b_bnd
))
=>
{
// check for a case where a non-region pointer (@, ~) is
// being assigned to a region pointer:
match
(
ty
::
get
(
a_bnd
)
.struct
,
ty
::
get
(
b_bnd
)
.struct
)
{
(
ty
::
ty_box
(
_
),
ty
::
ty_rptr
(
r_b
,
mt_b
))
=>
{
let
nr_b
=
ty
::
mk_box
(
self
.infcx.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
});
self
.try_assign
(
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
(
ty
::
ty_uniq
(
_
),
ty
::
ty_rptr
(
r_b
,
mt_b
))
=>
{
let
nr_b
=
ty
::
mk_uniq
(
self
.infcx.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
});
self
.try_assign
(
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
(
ty
::
ty_estr
(
vs_a
),
ty
::
ty_estr
(
ty
::
vstore_slice
(
r_b
)))
if
is_borrowable
(
vs_a
)
=>
{
let
nr_b
=
ty
::
mk_estr
(
self
.infcx.tcx
,
vs_a
);
self
.try_assign
(
a
,
nr_b
,
m_imm
,
r_b
)
}
(
ty
::
ty_evec
(
_
,
vs_a
),
ty
::
ty_evec
(
mt_b
,
ty
::
vstore_slice
(
r_b
)))
if
is_borrowable
(
vs_a
)
=>
{
let
nr_b
=
ty
::
mk_evec
(
self
.infcx.tcx
,
{
ty
:
mt_b
.ty
,
mutbl
:
m_const
},
vs_a
);
self
.try_assign
(
a
,
nr_b
,
mt_b
.mutbl
,
r_b
)
}
_
=>
{
// otherwise, assignment follows normal subtype rules:
to_ares
(
Sub
(
*
self
)
.tys
(
a
,
b
))
}
}
}
_
=>
{
// if insufficient bounds were available, just follow
// normal subtype rules:
to_ares
(
Sub
(
*
self
)
.tys
(
a
,
b
))
}
}
_
=>
{
mk_sub
(
self
,
false
,
anmnt
.span
)
.tys
(
a
,
b
)
.to_ures
()
}
}
}
fn
crosspollinate
(
anmnt
:
&
assignment
,
a
:
ty
::
t
,
nr_b
:
ty
::
t
,
m
:
ast
::
mutability
,
r_b
:
ty
::
region
)
->
ures
{
debug!
(
"crosspollinate(anmnt=%?, a=%s, nr_b=%s, r_b=%s)"
,
anmnt
,
a
.to_str
(
self
),
nr_b
.to_str
(
self
),
r_b
.to_str
(
self
));
/// Given an assignment from a type like `@a` to `&r_b/m nr_b`,
/// this function checks that `a <: nr_b`. In that case, the
/// assignment is permitted, so it constructs a fresh region
/// variable `r_a >= r_b` and returns a corresponding assignment
/// record. See the discussion at the top of this file for more
/// details.
fn
try_assign
(
a
:
ty
::
t
,
nr_b
:
ty
::
t
,
m
:
ast
::
mutability
,
r_b
:
ty
::
region
)
->
ares
{
debug!
(
"try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)"
,
a
.to_str
(
self
.infcx
),
nr_b
.to_str
(
self
.infcx
),
m
,
r_b
.to_str
(
self
.infcx
));
do
indent
{
let
sub
=
mk_sub
(
self
,
false
,
anmnt
.span
);
let
sub
=
Sub
(
*
self
);
do
sub
.tys
(
a
,
nr_b
)
.chain
|
_
t
|
{
// Create a fresh region variable `r_a` with the given
// borrow bounds:
let
r_a
=
self
.next_region_var
(
anmnt
.span
,
anmnt
.borrow_lb
);
debug!
(
"anmnt=%?"
,
anmnt
);
let
r_a
=
self
.infcx
.next_region_var_nb
(
self
.span
);
do
sub
.contraregions
(
r_a
,
r_b
)
.chain
|
_
r
|
{
// if successful, add an entry indicating that
// borrowing occurred
debug!
(
"borrowing expression #%?, scope=%?, m=%?"
,
anmnt
,
r_a
,
m
);
self
.borrowings
.push
({
expr_id
:
anmnt
.expr_id
,
span
:
anmnt
.span
,
scope
:
r_a
,
mutbl
:
m
});
uok
()
Ok
(
Some
({
region
:
r_a
,
mutbl
:
m
}))
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录