Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
4eac052a
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,发现更多精彩内容 >>
提交
4eac052a
编写于
1月 25, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: move object default lifetimes to resolve_lifetimes.
上级
c5befdc6
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
445 addition
and
459 deletion
+445
-459
src/librustc/middle/cstore.rs
src/librustc/middle/cstore.rs
+6
-0
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+322
-21
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+0
-19
src/librustc/ty/structural_impls.rs
src/librustc/ty/structural_impls.rs
+1
-25
src/librustc/util/ppaux.rs
src/librustc/util/ppaux.rs
+0
-10
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/cstore_impl.rs
+7
-0
src/librustc_metadata/decoder.rs
src/librustc_metadata/decoder.rs
+7
-0
src/librustc_metadata/encoder.rs
src/librustc_metadata/encoder.rs
+7
-0
src/librustc_metadata/schema.rs
src/librustc_metadata/schema.rs
+2
-0
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+45
-130
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+5
-23
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+19
-117
src/librustc_typeck/lib.rs
src/librustc_typeck/lib.rs
+0
-1
src/librustc_typeck/rscope.rs
src/librustc_typeck/rscope.rs
+0
-113
src/test/run-pass/object-lifetime-default-from-ref-struct.rs
src/test/run-pass/object-lifetime-default-from-ref-struct.rs
+18
-0
src/test/run-pass/object-lifetime-default-from-rptr.rs
src/test/run-pass/object-lifetime-default-from-rptr.rs
+6
-0
未找到文件。
src/librustc/middle/cstore.rs
浏览文件 @
4eac052a
...
...
@@ -28,6 +28,7 @@
use
hir
::
map
::
definitions
::{
Definitions
,
DefKey
,
DisambiguatedDefPathData
};
use
hir
::
svh
::
Svh
;
use
middle
::
lang_items
;
use
middle
::
resolve_lifetime
::
ObjectLifetimeDefault
;
use
ty
::{
self
,
Ty
,
TyCtxt
};
use
mir
::
Mir
;
use
session
::
Session
;
...
...
@@ -183,6 +184,8 @@ fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
fn
item_generics
<
'a
>
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def
:
DefId
)
->
ty
::
Generics
<
'tcx
>
;
fn
item_generics_own_param_counts
(
&
self
,
def
:
DefId
)
->
(
usize
,
usize
);
fn
item_generics_object_lifetime_defaults
(
&
self
,
def
:
DefId
)
->
Vec
<
ObjectLifetimeDefault
>
;
fn
item_attrs
(
&
self
,
def_id
:
DefId
)
->
Vec
<
ast
::
Attribute
>
;
fn
trait_def
<
'a
>
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def
:
DefId
)
->
ty
::
TraitDef
;
fn
adt_def
<
'a
>
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def
:
DefId
)
->
&
'tcx
ty
::
AdtDef
;
...
...
@@ -334,6 +337,9 @@ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
->
ty
::
Generics
<
'tcx
>
{
bug!
(
"item_generics"
)
}
fn
item_generics_own_param_counts
(
&
self
,
def
:
DefId
)
->
(
usize
,
usize
)
{
bug!
(
"item_generics_own_param_counts"
)
}
fn
item_generics_object_lifetime_defaults
(
&
self
,
def
:
DefId
)
->
Vec
<
ObjectLifetimeDefault
>
{
bug!
(
"item_generics_object_lifetime_defaults"
)
}
fn
item_attrs
(
&
self
,
def_id
:
DefId
)
->
Vec
<
ast
::
Attribute
>
{
bug!
(
"item_attrs"
)
}
fn
trait_def
<
'a
>
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def
:
DefId
)
->
ty
::
TraitDef
{
bug!
(
"trait_def"
)
}
...
...
src/librustc/middle/resolve_lifetime.rs
浏览文件 @
4eac052a
...
...
@@ -26,11 +26,12 @@
use
std
::
cell
::
Cell
;
use
std
::
mem
::
replace
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
ptr
::
P
;
use
syntax
::
symbol
::
keywords
;
use
syntax_pos
::
Span
;
use
errors
::
DiagnosticBuilder
;
use
util
::
nodemap
::{
NodeMap
,
FxHashSet
,
FxHashMap
};
use
util
::
nodemap
::{
NodeMap
,
FxHashSet
,
FxHashMap
,
DefIdMap
};
use
rustc_back
::
slice
;
use
hir
;
...
...
@@ -102,8 +103,46 @@ fn from_depth(self, depth: u32) -> Region {
_
=>
self
}
}
fn
subst
(
self
,
params
:
&
[
hir
::
Lifetime
],
map
:
&
NamedRegionMap
)
->
Option
<
Region
>
{
if
let
Region
::
EarlyBound
(
index
,
_
)
=
self
{
params
.get
(
index
as
usize
)
.and_then
(|
lifetime
|
{
map
.defs
.get
(
&
lifetime
.id
)
.cloned
()
})
}
else
{
Some
(
self
)
}
}
}
/// A set containing, at most, one known element.
/// If two distinct values are inserted into a set, then it
/// becomes `Many`, which can be used to detect ambiguities.
#[derive(Copy,
Clone,
PartialEq,
Eq,
RustcEncodable,
RustcDecodable,
Debug)]
pub
enum
Set1
<
T
>
{
Empty
,
One
(
T
),
Many
}
impl
<
T
:
PartialEq
>
Set1
<
T
>
{
pub
fn
insert
(
&
mut
self
,
value
:
T
)
{
if
let
Set1
::
Empty
=
*
self
{
*
self
=
Set1
::
One
(
value
);
return
;
}
if
let
Set1
::
One
(
ref
old
)
=
*
self
{
if
*
old
==
value
{
return
;
}
}
*
self
=
Set1
::
Many
;
}
}
pub
type
ObjectLifetimeDefault
=
Set1
<
Region
>
;
// Maps the id of each lifetime reference to the lifetime decl
// that it corresponds to.
pub
struct
NamedRegionMap
{
...
...
@@ -115,6 +154,10 @@ pub struct NamedRegionMap {
// are named regions appearing in fn arguments that do not appear
// in where-clauses
pub
late_bound
:
NodeMap
<
ty
::
Issue32330
>
,
// For each type and trait definition, maps type parameters
// to the trait object lifetime defaults computed from them.
pub
object_lifetime_defaults
:
NodeMap
<
Vec
<
ObjectLifetimeDefault
>>
,
}
struct
LifetimeContext
<
'a
,
'tcx
:
'a
>
{
...
...
@@ -141,6 +184,9 @@ struct LifetimeContext<'a, 'tcx: 'a> {
// List of labels in the function/method currently under analysis.
labels_in_fn
:
Vec
<
(
ast
::
Name
,
Span
)
>
,
// Cache for cross-crate per-definition object lifetime defaults.
xcrate_object_lifetime_defaults
:
DefIdMap
<
Vec
<
ObjectLifetimeDefault
>>
,
}
#[derive(Debug)]
...
...
@@ -170,6 +216,14 @@ enum Scope<'a> {
s
:
ScopeRef
<
'a
>
},
/// Use a specific lifetime (if `Some`) or leave it unset (to be
/// inferred in a function body or potentially error outside one),
/// for the default choice of lifetime in a trait object type.
ObjectLifetimeDefault
{
lifetime
:
Option
<
Region
>
,
s
:
ScopeRef
<
'a
>
},
Root
}
...
...
@@ -208,6 +262,7 @@ pub fn krate(sess: &Session,
let
mut
map
=
NamedRegionMap
{
defs
:
NodeMap
(),
late_bound
:
NodeMap
(),
object_lifetime_defaults
:
compute_object_lifetime_defaults
(
sess
,
hir_map
),
};
sess
.track_errors
(||
{
let
mut
visitor
=
LifetimeContext
{
...
...
@@ -217,6 +272,7 @@ pub fn krate(sess: &Session,
scope
:
ROOT_SCOPE
,
trait_ref_hack
:
false
,
labels_in_fn
:
vec!
[],
xcrate_object_lifetime_defaults
:
DefIdMap
(),
};
for
(
_
,
item
)
in
&
krate
.items
{
visitor
.visit_item
(
item
);
...
...
@@ -326,10 +382,20 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
for
bound
in
bounds
{
self
.visit_poly_trait_ref
(
bound
,
hir
::
TraitBoundModifier
::
None
);
}
if
!
lifetime
.is_elided
()
{
if
lifetime
.is_elided
()
{
self
.resolve_object_lifetime_default
(
lifetime
)
}
else
{
self
.visit_lifetime
(
lifetime
);
}
}
hir
::
TyRptr
(
ref
lifetime_ref
,
ref
mt
)
=>
{
self
.visit_lifetime
(
lifetime_ref
);
let
scope
=
Scope
::
ObjectLifetimeDefault
{
lifetime
:
self
.map.defs
.get
(
&
lifetime_ref
.id
)
.cloned
(),
s
:
self
.scope
};
self
.with
(
scope
,
|
_
,
this
|
this
.visit_ty
(
&
mt
.ty
));
}
_
=>
{
intravisit
::
walk_ty
(
self
,
ty
)
}
...
...
@@ -372,20 +438,10 @@ fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
self
.resolve_lifetime_ref
(
lifetime_ref
);
}
fn
visit_path_parameters
(
&
mut
self
,
_
:
Span
,
params
:
&
'tcx
hir
::
PathParameters
)
{
match
*
params
{
hir
::
AngleBracketedParameters
(
ref
data
)
=>
{
if
data
.lifetimes
.iter
()
.all
(|
l
|
l
.is_elided
())
{
self
.resolve_elided_lifetimes
(
&
data
.lifetimes
);
}
else
{
for
l
in
&
data
.lifetimes
{
self
.visit_lifetime
(
l
);
}
}
for
ty
in
&
data
.types
{
self
.visit_ty
(
ty
);
}
for
b
in
&
data
.bindings
{
self
.visit_assoc_type_binding
(
b
);
}
}
hir
::
ParenthesizedParameters
(
ref
data
)
=>
{
self
.visit_fn_like_elision
(
&
data
.inputs
,
data
.output
.as_ref
());
}
fn
visit_path
(
&
mut
self
,
path
:
&
'tcx
hir
::
Path
,
_
:
ast
::
NodeId
)
{
for
(
i
,
segment
)
in
path
.segments
.iter
()
.enumerate
()
{
let
depth
=
path
.segments
.len
()
-
i
-
1
;
self
.visit_segment_parameters
(
path
.def
,
depth
,
&
segment
.parameters
);
}
}
...
...
@@ -466,7 +522,7 @@ fn visit_poly_trait_ref(&mut self,
for
lifetime
in
&
trait_ref
.bound_lifetimes
{
this
.visit_lifetime_def
(
lifetime
);
}
intravisit
::
walk_path
(
this
,
&
trait_ref
.trait_ref.path
)
this
.visit_trait_ref
(
&
trait_ref
.trait_ref
)
})
}
else
{
self
.visit_trait_ref
(
&
trait_ref
.trait_ref
)
...
...
@@ -585,7 +641,8 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
loop
{
match
*
scope
{
Scope
::
Body
{
s
,
..
}
|
Scope
::
Elision
{
s
,
..
}
=>
{
scope
=
s
;
}
Scope
::
Elision
{
s
,
..
}
|
Scope
::
ObjectLifetimeDefault
{
s
,
..
}
=>
{
scope
=
s
;
}
Scope
::
Root
=>
{
return
;
}
...
...
@@ -606,6 +663,103 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
}
}
fn
compute_object_lifetime_defaults
(
sess
:
&
Session
,
hir_map
:
&
Map
)
->
NodeMap
<
Vec
<
ObjectLifetimeDefault
>>
{
let
mut
map
=
NodeMap
();
for
item
in
hir_map
.krate
()
.items
.values
()
{
match
item
.node
{
hir
::
ItemStruct
(
_
,
ref
generics
)
|
hir
::
ItemUnion
(
_
,
ref
generics
)
|
hir
::
ItemEnum
(
_
,
ref
generics
)
|
hir
::
ItemTy
(
_
,
ref
generics
)
|
hir
::
ItemTrait
(
_
,
ref
generics
,
..
)
=>
{
let
result
=
object_lifetime_defaults_for_item
(
hir_map
,
generics
);
// Debugging aid.
if
attr
::
contains_name
(
&
item
.attrs
,
"rustc_object_lifetime_default"
)
{
let
object_lifetime_default_reprs
:
String
=
result
.iter
()
.map
(|
set
|
{
match
*
set
{
Set1
::
Empty
=>
"BaseDefault"
.to_string
(),
Set1
::
One
(
Region
::
Static
)
=>
"'static"
.to_string
(),
Set1
::
One
(
Region
::
EarlyBound
(
i
,
_
))
=>
{
generics
.lifetimes
[
i
as
usize
]
.lifetime.name
.to_string
()
}
Set1
::
One
(
_
)
=>
bug!
(),
Set1
::
Many
=>
"Ambiguous"
.to_string
(),
}
})
.collect
::
<
Vec
<
String
>>
()
.join
(
","
);
sess
.span_err
(
item
.span
,
&
object_lifetime_default_reprs
);
}
map
.insert
(
item
.id
,
result
);
}
_
=>
{}
}
}
map
}
/// Scan the bounds and where-clauses on parameters to extract bounds
/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
/// for each type parameter.
fn
object_lifetime_defaults_for_item
(
hir_map
:
&
Map
,
generics
:
&
hir
::
Generics
)
->
Vec
<
ObjectLifetimeDefault
>
{
fn
add_bounds
(
set
:
&
mut
Set1
<
ast
::
Name
>
,
bounds
:
&
[
hir
::
TyParamBound
])
{
for
bound
in
bounds
{
if
let
hir
::
RegionTyParamBound
(
ref
lifetime
)
=
*
bound
{
set
.insert
(
lifetime
.name
);
}
}
}
generics
.ty_params
.iter
()
.map
(|
param
|
{
let
mut
set
=
Set1
::
Empty
;
add_bounds
(
&
mut
set
,
&
param
.bounds
);
let
param_def_id
=
hir_map
.local_def_id
(
param
.id
);
for
predicate
in
&
generics
.where_clause.predicates
{
// Look for `type: ...` where clauses.
let
data
=
match
*
predicate
{
hir
::
WherePredicate
::
BoundPredicate
(
ref
data
)
=>
data
,
_
=>
continue
};
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if
!
data
.bound_lifetimes
.is_empty
()
{
continue
;
}
let
def
=
match
data
.bounded_ty.node
{
hir
::
TyPath
(
hir
::
QPath
::
Resolved
(
None
,
ref
path
))
=>
path
.def
,
_
=>
continue
};
if
def
==
Def
::
TyParam
(
param_def_id
)
{
add_bounds
(
&
mut
set
,
&
data
.bounds
);
}
}
match
set
{
Set1
::
Empty
=>
Set1
::
Empty
,
Set1
::
One
(
name
)
=>
{
if
name
==
keywords
::
StaticLifetime
.name
()
{
Set1
::
One
(
Region
::
Static
)
}
else
{
generics
.lifetimes
.iter
()
.enumerate
()
.find
(|
&
(
_
,
def
)|
{
def
.lifetime.name
==
name
})
.map_or
(
Set1
::
Many
,
|(
i
,
def
)|
{
Set1
::
One
(
Region
::
EarlyBound
(
i
as
u32
,
def
.lifetime.id
))
})
}
}
Set1
::
Many
=>
Set1
::
Many
}
})
.collect
()
}
impl
<
'a
,
'tcx
>
LifetimeContext
<
'a
,
'tcx
>
{
// FIXME(#37666) this works around a limitation in the region inferencer
fn
hack
<
F
>
(
&
mut
self
,
f
:
F
)
where
...
...
@@ -619,6 +773,8 @@ fn with<F>(&mut self, wrap_scope: Scope, f: F) where
{
let
LifetimeContext
{
sess
,
hir_map
,
ref
mut
map
,
..
}
=
*
self
;
let
labels_in_fn
=
replace
(
&
mut
self
.labels_in_fn
,
vec!
[]);
let
xcrate_object_lifetime_defaults
=
replace
(
&
mut
self
.xcrate_object_lifetime_defaults
,
DefIdMap
());
let
mut
this
=
LifetimeContext
{
sess
:
sess
,
hir_map
:
hir_map
,
...
...
@@ -626,11 +782,13 @@ fn with<F>(&mut self, wrap_scope: Scope, f: F) where
scope
:
&
wrap_scope
,
trait_ref_hack
:
self
.trait_ref_hack
,
labels_in_fn
:
labels_in_fn
,
xcrate_object_lifetime_defaults
:
xcrate_object_lifetime_defaults
,
};
debug!
(
"entering scope {:?}"
,
this
.scope
);
f
(
self
.scope
,
&
mut
this
);
debug!
(
"exiting scope {:?}"
,
this
.scope
);
self
.labels_in_fn
=
this
.labels_in_fn
;
self
.xcrate_object_lifetime_defaults
=
this
.xcrate_object_lifetime_defaults
;
}
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
...
...
@@ -727,7 +885,8 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
}
}
Scope
::
Elision
{
s
,
..
}
=>
{
Scope
::
Elision
{
s
,
..
}
|
Scope
::
ObjectLifetimeDefault
{
s
,
..
}
=>
{
scope
=
s
;
}
}
...
...
@@ -763,6 +922,109 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
}
}
fn
visit_segment_parameters
(
&
mut
self
,
def
:
Def
,
depth
:
usize
,
params
:
&
'tcx
hir
::
PathParameters
)
{
let
data
=
match
*
params
{
hir
::
ParenthesizedParameters
(
ref
data
)
=>
{
self
.visit_fn_like_elision
(
&
data
.inputs
,
data
.output
.as_ref
());
return
;
}
hir
::
AngleBracketedParameters
(
ref
data
)
=>
data
};
if
data
.lifetimes
.iter
()
.all
(|
l
|
l
.is_elided
())
{
self
.resolve_elided_lifetimes
(
&
data
.lifetimes
);
}
else
{
for
l
in
&
data
.lifetimes
{
self
.visit_lifetime
(
l
);
}
}
// Figure out if this is a type/trait segment,
// which requires object lifetime defaults.
let
parent_def_id
=
|
this
:
&
mut
Self
,
def_id
:
DefId
|
{
let
def_key
=
if
def_id
.is_local
()
{
this
.hir_map
.def_key
(
def_id
)
}
else
{
this
.sess.cstore
.def_key
(
def_id
)
};
DefId
{
krate
:
def_id
.krate
,
index
:
def_key
.parent
.expect
(
"missing parent"
)
}
};
let
type_def_id
=
match
def
{
Def
::
AssociatedTy
(
def_id
)
if
depth
==
1
=>
{
Some
(
parent_def_id
(
self
,
def_id
))
}
Def
::
Variant
(
def_id
)
if
depth
==
0
=>
{
Some
(
parent_def_id
(
self
,
def_id
))
}
Def
::
Struct
(
def_id
)
|
Def
::
Union
(
def_id
)
|
Def
::
Enum
(
def_id
)
|
Def
::
TyAlias
(
def_id
)
|
Def
::
Trait
(
def_id
)
if
depth
==
0
=>
Some
(
def_id
),
_
=>
None
};
let
object_lifetime_defaults
=
type_def_id
.map_or
(
vec!
[],
|
def_id
|
{
let
in_body
=
{
let
mut
scope
=
self
.scope
;
loop
{
match
*
scope
{
Scope
::
Root
=>
break
false
,
Scope
::
Body
{
..
}
=>
break
true
,
Scope
::
Binder
{
s
,
..
}
|
Scope
::
Elision
{
s
,
..
}
|
Scope
::
ObjectLifetimeDefault
{
s
,
..
}
=>
{
scope
=
s
;
}
}
}
};
let
map
=
&
self
.map
;
let
unsubst
=
if
let
Some
(
id
)
=
self
.hir_map
.as_local_node_id
(
def_id
)
{
&
map
.object_lifetime_defaults
[
&
id
]
}
else
{
let
cstore
=
&
self
.sess.cstore
;
self
.xcrate_object_lifetime_defaults
.entry
(
def_id
)
.or_insert_with
(||
{
cstore
.item_generics_object_lifetime_defaults
(
def_id
)
})
};
unsubst
.iter
()
.map
(|
set
|
{
match
*
set
{
Set1
::
Empty
=>
{
if
in_body
{
None
}
else
{
Some
(
Region
::
Static
)
}
}
Set1
::
One
(
r
)
=>
r
.subst
(
&
data
.lifetimes
,
map
),
Set1
::
Many
=>
None
}
})
.collect
()
});
for
(
i
,
ty
)
in
data
.types
.iter
()
.enumerate
()
{
if
let
Some
(
&
lt
)
=
object_lifetime_defaults
.get
(
i
)
{
let
scope
=
Scope
::
ObjectLifetimeDefault
{
lifetime
:
lt
,
s
:
self
.scope
};
self
.with
(
scope
,
|
_
,
this
|
this
.visit_ty
(
ty
));
}
else
{
self
.visit_ty
(
ty
);
}
}
for
b
in
&
data
.bindings
{
self
.visit_assoc_type_binding
(
b
);
}
}
fn
visit_fn_like_elision
(
&
mut
self
,
inputs
:
&
'tcx
[
P
<
hir
::
Ty
>
],
output
:
Option
<&
'tcx
P
<
hir
::
Ty
>>
)
{
let
mut
arg_elide
=
Elide
::
FreshLateAnon
(
Cell
::
new
(
0
));
...
...
@@ -962,7 +1224,19 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
if
let
hir
::
TyBareFn
(
_
)
=
ty
.node
{
self
.binder_depth
+=
1
;
}
intravisit
::
walk_ty
(
self
,
ty
);
if
let
hir
::
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=
ty
.node
{
for
bound
in
bounds
{
self
.visit_poly_trait_ref
(
bound
,
hir
::
TraitBoundModifier
::
None
);
}
// Stay on the safe side and don't include the object
// lifetime default (which may not end up being used).
if
!
lifetime
.is_elided
()
{
self
.visit_lifetime
(
lifetime
);
}
}
else
{
intravisit
::
walk_ty
(
self
,
ty
);
}
if
let
hir
::
TyBareFn
(
_
)
=
ty
.node
{
self
.binder_depth
-=
1
;
}
...
...
@@ -1045,6 +1319,10 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[hir::Lifetime]) {
}
return
;
}
Scope
::
ObjectLifetimeDefault
{
s
,
..
}
=>
{
scope
=
s
;
}
}
};
...
...
@@ -1134,6 +1412,28 @@ fn report_elision_failure(&mut self,
}
}
fn
resolve_object_lifetime_default
(
&
mut
self
,
lifetime_ref
:
&
hir
::
Lifetime
)
{
let
mut
late_depth
=
0
;
let
mut
scope
=
self
.scope
;
let
lifetime
=
loop
{
match
*
scope
{
Scope
::
Binder
{
s
,
..
}
=>
{
late_depth
+=
1
;
scope
=
s
;
}
Scope
::
Root
|
Scope
::
Elision
{
..
}
=>
break
Region
::
Static
,
Scope
::
Body
{
..
}
|
Scope
::
ObjectLifetimeDefault
{
lifetime
:
None
,
..
}
=>
return
,
Scope
::
ObjectLifetimeDefault
{
lifetime
:
Some
(
l
),
..
}
=>
break
l
}
};
self
.insert_lifetime
(
lifetime_ref
,
lifetime
.shifted
(
late_depth
));
}
fn
check_lifetime_defs
(
&
mut
self
,
old_scope
:
ScopeRef
,
lifetimes
:
&
[
hir
::
LifetimeDef
])
{
for
i
in
0
..
lifetimes
.len
()
{
let
lifetime_i
=
&
lifetimes
[
i
];
...
...
@@ -1192,7 +1492,8 @@ fn check_lifetime_def_for_shadowing(&self,
loop
{
match
*
old_scope
{
Scope
::
Body
{
s
,
..
}
|
Scope
::
Elision
{
s
,
..
}
=>
{
Scope
::
Elision
{
s
,
..
}
|
Scope
::
ObjectLifetimeDefault
{
s
,
..
}
=>
{
old_scope
=
s
;
}
...
...
src/librustc/ty/mod.rs
浏览文件 @
4eac052a
...
...
@@ -592,24 +592,6 @@ pub enum IntVarValue {
UintType
(
ast
::
UintTy
),
}
/// Default region to use for the bound of objects that are
/// supplied as the value for this type parameter. This is derived
/// from `T:'a` annotations appearing in the type definition. If
/// this is `None`, then the default is inherited from the
/// surrounding context. See RFC #599 for details.
#[derive(Copy,
Clone,
RustcEncodable,
RustcDecodable)]
pub
enum
ObjectLifetimeDefault
<
'tcx
>
{
/// Require an explicit annotation. Occurs when multiple
/// `T:'a` constraints are found.
Ambiguous
,
/// Use the base default, typically 'static, but in a fn body it is a fresh variable
BaseDefault
,
/// Use the given region as the default.
Specific
(
&
'tcx
Region
),
}
#[derive(Clone,
RustcEncodable,
RustcDecodable)]
pub
struct
TypeParameterDef
<
'tcx
>
{
pub
name
:
Name
,
...
...
@@ -617,7 +599,6 @@ pub struct TypeParameterDef<'tcx> {
pub
index
:
u32
,
pub
default_def_id
:
DefId
,
// for use in error reporing about defaults
pub
default
:
Option
<
Ty
<
'tcx
>>
,
pub
object_lifetime_default
:
ObjectLifetimeDefault
<
'tcx
>
,
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
/// on generic parameter `T`, asserts data behind the parameter
...
...
src/librustc/ty/structural_impls.rs
浏览文件 @
4eac052a
...
...
@@ -726,36 +726,12 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
index
:
self
.index
,
default
:
self
.default
.fold_with
(
folder
),
default_def_id
:
self
.default_def_id
,
object_lifetime_default
:
self
.object_lifetime_default
.fold_with
(
folder
),
pure_wrt_drop
:
self
.pure_wrt_drop
,
}
}
fn
super_visit_with
<
V
:
TypeVisitor
<
'tcx
>>
(
&
self
,
visitor
:
&
mut
V
)
->
bool
{
self
.default
.visit_with
(
visitor
)
||
self
.object_lifetime_default
.visit_with
(
visitor
)
}
}
impl
<
'tcx
>
TypeFoldable
<
'tcx
>
for
ty
::
ObjectLifetimeDefault
<
'tcx
>
{
fn
super_fold_with
<
'gcx
:
'tcx
,
F
:
TypeFolder
<
'gcx
,
'tcx
>>
(
&
self
,
folder
:
&
mut
F
)
->
Self
{
match
*
self
{
ty
::
ObjectLifetimeDefault
::
Ambiguous
=>
ty
::
ObjectLifetimeDefault
::
Ambiguous
,
ty
::
ObjectLifetimeDefault
::
BaseDefault
=>
ty
::
ObjectLifetimeDefault
::
BaseDefault
,
ty
::
ObjectLifetimeDefault
::
Specific
(
r
)
=>
ty
::
ObjectLifetimeDefault
::
Specific
(
r
.fold_with
(
folder
)),
}
}
fn
super_visit_with
<
V
:
TypeVisitor
<
'tcx
>>
(
&
self
,
visitor
:
&
mut
V
)
->
bool
{
match
*
self
{
ty
::
ObjectLifetimeDefault
::
Specific
(
r
)
=>
r
.visit_with
(
visitor
),
_
=>
false
,
}
self
.default
.visit_with
(
visitor
)
}
}
...
...
src/librustc/util/ppaux.rs
浏览文件 @
4eac052a
...
...
@@ -523,16 +523,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl
<
'tcx
>
fmt
::
Debug
for
ty
::
ObjectLifetimeDefault
<
'tcx
>
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
match
*
self
{
ty
::
ObjectLifetimeDefault
::
Ambiguous
=>
write!
(
f
,
"Ambiguous"
),
ty
::
ObjectLifetimeDefault
::
BaseDefault
=>
write!
(
f
,
"BaseDefault"
),
ty
::
ObjectLifetimeDefault
::
Specific
(
ref
r
)
=>
write!
(
f
,
"{:?}"
,
r
),
}
}
}
impl
fmt
::
Display
for
ty
::
Region
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
if
verbose
()
{
...
...
src/librustc_metadata/cstore_impl.rs
浏览文件 @
4eac052a
...
...
@@ -17,6 +17,7 @@
use
rustc
::
middle
::
cstore
::{
NativeLibrary
,
LinkMeta
,
LinkagePreference
,
LoadedMacro
};
use
rustc
::
hir
::
def
::{
self
,
Def
};
use
rustc
::
middle
::
lang_items
;
use
rustc
::
middle
::
resolve_lifetime
::
ObjectLifetimeDefault
;
use
rustc
::
session
::
Session
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
hir
::
def_id
::{
CrateNum
,
DefId
,
DefIndex
,
CRATE_DEF_INDEX
,
LOCAL_CRATE
};
...
...
@@ -115,6 +116,12 @@ fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) {
self
.get_crate_data
(
def
.krate
)
.generics_own_param_counts
(
def
.index
)
}
fn
item_generics_object_lifetime_defaults
(
&
self
,
def
:
DefId
)
->
Vec
<
ObjectLifetimeDefault
>
{
self
.dep_graph
.read
(
DepNode
::
MetaData
(
def
));
self
.get_crate_data
(
def
.krate
)
.generics_object_lifetime_defaults
(
def
.index
)
}
fn
item_attrs
(
&
self
,
def_id
:
DefId
)
->
Vec
<
ast
::
Attribute
>
{
self
.dep_graph
.read
(
DepNode
::
MetaData
(
def_id
));
...
...
src/librustc_metadata/decoder.rs
浏览文件 @
4eac052a
...
...
@@ -20,6 +20,7 @@
use
rustc
::
hir
::
def
::{
self
,
Def
,
CtorKind
};
use
rustc
::
hir
::
def_id
::{
CrateNum
,
DefId
,
DefIndex
,
CRATE_DEF_INDEX
,
LOCAL_CRATE
};
use
rustc
::
middle
::
lang_items
;
use
rustc
::
middle
::
resolve_lifetime
::
ObjectLifetimeDefault
;
use
rustc
::
session
::
Session
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
subst
::
Substs
;
...
...
@@ -614,6 +615,12 @@ pub fn generics_own_param_counts(&self, item_id: DefIndex) -> (usize, usize) {
(
g
.regions.len
,
g
.types.len
)
}
pub
fn
generics_object_lifetime_defaults
(
&
self
,
item_id
:
DefIndex
)
->
Vec
<
ObjectLifetimeDefault
>
{
self
.entry
(
item_id
)
.generics
.unwrap
()
.decode
(
self
)
.object_lifetime_defaults
.decode
(
self
)
.collect
()
}
pub
fn
get_type
(
&
self
,
id
:
DefIndex
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
)
->
Ty
<
'tcx
>
{
self
.entry
(
id
)
.ty
.unwrap
()
.decode
((
self
,
tcx
))
}
...
...
src/librustc_metadata/encoder.rs
浏览文件 @
4eac052a
...
...
@@ -422,6 +422,12 @@ fn encode_generics(&mut self, def_id: DefId) -> Lazy<Generics<'tcx>> {
let
g
=
tcx
.item_generics
(
def_id
);
let
regions
=
self
.lazy_seq_ref
(
&
g
.regions
);
let
types
=
self
.lazy_seq_ref
(
&
g
.types
);
let
mut
object_lifetime_defaults
=
LazySeq
::
empty
();
if
let
Some
(
id
)
=
tcx
.hir
.as_local_node_id
(
def_id
)
{
if
let
Some
(
o
)
=
tcx
.named_region_map.object_lifetime_defaults
.get
(
&
id
)
{
object_lifetime_defaults
=
self
.lazy_seq_ref
(
o
);
}
}
self
.lazy
(
&
Generics
{
parent
:
g
.parent
,
parent_regions
:
g
.parent_regions
,
...
...
@@ -429,6 +435,7 @@ fn encode_generics(&mut self, def_id: DefId) -> Lazy<Generics<'tcx>> {
regions
:
regions
,
types
:
types
,
has_self
:
g
.has_self
,
object_lifetime_defaults
:
object_lifetime_defaults
,
})
}
...
...
src/librustc_metadata/schema.rs
浏览文件 @
4eac052a
...
...
@@ -16,6 +16,7 @@
use
rustc
::
hir
::
def_id
::{
DefIndex
,
DefId
};
use
rustc
::
middle
::
cstore
::{
DepKind
,
LinkagePreference
,
NativeLibrary
};
use
rustc
::
middle
::
lang_items
;
use
rustc
::
middle
::
resolve_lifetime
::
ObjectLifetimeDefault
;
use
rustc
::
mir
;
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc_back
::
PanicStrategy
;
...
...
@@ -258,6 +259,7 @@ pub struct Generics<'tcx> {
pub
regions
:
LazySeq
<
ty
::
RegionParameterDef
<
'tcx
>>
,
pub
types
:
LazySeq
<
ty
::
TypeParameterDef
<
'tcx
>>
,
pub
has_self
:
bool
,
pub
object_lifetime_defaults
:
LazySeq
<
ObjectLifetimeDefault
>
,
}
#[derive(RustcEncodable,
RustcDecodable)]
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
4eac052a
此差异已折叠。
点击以展开。
src/librustc_typeck/check/mod.rs
浏览文件 @
4eac052a
...
...
@@ -97,7 +97,6 @@
use
rustc
::
ty
::
fold
::{
BottomUpFolder
,
TypeFoldable
};
use
rustc
::
ty
::
util
::{
Representability
,
IntTypeExt
};
use
require_c_abi_if_variadic
;
use
rscope
::
RegionScope
;
use
session
::{
Session
,
CompileResult
};
use
CrateCtxt
;
use
TypeAndSubsts
;
...
...
@@ -1411,12 +1410,12 @@ fn get_type_parameter_bounds(&self,
}
fn
re_infer
(
&
self
,
span
:
Span
,
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
&
'tcx
ty
::
Region
{
->
Option
<&
'tcx
ty
::
Region
>
{
let
v
=
match
def
{
Some
(
def
)
=>
infer
::
EarlyBoundRegion
(
span
,
def
.name
),
None
=>
infer
::
MiscVariable
(
span
)
};
self
.next_region_var
(
v
)
Some
(
self
.next_region_var
(
v
)
)
}
fn
ty_infer
(
&
self
,
span
:
Span
)
->
Ty
<
'tcx
>
{
...
...
@@ -1459,23 +1458,6 @@ fn set_tainted_by_errors(&self) {
}
}
impl
<
'a
,
'gcx
,
'tcx
>
RegionScope
for
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
span
:
Span
)
->
ty
::
Region
{
// RFC #599 specifies that object lifetime defaults take
// precedence over other defaults. But within a fn body we
// don't have a *default* region, rather we use inference to
// find the *correct* region, which is strictly more general
// (and anyway, within a fn body the right region may not even
// be something the user can write explicitly, since it might
// be some expression).
*
self
.next_region_var
(
infer
::
MiscVariable
(
span
))
}
}
/// Controls whether the arguments are tupled. This is used for the call
/// operator.
///
...
...
@@ -1832,7 +1814,7 @@ pub fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T
}
pub
fn
to_ty
(
&
self
,
ast_t
:
&
hir
::
Ty
)
->
Ty
<
'tcx
>
{
let
t
=
AstConv
::
ast_ty_to_ty
(
self
,
self
,
ast_t
);
let
t
=
AstConv
::
ast_ty_to_ty
(
self
,
ast_t
);
self
.register_wf_obligation
(
t
,
ast_t
.span
,
traits
::
MiscObligation
);
t
}
...
...
@@ -3976,7 +3958,7 @@ fn finish_resolving_struct_path(&self,
match
*
qpath
{
hir
::
QPath
::
Resolved
(
ref
maybe_qself
,
ref
path
)
=>
{
let
opt_self_ty
=
maybe_qself
.as_ref
()
.map
(|
qself
|
self
.to_ty
(
qself
));
let
ty
=
AstConv
::
def_to_ty
(
self
,
self
,
opt_self_ty
,
path
,
true
);
let
ty
=
AstConv
::
def_to_ty
(
self
,
opt_self_ty
,
path
,
true
);
(
path
.def
,
ty
)
}
hir
::
QPath
::
TypeRelative
(
ref
qself
,
ref
segment
)
=>
{
...
...
@@ -4411,7 +4393,7 @@ pub fn instantiate_value_path(&self,
if
let
Some
(
lifetime
)
=
lifetimes
.get
(
i
)
{
AstConv
::
ast_region_to_region
(
self
,
lifetime
,
Some
(
def
))
}
else
{
self
.re_infer
(
span
,
Some
(
def
))
self
.re_infer
(
span
,
Some
(
def
))
.unwrap
()
}
},
|
def
,
substs
|
{
let
mut
i
=
def
.index
as
usize
;
...
...
src/librustc_typeck/collect.rs
浏览文件 @
4eac052a
...
...
@@ -68,10 +68,9 @@
use
rustc
::
ty
::{
ToPredicate
,
ImplContainer
,
AssociatedItemContainer
,
TraitContainer
};
use
rustc
::
ty
::{
self
,
AdtKind
,
ToPolyTraitRef
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
util
::
IntTypeExt
;
use
rscope
::
*
;
use
rustc
::
dep_graph
::
DepNode
;
use
util
::
common
::{
ErrorReported
,
MemoizationMap
};
use
util
::
nodemap
::{
NodeMap
,
FxHashMap
,
FxHashSet
};
use
util
::
nodemap
::{
NodeMap
,
FxHashMap
};
use
CrateCtxt
;
use
rustc_const_math
::
ConstInt
;
...
...
@@ -373,8 +372,8 @@ fn ensure_super_predicates(&self, span: Span, trait_def_id: DefId)
}
impl
<
'a
,
'tcx
>
ItemCtxt
<
'a
,
'tcx
>
{
fn
to_ty
<
RS
:
RegionScope
>
(
&
self
,
rs
:
&
RS
,
ast_ty
:
&
hir
::
Ty
)
->
Ty
<
'tcx
>
{
AstConv
::
ast_ty_to_ty
(
self
,
rs
,
ast_ty
)
fn
to_ty
(
&
self
,
ast_ty
:
&
hir
::
Ty
)
->
Ty
<
'tcx
>
{
AstConv
::
ast_ty_to_ty
(
self
,
ast_ty
)
}
}
...
...
@@ -437,9 +436,9 @@ fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
None
}
fn
re_infer
(
&
self
,
span
:
Span
,
_
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
&
'tcx
ty
::
Region
{
span_bug!
(
span
,
"unelided lifetime in signature"
);
fn
re_infer
(
&
self
,
_
span
:
Span
,
_
def
:
Option
<&
ty
::
RegionParameterDef
>
)
->
Option
<&
'tcx
ty
::
Region
>
{
None
}
fn
ty_infer
(
&
self
,
span
:
Span
)
->
Ty
<
'tcx
>
{
...
...
@@ -631,7 +630,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
field
:
&
hir
::
StructField
,
ty_f
:
&
'tcx
ty
::
FieldDef
)
{
let
tt
=
ccx
.icx
(
struct_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
field
.ty
);
let
tt
=
ccx
.icx
(
struct_predicates
)
.to_ty
(
&
field
.ty
);
ccx
.tcx.item_types
.borrow_mut
()
.insert
(
ty_f
.did
,
tt
);
let
def_id
=
ccx
.tcx.hir
.local_def_id
(
field
.id
);
...
...
@@ -757,7 +756,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
hir
::
ItemDefaultImpl
(
_
,
ref
ast_trait_ref
)
=>
{
let
trait_ref
=
AstConv
::
instantiate_mono_trait_ref
(
&
ccx
.icx
(
&
()),
&
ExplicitRscope
,
ast_trait_ref
,
tcx
.mk_self_type
());
...
...
@@ -779,12 +777,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
debug!
(
"convert: impl_bounds={:?}"
,
ty_predicates
);
let
selfty
=
ccx
.icx
(
&
ty_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
selfty
);
let
selfty
=
ccx
.icx
(
&
ty_predicates
)
.to_ty
(
&
selfty
);
tcx
.item_types
.borrow_mut
()
.insert
(
def_id
,
selfty
);
let
trait_ref
=
opt_trait_ref
.as_ref
()
.map
(|
ast_trait_ref
|
{
AstConv
::
instantiate_mono_trait_ref
(
&
ccx
.icx
(
&
ty_predicates
),
&
ExplicitRscope
,
ast_trait_ref
,
selfty
)
});
...
...
@@ -850,8 +847,7 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
hir
::
TraitItemKind
::
Const
(
ref
ty
,
_
)
=>
{
let
const_def_id
=
ccx
.tcx.hir
.local_def_id
(
trait_item
.id
);
generics_of_def_id
(
ccx
,
const_def_id
);
let
ty
=
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
ty
);
let
ty
=
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ty
);
tcx
.item_types
.borrow_mut
()
.insert
(
const_def_id
,
ty
);
convert_associated_const
(
ccx
,
TraitContainer
(
trait_def_id
),
trait_item
.id
,
ty
);
...
...
@@ -862,7 +858,7 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
generics_of_def_id
(
ccx
,
type_def_id
);
let
typ
=
opt_ty
.as_ref
()
.map
({
|
ty
|
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
ty
)
|
ty
|
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ty
)
});
convert_associated_type
(
ccx
,
TraitContainer
(
trait_def_id
),
trait_item
.id
,
typ
);
...
...
@@ -887,8 +883,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
hir
::
ImplItemKind
::
Const
(
ref
ty
,
_
)
=>
{
let
const_def_id
=
ccx
.tcx.hir
.local_def_id
(
impl_item
.id
);
generics_of_def_id
(
ccx
,
const_def_id
);
let
ty
=
ccx
.icx
(
&
impl_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
ty
);
let
ty
=
ccx
.icx
(
&
impl_predicates
)
.to_ty
(
&
ty
);
tcx
.item_types
.borrow_mut
()
.insert
(
const_def_id
,
ty
);
convert_associated_const
(
ccx
,
ImplContainer
(
impl_def_id
),
impl_item
.id
,
ty
);
...
...
@@ -903,7 +898,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
"associated types are not allowed in inherent impls"
);
}
let
typ
=
ccx
.icx
(
&
impl_predicates
)
.to_ty
(
&
ExplicitRscope
,
ty
);
let
typ
=
ccx
.icx
(
&
impl_predicates
)
.to_ty
(
ty
);
convert_associated_type
(
ccx
,
ImplContainer
(
impl_def_id
),
impl_item
.id
,
Some
(
typ
));
}
...
...
@@ -1410,7 +1405,6 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def_id
:
tcx
.hir
.local_def_id
(
param_id
),
default_def_id
:
tcx
.hir
.local_def_id
(
parent
),
default
:
None
,
object_lifetime_default
:
ty
::
ObjectLifetimeDefault
::
BaseDefault
,
pure_wrt_drop
:
false
,
};
tcx
.ty_param_defs
.borrow_mut
()
.insert
(
param_id
,
def
.clone
());
...
...
@@ -1463,7 +1457,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let
type_start
=
own_start
+
regions
.len
()
as
u32
;
let
types
=
ast_generics
.ty_params
.iter
()
.enumerate
()
.map
(|(
i
,
p
)|
{
let
i
=
type_start
+
i
as
u32
;
get_or_create_type_parameter_def
(
ccx
,
ast_generics
,
i
,
p
,
allow_defaults
)
get_or_create_type_parameter_def
(
ccx
,
i
,
p
,
allow_defaults
)
});
let
mut
types
:
Vec
<
_
>
=
opt_self
.into_iter
()
.chain
(
types
)
.collect
();
...
...
@@ -1478,24 +1472,11 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def_id
:
def_id
,
default_def_id
:
parent_def_id
.unwrap
(),
default
:
None
,
object_lifetime_default
:
ty
::
ObjectLifetimeDefault
::
BaseDefault
,
pure_wrt_drop
:
false
,
}));
});
}
// Debugging aid.
if
tcx
.has_attr
(
def_id
,
"rustc_object_lifetime_default"
)
{
let
object_lifetime_default_reprs
:
String
=
types
.iter
()
.map
(|
t
|
{
match
t
.object_lifetime_default
{
ty
::
ObjectLifetimeDefault
::
Specific
(
r
)
=>
r
.to_string
(),
d
=>
format!
(
"{:?}"
,
d
),
}
})
.collect
::
<
Vec
<
String
>>
()
.join
(
","
);
tcx
.sess
.span_err
(
tcx
.hir
.span
(
node_id
),
&
object_lifetime_default_reprs
);
}
tcx
.alloc_generics
(
ty
::
Generics
{
parent
:
parent_def_id
,
parent_regions
:
parent_regions
,
...
...
@@ -1526,7 +1507,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
NodeItem
(
item
)
=>
{
match
item
.node
{
ItemStatic
(
ref
t
,
..
)
|
ItemConst
(
ref
t
,
_
)
=>
{
ccx
.icx
(
&
())
.to_ty
(
&
ExplicitRscope
,
&
t
)
ccx
.icx
(
&
())
.to_ty
(
&
t
)
}
ItemFn
(
ref
decl
,
unsafety
,
_
,
abi
,
ref
generics
,
_
)
=>
{
let
tofd
=
AstConv
::
ty_of_fn
(
&
ccx
.icx
(
generics
),
unsafety
,
abi
,
&
decl
);
...
...
@@ -1534,7 +1515,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ccx
.tcx
.mk_fn_def
(
def_id
,
substs
,
tofd
)
}
ItemTy
(
ref
t
,
ref
generics
)
=>
{
ccx
.icx
(
generics
)
.to_ty
(
&
ExplicitRscope
,
&
t
)
ccx
.icx
(
generics
)
.to_ty
(
&
t
)
}
ItemEnum
(
ref
ei
,
ref
generics
)
=>
{
let
def
=
convert_enum_def
(
ccx
,
item
,
ei
);
...
...
@@ -1575,7 +1556,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fn_decl
,
generics
,
abi
)
}
ForeignItemStatic
(
ref
t
,
_
)
=>
{
ccx
.icx
(
&
())
.to_ty
(
&
ExplicitRscope
,
t
)
ccx
.icx
(
&
())
.to_ty
(
t
)
}
}
}
...
...
@@ -1771,7 +1752,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
match
predicate
{
&
hir
::
WherePredicate
::
BoundPredicate
(
ref
bound_pred
)
=>
{
let
ty
=
AstConv
::
ast_ty_to_ty
(
&
ccx
.icx
(
&
(
base_predicates
,
ast_generics
)),
&
ExplicitRscope
,
&
bound_pred
.bounded_ty
);
for
bound
in
bound_pred
.bounds
.iter
()
{
...
...
@@ -1782,7 +1762,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let
trait_ref
=
AstConv
::
instantiate_poly_trait_ref
(
&
ccx
.icx
(
&
(
base_predicates
,
ast_generics
)),
&
ExplicitRscope
,
poly_trait_ref
,
ty
,
&
mut
projections
);
...
...
@@ -1827,7 +1806,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
fn
get_or_create_type_parameter_def
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
ast_generics
:
&
hir
::
Generics
,
index
:
u32
,
param
:
&
hir
::
TyParam
,
allow_defaults
:
bool
)
...
...
@@ -1840,11 +1818,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
let
default
=
param
.default
.as_ref
()
.map
(|
def
|
ccx
.icx
(
&
())
.to_ty
(
&
ExplicitRscope
,
def
));
let
object_lifetime_default
=
compute_object_lifetime_default
(
ccx
,
param
.id
,
&
param
.bounds
,
&
ast_generics
.where_clause
);
param
.default
.as_ref
()
.map
(|
def
|
ccx
.icx
(
&
())
.to_ty
(
def
));
let
parent
=
tcx
.hir
.get_parent
(
param
.id
);
...
...
@@ -1865,7 +1839,6 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
def_id
:
ccx
.tcx.hir
.local_def_id
(
param
.id
),
default_def_id
:
ccx
.tcx.hir
.local_def_id
(
parent
),
default
:
default
,
object_lifetime_default
:
object_lifetime_default
,
pure_wrt_drop
:
param
.pure_wrt_drop
,
};
...
...
@@ -1880,75 +1853,6 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
def
}
/// Scan the bounds and where-clauses on a parameter to extract bounds
/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
/// This runs as part of computing the minimal type scheme, so we
/// intentionally avoid just asking astconv to convert all the where
/// clauses into a `ty::Predicate`. This is because that could induce
/// artificial cycles.
fn
compute_object_lifetime_default
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
param_id
:
ast
::
NodeId
,
param_bounds
:
&
[
hir
::
TyParamBound
],
where_clause
:
&
hir
::
WhereClause
)
->
ty
::
ObjectLifetimeDefault
<
'tcx
>
{
let
inline_bounds
=
from_bounds
(
ccx
,
param_bounds
);
let
where_bounds
=
from_predicates
(
ccx
,
param_id
,
&
where_clause
.predicates
);
let
all_bounds
:
FxHashSet
<
_
>
=
inline_bounds
.into_iter
()
.chain
(
where_bounds
)
.collect
();
return
if
all_bounds
.len
()
>
1
{
ty
::
ObjectLifetimeDefault
::
Ambiguous
}
else
if
all_bounds
.len
()
==
0
{
ty
::
ObjectLifetimeDefault
::
BaseDefault
}
else
{
ty
::
ObjectLifetimeDefault
::
Specific
(
all_bounds
.into_iter
()
.next
()
.unwrap
())
};
fn
from_bounds
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
bounds
:
&
[
hir
::
TyParamBound
])
->
Vec
<&
'tcx
ty
::
Region
>
{
bounds
.iter
()
.filter_map
(|
bound
|
{
match
*
bound
{
hir
::
TraitTyParamBound
(
..
)
=>
None
,
hir
::
RegionTyParamBound
(
ref
lifetime
)
=>
Some
(
AstConv
::
ast_region_to_region
(
&
ccx
.icx
(
&
()),
lifetime
,
None
)),
}
})
.collect
()
}
fn
from_predicates
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
param_id
:
ast
::
NodeId
,
predicates
:
&
[
hir
::
WherePredicate
])
->
Vec
<&
'tcx
ty
::
Region
>
{
predicates
.iter
()
.flat_map
(|
predicate
|
{
match
*
predicate
{
hir
::
WherePredicate
::
BoundPredicate
(
ref
data
)
=>
{
if
data
.bound_lifetimes
.is_empty
()
&&
is_param
(
ccx
.tcx
,
&
data
.bounded_ty
,
param_id
)
{
from_bounds
(
ccx
,
&
data
.bounds
)
.into_iter
()
}
else
{
Vec
::
new
()
.into_iter
()
}
}
hir
::
WherePredicate
::
RegionPredicate
(
..
)
|
hir
::
WherePredicate
::
EqPredicate
(
..
)
=>
{
Vec
::
new
()
.into_iter
()
}
}
})
.collect
()
}
}
pub
enum
SizedByDefault
{
Yes
,
No
,
}
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
...
...
@@ -1978,8 +1882,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
let
mut
projection_bounds
=
vec!
[];
let
mut
trait_bounds
:
Vec
<
_
>
=
trait_bounds
.iter
()
.map
(|
&
bound
|
{
astconv
.instantiate_poly_trait_ref
(
&
ExplicitRscope
,
bound
,
astconv
.instantiate_poly_trait_ref
(
bound
,
param_ty
,
&
mut
projection_bounds
)
})
.collect
();
...
...
@@ -2017,8 +1920,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
match
*
bound
{
hir
::
TraitTyParamBound
(
ref
tr
,
hir
::
TraitBoundModifier
::
None
)
=>
{
let
mut
projections
=
Vec
::
new
();
let
pred
=
astconv
.instantiate_poly_trait_ref
(
&
ExplicitRscope
,
tr
,
let
pred
=
astconv
.instantiate_poly_trait_ref
(
tr
,
param_ty
,
&
mut
projections
);
projections
.into_iter
()
...
...
src/librustc_typeck/lib.rs
浏览文件 @
4eac052a
...
...
@@ -127,7 +127,6 @@
pub
mod
check
;
pub
mod
check_unused
;
mod
rscope
;
mod
astconv
;
pub
mod
collect
;
mod
constrained_type_params
;
...
...
src/librustc_typeck/rscope.rs
已删除
100644 → 0
浏览文件 @
c5befdc6
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
rustc
::
ty
;
use
syntax_pos
::
Span
;
/// Defines strategies for handling regions that are omitted. For
/// example, if one writes the type `&Foo`, then the lifetime of
/// this reference has been omitted. When converting this
/// type, the generic functions in astconv will invoke `anon_region`
/// on the provided region-scope to decide how to translate this
/// omitted region.
///
/// It is not always legal to omit regions, therefore `anon_region`
/// can return `Err(())` to indicate that this is not a scope in which
/// regions can legally be omitted.
pub
trait
RegionScope
{
/// If an object omits any explicit lifetime bound, and none can
/// be derived from the object traits, what should we use? If
/// `None` is returned, an explicit annotation is required.
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
;
/// The "base" default is the initial default for a scope. This is
/// 'static except for in fn bodies, where it is a fresh inference
/// variable. You shouldn't call this except for as part of
/// computing `object_lifetime_default` (in particular, in legacy
/// modes, it may not be relevant).
fn
base_object_lifetime_default
(
&
self
,
span
:
Span
)
->
ty
::
Region
;
}
// A scope in which all regions must be explicitly named. This is used
// for types that appear in structs and so on.
#[derive(Copy,
Clone)]
pub
struct
ExplicitRscope
;
impl
RegionScope
for
ExplicitRscope
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
Some
(
self
.base_object_lifetime_default
(
span
))
}
fn
base_object_lifetime_default
(
&
self
,
_
span
:
Span
)
->
ty
::
Region
{
ty
::
ReStatic
}
}
/// A scope which overrides the default object lifetime but has no other effect.
pub
struct
ObjectLifetimeDefaultRscope
<
'r
>
{
base_scope
:
&
'r
(
RegionScope
+
'r
),
default
:
ty
::
ObjectLifetimeDefault
<
'r
>
,
}
impl
<
'r
>
ObjectLifetimeDefaultRscope
<
'r
>
{
pub
fn
new
(
base_scope
:
&
'r
(
RegionScope
+
'r
),
default
:
ty
::
ObjectLifetimeDefault
<
'r
>
)
->
ObjectLifetimeDefaultRscope
<
'r
>
{
ObjectLifetimeDefaultRscope
{
base_scope
:
base_scope
,
default
:
default
,
}
}
}
impl
<
'r
>
RegionScope
for
ObjectLifetimeDefaultRscope
<
'r
>
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
match
self
.default
{
ty
::
ObjectLifetimeDefault
::
Ambiguous
=>
None
,
ty
::
ObjectLifetimeDefault
::
BaseDefault
=>
// NB: This behavior changed in Rust 1.3.
Some
(
self
.base_object_lifetime_default
(
span
)),
ty
::
ObjectLifetimeDefault
::
Specific
(
r
)
=>
Some
(
*
r
),
}
}
fn
base_object_lifetime_default
(
&
self
,
span
:
Span
)
->
ty
::
Region
{
self
.base_scope
.base_object_lifetime_default
(
span
)
}
}
/// A scope which simply shifts the Debruijn index of other scopes
/// to account for binding levels.
pub
struct
ShiftedRscope
<
'r
>
{
base_scope
:
&
'r
(
RegionScope
+
'r
)
}
impl
<
'r
>
ShiftedRscope
<
'r
>
{
pub
fn
new
(
base_scope
:
&
'r
(
RegionScope
+
'r
))
->
ShiftedRscope
<
'r
>
{
ShiftedRscope
{
base_scope
:
base_scope
}
}
}
impl
<
'r
>
RegionScope
for
ShiftedRscope
<
'r
>
{
fn
object_lifetime_default
(
&
self
,
span
:
Span
)
->
Option
<
ty
::
Region
>
{
self
.base_scope
.object_lifetime_default
(
span
)
.map
(|
r
|
ty
::
fold
::
shift_region
(
r
,
1
))
}
fn
base_object_lifetime_default
(
&
self
,
span
:
Span
)
->
ty
::
Region
{
ty
::
fold
::
shift_region
(
self
.base_scope
.base_object_lifetime_default
(
span
),
1
)
}
}
src/test/run-pass/object-lifetime-default-from-ref-struct.rs
浏览文件 @
4eac052a
...
...
@@ -15,6 +15,8 @@
#![allow(dead_code)]
use
std
::
fmt
::
Display
;
trait
Test
{
fn
foo
(
&
self
)
{
}
}
...
...
@@ -23,6 +25,11 @@ struct Ref<'a,T:'a+?Sized> {
r
:
&
'a
T
}
struct
Ref2
<
'a
,
'b
,
T
:
'a
+
'b
+?
Sized
>
{
a
:
&
'a
T
,
b
:
&
'b
T
}
struct
SomeStruct
<
'a
>
{
t
:
Ref
<
'a
,
Test
>
,
u
:
Ref
<
'a
,
Test
+
'a
>
,
...
...
@@ -44,6 +51,17 @@ fn d<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
ss
.u
=
t
;
}
fn
e
<
'a
>
(
_
:
Ref
<
'a
,
Display
+
'static
>
)
{}
fn
g
<
'a
,
'b
>
(
_
:
Ref2
<
'a
,
'b
,
Display
+
'static
>
)
{}
fn
main
()
{
// Inside a function body, we can just infer all
// lifetimes, to allow Ref<'tmp, Display+'static>
// and Ref2<'tmp, 'tmp, Display+'static>.
let
x
=
&
0
as
&
(
Display
+
'static
);
let
r
:
Ref
<
Display
>
=
Ref
{
r
:
x
};
let
r2
:
Ref2
<
Display
>
=
Ref2
{
a
:
x
,
b
:
x
};
e
(
r
);
g
(
r2
);
}
src/test/run-pass/object-lifetime-default-from-rptr.rs
浏览文件 @
4eac052a
...
...
@@ -15,6 +15,8 @@
#![allow(dead_code)]
use
std
::
fmt
::
Display
;
trait
Test
{
fn
foo
(
&
self
)
{
}
}
...
...
@@ -40,6 +42,10 @@ fn d<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
ss
.u
=
t
;
}
fn
e
<
'a
>
(
_
:
&
'a
(
Display
+
'static
))
{}
fn
main
()
{
// Inside a function body, we can just infer both
// lifetimes, to allow &'tmp (Display+'static).
e
(
&
0
as
&
Display
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录