Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
dc8a8e9b
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
dc8a8e9b
编写于
4月 03, 2015
作者:
N
Nick Cameron
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Check uses of `Self` in impls in the compiler rather than during expansion
Closes #23909
上级
5e30f05a
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
326 addition
and
219 deletion
+326
-219
src/librustc/middle/astencode.rs
src/librustc/middle/astencode.rs
+5
-1
src/librustc/middle/def.rs
src/librustc/middle/def.rs
+7
-5
src/librustc_privacy/lib.rs
src/librustc_privacy/lib.rs
+1
-1
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+94
-83
src/librustc_trans/save/mod.rs
src/librustc_trans/save/mod.rs
+1
-1
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+145
-72
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+11
-5
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+9
-8
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+2
-41
src/test/compile-fail/self-impl.rs
src/test/compile-fail/self-impl.rs
+32
-0
src/test/run-pass/self-impl.rs
src/test/run-pass/self-impl.rs
+19
-2
未找到文件。
src/librustc/middle/astencode.rs
浏览文件 @
dc8a8e9b
...
...
@@ -457,7 +457,11 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
def
::
DefMethod
(
did
,
p
)
=>
{
def
::
DefMethod
(
did
.tr
(
dcx
),
p
.map
(|
did2
|
did2
.tr
(
dcx
)))
}
def
::
DefSelfTy
(
nid
)
=>
{
def
::
DefSelfTy
(
dcx
.tr_id
(
nid
))
}
def
::
DefSelfTy
(
opt_did
,
impl_ids
)
=>
{
def
::
DefSelfTy
(
opt_did
.map
(|
did
|
did
.tr
(
dcx
)),
impl_ids
.map
(|(
nid1
,
nid2
)|
{
(
dcx
.tr_id
(
nid1
),
dcx
.tr_id
(
nid2
))
}))
}
def
::
DefMod
(
did
)
=>
{
def
::
DefMod
(
did
.tr
(
dcx
))
}
def
::
DefForeignMod
(
did
)
=>
{
def
::
DefForeignMod
(
did
.tr
(
dcx
))
}
def
::
DefStatic
(
did
,
m
)
=>
{
def
::
DefStatic
(
did
.tr
(
dcx
),
m
)
}
...
...
src/librustc/middle/def.rs
浏览文件 @
dc8a8e9b
...
...
@@ -22,7 +22,8 @@
#[derive(Clone,
Copy,
PartialEq,
Eq,
RustcEncodable,
RustcDecodable,
Hash,
Debug)]
pub
enum
Def
{
DefFn
(
ast
::
DefId
,
bool
/* is_ctor */
),
DefSelfTy
(
/* trait id */
ast
::
NodeId
),
DefSelfTy
(
Option
<
ast
::
DefId
>
,
// trait id
Option
<
(
ast
::
NodeId
,
ast
::
NodeId
)
>
),
// (impl id, self type id)
DefMod
(
ast
::
DefId
),
DefForeignMod
(
ast
::
DefId
),
DefStatic
(
ast
::
DefId
,
bool
/* is_mutbl */
),
...
...
@@ -139,18 +140,19 @@ pub fn def_id(&self) -> ast::DefId {
DefFn
(
id
,
_
)
|
DefMod
(
id
)
|
DefForeignMod
(
id
)
|
DefStatic
(
id
,
_
)
|
DefVariant
(
_
,
id
,
_
)
|
DefTy
(
id
,
_
)
|
DefAssociatedTy
(
_
,
id
)
|
DefTyParam
(
_
,
_
,
id
,
_
)
|
DefUse
(
id
)
|
DefStruct
(
id
)
|
DefTrait
(
id
)
|
DefMethod
(
id
,
_
)
|
DefConst
(
id
)
=>
{
DefMethod
(
id
,
_
)
|
DefConst
(
id
)
|
DefSelfTy
(
Some
(
id
),
None
)
=>
{
id
}
DefLocal
(
id
)
|
DefSelfTy
(
id
)
|
DefUpvar
(
id
,
_
)
|
DefRegion
(
id
)
|
DefLabel
(
id
)
=>
{
DefLabel
(
id
)
|
DefSelfTy
(
_
,
Some
((
_
,
id
)))
=>
{
local_def
(
id
)
}
DefPrimTy
(
_
)
=>
panic!
(
"attempted .def_id() on DefPrimTy"
)
DefPrimTy
(
_
)
=>
panic!
(
"attempted .def_id() on DefPrimTy"
),
DefSelfTy
(
..
)
=>
panic!
(
"attempted .def_id() on invalid DefSelfTy"
),
}
}
...
...
src/librustc_privacy/lib.rs
浏览文件 @
dc8a8e9b
...
...
@@ -1178,7 +1178,7 @@ fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
let
did
=
match
self
.tcx.def_map
.borrow
()
.get
(
&
path_id
)
.map
(|
d
|
d
.full_def
())
{
// `int` etc. (None doesn't seem to occur.)
None
|
Some
(
def
::
DefPrimTy
(
..
))
=>
return
false
,
Some
(
def
)
=>
def
.def_id
()
Some
(
def
)
=>
def
.def_id
()
,
};
// A path can only be private if:
// it's in this crate...
...
...
src/librustc_resolve/lib.rs
浏览文件 @
dc8a8e9b
...
...
@@ -1689,7 +1689,7 @@ fn upvarify(&self,
}
}
}
DefTyParam
(
..
)
|
DefSelfTy
(
_
)
=>
{
DefTyParam
(
..
)
|
DefSelfTy
(
..
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
|
MethodRibKind
|
ClosureRibKind
(
..
)
=>
{
...
...
@@ -1797,63 +1797,57 @@ fn resolve_item(&mut self, item: &Item) {
}
ItemDefaultImpl
(
_
,
ref
trait_ref
)
=>
{
self
.with_optional_trait_ref
(
Some
(
trait_ref
),
|
_
|
{});
self
.with_optional_trait_ref
(
Some
(
trait_ref
),
|
_
,
_
|
{});
}
ItemImpl
(
_
,
_
,
ItemImpl
(
_
,
_
,
ref
generics
,
ref
implemented_traits
,
ref
opt_trait_ref
,
ref
self_type
,
ref
impl_items
)
=>
{
self
.resolve_implementation
(
generics
,
implemented_traits
,
opt_trait_ref
,
&**
self_type
,
item
.id
,
&
impl_items
[
..
]);
}
ItemTrait
(
_
,
ref
generics
,
ref
bounds
,
ref
trait_items
)
=>
{
self
.check_if_primitive_type_name
(
name
,
item
.span
);
// Create a new rib for the self type.
let
mut
self_type_rib
=
Rib
::
new
(
ItemRibKind
);
// plain insert (no renaming, types are not currently hygienic....)
let
name
=
special_names
::
type_self
;
self_type_rib
.bindings
.insert
(
name
,
DlDef
(
DefSelfTy
(
item
.id
)));
self
.type_ribs
.push
(
self_type_rib
);
// Create a new rib for the trait-wide type parameters.
self
.with_type_parameter_rib
(
HasTypeParameters
(
generics
,
TypeSpace
,
NormalRibKind
),
|
this
|
{
this
.visit_generics
(
generics
);
visit
::
walk_ty_param_bounds_helper
(
this
,
bounds
);
for
trait_item
in
trait_items
{
// Create a new rib for the trait_item-specific type
// parameters.
//
// FIXME #4951: Do we need a node ID here?
let
type_parameters
=
match
trait_item
.node
{
ast
::
MethodTraitItem
(
ref
sig
,
_
)
=>
{
HasTypeParameters
(
&
sig
.generics
,
FnSpace
,
MethodRibKind
)
}
ast
::
TypeTraitItem
(
..
)
=>
{
this
.check_if_primitive_type_name
(
trait_item
.ident.name
,
trait_item
.span
);
NoTypeParameters
}
};
this
.with_type_parameter_rib
(
type_parameters
,
|
this
|
{
visit
::
walk_trait_item
(
this
,
trait_item
)
});
}
self
.with_self_rib
(
DefSelfTy
(
Some
(
local_def
(
item
.id
)),
None
),
|
this
|
{
// Create a new rib for the trait-wide type parameters.
this
.with_type_parameter_rib
(
HasTypeParameters
(
generics
,
TypeSpace
,
NormalRibKind
),
|
this
|
{
this
.visit_generics
(
generics
);
visit
::
walk_ty_param_bounds_helper
(
this
,
bounds
);
for
trait_item
in
trait_items
{
// Create a new rib for the trait_item-specific type
// parameters.
//
// FIXME #4951: Do we need a node ID here?
let
type_parameters
=
match
trait_item
.node
{
ast
::
MethodTraitItem
(
ref
sig
,
_
)
=>
{
HasTypeParameters
(
&
sig
.generics
,
FnSpace
,
MethodRibKind
)
}
ast
::
TypeTraitItem
(
..
)
=>
{
this
.check_if_primitive_type_name
(
trait_item
.ident.name
,
trait_item
.span
);
NoTypeParameters
}
};
this
.with_type_parameter_rib
(
type_parameters
,
|
this
|
{
visit
::
walk_trait_item
(
this
,
trait_item
)
});
}
});
});
self
.type_ribs
.pop
();
}
ItemMod
(
_
)
|
ItemForeignMod
(
_
)
=>
{
...
...
@@ -2030,8 +2024,8 @@ fn resolve_generics(&mut self, generics: &Generics) {
visit
::
walk_generics
(
self
,
generics
);
}
fn
with_current_self_type
<
T
,
F
>
(
&
mut
self
,
self_type
:
&
Ty
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
Resolver
)
->
T
,
fn
with_current_self_type
<
T
,
F
>
(
&
mut
self
,
self_type
:
&
Ty
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
Resolver
)
->
T
{
// Handle nested impls (inside fn bodies)
let
previous_value
=
replace
(
&
mut
self
.current_self_type
,
Some
(
self_type
.clone
()));
...
...
@@ -2044,29 +2038,44 @@ fn with_optional_trait_ref<T, F>(&mut self,
opt_trait_ref
:
Option
<&
TraitRef
>
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
Resolver
)
->
T
,
where
F
:
FnOnce
(
&
mut
Resolver
,
Option
<
DefId
>
)
->
T
{
let
mut
new_val
=
None
;
let
mut
new_id
=
None
;
if
let
Some
(
trait_ref
)
=
opt_trait_ref
{
match
self
.resolve_trait_reference
(
trait_ref
.ref_id
,
&
trait_ref
.path
,
0
)
{
Ok
(
path_res
)
=>
{
self
.record_def
(
trait_ref
.ref_id
,
path_res
);
new_val
=
Some
((
path_res
.base_def
.def_id
(),
trait_ref
.clone
())
);
}
Err
(
_
)
=>
{
/* error was already reported */
}
if
let
Ok
(
path_res
)
=
self
.resolve_trait_reference
(
trait_ref
.ref_id
,
&
trait_ref
.path
,
0
)
{
assert
!
(
path_res
.depth
==
0
);
self
.record_def
(
trait_ref
.ref_id
,
path_res
);
new_val
=
Some
((
path_res
.base_def
.def_id
(),
trait_ref
.clone
()));
new_id
=
Some
(
path_res
.base_def
.def_id
());
}
visit
::
walk_trait_ref
(
self
,
trait_ref
);
}
let
original_trait_ref
=
replace
(
&
mut
self
.current_trait_ref
,
new_val
);
let
result
=
f
(
self
);
let
result
=
f
(
self
,
new_id
);
self
.current_trait_ref
=
original_trait_ref
;
result
}
fn
with_self_rib
<
F
>
(
&
mut
self
,
self_def
:
Def
,
f
:
F
)
where
F
:
FnOnce
(
&
mut
Resolver
)
{
let
mut
self_type_rib
=
Rib
::
new
(
NormalRibKind
);
// plain insert (no renaming, types are not currently hygienic....)
let
name
=
special_names
::
type_self
;
self_type_rib
.bindings
.insert
(
name
,
DlDef
(
self_def
));
self
.type_ribs
.push
(
self_type_rib
);
f
(
self
);
self
.type_ribs
.pop
();
}
fn
resolve_implementation
(
&
mut
self
,
generics
:
&
Generics
,
opt_trait_reference
:
&
Option
<
TraitRef
>
,
self_type
:
&
Ty
,
item_id
:
NodeId
,
impl_items
:
&
[
P
<
ImplItem
>
])
{
// If applicable, create a rib for the type parameters.
self
.with_type_parameter_rib
(
HasTypeParameters
(
generics
,
...
...
@@ -2077,40 +2086,42 @@ fn resolve_implementation(&mut self,
this
.visit_generics
(
generics
);
// Resolve the trait reference, if necessary.
this
.with_optional_trait_ref
(
opt_trait_reference
.as_ref
(),
|
this
|
{
this
.with_optional_trait_ref
(
opt_trait_reference
.as_ref
(),
|
this
,
trait_id
|
{
// Resolve the self type.
this
.visit_ty
(
self_type
);
this
.with_current_self_type
(
self_type
,
|
this
|
{
for
impl_item
in
impl_items
{
match
impl_item
.node
{
MethodImplItem
(
ref
sig
,
_
)
=>
{
// If this is a trait impl, ensure the method
// exists in trait
this
.check_trait_item
(
impl_item
.ident.name
,
impl_item
.span
);
// We also need a new scope for the method-
// specific type parameters.
let
type_parameters
=
HasTypeParameters
(
&
sig
.generics
,
FnSpace
,
MethodRibKind
);
this
.with_type_parameter_rib
(
type_parameters
,
|
this
|
{
visit
::
walk_impl_item
(
this
,
impl_item
);
});
}
TypeImplItem
(
ref
ty
)
=>
{
// If this is a trait impl, ensure the method
// exists in trait
this
.check_trait_item
(
impl_item
.ident.name
,
impl_item
.span
);
this
.with_self_rib
(
DefSelfTy
(
trait_id
,
Some
((
item_id
,
self_type
.id
))),
|
this
|
{
this
.with_current_self_type
(
self_type
,
|
this
|
{
for
impl_item
in
impl_items
{
match
impl_item
.node
{
MethodImplItem
(
ref
sig
,
_
)
=>
{
// If this is a trait impl, ensure the method
// exists in trait
this
.check_trait_item
(
impl_item
.ident.name
,
impl_item
.span
);
// We also need a new scope for the method-
// specific type parameters.
let
type_parameters
=
HasTypeParameters
(
&
sig
.generics
,
FnSpace
,
MethodRibKind
);
this
.with_type_parameter_rib
(
type_parameters
,
|
this
|
{
visit
::
walk_impl_item
(
this
,
impl_item
);
});
}
TypeImplItem
(
ref
ty
)
=>
{
// If this is a trait impl, ensure the method
// exists in trait
this
.check_trait_item
(
impl_item
.ident.name
,
impl_item
.span
);
this
.visit_ty
(
ty
);
this
.visit_ty
(
ty
);
}
ast
::
MacImplItem
(
_
)
=>
{}
}
ast
::
MacImplItem
(
_
)
=>
{}
}
}
}
);
});
});
});
...
...
src/librustc_trans/save/mod.rs
浏览文件 @
dc8a8e9b
...
...
@@ -248,7 +248,7 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
def
::
DefFn
(
..
)
=>
Some
(
recorder
::
FnRef
),
def
::
DefSelfTy
(
_
)
|
def
::
DefSelfTy
(
..
)
|
def
::
DefRegion
(
_
)
|
def
::
DefLabel
(
_
)
|
def
::
DefTyParam
(
..
)
|
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
dc8a8e9b
...
...
@@ -56,7 +56,7 @@
use
middle
::
subst
::{
FnSpace
,
TypeSpace
,
SelfSpace
,
Subst
,
Substs
};
use
middle
::
traits
;
use
middle
::
ty
::{
self
,
RegionEscape
,
Ty
};
use
rscope
::{
self
,
UnelidableRscope
,
RegionScope
,
ElidableRscope
,
use
rscope
::{
self
,
UnelidableRscope
,
RegionScope
,
ElidableRscope
,
ExplicitRscope
,
ObjectLifetimeDefaultRscope
,
ShiftedRscope
,
BindingRscope
};
use
util
::
common
::{
ErrorReported
,
FN_OUTPUT_NAME
};
use
util
::
ppaux
::{
self
,
Repr
,
UserString
};
...
...
@@ -1041,53 +1041,30 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
type_str
,
trait_str
,
name
);
}
// Create a type from a a path to an associated type.
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
// and item_segment is the path segment for D. We return a type and a def for
// the whole path.
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
// parameter or Self.
fn
associated_path_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
,
// Search for a bound on a type parameter which includes the associated item
// given by assoc_name. We assume that ty_path_def is the def for such a type
// parameter (which might be `Self`). This function will fail if there are no
// suitable bounds or there is any ambiguity.
fn
find_bound_for_assoc_item
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
ty_path_def
:
def
::
Def
,
item_segment
:
&
ast
::
PathSegment
)
->
(
Ty
<
'tcx
>
,
def
::
Def
)
assoc_name
:
ast
::
Name
,
span
:
Span
)
->
Result
<
ty
::
PolyTraitRef
<
'tcx
>
,
ErrorReported
>
{
let
tcx
=
this
.tcx
();
let
assoc_name
=
item_segment
.identifier.name
;
debug!
(
"associated_path_def_to_ty: {}::{}"
,
ty
.repr
(
tcx
),
token
::
get_name
(
assoc_name
));
check_path_args
(
tcx
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
// Check that the path prefix given by ty/ty_path_def is a type parameter/Self.
match
(
&
ty
.sty
,
ty_path_def
)
{
(
&
ty
::
ty_param
(
_
),
def
::
DefTyParam
(
..
))
|
(
&
ty
::
ty_param
(
_
),
def
::
DefSelfTy
(
_
))
=>
{}
_
=>
{
report_ambiguous_associated_type
(
tcx
,
span
,
&
ty
.user_string
(
tcx
),
"Trait"
,
&
token
::
get_name
(
assoc_name
));
return
(
tcx
.types.err
,
ty_path_def
);
}
}
let
ty_param_node_id
=
ty_path_def
.local_node_id
();
let
ty_param_name
=
tcx
.ty_param_defs
.borrow
()
.get
(
&
ty_param_node_id
)
.unwrap
()
.name
;
let
bounds
=
match
this
.get_type_parameter_bounds
(
span
,
ty_param_node_id
)
{
Ok
(
v
)
=>
v
,
Err
(
ErrorReported
)
=>
{
return
(
tcx
.types.err
,
ty_path_def
);
return
Err
(
ErrorReported
);
}
};
// Ensure the super predicates and stop if we encountered an error.
if
bounds
.iter
()
.any
(|
b
|
this
.ensure_super_predicates
(
span
,
b
.def_id
())
.is_err
())
{
return
(
this
.tcx
()
.types.err
,
ty_path_def
);
return
Err
(
ErrorReported
);
}
// Check that there is exactly one way to find an associated type with the
...
...
@@ -1097,12 +1074,13 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
.filter
(|
b
|
this
.trait_defines_associated_type_named
(
b
.def_id
(),
assoc_name
))
.collect
();
let
ty_param_name
=
tcx
.ty_param_defs
.borrow
()
.get
(
&
ty_param_node_id
)
.unwrap
()
.name
;
if
suitable_bounds
.len
()
==
0
{
span_err!
(
tcx
.sess
,
span
,
E0220
,
"associated type `{}` not found for type parameter `{}`"
,
token
::
get_name
(
assoc_name
),
token
::
get_name
(
ty_param_name
));
return
(
this
.tcx
()
.types.err
,
ty_path_def
);
return
Err
(
ErrorReported
);
}
if
suitable_bounds
.len
()
>
1
{
...
...
@@ -1112,22 +1090,87 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
token
::
get_name
(
ty_param_name
));
for
suitable_bound
in
&
suitable_bounds
{
span_note!
(
t
his
.tcx
()
.sess
,
span
,
span_note!
(
t
cx
.sess
,
span
,
"associated type `{}` could derive from `{}`"
,
token
::
get_name
(
ty_param_name
),
suitable_bound
.user_string
(
t
his
.tcx
()
));
suitable_bound
.user_string
(
t
cx
));
}
}
let
suitable_bound
=
suitable_bounds
.pop
()
.unwrap
()
.clone
();
let
trait_did
=
suitable_bound
.0
.def_id
;
Ok
(
suitable_bounds
.pop
()
.unwrap
()
.clone
())
}
// Create a type from a a path to an associated type.
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
// and item_segment is the path segment for D. We return a type and a def for
// the whole path.
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
// parameter or Self.
fn
associated_path_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
,
ty_path_def
:
def
::
Def
,
item_segment
:
&
ast
::
PathSegment
)
->
(
Ty
<
'tcx
>
,
def
::
Def
)
{
let
tcx
=
this
.tcx
();
let
assoc_name
=
item_segment
.identifier.name
;
debug!
(
"associated_path_def_to_ty: {}::{}"
,
ty
.repr
(
tcx
),
token
::
get_name
(
assoc_name
));
check_path_args
(
tcx
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
let
ty
=
this
.projected_ty_from_poly_trait_ref
(
span
,
suitable_bound
,
assoc_name
);
// Find the type of the associated item, and the trait where the associated
// item is declared.
let
(
ty
,
trait_did
)
=
match
(
&
ty
.sty
,
ty_path_def
)
{
(
_
,
def
::
DefSelfTy
(
Some
(
trait_did
),
Some
((
impl_id
,
_
))))
=>
{
// `Self` in an impl of a trait - we have a concrete self type and a
// trait reference.
match
tcx
.map
.expect_item
(
impl_id
)
.node
{
ast
::
ItemImpl
(
_
,
_
,
_
,
Some
(
ref
trait_ref
),
_
,
_
)
=>
{
let
trait_segment
=
&
trait_ref
.path.segments
.last
()
.unwrap
();
let
trait_ref
=
ast_path_to_mono_trait_ref
(
this
,
&
ExplicitRscope
,
span
,
PathParamMode
::
Explicit
,
trait_did
,
Some
(
ty
),
trait_segment
);
let
ty
=
this
.projected_ty
(
span
,
trait_ref
,
assoc_name
);
(
ty
,
trait_did
)
}
_
=>
unreachable!
()
}
}
(
&
ty
::
ty_param
(
_
),
def
::
DefTyParam
(
..
))
|
(
&
ty
::
ty_param
(
_
),
def
::
DefSelfTy
(
Some
(
_
),
None
))
=>
{
// A type parameter or Self, we need to find the associated item from
// a bound.
let
bound
=
match
find_bound_for_assoc_item
(
this
,
ty_path_def
,
assoc_name
,
span
)
{
Ok
(
bound
)
=>
bound
,
Err
(
ErrorReported
)
=>
return
(
tcx
.types.err
,
ty_path_def
),
};
let
trait_did
=
bound
.0
.def_id
;
let
ty
=
this
.projected_ty_from_poly_trait_ref
(
span
,
bound
,
assoc_name
);
(
ty
,
trait_did
)
}
_
=>
{
println!
(
"{:?} {:?}"
,
ty
.sty
,
ty_path_def
);
report_ambiguous_associated_type
(
tcx
,
span
,
&
ty
.user_string
(
tcx
),
"Trait"
,
&
token
::
get_name
(
assoc_name
));
return
(
tcx
.types.err
,
ty_path_def
);
}
};
let
item_did
=
if
trait_did
.krate
==
ast
::
LOCAL_CRATE
{
// `ty::trait_items` used below requires information generated
// by type collection, which may be in progress at this point.
match
t
his
.tcx
()
.map
.expect_item
(
trait_did
.node
)
.node
{
match
t
cx
.map
.expect_item
(
trait_did
.node
)
.node
{
ast
::
ItemTrait
(
_
,
_
,
_
,
ref
trait_items
)
=>
{
let
item
=
trait_items
.iter
()
.find
(|
i
|
i
.ident.name
==
assoc_name
)
...
...
@@ -1137,7 +1180,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
_
=>
unreachable!
()
}
}
else
{
let
trait_items
=
ty
::
trait_items
(
t
his
.tcx
()
,
trait_did
);
let
trait_items
=
ty
::
trait_items
(
t
cx
,
trait_did
);
let
item
=
trait_items
.iter
()
.find
(|
i
|
i
.name
()
==
assoc_name
);
item
.expect
(
"missing associated type"
)
.def_id
()
};
...
...
@@ -1173,14 +1216,13 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
debug!
(
"qpath_to_ty: self_type={}"
,
self_ty
.repr
(
tcx
));
let
trait_ref
=
ast_path_to_mono_trait_ref
(
this
,
rscope
,
span
,
param_mode
,
trait_def_id
,
Some
(
self_ty
),
trait_segment
);
let
trait_ref
=
ast_path_to_mono_trait_ref
(
this
,
rscope
,
span
,
param_mode
,
trait_def_id
,
Some
(
self_ty
),
trait_segment
);
debug!
(
"qpath_to_ty: trait_ref={}"
,
trait_ref
.repr
(
tcx
));
...
...
@@ -1220,20 +1262,20 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
}
}
//
Note that both base_segments and assoc_segments may be empty, although not at
//
the same time.
pub
fn
finish_resolving_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
def
:
&
def
::
Def
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
base_segments
:
&
[
ast
::
PathSegment
]
,
assoc
_segments
:
&
[
ast
::
PathSegment
])
->
Ty
<
'tcx
>
{
//
Check the base def in a PathResolution and convert it to a Ty. If there are
//
associated types in the PathResolution, these will need to be seperately
// resolved.
fn
base_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
def
:
&
def
::
Def
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
base
_segments
:
&
[
ast
::
PathSegment
])
->
Ty
<
'tcx
>
{
let
tcx
=
this
.tcx
();
let
base_ty
=
match
*
def
{
match
*
def
{
def
::
DefTrait
(
trait_def_id
)
=>
{
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
...
...
@@ -1257,18 +1299,28 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
}
def
::
DefTy
(
did
,
_
)
|
def
::
DefStruct
(
did
)
=>
{
check_path_args
(
tcx
,
base_segments
.init
(),
NO_TPS
|
NO_REGIONS
);
ast_path_to_ty
(
this
,
rscope
,
span
,
param_mode
,
did
,
ast_path_to_ty
(
this
,
rscope
,
span
,
param_mode
,
did
,
base_segments
.last
()
.unwrap
())
}
def
::
DefTyParam
(
space
,
index
,
_
,
name
)
=>
{
check_path_args
(
tcx
,
base_segments
,
NO_TPS
|
NO_REGIONS
);
ty
::
mk_param
(
tcx
,
space
,
index
,
name
)
}
def
::
DefSelfTy
(
_
)
=>
{
// N.b.: resolve guarantees that the this type only appears in a
// trait, which we rely upon in various places when creating
// substs.
def
::
DefSelfTy
(
_
,
Some
((
_
,
self_ty_id
)))
=>
{
// Self in impl (we know the concrete type).
check_path_args
(
tcx
,
base_segments
,
NO_TPS
|
NO_REGIONS
);
if
let
Some
(
&
ty
)
=
tcx
.ast_ty_to_ty_cache
.borrow
()
.get
(
&
self_ty_id
)
{
ty
}
else
{
tcx
.sess
.span_bug
(
span
,
"self type has not been fully resolved"
)
}
}
def
::
DefSelfTy
(
Some
(
_
),
None
)
=>
{
// Self in trait.
check_path_args
(
tcx
,
base_segments
,
NO_TPS
|
NO_REGIONS
);
ty
::
mk_self_type
(
tcx
)
}
...
...
@@ -1288,6 +1340,9 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
// FIXME(#22519) This part of the resolution logic should be
// avoided entirely for that form, once we stop needed a Def
// for `associated_path_def_to_ty`.
// Fixing this will also let use resolve <Self>::Foo the same way we
// resolve Self::Foo, at the moment we can't resolve the former because
// we don't have the trait information around, which is just sad.
if
!
base_segments
.is_empty
()
{
span_err!
(
tcx
.sess
,
...
...
@@ -1308,11 +1363,29 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
"found value name used as a type: {:?}"
,
*
def
);
return
this
.tcx
()
.types.err
;
}
};
}
}
// If any associated type segments remain, attempt to resolve them.
let
mut
ty
=
base_ty
;
// Note that both base_segments and assoc_segments may be empty, although not at
// the same time.
pub
fn
finish_resolving_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
def
:
&
def
::
Def
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
base_segments
:
&
[
ast
::
PathSegment
],
assoc_segments
:
&
[
ast
::
PathSegment
])
->
Ty
<
'tcx
>
{
let
mut
ty
=
base_def_to_ty
(
this
,
rscope
,
span
,
param_mode
,
def
,
opt_self_ty
,
base_segments
);
let
mut
def
=
*
def
;
// If any associated type segments remain, attempt to resolve them.
for
segment
in
assoc_segments
{
if
ty
.sty
==
ty
::
ty_err
{
break
;
...
...
@@ -1996,7 +2069,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
check_type_argument_count
(
tcx
,
b
.trait_ref.path.span
,
parameters
.types
()
.len
(),
0
,
0
);
}
if
parameters
.lifetimes
()
.len
()
>
0
{
if
parameters
.lifetimes
()
.len
()
>
0
{
report_lifetime_number_error
(
tcx
,
b
.trait_ref.path.span
,
parameters
.lifetimes
()
.len
(),
0
);
}
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
dc8a8e9b
...
...
@@ -3341,11 +3341,17 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
let
def
=
path_res
.base_def
;
if
path_res
.depth
==
0
{
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
def
);
instantiate_path
(
fcx
,
&
path
.segments
,
scheme
,
&
predicates
,
opt_self_ty
,
def
,
expr
.span
,
id
);
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
def
);
instantiate_path
(
fcx
,
&
path
.segments
,
scheme
,
&
predicates
,
opt_self_ty
,
def
,
expr
.span
,
id
);
}
else
{
let
ty_segments
=
path
.segments
.init
();
let
base_ty_end
=
path
.segments
.len
()
-
path_res
.depth
;
...
...
src/librustc_typeck/collect.rs
浏览文件 @
dc8a8e9b
...
...
@@ -547,14 +547,15 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
if
let
ast
::
TyPath
(
None
,
_
)
=
ast_ty
.node
{
let
path_res
=
*
tcx
.def_map
.borrow
()
.get
(
&
ast_ty
.id
)
.unwrap
();
match
path_res
.base_def
{
def
::
DefSelfTy
(
node_id
)
=>
path_res
.depth
==
0
&&
node_id
==
param_id
,
def
::
DefTyParam
(
_
,
_
,
def_id
,
_
)
=>
path_res
.depth
==
0
&&
def_id
==
local_def
(
param_id
),
_
=>
false
,
def
::
DefSelfTy
(
Some
(
def_id
),
None
)
=>
{
path_res
.depth
==
0
&&
def_id
.node
==
param_id
}
def
::
DefTyParam
(
_
,
_
,
def_id
,
_
)
=>
{
path_res
.depth
==
0
&&
def_id
==
local_def
(
param_id
)
}
_
=>
{
false
}
}
}
else
{
false
...
...
src/libsyntax/ext/expand.rs
浏览文件 @
dc8a8e9b
...
...
@@ -14,7 +14,6 @@
use
ast
::{
StmtExpr
,
StmtSemi
};
use
ast
::
TokenTree
;
use
ast
;
use
ast_util
::
path_to_ident
;
use
ext
::
mtwt
;
use
ext
::
build
::
AstBuilder
;
use
attr
;
...
...
@@ -34,30 +33,6 @@
use
visit
::
Visitor
;
use
std_inject
;
pub
fn
expand_type
(
t
:
P
<
ast
::
Ty
>
,
fld
:
&
mut
MacroExpander
,
impl_ty
:
Option
<
P
<
ast
::
Ty
>>
)
->
P
<
ast
::
Ty
>
{
debug!
(
"expanding type {:?} with impl_ty {:?}"
,
t
,
impl_ty
);
let
t
=
match
(
t
.node
.clone
(),
impl_ty
)
{
// Expand uses of `Self` in impls to the concrete type.
(
ast
::
Ty_
::
TyPath
(
None
,
ref
path
),
Some
(
ref
impl_ty
))
=>
{
let
path_as_ident
=
path_to_ident
(
path
);
// Note unhygenic comparison here. I think this is correct, since
// even though `Self` is almost just a type parameter, the treatment
// for this expansion is as if it were a keyword.
if
path_as_ident
.is_some
()
&&
path_as_ident
.unwrap
()
.name
==
token
::
special_idents
::
type_self
.name
{
impl_ty
.clone
()
}
else
{
t
}
}
_
=>
t
};
fold
::
noop_fold_ty
(
t
,
fld
)
}
pub
fn
expand_expr
(
e
:
P
<
ast
::
Expr
>
,
fld
:
&
mut
MacroExpander
)
->
P
<
ast
::
Expr
>
{
e
.and_then
(|
ast
::
Expr
{
id
,
node
,
span
}|
match
node
{
// expr_mac should really be expr_ext or something; it's the
...
...
@@ -1354,13 +1329,11 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
/// A tree-folder that performs macro expansion
pub
struct
MacroExpander
<
'a
,
'b
:
'a
>
{
pub
cx
:
&
'a
mut
ExtCtxt
<
'b
>
,
// The type of the impl currently being expanded.
current_impl_type
:
Option
<
P
<
ast
::
Ty
>>
,
}
impl
<
'a
,
'b
>
MacroExpander
<
'a
,
'b
>
{
pub
fn
new
(
cx
:
&
'a
mut
ExtCtxt
<
'b
>
)
->
MacroExpander
<
'a
,
'b
>
{
MacroExpander
{
cx
:
cx
,
current_impl_type
:
None
}
MacroExpander
{
cx
:
cx
}
}
}
...
...
@@ -1374,14 +1347,7 @@ fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
}
fn
fold_item
(
&
mut
self
,
item
:
P
<
ast
::
Item
>
)
->
SmallVector
<
P
<
ast
::
Item
>>
{
let
prev_type
=
self
.current_impl_type
.clone
();
if
let
ast
::
Item_
::
ItemImpl
(
_
,
_
,
_
,
_
,
ref
ty
,
_
)
=
item
.node
{
self
.current_impl_type
=
Some
(
ty
.clone
());
}
let
result
=
expand_item
(
item
,
self
);
self
.current_impl_type
=
prev_type
;
result
expand_item
(
item
,
self
)
}
fn
fold_item_underscore
(
&
mut
self
,
item
:
ast
::
Item_
)
->
ast
::
Item_
{
...
...
@@ -1410,11 +1376,6 @@ fn fold_impl_item(&mut self, i: P<ast::ImplItem>) -> SmallVector<P<ast::ImplItem
.into_iter
()
.map
(|
i
|
i
.expect_impl_item
())
.collect
()
}
fn
fold_ty
(
&
mut
self
,
t
:
P
<
ast
::
Ty
>
)
->
P
<
ast
::
Ty
>
{
let
impl_type
=
self
.current_impl_type
.clone
();
expand_type
(
t
,
self
,
impl_type
)
}
fn
new_span
(
&
mut
self
,
span
:
Span
)
->
Span
{
new_span
(
self
.cx
,
span
)
}
...
...
src/test/compile-fail/self-impl.rs
0 → 100644
浏览文件 @
dc8a8e9b
// Copyright 2015 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.
// Test that unsupported uses of `Self` in impls don't crash
struct
Bar
;
trait
Foo
{
type
Baz
;
}
impl
Foo
for
Bar
{
type
Baz
=
bool
;
}
impl
Bar
{
fn
f
()
{
let
_
:
<
Self
>
::
Baz
=
true
;
//~^ERROR: ambiguous associated type; specify the type using the syntax `<Bar as Trait>::Baz`
let
_
:
Self
::
Baz
=
true
;
//~^ERROR: ambiguous associated type; specify the type using the syntax `<Bar as Trait>::Baz`
}
}
fn
main
()
{}
src/test/run-pass/self-impl.rs
浏览文件 @
dc8a8e9b
...
...
@@ -22,6 +22,17 @@ impl Foo {
fn
foo
(
_
x
:
Self
,
_
y
:
&
Self
,
_
z
:
Box
<
Self
>
)
->
Self
{
Foo
}
fn
baz
()
{
// Test that Self cannot be shadowed.
type
Foo
=
i32
;
// There is no empty method on i32.
Self
::
empty
();
let
_
:
Self
=
Foo
;
}
fn
empty
()
{}
}
// Test uses when implementing a trait and with a type parameter.
...
...
@@ -30,12 +41,18 @@ pub struct Baz<X> {
}
trait
Bar
<
X
>
{
type
Qux
;
fn
bar
(
x
:
Self
,
y
:
&
Self
,
z
:
Box
<
Self
>
)
->
Self
;
fn
dummy
(
&
self
,
x
:
X
)
{
}
}
impl
Bar
<
isize
>
for
Box
<
Baz
<
isize
>>
{
type
Qux
=
i32
;
fn
bar
(
_
x
:
Self
,
_
y
:
&
Self
,
_
z
:
Box
<
Self
>
)
->
Self
{
let
_
:
Self
::
Qux
=
42
;
let
_
:
<
Self
as
Bar
<
isize
>>
::
Qux
=
42
;
box
Baz
{
f
:
42
}
}
}
...
...
@@ -43,6 +60,6 @@ fn bar(_x: Self, _y: &Self, _z: Box<Self>) -> Self {
fn
main
()
{
let
_
:
Foo
=
Foo
::
foo
(
Foo
,
&
Foo
,
box
Foo
);
let
_
:
Box
<
Baz
<
isize
>>
=
Bar
::
bar
(
box
Baz
{
f
:
42
},
&
box
Baz
{
f
:
42
},
box
box
Baz
{
f
:
42
});
&
box
Baz
{
f
:
42
},
box
box
Baz
{
f
:
42
});
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录