Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
efc45758
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,发现更多精彩内容 >>
提交
efc45758
编写于
12月 27, 2015
作者:
A
Ariel Ben-Yehuda
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rewrite the method-receiver matching code
the old code was *so terrible*.
上级
2ced1499
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
164 addition
and
359 deletion
+164
-359
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/mod.rs
+0
-1
src/librustc/middle/ty/sty.rs
src/librustc/middle/ty/sty.rs
+0
-1
src/librustc/util/ppaux.rs
src/librustc/util/ppaux.rs
+1
-2
src/librustc_driver/test.rs
src/librustc_driver/test.rs
+0
-1
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tydecode.rs
+0
-2
src/librustc_metadata/tyencode.rs
src/librustc_metadata/tyencode.rs
+1
-2
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+34
-69
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/wfcheck.rs
+47
-3
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+63
-259
src/librustc_typeck/variance.rs
src/librustc_typeck/variance.rs
+4
-2
src/test/compile-fail/issue-17740.rs
src/test/compile-fail/issue-17740.rs
+4
-4
src/test/compile-fail/issue-17905.rs
src/test/compile-fail/issue-17905.rs
+0
-4
src/test/compile-fail/issue-26194.rs
src/test/compile-fail/issue-26194.rs
+1
-1
src/test/compile-fail/ufcs-explicit-self-bad.rs
src/test/compile-fail/ufcs-explicit-self-bad.rs
+9
-8
未找到文件。
src/librustc/middle/ty/mod.rs
浏览文件 @
efc45758
...
...
@@ -633,7 +633,6 @@ pub struct RegionParameterDef {
impl
RegionParameterDef
{
pub
fn
to_early_bound_region
(
&
self
)
->
ty
::
Region
{
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
self
.def_id
,
space
:
self
.space
,
index
:
self
.index
,
name
:
self
.name
,
...
...
src/librustc/middle/ty/sty.rs
浏览文件 @
efc45758
...
...
@@ -695,7 +695,6 @@ pub enum Region {
#[derive(Copy,
Clone,
PartialEq,
Eq,
Hash,
RustcEncodable,
RustcDecodable,
Debug)]
pub
struct
EarlyBoundRegion
{
pub
def_id
:
DefId
,
pub
space
:
subst
::
ParamSpace
,
pub
index
:
u32
,
pub
name
:
Name
,
...
...
src/librustc/util/ppaux.rs
浏览文件 @
efc45758
...
...
@@ -462,8 +462,7 @@ impl fmt::Debug for ty::Region {
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
match
*
self
{
ty
::
ReEarlyBound
(
ref
data
)
=>
{
write!
(
f
,
"ReEarlyBound({:?}, {:?}, {}, {})"
,
data
.def_id
,
write!
(
f
,
"ReEarlyBound({:?}, {}, {})"
,
data
.space
,
data
.index
,
data
.name
)
...
...
src/librustc_driver/test.rs
浏览文件 @
efc45758
...
...
@@ -289,7 +289,6 @@ pub fn re_early_bound(&self,
->
ty
::
Region
{
let
name
=
token
::
intern
(
name
);
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
self
.infcx.tcx.map
.local_def_id
(
ast
::
DUMMY_NODE_ID
),
space
:
space
,
index
:
index
,
name
:
name
,
...
...
src/librustc_metadata/tydecode.rs
浏览文件 @
efc45758
...
...
@@ -192,14 +192,12 @@ pub fn parse_region(&mut self) -> ty::Region {
}
'B'
=>
{
assert_eq!
(
self
.next
(),
'['
);
let
def_id
=
self
.parse_def
();
let
space
=
self
.parse_param_space
();
assert_eq!
(
self
.next
(),
'|'
);
let
index
=
self
.parse_u32
();
assert_eq!
(
self
.next
(),
'|'
);
let
name
=
token
::
intern
(
&
self
.parse_str
(
']'
));
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
def_id
,
space
:
space
,
index
:
index
,
name
:
name
...
...
src/librustc_metadata/tyencode.rs
浏览文件 @
efc45758
...
...
@@ -253,8 +253,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
mywrite!
(
w
,
"]"
);
}
ty
::
ReEarlyBound
(
ref
data
)
=>
{
mywrite!
(
w
,
"B[{}|{}|{}|{}]"
,
(
cx
.ds
)(
data
.def_id
),
mywrite!
(
w
,
"B[{}|{}|{}]"
,
data
.space
.to_uint
(),
data
.index
,
data
.name
);
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
efc45758
...
...
@@ -57,7 +57,7 @@
use
middle
::
privacy
::{
AllPublic
,
LastMod
};
use
middle
::
subst
::{
FnSpace
,
TypeSpace
,
SelfSpace
,
Subst
,
Substs
,
ParamSpace
};
use
middle
::
traits
;
use
middle
::
ty
::{
self
,
RegionEscape
,
Ty
,
ToPredicate
,
HasTypeFlags
};
use
middle
::
ty
::{
self
,
Ty
,
ToPredicate
,
HasTypeFlags
};
use
middle
::
ty
::
wf
::
object_region_bounds
;
use
require_c_abi_if_variadic
;
use
rscope
::{
self
,
UnelidableRscope
,
RegionScope
,
ElidableRscope
,
...
...
@@ -169,10 +169,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
ty
::
ReLateBound
(
debruijn
,
ty
::
BrNamed
(
tcx
.map
.local_def_id
(
id
),
lifetime
.name
))
}
Some
(
&
rl
::
DefEarlyBoundRegion
(
space
,
index
,
id
))
=>
{
let
def_id
=
tcx
.map
.local_def_id
(
id
);
Some
(
&
rl
::
DefEarlyBoundRegion
(
space
,
index
,
_
))
=>
{
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
def_id
,
space
:
space
,
index
:
index
,
name
:
lifetime
.name
...
...
@@ -1797,75 +1795,31 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
// lifetime elision, we can determine it in two ways. First (determined
// here), if self is by-reference, then the implied output region is the
// region of the self parameter.
let
mut
explicit_self_category_result
=
None
;
let
(
self_ty
,
implied_output_region
)
=
match
opt_self_info
{
let
(
self_ty
,
explicit_self_category
)
=
match
opt_self_info
{
None
=>
(
None
,
None
),
Some
(
self_info
)
=>
{
// This type comes from an impl or trait; no late-bound
// regions should be present.
assert
!
(
!
self_info
.untransformed_self_ty
.has_escaping_regions
());
// Figure out and record the explicit self category.
let
explicit_self_category
=
determine_explicit_self_category
(
this
,
&
rb
,
&
self_info
);
explicit_self_category_result
=
Some
(
explicit_self_category
);
match
explicit_self_category
{
ty
::
StaticExplicitSelfCategory
=>
{
(
None
,
None
)
}
ty
::
ByValueExplicitSelfCategory
=>
{
(
Some
(
self_info
.untransformed_self_ty
),
None
)
}
ty
::
ByReferenceExplicitSelfCategory
(
region
,
mutability
)
=>
{
(
Some
(
this
.tcx
()
.mk_ref
(
this
.tcx
()
.mk_region
(
region
),
ty
::
TypeAndMut
{
ty
:
self_info
.untransformed_self_ty
,
mutbl
:
mutability
})),
Some
(
region
))
}
ty
::
ByBoxExplicitSelfCategory
=>
{
(
Some
(
this
.tcx
()
.mk_box
(
self_info
.untransformed_self_ty
)),
None
)
}
}
}
Some
(
self_info
)
=>
determine_self_type
(
this
,
&
rb
,
self_info
)
};
// HACK(eddyb) replace the fake self type in the AST with the actual type.
let
input
_params
=
if
self_ty
.is_some
()
{
let
arg
_params
=
if
self_ty
.is_some
()
{
&
decl
.inputs
[
1
..
]
}
else
{
&
decl
.inputs
[
..
]
};
let
input_tys
=
input_params
.iter
()
.map
(|
a
|
ty_of_arg
(
this
,
&
rb
,
a
,
None
));
let
input_pats
:
Vec
<
String
>
=
input_params
.iter
()
.map
(|
a
|
pprust
::
pat_to_string
(
&*
a
.pat
))
.collect
();
let
self_and_input_tys
:
Vec
<
Ty
>
=
self_ty
.into_iter
()
.chain
(
input_tys
)
.collect
();
let
arg_tys
:
Vec
<
Ty
>
=
arg_params
.iter
()
.map
(|
a
|
ty_of_arg
(
this
,
&
rb
,
a
,
None
))
.collect
();
let
arg_pats
:
Vec
<
String
>
=
arg_params
.iter
()
.map
(|
a
|
pprust
::
pat_to_string
(
&*
a
.pat
))
.collect
();
// Second, if there was exactly one lifetime (either a substitution or a
// reference) in the arguments, then any anonymous regions in the output
// have that lifetime.
let
implied_output_region
=
match
implied_output_region
{
Some
(
r
)
=>
Ok
(
r
),
None
=>
{
let
input_tys
=
if
self_ty
.is_some
()
{
// Skip the first argument if `self` is present.
&
self_and_input_tys
[
1
..
]
}
else
{
&
self_and_input_tys
[
..
]
};
find_implied_output_region
(
this
.tcx
(),
input_tys
,
input_pats
)
}
let
implied_output_region
=
match
explicit_self_category
{
Some
(
ty
::
ByReferenceExplicitSelfCategory
(
region
,
_
))
=>
Ok
(
region
),
_
=>
find_implied_output_region
(
this
.tcx
(),
&
arg_tys
,
arg_pats
)
};
let
output_ty
=
match
decl
.output
{
hir
::
Return
(
ref
output
)
if
output
.node
==
hir
::
TyInfer
=>
ty
::
FnConverging
(
this
.ty_infer
(
None
,
None
,
None
,
output
.span
)),
hir
::
Return
(
ref
output
)
=>
ty
::
FnConverging
(
convert_ty_with_lifetime_elision
(
this
,
implied_output_region
,
...
...
@@ -1878,28 +1832,37 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
unsafety
:
unsafety
,
abi
:
abi
,
sig
:
ty
::
Binder
(
ty
::
FnSig
{
inputs
:
self_
and_input_tys
,
inputs
:
self_
ty
.into_iter
()
.chain
(
arg_tys
)
.collect
()
,
output
:
output_ty
,
variadic
:
decl
.variadic
}),
},
explicit_self_category
_result
)
},
explicit_self_category
)
}
fn
determine_
explicit_self_category
<
'a
,
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
self_info
:
&
SelfInfo
<
'a
,
'tcx
>
)
->
ty
::
ExplicitSelfCategory
fn
determine_
self_type
<
'a
,
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
self_info
:
SelfInfo
<
'a
,
'tcx
>
)
->
(
Option
<
Ty
<
'tcx
>>
,
Option
<
ty
::
ExplicitSelfCategory
>
)
{
let
self_ty
=
self_info
.untransformed_self_ty
;
return
match
self_info
.explicit_self.node
{
hir
::
SelfStatic
=>
ty
::
StaticExplicitSelfCategory
,
hir
::
SelfValue
(
_
)
=>
ty
::
ByValueExplicitSelfCategory
,
hir
::
SelfStatic
=>
(
None
,
Some
(
ty
::
StaticExplicitSelfCategory
)),
hir
::
SelfValue
(
_
)
=>
{
(
Some
(
self_ty
),
Some
(
ty
::
ByValueExplicitSelfCategory
))
}
hir
::
SelfRegion
(
ref
lifetime
,
mutability
,
_
)
=>
{
let
region
=
opt_ast_region_to_region
(
this
,
rscope
,
self_info
.explicit_self.span
,
lifetime
);
ty
::
ByReferenceExplicitSelfCategory
(
region
,
mutability
)
(
Some
(
this
.tcx
()
.mk_ref
(
this
.tcx
()
.mk_region
(
region
),
ty
::
TypeAndMut
{
ty
:
self_ty
,
mutbl
:
mutability
})),
Some
(
ty
::
ByReferenceExplicitSelfCategory
(
region
,
mutability
)))
}
hir
::
SelfExplicit
(
ref
ast_type
,
_
)
=>
{
let
explicit_type
=
ast_ty_to_ty
(
this
,
rscope
,
&**
ast_type
);
...
...
@@ -1944,7 +1907,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
impl_modifiers
,
method_modifiers
);
if
impl_modifiers
>=
method_modifiers
{
let
category
=
if
impl_modifiers
>=
method_modifiers
{
ty
::
ByValueExplicitSelfCategory
}
else
{
match
explicit_type
.sty
{
...
...
@@ -1952,7 +1915,9 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
ty
::
TyBox
(
_
)
=>
ty
::
ByBoxExplicitSelfCategory
,
_
=>
ty
::
ByValueExplicitSelfCategory
,
}
}
};
(
Some
(
explicit_type
),
Some
(
category
))
}
};
...
...
src/librustc_typeck/check/wfcheck.rs
浏览文件 @
efc45758
...
...
@@ -136,9 +136,10 @@ fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
let
item
=
fcx
.tcx
()
.impl_or_trait_item
(
fcx
.tcx
()
.map
.local_def_id
(
item_id
));
let
mut
implied_bounds
=
match
item
.container
()
{
ty
::
TraitContainer
(
_
)
=>
vec!
[],
ty
::
ImplContainer
(
def_id
)
=>
impl_implied_bounds
(
fcx
,
def_id
,
span
)
let
(
mut
implied_bounds
,
self_ty
)
=
match
item
.container
()
{
ty
::
TraitContainer
(
_
)
=>
(
vec!
[],
fcx
.tcx
()
.mk_self_type
()),
ty
::
ImplContainer
(
def_id
)
=>
(
impl_implied_bounds
(
fcx
,
def_id
,
span
),
fcx
.tcx
()
.lookup_item_type
(
def_id
)
.ty
)
};
match
item
{
...
...
@@ -152,6 +153,8 @@ fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
let
predicates
=
fcx
.instantiate_bounds
(
span
,
free_substs
,
&
method
.predicates
);
this
.check_fn_or_method
(
fcx
,
span
,
&
method_ty
,
&
predicates
,
free_id_outlive
,
&
mut
implied_bounds
);
this
.check_method_receiver
(
fcx
,
span
,
&
method
,
free_id_outlive
,
self_ty
);
}
ty
::
TypeTraitItem
(
assoc_type
)
=>
{
if
let
Some
(
ref
ty
)
=
assoc_type
.ty
{
...
...
@@ -377,6 +380,47 @@ fn check_fn_or_method<'fcx>(&mut self,
self
.check_where_clauses
(
fcx
,
span
,
predicates
);
}
fn
check_method_receiver
<
'fcx
>
(
&
mut
self
,
fcx
:
&
FnCtxt
<
'fcx
,
'tcx
>
,
span
:
Span
,
method
:
&
ty
::
Method
<
'tcx
>
,
free_id_outlive
:
CodeExtent
,
self_ty
:
ty
::
Ty
<
'tcx
>
)
{
// check that the type of the method's receiver matches the
// method's first parameter.
let
free_substs
=
&
fcx
.inh.infcx.parameter_environment.free_substs
;
let
fty
=
fcx
.instantiate_type_scheme
(
span
,
free_substs
,
&
method
.fty
);
let
sig
=
fcx
.tcx
()
.liberate_late_bound_regions
(
free_id_outlive
,
&
fty
.sig
);
debug!
(
"check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})"
,
method
.name
,
method
.explicit_self
,
self_ty
,
sig
);
let
rcvr_ty
=
match
method
.explicit_self
{
ty
::
StaticExplicitSelfCategory
=>
return
,
ty
::
ByValueExplicitSelfCategory
=>
self_ty
,
ty
::
ByReferenceExplicitSelfCategory
(
region
,
mutability
)
=>
{
fcx
.tcx
()
.mk_ref
(
fcx
.tcx
()
.mk_region
(
region
),
ty
::
TypeAndMut
{
ty
:
self_ty
,
mutbl
:
mutability
})
}
ty
::
ByBoxExplicitSelfCategory
=>
fcx
.tcx
()
.mk_box
(
self_ty
)
};
let
rcvr_ty
=
fcx
.instantiate_type_scheme
(
span
,
free_substs
,
&
rcvr_ty
);
let
rcvr_ty
=
fcx
.tcx
()
.liberate_late_bound_regions
(
free_id_outlive
,
&
ty
::
Binder
(
rcvr_ty
));
debug!
(
"check_method_receiver: receiver ty = {:?}"
,
rcvr_ty
);
let
_
=
::
require_same_types
(
fcx
.tcx
(),
Some
(
fcx
.infcx
()),
false
,
span
,
sig
.inputs
[
0
],
rcvr_ty
,
||
"mismatched method receiver"
.to_owned
()
);
}
fn
check_variances_for_type_defn
(
&
self
,
item
:
&
hir
::
Item
,
ast_generics
:
&
hir
::
Generics
)
...
...
src/librustc_typeck/collect.rs
浏览文件 @
efc45758
...
...
@@ -69,18 +69,15 @@
use
middle
::
def_id
::
DefId
;
use
constrained_type_params
as
ctp
;
use
middle
::
lang_items
::
SizedTraitLangItem
;
use
middle
::
free_region
::
FreeRegionMap
;
use
middle
::
region
;
use
middle
::
resolve_lifetime
;
use
middle
::
const_eval
::{
self
,
ConstVal
};
use
middle
::
const_eval
::
EvalHint
::
UncheckedExprHint
;
use
middle
::
subst
::{
Substs
,
FnSpace
,
ParamSpace
,
SelfSpace
,
TypeSpace
,
VecPerParamSpace
};
use
middle
::
ty
::{
ToPredicate
,
ImplContainer
,
ImplOrTraitItemContainer
,
TraitContainer
};
use
middle
::
ty
::{
self
,
RegionEscape
,
ToPolyTraitRef
,
Ty
,
TypeScheme
};
use
middle
::
ty
::{
self
,
ToPolyTraitRef
,
Ty
,
TypeScheme
};
use
middle
::
ty
::{
VariantKind
};
use
middle
::
ty
::
fold
::{
TypeFolder
,
TypeFoldable
};
use
middle
::
ty
::
fold
::{
TypeFolder
};
use
middle
::
ty
::
util
::
IntTypeExt
;
use
middle
::
infer
;
use
rscope
::
*
;
use
rustc
::
front
::
map
as
hir_map
;
use
util
::
common
::{
ErrorReported
,
memoized
};
...
...
@@ -195,16 +192,6 @@ fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,
ItemCtxt
{
ccx
:
self
,
param_bounds
:
param_bounds
}
}
fn
method_ty
(
&
self
,
method_id
:
ast
::
NodeId
)
->
Rc
<
ty
::
Method
<
'tcx
>>
{
let
def_id
=
self
.tcx.map
.local_def_id
(
method_id
);
match
*
self
.tcx.impl_or_trait_items
.borrow
()
.get
(
&
def_id
)
.unwrap
()
{
ty
::
MethodTraitItem
(
ref
mty
)
=>
mty
.clone
(),
_
=>
{
self
.tcx.sess
.bug
(
&
format!
(
"method with id {} has the wrong type"
,
method_id
));
}
}
}
fn
cycle_check
<
F
,
R
>
(
&
self
,
span
:
Span
,
request
:
AstConvRequest
,
...
...
@@ -573,10 +560,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
fn
convert_method
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
container
:
ImplOrTraitItemContainer
,
sig
:
&
hir
::
MethodSig
,
id
:
ast
::
NodeId
,
name
:
ast
::
Name
,
id
:
ast
::
NodeId
,
vis
:
hir
::
Visibility
,
sig
:
&
hir
::
MethodSig
,
untransformed_rcvr_ty
:
Ty
<
'tcx
>
,
rcvr_ty_generics
:
&
ty
::
Generics
<
'tcx
>
,
rcvr_ty_predicates
:
&
ty
::
GenericPredicates
<
'tcx
>
)
{
...
...
@@ -681,33 +668,6 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
.insert
(
ccx
.tcx.map
.local_def_id
(
id
),
ty
::
TypeTraitItem
(
associated_type
));
}
fn
convert_methods
<
'a
,
'tcx
,
'i
,
I
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
container
:
ImplOrTraitItemContainer
,
methods
:
I
,
untransformed_rcvr_ty
:
Ty
<
'tcx
>
,
rcvr_ty_generics
:
&
ty
::
Generics
<
'tcx
>
,
rcvr_ty_predicates
:
&
ty
::
GenericPredicates
<
'tcx
>
)
where
I
:
Iterator
<
Item
=
(
&
'i
hir
::
MethodSig
,
ast
::
NodeId
,
ast
::
Name
,
hir
::
Visibility
,
Span
)
>
{
debug!
(
"convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?},
\
rcvr_ty_predicates={:?})"
,
untransformed_rcvr_ty
,
rcvr_ty_generics
,
rcvr_ty_predicates
);
for
(
sig
,
id
,
name
,
vis
,
_
span
)
in
methods
{
convert_method
(
ccx
,
container
,
sig
,
id
,
name
,
vis
,
untransformed_rcvr_ty
,
rcvr_ty_generics
,
rcvr_ty_predicates
);
}
}
fn
ensure_no_ty_param_bounds
(
ccx
:
&
CrateCtxt
,
span
:
Span
,
generics
:
&
hir
::
Generics
,
...
...
@@ -867,36 +827,17 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
}
}
let
methods
=
impl_items
.iter
()
.filter_map
(|
ii
|
{
if
let
hir
::
ImplItemKind
::
Method
(
ref
sig
,
_
)
=
i
i
.node
{
for
impl_item
in
impl_items
{
if
let
hir
::
ImplItemKind
::
Method
(
ref
sig
,
_
)
=
i
mpl_item
.node
{
// if the method specifies a visibility, use that, otherwise
// inherit the visibility from the impl (so `foo` in `pub impl
// { fn foo(); }` is public, but private in `impl { fn
// foo(); }`).
let
method_vis
=
ii
.vis
.inherit_from
(
parent_visibility
);
Some
((
sig
,
ii
.id
,
ii
.name
,
method_vis
,
ii
.span
))
}
else
{
None
}
});
convert_methods
(
ccx
,
ImplContainer
(
def_id
),
methods
,
selfty
,
&
ty_generics
,
&
ty_predicates
);
let
method_vis
=
impl_item
.vis
.inherit_from
(
parent_visibility
);
for
impl_item
in
impl_items
{
if
let
hir
::
ImplItemKind
::
Method
(
ref
sig
,
ref
body
)
=
impl_item
.node
{
let
body_id
=
body
.id
;
let
body_scope
=
ccx
.tcx.region_maps
.call_site_extent
(
impl_item
.id
,
body_id
);
check_method_self_type
(
ccx
,
&
BindingRscope
::
new
(),
ccx
.method_ty
(
impl_item
.id
),
selfty
,
&
sig
.explicit_self
,
body_scope
,
body_id
);
convert_method
(
ccx
,
ImplContainer
(
def_id
),
impl_item
.name
,
impl_item
.id
,
method_vis
,
sig
,
selfty
,
&
ty_generics
,
&
ty_predicates
);
}
}
...
...
@@ -904,112 +845,80 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
},
hir
::
ItemTrait
(
_
,
_
,
_
,
ref
trait_items
)
=>
{
let
trait_def
=
trait_def_of_item
(
ccx
,
it
);
let
def_id
=
trait_def
.trait_ref.def_id
;
let
_
:
Result
<
(),
ErrorReported
>
=
// any error is already reported, can ignore
ccx
.ensure_super_predicates
(
it
.span
,
ccx
.tcx.map
.local_def_id
(
it
.id
)
);
ccx
.ensure_super_predicates
(
it
.span
,
def_id
);
convert_trait_predicates
(
ccx
,
it
);
let
trait_predicates
=
tcx
.lookup_predicates
(
ccx
.tcx.map
.local_def_id
(
it
.id
)
);
let
trait_predicates
=
tcx
.lookup_predicates
(
def_id
);
debug!
(
"convert: trait_bounds={:?}"
,
trait_predicates
);
// Convert all the associated types.
// FIXME: is the ordering here important? I think it is.
let
container
=
TraitContainer
(
def_id
);
// Convert all the associated constants.
for
trait_item
in
trait_items
{
match
trait_item
.node
{
hir
::
ConstTraitItem
(
ref
ty
,
ref
default
)
=>
{
let
ty
=
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
ty
);
tcx
.register_item_type
(
ccx
.tcx.map
.local_def_id
(
trait_item
.id
),
TypeScheme
{
generics
:
trait_def
.generics
.clone
(),
ty
:
ty
,
});
convert_associated_const
(
ccx
,
TraitContainer
(
ccx
.tcx.map
.local_def_id
(
it
.id
)),
trait_item
.name
,
trait_item
.id
,
hir
::
Public
,
ty
,
default
.is_some
())
}
_
=>
{}
if
let
hir
::
ConstTraitItem
(
ref
ty
,
ref
default
)
=
trait_item
.node
{
let
ty
=
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
ty
);
tcx
.register_item_type
(
ccx
.tcx.map
.local_def_id
(
trait_item
.id
),
TypeScheme
{
generics
:
trait_def
.generics
.clone
(),
ty
:
ty
,
});
convert_associated_const
(
ccx
,
container
,
trait_item
.name
,
trait_item
.id
,
hir
::
Public
,
ty
,
default
.is_some
())
}
}
;
}
// Convert all the associated types.
for
trait_item
in
trait_items
{
match
trait_item
.node
{
hir
::
TypeTraitItem
(
_
,
ref
opt_ty
)
=>
{
let
typ
=
opt_ty
.as_ref
()
.map
({
|
ty
|
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
ty
)
});
convert_associated_type
(
ccx
,
TraitContainer
(
ccx
.tcx.map
.local_def_id
(
it
.id
)),
trait_item
.name
,
trait_item
.id
,
hir
::
Public
,
typ
);
}
_
=>
{}
if
let
hir
::
TypeTraitItem
(
_
,
ref
opt_ty
)
=
trait_item
.node
{
let
typ
=
opt_ty
.as_ref
()
.map
({
|
ty
|
ccx
.icx
(
&
trait_predicates
)
.to_ty
(
&
ExplicitRscope
,
&
ty
)
});
convert_associated_type
(
ccx
,
container
,
trait_item
.name
,
trait_item
.id
,
hir
::
Public
,
typ
);
}
}
;
}
let
methods
=
trait_items
.iter
()
.filter_map
(|
ti
|
{
let
sig
=
match
ti
.node
{
hir
::
MethodTraitItem
(
ref
sig
,
_
)
=>
sig
,
_
=>
return
None
,
};
Some
((
sig
,
ti
.id
,
ti
.name
,
hir
::
Inherited
,
ti
.span
))
});
// Convert all the methods
for
trait_item
in
trait_items
{
if
let
hir
::
MethodTraitItem
(
ref
sig
,
_
)
=
trait_item
.node
{
convert_method
(
ccx
,
container
,
trait_item
.name
,
trait_item
.id
,
hir
::
Inherited
,
sig
,
tcx
.mk_self_type
(),
&
trait_def
.generics
,
&
trait_predicates
);
// Run convert_methods on the trait methods.
convert_methods
(
ccx
,
TraitContainer
(
ccx
.tcx.map
.local_def_id
(
it
.id
)),
methods
,
tcx
.mk_self_type
(),
&
trait_def
.generics
,
&
trait_predicates
);
}
}
// Add an entry mapping
let
trait_item_def_ids
=
Rc
::
new
(
trait_items
.iter
()
.map
(|
trait_item
|
{
let
def_id
=
ccx
.tcx.map
.local_def_id
(
trait_item
.id
);
match
trait_item
.node
{
hir
::
ConstTraitItem
(
..
)
=>
{
ty
::
ConstTraitItemId
(
def_id
)
}
hir
::
MethodTraitItem
(
..
)
=>
{
ty
::
MethodTraitItemId
(
def_id
)
}
hir
::
TypeTraitItem
(
..
)
=>
{
ty
::
TypeTraitItemId
(
def_id
)
}
hir
::
ConstTraitItem
(
..
)
=>
ty
::
ConstTraitItemId
(
def_id
),
hir
::
MethodTraitItem
(
..
)
=>
ty
::
MethodTraitItemId
(
def_id
),
hir
::
TypeTraitItem
(
..
)
=>
ty
::
TypeTraitItemId
(
def_id
)
}
})
.collect
());
tcx
.trait_item_def_ids
.borrow_mut
()
.insert
(
ccx
.tcx.map
.local_def_id
(
it
.id
),
trait_item_def_ids
);
// This must be done after `collect_trait_methods` so that
// we have a method type stored for every method.
for
trait_item
in
trait_items
{
let
(
sig
,
the_scope
,
the_id
)
=
match
trait_item
.node
{
hir
::
MethodTraitItem
(
ref
sig
,
Some
(
ref
body
))
=>
{
let
body_scope
=
ccx
.tcx.region_maps
.call_site_extent
(
trait_item
.id
,
body
.id
);
(
sig
,
body_scope
,
body
.id
)
}
hir
::
MethodTraitItem
(
ref
sig
,
None
)
=>
{
let
item_scope
=
ccx
.tcx.region_maps
.item_extent
(
trait_item
.id
);
(
sig
,
item_scope
,
it
.id
)
}
_
=>
continue
};
check_method_self_type
(
ccx
,
&
BindingRscope
::
new
(),
ccx
.method_ty
(
trait_item
.id
),
tcx
.mk_self_type
(),
&
sig
.explicit_self
,
the_scope
,
the_id
)
}
},
hir
::
ItemStruct
(
ref
struct_def
,
_
)
=>
{
let
(
scheme
,
predicates
)
=
convert_typed_item
(
ccx
,
it
);
...
...
@@ -1395,7 +1304,6 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
.iter
()
.enumerate
()
.map
(|(
i
,
def
)|
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
tcx
.map
.local_def_id
(
def
.lifetime.id
),
space
:
TypeSpace
,
index
:
i
as
u32
,
name
:
def
.lifetime.name
...
...
@@ -1870,10 +1778,8 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let
early_lifetimes
=
early_bound_lifetimes_from_generics
(
space
,
ast_generics
);
for
(
index
,
param
)
in
early_lifetimes
.iter
()
.enumerate
()
{
let
index
=
index
as
u32
;
let
def_id
=
tcx
.map
.local_def_id
(
param
.lifetime.id
);
let
region
=
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
def_id
:
def_id
,
space
:
space
,
index
:
index
,
name
:
param
.lifetime.name
...
...
@@ -2281,106 +2187,6 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
Substs
::
new
(
types
,
regions
)
}
/// Verifies that the explicit self type of a method matches the impl
/// or trait. This is a bit weird but basically because right now we
/// don't handle the general case, but instead map it to one of
/// several pre-defined options using various heuristics, this method
/// comes back to check after the fact that explicit type the user
/// wrote actually matches what the pre-defined option said.
fn
check_method_self_type
<
'a
,
'tcx
,
RS
:
RegionScope
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
rs
:
&
RS
,
method_type
:
Rc
<
ty
::
Method
<
'tcx
>>
,
required_type
:
Ty
<
'tcx
>
,
explicit_self
:
&
hir
::
ExplicitSelf
,
body_scope
:
region
::
CodeExtent
,
body_id
:
ast
::
NodeId
)
{
let
tcx
=
ccx
.tcx
;
if
let
hir
::
SelfExplicit
(
ref
ast_type
,
_
)
=
explicit_self
.node
{
let
typ
=
ccx
.icx
(
&
method_type
.predicates
)
.to_ty
(
rs
,
&**
ast_type
);
let
base_type
=
match
typ
.sty
{
ty
::
TyRef
(
_
,
tm
)
=>
tm
.ty
,
ty
::
TyBox
(
typ
)
=>
typ
,
_
=>
typ
,
};
// "Required type" comes from the trait definition. It may
// contain late-bound regions from the method, but not the
// trait (since traits only have early-bound region
// parameters).
assert
!
(
!
base_type
.has_regions_escaping_depth
(
1
));
let
required_type_free
=
liberate_early_bound_regions
(
tcx
,
body_scope
,
&
tcx
.liberate_late_bound_regions
(
body_scope
,
&
ty
::
Binder
(
required_type
)));
// The "base type" comes from the impl. It too may have late-bound
// regions from the method.
assert
!
(
!
base_type
.has_regions_escaping_depth
(
1
));
let
base_type_free
=
liberate_early_bound_regions
(
tcx
,
body_scope
,
&
tcx
.liberate_late_bound_regions
(
body_scope
,
&
ty
::
Binder
(
base_type
)));
debug!
(
"required_type={:?} required_type_free={:?}
\
base_type={:?} base_type_free={:?}"
,
required_type
,
required_type_free
,
base_type
,
base_type_free
);
let
infcx
=
infer
::
new_infer_ctxt
(
tcx
,
&
tcx
.tables
,
None
,
false
);
drop
(::
require_same_types
(
tcx
,
Some
(
&
infcx
),
false
,
explicit_self
.span
,
base_type_free
,
required_type_free
,
||
{
format!
(
"mismatched self type: expected `{}`"
,
required_type
)
}));
// We could conceviably add more free-region relations here,
// but since this code is just concerned with checking that
// the `&Self` types etc match up, it's not really necessary.
// It would just allow people to be more approximate in some
// cases. In any case, we can do it later as we feel the need;
// I'd like this function to go away eventually.
let
free_regions
=
FreeRegionMap
::
new
();
infcx
.resolve_regions_and_report_errors
(
&
free_regions
,
body_id
);
}
fn
liberate_early_bound_regions
<
'tcx
,
T
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
scope
:
region
::
CodeExtent
,
value
:
&
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
{
/*!
* Convert early-bound regions into free regions; normally this is done by
* applying the `free_substs` from the `ParameterEnvironment`, but this particular
* method-self-type check is kind of hacky and done very early in the process,
* before we really have a `ParameterEnvironment` to check.
*/
tcx
.fold_regions
(
value
,
&
mut
false
,
|
region
,
_
|
{
match
region
{
ty
::
ReEarlyBound
(
data
)
=>
{
ty
::
ReFree
(
ty
::
FreeRegion
{
scope
:
scope
,
bound_region
:
ty
::
BrNamed
(
data
.def_id
,
data
.name
)
})
}
_
=>
region
}
})
}
}
/// Checks that all the type parameters on an impl
fn
enforce_impl_params_are_constrained
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
ast_generics
:
&
hir
::
Generics
,
...
...
@@ -2450,9 +2256,7 @@ fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
.collect
();
for
(
index
,
lifetime_def
)
in
ast_generics
.lifetimes
.iter
()
.enumerate
()
{
let
def_id
=
tcx
.map
.local_def_id
(
lifetime_def
.lifetime.id
);
let
region
=
ty
::
EarlyBoundRegion
{
def_id
:
def_id
,
space
:
TypeSpace
,
let
region
=
ty
::
EarlyBoundRegion
{
space
:
TypeSpace
,
index
:
index
as
u32
,
name
:
lifetime_def
.lifetime.name
};
if
...
...
src/librustc_typeck/variance.rs
浏览文件 @
efc45758
...
...
@@ -1002,12 +1002,14 @@ fn add_constraints_from_sig(&mut self,
/// Adds constraints appropriate for a region appearing in a
/// context with ambient variance `variance`
fn
add_constraints_from_region
(
&
mut
self
,
_
generics
:
&
ty
::
Generics
<
'tcx
>
,
generics
:
&
ty
::
Generics
<
'tcx
>
,
region
:
ty
::
Region
,
variance
:
VarianceTermPtr
<
'a
>
)
{
match
region
{
ty
::
ReEarlyBound
(
ref
data
)
=>
{
let
node_id
=
self
.tcx
()
.map
.as_local_node_id
(
data
.def_id
)
.unwrap
();
let
def_id
=
generics
.regions
.get
(
data
.space
,
data
.index
as
usize
)
.def_id
;
let
node_id
=
self
.tcx
()
.map
.as_local_node_id
(
def_id
)
.unwrap
();
if
self
.is_to_be_inferred
(
node_id
)
{
let
index
=
self
.inferred_index
(
node_id
);
self
.add_constraint
(
index
,
variance
);
...
...
src/test/compile-fail/issue-17740.rs
浏览文件 @
efc45758
...
...
@@ -15,12 +15,12 @@ struct Foo<'a> {
impl
<
'a
>
Foo
<
'a
>
{
fn
bar
(
self
:
&
mut
Foo
)
{
//~^ mismatched types
//~| expected `Foo<'a>`
//~| found `Foo<'_>`
//~| expected `
&mut
Foo<'a>`
//~| found `
&mut
Foo<'_>`
//~| lifetime mismatch
//~| mismatched types
//~| expected `Foo<'a>`
//~| found `Foo<'_>`
//~| expected `
&mut
Foo<'a>`
//~| found `
&mut
Foo<'_>`
//~| lifetime mismatch
}
}
...
...
src/test/compile-fail/issue-17905.rs
浏览文件 @
efc45758
...
...
@@ -16,10 +16,6 @@ impl Pair<
isize
>
{
fn
say
(
self
:
&
Pair
<&
str
,
isize
>
)
{
//~^ ERROR mismatched types
//~| expected `Pair<&'static str, isize>`
//~| found `Pair<&str, isize>`
//~| lifetime mismatch
println!
(
"{}"
,
self
);
}
}
...
...
src/test/compile-fail/issue-26194.rs
浏览文件 @
efc45758
...
...
@@ -12,7 +12,7 @@
impl
S
{
fn
f
(
self
:
*
mut
S
)
->
String
{
self
.0
}
//~^ ERROR mismatched
self type
//~^ ERROR mismatched
method receiver
}
fn
main
()
{
S
(
""
.to_owned
())
.f
();
}
src/test/compile-fail/ufcs-explicit-self-bad.rs
浏览文件 @
efc45758
...
...
@@ -15,7 +15,7 @@ struct Foo {
}
impl
Foo
{
fn
foo
(
self
:
isize
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
self type
fn
foo
(
self
:
isize
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
method receiver
self
.f
+
x
}
}
...
...
@@ -25,10 +25,10 @@ struct Bar<T> {
}
impl
<
T
>
Bar
<
T
>
{
fn
foo
(
self
:
Bar
<
isize
>
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
self type
fn
foo
(
self
:
Bar
<
isize
>
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
method receiver
x
}
fn
bar
(
self
:
&
Bar
<
usize
>
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
self type
fn
bar
(
self
:
&
Bar
<
usize
>
,
x
:
isize
)
->
isize
{
//~ ERROR mismatched
method receiver
x
}
}
...
...
@@ -41,15 +41,16 @@ trait SomeTrait {
impl
<
'a
,
T
>
SomeTrait
for
&
'a
Bar
<
T
>
{
fn
dummy1
(
self
:
&&
'a
Bar
<
T
>
)
{
}
fn
dummy2
(
self
:
&
Bar
<
T
>
)
{}
//~ ERROR mismatched self type
fn
dummy2
(
self
:
&
Bar
<
T
>
)
{}
//~ ERROR mismatched types
//~^ ERROR mismatched types
fn
dummy3
(
self
:
&&
Bar
<
T
>
)
{}
//~^ ERROR mismatched types
//~| expected `&'a Bar<T>`
//~| found `&Bar<T>`
//~| expected `&
&
'a Bar<T>`
//~| found `&
&
Bar<T>`
//~| lifetime mismatch
//~| ERROR mismatched types
//~| expected `&'a Bar<T>`
//~| found `&Bar<T>`
//~| expected `&
&
'a Bar<T>`
//~| found `&
&
Bar<T>`
//~| lifetime mismatch
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录