Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
fe4f9b8e
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,发现更多精彩内容 >>
提交
fe4f9b8e
编写于
2月 11, 2015
作者:
E
Eduard Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use partial path resolutions in expressions for UFCS desugaring.
上级
7a3054f5
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
387 addition
and
213 deletion
+387
-213
src/librustc/middle/astconv_util.rs
src/librustc/middle/astconv_util.rs
+16
-17
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+34
-4
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+135
-88
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/_match.rs
+4
-2
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/mod.rs
+22
-2
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/probe.rs
+76
-26
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+84
-70
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+2
-2
src/test/compile-fail/issue-3973.rs
src/test/compile-fail/issue-3973.rs
+0
-2
src/test/run-pass/const-polymorphic-paths.rs
src/test/run-pass/const-polymorphic-paths.rs
+14
-0
未找到文件。
src/librustc/middle/astconv_util.rs
浏览文件 @
fe4f9b8e
...
...
@@ -17,37 +17,36 @@
use
middle
::
def
;
use
middle
::
ty
::{
self
,
Ty
};
use
syntax
::
ast
;
use
syntax
::
codemap
::
Span
;
use
util
::
ppaux
::
Repr
;
pub
const
NO_REGIONS
:
uint
=
1
;
pub
const
NO_TPS
:
uint
=
2
;
pub
fn
check_path_args
(
tcx
:
&
ty
::
ctxt
,
span
:
Span
,
segments
:
&
[
ast
::
PathSegment
],
flags
:
uint
)
{
if
(
flags
&
NO_TPS
)
!=
0
{
if
segments
.iter
()
.any
(|
s
|
s
.parameters
.has_types
())
{
span_err!
(
tcx
.sess
,
span
,
E0109
,
"type parameters are not allowed on this type"
);
pub
fn
check_path_args
(
tcx
:
&
ty
::
ctxt
,
segments
:
&
[
ast
::
PathSegment
],
flags
:
uint
)
{
for
segment
in
segments
{
if
(
flags
&
NO_TPS
)
!=
0
{
for
typ
in
segment
.parameters
.types
(
)
{
span_err!
(
tcx
.sess
,
typ
.span
,
E0109
,
"type parameters are not allowed on this type"
);
break
;
}
}
}
if
(
flags
&
NO_REGIONS
)
!=
0
{
if
segments
.iter
()
.any
(|
s
|
s
.parameters
.has_lifetimes
())
{
span_err!
(
tcx
.sess
,
span
,
E0110
,
"lifetime parameters are not allowed on this type"
);
if
(
flags
&
NO_REGIONS
)
!=
0
{
for
lifetime
in
segment
.parameters
.lifetimes
()
{
span_err!
(
tcx
.sess
,
lifetime
.span
,
E0110
,
"lifetime parameters are not allowed on this type"
);
break
;
}
}
}
}
pub
fn
prim_ty_to_ty
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
span
:
Span
,
segments
:
&
[
ast
::
PathSegment
],
nty
:
ast
::
PrimTy
)
->
Ty
<
'tcx
>
{
check_path_args
(
tcx
,
s
pan
,
s
egments
,
NO_TPS
|
NO_REGIONS
);
check_path_args
(
tcx
,
segments
,
NO_TPS
|
NO_REGIONS
);
match
nty
{
ast
::
TyBool
=>
tcx
.types.bool
,
ast
::
TyChar
=>
tcx
.types.char
,
...
...
@@ -69,7 +68,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
Some
(
&
d
)
=>
d
};
if
let
def
::
DefPrimTy
(
nty
)
=
def
{
Some
(
prim_ty_to_ty
(
tcx
,
path
.span
,
&
path
.segments
[],
nty
))
Some
(
prim_ty_to_ty
(
tcx
,
&
path
.segments
[],
nty
))
}
else
{
None
}
...
...
src/librustc_resolve/lib.rs
浏览文件 @
fe4f9b8e
...
...
@@ -3018,7 +3018,7 @@ fn resolve_trait_reference(&mut self,
}
fn
resolve_generics
(
&
mut
self
,
generics
:
&
Generics
)
{
for
type_parameter
in
&
generics
.ty_params
{
for
type_parameter
in
&
*
generics
.ty_params
{
self
.check_if_primitive_type_name
(
type_parameter
.ident.name
,
type_parameter
.span
);
}
for
predicate
in
&
generics
.where_clause.predicates
{
...
...
@@ -4083,16 +4083,35 @@ fn resolve_expr(&mut self, expr: &Expr) {
// multiple elements in it or not.
ExprPath
(
ref
path
)
|
ExprQPath
(
ast
::
QPath
{
ref
path
,
..
})
=>
{
if
let
ExprQPath
(
_
)
=
expr
.node
{
let
max_assoc_types
=
if
let
ExprQPath
(
_
)
=
expr
.node
{
// Make sure the trait is valid.
let
_
=
self
.resolve_trait_reference
(
expr
.id
,
path
,
1
);
1
}
else
{
path
.segments
.len
()
};
let
mut
result
=
self
.with_no_errors
(|
this
|
{
this
.resolve_path
(
expr
.id
,
path
,
0
,
ValueNS
,
true
)
});
for
depth
in
1
..
max_assoc_types
{
if
result
.is_some
()
{
break
;
}
self
.with_no_errors
(|
this
|
{
result
=
this
.resolve_path
(
expr
.id
,
path
,
depth
,
TypeNS
,
true
);
});
}
if
let
Some
((
DefMod
(
_
),
_
,
_
))
=
result
{
// A module is not a valid type or value.
result
=
None
;
}
// This is a local path in the value namespace. Walk through
// scopes looking for it.
match
self
.resolve_path
(
expr
.id
,
path
,
0
,
ValueNS
,
true
)
{
match
result
{
// Check if struct variant
Some
((
DefVariant
(
_
,
_
,
true
),
_
,
_
))
=>
{
Some
((
DefVariant
(
_
,
_
,
true
),
_
,
0
))
=>
{
let
path_name
=
self
.path_names_to_string
(
path
,
0
);
self
.resolve_error
(
expr
.span
,
&
format!
(
"`{}` is a struct variant name, but
\
...
...
@@ -4110,6 +4129,14 @@ fn resolve_expr(&mut self, expr: &Expr) {
debug!
(
"(resolving expr) resolved `{}`"
,
self
.path_names_to_string
(
path
,
0
));
// Partial resolutions will need the set of traits in scope,
// so they can be completed during typeck.
if
def
.2
!=
0
{
let
method_name
=
path
.segments
.last
()
.unwrap
()
.identifier.name
;
let
traits
=
self
.search_for_traits_containing_method
(
method_name
);
self
.trait_map
.insert
(
expr
.id
,
traits
);
}
self
.record_def
(
expr
.id
,
def
);
}
None
=>
{
...
...
@@ -4135,6 +4162,9 @@ fn resolve_expr(&mut self, expr: &Expr) {
}
_
=>
{
// Keep reporting some errors even if they're ignored above.
self
.resolve_path
(
expr
.id
,
path
,
0
,
ValueNS
,
true
);
let
mut
method_scope
=
false
;
self
.value_ribs
.iter
()
.rev
()
.all
(|
rib
|
{
method_scope
=
match
rib
.kind
{
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
fe4f9b8e
...
...
@@ -246,6 +246,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
decl_generics
:
&
ty
::
Generics
<
'tcx
>
,
item_segment
:
&
ast
::
PathSegment
)
->
Substs
<
'tcx
>
...
...
@@ -265,12 +266,12 @@ pub fn ast_path_substs_for_ty<'tcx>(
let
(
regions
,
types
,
assoc_bindings
)
=
match
item_segment
.parameters
{
ast
::
AngleBracketedParameters
(
ref
data
)
=>
{
convert_angle_bracketed_parameters
(
this
,
rscope
,
path
.
span
,
decl_generics
,
data
)
convert_angle_bracketed_parameters
(
this
,
rscope
,
span
,
decl_generics
,
data
)
}
ast
::
ParenthesizedParameters
(
ref
data
)
=>
{
span_err!
(
tcx
.sess
,
span
,
E0214
,
"parenthesized parameters may only be used with a trait"
);
convert_parenthesized_parameters
(
this
,
rscope
,
path
.
span
,
decl_generics
,
data
)
convert_parenthesized_parameters
(
this
,
rscope
,
span
,
decl_generics
,
data
)
}
};
...
...
@@ -278,12 +279,21 @@ pub fn ast_path_substs_for_ty<'tcx>(
create_substs_for_ast_path
(
this
,
span
,
param_mode
,
decl_generics
,
None
,
types
,
regions
)
}
#[derive(PartialEq,
Eq)]
pub
enum
PathParamMode
{
// Any path in a type context.
Explicit
,
// The `module::Type` in `module::Type::method` in an expression.
Optional
}
fn
create_region_substs
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
...
...
@@ -331,6 +341,7 @@ fn create_region_substs<'tcx>(
fn
create_substs_for_ast_path
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
span
:
Span
,
param_mode
:
PathParamMode
,
decl_generics
:
&
ty
::
Generics
<
'tcx
>
,
self_ty
:
Option
<
Ty
<
'tcx
>>
,
types_provided
:
Vec
<
Ty
<
'tcx
>>
,
...
...
@@ -349,13 +360,21 @@ fn create_substs_for_ast_path<'tcx>(
// Convert the type parameters supplied by the user.
let
ty_param_defs
=
decl_generics
.types
.get_slice
(
TypeSpace
);
let
supplied_ty_param_count
=
types_provided
.len
();
let
formal_ty_param_count
=
ty_param_defs
.len
();
let
required_ty_param_count
=
ty_param_defs
.iter
()
.take_while
(|
x
|
x
.default
.is_none
())
.count
();
let
mut
type_substs
=
types_provided
;
// Fill with `ty_infer` if no params were specified, as long as
// they were optional (e.g. paths inside expressions).
let
mut
type_substs
=
if
param_mode
==
PathParamMode
::
Optional
&&
types_provided
.is_empty
()
{
(
0
..
formal_ty_param_count
)
.map
(|
_
|
this
.ty_infer
(
span
))
.collect
()
}
else
{
types_provided
};
let
supplied_ty_param_count
=
type_substs
.len
();
check_type_argument_count
(
this
.tcx
(),
span
,
supplied_ty_param_count
,
required_ty_param_count
,
formal_ty_param_count
);
...
...
@@ -415,7 +434,7 @@ fn create_substs_for_ast_path<'tcx>(
}
}
return
substs
;
substs
}
struct
ConvertedBinding
<
'tcx
>
{
...
...
@@ -607,6 +626,7 @@ pub fn instantiate_trait_ref<'tcx>(
let
trait_ref
=
ast_path_to_trait_ref
(
this
,
rscope
,
path
.span
,
PathParamMode
::
Explicit
,
trait_def_id
,
self_ty
,
path
.segments
.last
()
.unwrap
(),
...
...
@@ -627,6 +647,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
trait_def_id
:
ast
::
DefId
,
trait_segment
:
&
ast
::
PathSegment
,
mut
projections
:
&
mut
Vec
<
ty
::
PolyProjectionPredicate
<
'tcx
>>
)
...
...
@@ -640,6 +661,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
let
trait_ref
=
ty
::
Binder
(
ast_path_to_trait_ref
(
this
,
&
shifted_rscope
,
span
,
param_mode
,
trait_def_id
,
None
,
trait_segment
,
...
...
@@ -652,6 +674,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
trait_def_id
:
ast
::
DefId
,
self_ty
:
Option
<
Ty
<
'tcx
>>
,
trait_segment
:
&
ast
::
PathSegment
,
...
...
@@ -674,7 +697,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
the crate attributes to enable"
);
}
convert_angle_bracketed_parameters
(
this
,
rscope
,
path
.
span
,
&
trait_def
.generics
,
data
)
convert_angle_bracketed_parameters
(
this
,
rscope
,
span
,
&
trait_def
.generics
,
data
)
}
ast
::
ParenthesizedParameters
(
ref
data
)
=>
{
// For now, require that parenthetical notation be used
...
...
@@ -688,12 +711,13 @@ fn ast_path_to_trait_ref<'a,'tcx>(
the crate attributes to enable"
);
}
convert_parenthesized_parameters
(
this
,
rscope
,
path
.
span
,
&
trait_def
.generics
,
data
)
convert_parenthesized_parameters
(
this
,
rscope
,
span
,
&
trait_def
.generics
,
data
)
}
};
let
substs
=
create_substs_for_ast_path
(
this
,
span
,
param_mode
,
&
trait_def
.generics
,
self_ty
,
types
,
...
...
@@ -830,6 +854,7 @@ fn ast_path_to_ty<'tcx>(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
did
:
ast
::
DefId
,
item_segment
:
&
ast
::
PathSegment
)
->
Ty
<
'tcx
>
...
...
@@ -839,7 +864,9 @@ fn ast_path_to_ty<'tcx>(
ty
:
decl_ty
}
=
this
.get_item_type_scheme
(
did
);
let
substs
=
ast_path_substs_for_ty
(
this
,
rscope
,
span
,
&
generics
,
item_segment
);
let
substs
=
ast_path_substs_for_ty
(
this
,
rscope
,
span
,
param_mode
,
&
generics
,
item_segment
);
// FIXME(#12938): This is a hack until we have full support for DST.
if
Some
(
did
)
==
this
.tcx
()
.lang_items
.owned_box
()
{
...
...
@@ -878,6 +905,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
let
trait_ref
=
object_path_to_poly_trait_ref
(
this
,
rscope
,
path
.span
,
PathParamMode
::
Explicit
,
trait_def_id
,
path
.segments
.last
()
.unwrap
(),
&
mut
projection_bounds
);
...
...
@@ -950,8 +978,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
->
(
Ty
<
'tcx
>
,
def
::
Def
)
{
let
tcx
=
this
.tcx
();
check_path_args
(
tcx
,
span
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
check_path_args
(
tcx
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
let
assoc_name
=
item_segment
.identifier.name
;
let
ty_param_node_id
=
if
let
ty
::
ty_param
(
_
)
=
ty
.sty
{
...
...
@@ -1043,7 +1070,8 @@ fn trait_defines_associated_type_named(this: &AstConv,
fn
qpath_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
opt_self_ty
:
Option
<&
ast
::
Ty
>
,
param_mode
:
PathParamMode
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
trait_def_id
:
ast
::
DefId
,
trait_segment
:
&
ast
::
PathSegment
,
item_segment
:
&
ast
::
PathSegment
)
...
...
@@ -1051,11 +1079,10 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
{
let
tcx
=
this
.tcx
();
check_path_args
(
tcx
,
span
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
check_path_args
(
tcx
,
slice
::
ref_slice
(
item_segment
),
NO_TPS
|
NO_REGIONS
);
let
self_ty
=
if
let
Some
(
ty
)
=
opt_self_ty
{
ast_ty_to_ty
(
this
,
rscope
,
ty
)
ty
}
else
{
let
path_str
=
ty
::
item_path_str
(
tcx
,
trait_def_id
);
span_err!
(
tcx
.sess
,
span
,
E0223
,
...
...
@@ -1070,6 +1097,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
let
trait_ref
=
ast_path_to_trait_ref
(
this
,
rscope
,
span
,
param_mode
,
trait_def_id
,
Some
(
self_ty
),
trait_segment
,
...
...
@@ -1113,6 +1141,88 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
}
}
pub
fn
finish_resolving_def_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
rscope
:
&
RegionScope
,
span
:
Span
,
param_mode
:
PathParamMode
,
def
:
&
mut
def
::
Def
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
segments
:
&
[
ast
::
PathSegment
],
assoc_segments
:
&
[
ast
::
PathSegment
])
->
Ty
<
'tcx
>
{
let
tcx
=
this
.tcx
();
let
base_ty
=
match
*
def
{
def
::
DefTrait
(
trait_def_id
)
=>
{
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let
mut
projection_bounds
=
Vec
::
new
();
let
trait_ref
=
object_path_to_poly_trait_ref
(
this
,
rscope
,
span
,
param_mode
,
trait_def_id
,
segments
.last
()
.unwrap
(),
&
mut
projection_bounds
);
check_path_args
(
tcx
,
segments
.init
(),
NO_TPS
|
NO_REGIONS
);
trait_ref_to_object_type
(
this
,
rscope
,
span
,
trait_ref
,
projection_bounds
,
&
[])
}
def
::
DefTy
(
did
,
_
)
|
def
::
DefStruct
(
did
)
=>
{
check_path_args
(
tcx
,
segments
.init
(),
NO_TPS
|
NO_REGIONS
);
ast_path_to_ty
(
this
,
rscope
,
span
,
param_mode
,
did
,
segments
.last
()
.unwrap
())
}
def
::
DefTyParam
(
space
,
index
,
_
,
name
)
=>
{
check_path_args
(
tcx
,
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
check_path_args
(
tcx
,
segments
,
NO_TPS
|
NO_REGIONS
);
ty
::
mk_self_type
(
tcx
)
}
def
::
DefAssociatedTy
(
trait_did
,
_
)
=>
{
check_path_args
(
tcx
,
&
segments
[
..
segments
.len
()
-
2
],
NO_TPS
|
NO_REGIONS
);
qpath_to_ty
(
this
,
rscope
,
span
,
param_mode
,
opt_self_ty
,
trait_did
,
&
segments
[
segments
.len
()
-
2
],
segments
.last
()
.unwrap
())
}
def
::
DefMod
(
id
)
=>
{
tcx
.sess
.span_bug
(
span
,
&
format!
(
"found module name used as a type: {}"
,
tcx
.map
.node_to_string
(
id
.node
)));
}
def
::
DefPrimTy
(
prim_ty
)
=>
{
prim_ty_to_ty
(
tcx
,
segments
,
prim_ty
)
}
_
=>
{
span_fatal!
(
tcx
.sess
,
span
,
E0248
,
"found value name used as a type: {:?}"
,
*
def
);
}
};
// If any associated type segments remain, attempt to resolve them.
let
mut
ty
=
base_ty
;
for
segment
in
assoc_segments
{
if
ty
.sty
==
ty
::
ty_err
{
break
;
}
// This is pretty bad (it will fail except for T::A and Self::A).
let
(
a_ty
,
a_def
)
=
associated_path_def_to_ty
(
this
,
span
,
ty
,
*
def
,
segment
);
ty
=
a_ty
;
*
def
=
a_def
;
}
ty
}
/// Parses the programmer's textual representation of a type into our
/// internal notion of a type.
pub
fn
ast_ty_to_ty
<
'tcx
>
(
this
:
&
AstConv
<
'tcx
>
,
...
...
@@ -1201,81 +1311,18 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
tcx
.sess
.span_bug
(
ast_ty
.span
,
&
format!
(
"unbound path {}"
,
ast_ty
.repr
(
tcx
)))
};
let
(
base_def
,
max_depth
)
=
result
;
let
span
=
ast_ty
.span
;
// Could be more granular.
let
segments
=
&
path
.segments
[
..
path
.segments
.len
()
-
max_depth
];
let
base_ty
=
match
base_def
{
def
::
DefTrait
(
trait_def_id
)
=>
{
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let
mut
projection_bounds
=
Vec
::
new
();
let
trait_ref
=
object_path_to_poly_trait_ref
(
this
,
rscope
,
span
,
trait_def_id
,
segments
.last
()
.unwrap
(),
&
mut
projection_bounds
);
check_path_args
(
tcx
,
span
,
segments
.init
(),
NO_TPS
|
NO_REGIONS
);
trait_ref_to_object_type
(
this
,
rscope
,
span
,
trait_ref
,
projection_bounds
,
&
[])
}
def
::
DefTy
(
did
,
_
)
|
def
::
DefStruct
(
did
)
=>
{
check_path_args
(
tcx
,
span
,
segments
.init
(),
NO_TPS
|
NO_REGIONS
);
ast_path_to_ty
(
this
,
rscope
,
span
,
did
,
segments
.last
()
.unwrap
())
}
def
::
DefTyParam
(
space
,
index
,
_
,
name
)
=>
{
check_path_args
(
tcx
,
span
,
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
check_path_args
(
tcx
,
span
,
segments
,
NO_TPS
|
NO_REGIONS
);
ty
::
mk_self_type
(
tcx
)
}
def
::
DefAssociatedTy
(
trait_did
,
_
)
=>
{
let
opt_self_ty
=
if
let
ast
::
TyQPath
(
ref
qpath
)
=
ast_ty
.node
{
Some
(
&*
qpath
.self_type
)
}
else
{
None
};
check_path_args
(
tcx
,
span
,
&
segments
[
..
segments
.len
()
-
2
],
NO_TPS
|
NO_REGIONS
);
qpath_to_ty
(
this
,
rscope
,
span
,
opt_self_ty
,
trait_did
,
&
segments
[
segments
.len
()
-
2
],
segments
.last
()
.unwrap
())
}
def
::
DefMod
(
id
)
=>
{
tcx
.sess
.span_bug
(
span
,
&
format!
(
"found module name used as a type: {}"
,
tcx
.map
.node_to_string
(
id
.node
)));
}
def
::
DefPrimTy
(
prim_ty
)
=>
{
prim_ty_to_ty
(
tcx
,
span
,
segments
,
prim_ty
)
}
_
=>
{
span_fatal!
(
tcx
.sess
,
span
,
E0248
,
"found value name used as a type: {:?}"
,
base_def
);
}
let
(
mut
def
,
max_depth
)
=
result
;
let
base_ty_end
=
path
.segments
.len
()
-
max_depth
;
let
opt_self_ty
=
if
let
ast
::
TyQPath
(
ref
qpath
)
=
ast_ty
.node
{
Some
(
ast_ty_to_ty
(
this
,
rscope
,
&*
qpath
.self_type
))
}
else
{
None
};
// If any associated type segments remain, attempt to resolve them.
let
mut
ty
=
base_ty
;
let
mut
def
=
base_def
;
for
depth
in
(
0
..
max_depth
)
.rev
()
{
if
ty
.sty
==
ty
::
ty_err
{
break
;
}
// This is pretty bad (it will fail except for T::A and Self::A).
let
segment
=
&
path
.segments
[
path
.segments
.len
()
-
depth
-
1
];
let
(
a_ty
,
a_def
)
=
associated_path_def_to_ty
(
this
,
span
,
ty
,
def
,
segment
);
ty
=
a_ty
;
def
=
a_def
;
}
let
ty
=
finish_resolving_def_to_ty
(
this
,
rscope
,
ast_ty
.span
,
PathParamMode
::
Explicit
,
&
mut
def
,
opt_self_ty
,
&
path
.segments
[
..
base_ty_end
],
&
path
.segments
[
base_ty_end
..
]);
if
max_depth
!=
0
&&
ty
.sty
!=
ty
::
ty_err
{
// Write back the new resolution.
...
...
src/librustc_typeck/check/_match.rs
浏览文件 @
fe4f9b8e
...
...
@@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
};
instantiate_path
(
pcx
.fcx
,
path
,
&
path
.segments
,
ty
::
lookup_item_type
(
tcx
,
enum_def_id
),
&
ty
::
lookup_predicates
(
tcx
,
enum_def_id
),
None
,
...
...
@@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
}
else
{
ctor_scheme
};
instantiate_path
(
pcx
.fcx
,
path
,
path_scheme
,
&
ctor_predicates
,
None
,
def
,
pat
.span
,
pat
.id
);
instantiate_path
(
pcx
.fcx
,
&
path
.segments
,
path_scheme
,
&
ctor_predicates
,
None
,
def
,
pat
.span
,
pat
.id
);
let
pat_ty
=
fcx
.node_ty
(
pat
.id
);
demand
::
eqtype
(
fcx
,
pat
.span
,
expected
,
pat_ty
);
...
...
src/librustc_typeck/check/method/mod.rs
浏览文件 @
fe4f9b8e
...
...
@@ -14,6 +14,7 @@
use
check
::{
FnCtxt
};
use
check
::
vtable
;
use
check
::
vtable
::
select_new_fcx_obligations
;
use
middle
::
def
;
use
middle
::
subst
;
use
middle
::
traits
;
use
middle
::
ty
::
*
;
...
...
@@ -66,7 +67,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr_id
:
ast
::
NodeId
)
->
bool
{
match
probe
::
probe
(
fcx
,
span
,
method_name
,
self_ty
,
call_expr_id
)
{
let
mode
=
probe
::
Mode
::
MethodCall
;
match
probe
::
probe
(
fcx
,
span
,
mode
,
method_name
,
self_ty
,
call_expr_id
)
{
Ok
(
..
)
=>
true
,
Err
(
NoMatch
(
..
))
=>
false
,
Err
(
Ambiguity
(
..
))
=>
true
,
...
...
@@ -103,8 +105,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr
.repr
(
fcx
.tcx
()),
self_expr
.repr
(
fcx
.tcx
()));
let
mode
=
probe
::
Mode
::
MethodCall
;
let
self_ty
=
fcx
.infcx
()
.resolve_type_vars_if_possible
(
&
self_ty
);
let
pick
=
try!
(
probe
::
probe
(
fcx
,
span
,
method_name
,
self_ty
,
call_expr
.id
));
let
pick
=
try!
(
probe
::
probe
(
fcx
,
span
,
m
ode
,
m
ethod_name
,
self_ty
,
call_expr
.id
));
Ok
(
confirm
::
confirm
(
fcx
,
span
,
self_expr
,
call_expr
,
self_ty
,
pick
,
supplied_method_types
))
}
...
...
@@ -301,6 +304,23 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Some
(
callee
)
}
pub
fn
resolve_ufcs
<
'a
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
span
:
Span
,
method_name
:
ast
::
Name
,
self_ty
:
Ty
<
'tcx
>
,
expr_id
:
ast
::
NodeId
)
->
Result
<
def
::
Def
,
MethodError
>
{
let
mode
=
probe
::
Mode
::
Path
;
let
pick
=
try!
(
probe
::
probe
(
fcx
,
span
,
mode
,
method_name
,
self_ty
,
expr_id
));
let
def_id
=
pick
.method_ty.def_id
;
let
provenance
=
match
pick
.kind
{
probe
::
InherentImplPick
(
impl_def_id
)
=>
def
::
FromImpl
(
impl_def_id
),
_
=>
def
::
FromTrait
(
pick
.method_ty.container
.id
())
};
Ok
(
def
::
DefMethod
(
def_id
,
provenance
))
}
/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
/// index (or `None`, if no such method).
...
...
src/librustc_typeck/check/method/probe.rs
浏览文件 @
fe4f9b8e
...
...
@@ -37,6 +37,7 @@
struct
ProbeContext
<
'a
,
'tcx
:
'a
>
{
fcx
:
&
'a
FnCtxt
<
'a
,
'tcx
>
,
span
:
Span
,
mode
:
Mode
,
method_name
:
ast
::
Name
,
steps
:
Rc
<
Vec
<
CandidateStep
<
'tcx
>>>
,
opt_simplified_steps
:
Option
<
Vec
<
fast_reject
::
SimplifiedType
>>
,
...
...
@@ -108,17 +109,30 @@ pub enum PickAdjustment {
AutoRef
(
ast
::
Mutability
,
Box
<
PickAdjustment
>
),
}
#[derive(PartialEq,
Eq,
Copy)]
pub
enum
Mode
{
// An expression of the form `receiver.method_name(...)`.
// Autoderefs are performed on `receiver`, lookup is done based on the
// `self` argument of the method, and static methods aren't considered.
MethodCall
,
// An expression of the form `Type::method` or `<T>::method`.
// No autoderefs are performed, lookup is done based on the type each
// implementation is for, and static methods are included.
Path
}
pub
fn
probe
<
'a
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
span
:
Span
,
mode
:
Mode
,
method_name
:
ast
::
Name
,
self_ty
:
Ty
<
'tcx
>
,
call
_expr_id
:
ast
::
NodeId
)
scope
_expr_id
:
ast
::
NodeId
)
->
PickResult
<
'tcx
>
{
debug!
(
"probe(self_ty={}, method_name={},
call
_expr_id={})"
,
debug!
(
"probe(self_ty={}, method_name={},
scope
_expr_id={})"
,
self_ty
.repr
(
fcx
.tcx
()),
method_name
,
call
_expr_id
);
scope
_expr_id
);
// FIXME(#18741) -- right now, creating the steps involves evaluating the
// `*` operator, which registers obligations that then escape into
...
...
@@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// it ride, although it's really not great, and in fact could I
// think cause spurious errors. Really though this part should
// take place in the `fcx.infcx().probe` below.
let
steps
=
match
create_steps
(
fcx
,
span
,
self_ty
)
{
Some
(
steps
)
=>
steps
,
None
=>
return
Err
(
MethodError
::
NoMatch
(
Vec
::
new
(),
Vec
::
new
())),
let
steps
=
if
mode
==
Mode
::
MethodCall
{
match
create_steps
(
fcx
,
span
,
self_ty
)
{
Some
(
steps
)
=>
steps
,
None
=>
return
Err
(
MethodError
::
NoMatch
(
Vec
::
new
(),
Vec
::
new
())),
}
}
else
{
vec!
[
CandidateStep
{
self_ty
:
self_ty
,
adjustment
:
AutoDeref
(
0
)
}]
};
// Create a list of simplified self types, if we can.
...
...
@@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// this creates one big transaction so that all type variables etc
// that we create during the probe process are removed later
let
mut
dummy
=
Some
((
steps
,
opt_simplified_steps
));
// FIXME(#18101) need once closures
fcx
.infcx
()
.probe
(|
_
|
{
let
(
steps
,
opt_simplified_steps
)
=
dummy
.take
()
.unwrap
();
let
mut
probe_cx
=
ProbeContext
::
new
(
fcx
,
span
,
method_name
,
steps
,
opt_simplified_steps
);
let
mut
probe_cx
=
ProbeContext
::
new
(
fcx
,
span
,
mode
,
method_name
,
steps
,
opt_simplified_steps
);
probe_cx
.assemble_inherent_candidates
();
try!
(
probe_cx
.assemble_extension_candidates_for_traits_in_scope
(
call
_expr_id
));
try!
(
probe_cx
.assemble_extension_candidates_for_traits_in_scope
(
scope
_expr_id
));
probe_cx
.pick
()
})
}
...
...
@@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
impl
<
'a
,
'tcx
>
ProbeContext
<
'a
,
'tcx
>
{
fn
new
(
fcx
:
&
'a
FnCtxt
<
'a
,
'tcx
>
,
span
:
Span
,
mode
:
Mode
,
method_name
:
ast
::
Name
,
steps
:
Vec
<
CandidateStep
<
'tcx
>>
,
opt_simplified_steps
:
Option
<
Vec
<
fast_reject
::
SimplifiedType
>>
)
...
...
@@ -206,6 +231,7 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
ProbeContext
{
fcx
:
fcx
,
span
:
span
,
mode
:
mode
,
method_name
:
method_name
,
inherent_candidates
:
Vec
::
new
(),
extension_candidates
:
Vec
::
new
(),
...
...
@@ -292,11 +318,12 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
return
self
.record_static_candidate
(
ImplSource
(
impl_def_id
));
}
let
impl_substs
=
self
.impl_substs
(
impl_def_id
);
let
(
impl_ty
,
impl_substs
)
=
self
.impl_ty_and_substs
(
impl_def_id
);
let
impl_ty
=
self
.fcx
.instantiate_type_scheme
(
self
.span
,
&
impl_substs
,
&
impl_ty
);
// Determine the receiver type that the method itself expects.
let
xform_self_ty
=
self
.xform_self_ty
(
&
method
,
&
impl_substs
);
self
.xform_self_ty
(
&
method
,
impl_ty
,
&
impl_substs
);
self
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
...
...
@@ -330,7 +357,9 @@ fn assemble_inherent_candidates_from_object(&mut self,
new_trait_ref
.def_id
,
method_num
);
let
xform_self_ty
=
this
.xform_self_ty
(
&
m
,
new_trait_ref
.substs
);
let
xform_self_ty
=
this
.xform_self_ty
(
&
m
,
new_trait_ref
.self_ty
(),
new_trait_ref
.substs
);
this
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
...
...
@@ -373,7 +402,9 @@ fn assemble_inherent_candidates_from_param(&mut self,
this
.erase_late_bound_regions
(
&
poly_trait_ref
);
let
xform_self_ty
=
this
.xform_self_ty
(
&
m
,
trait_ref
.substs
);
this
.xform_self_ty
(
&
m
,
trait_ref
.self_ty
(),
trait_ref
.substs
);
debug!
(
"found match: trait_ref={} substs={} m={}"
,
trait_ref
.repr
(
this
.tcx
()),
...
...
@@ -540,7 +571,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
continue
;
}
let
impl_substs
=
self
.impl
_substs
(
impl_def_id
);
let
(
_
,
impl_substs
)
=
self
.impl_ty_and
_substs
(
impl_def_id
);
debug!
(
"impl_substs={}"
,
impl_substs
.repr
(
self
.tcx
()));
...
...
@@ -553,7 +584,9 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
// Determine the receiver type that the method itself expects.
let
xform_self_ty
=
self
.xform_self_ty
(
&
method
,
impl_trait_ref
.substs
);
self
.xform_self_ty
(
&
method
,
impl_trait_ref
.self_ty
(),
impl_trait_ref
.substs
);
debug!
(
"xform_self_ty={}"
,
xform_self_ty
.repr
(
self
.tcx
()));
...
...
@@ -630,7 +663,9 @@ fn assemble_closure_candidates(&mut self,
&
trait_def
.generics
,
step
.self_ty
);
let
xform_self_ty
=
self
.xform_self_ty
(
&
method_ty
,
&
substs
);
let
xform_self_ty
=
self
.xform_self_ty
(
&
method_ty
,
step
.self_ty
,
&
substs
);
self
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
method_ty
:
method_ty
.clone
(),
...
...
@@ -684,7 +719,9 @@ fn assemble_projection_candidates(&mut self,
bound
.repr
(
self
.tcx
()));
if
self
.infcx
()
.can_equate
(
&
step
.self_ty
,
&
bound
.self_ty
())
.is_ok
()
{
let
xform_self_ty
=
self
.xform_self_ty
(
&
method
,
bound
.substs
);
let
xform_self_ty
=
self
.xform_self_ty
(
&
method
,
bound
.self_ty
(),
bound
.substs
);
debug!
(
"assemble_projection_candidates: bound={} xform_self_ty={}"
,
bound
.repr
(
self
.tcx
()),
...
...
@@ -714,7 +751,9 @@ fn assemble_where_clause_candidates(&mut self,
.filter
(|
b
|
b
.def_id
()
==
trait_def_id
)
{
let
bound
=
self
.erase_late_bound_regions
(
&
poly_bound
);
let
xform_self_ty
=
self
.xform_self_ty
(
&
method_ty
,
bound
.substs
);
let
xform_self_ty
=
self
.xform_self_ty
(
&
method_ty
,
bound
.self_ty
(),
bound
.substs
);
debug!
(
"assemble_where_clause_candidates: bound={} xform_self_ty={}"
,
bound
.repr
(
self
.tcx
()),
...
...
@@ -1023,7 +1062,9 @@ fn has_applicable_self(&self, method: &ty::Method) -> bool {
// "fast track" -- check for usage of sugar
match
method
.explicit_self
{
ty
::
StaticExplicitSelfCategory
=>
{
// fallthrough
if
self
.mode
==
Mode
::
Path
{
return
true
;
}
}
ty
::
ByValueExplicitSelfCategory
|
ty
::
ByReferenceExplicitSelfCategory
(
..
)
|
...
...
@@ -1047,11 +1088,13 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
fn
xform_self_ty
(
&
self
,
method
:
&
Rc
<
ty
::
Method
<
'tcx
>>
,
impl_ty
:
Ty
<
'tcx
>
,
substs
:
&
subst
::
Substs
<
'tcx
>
)
->
Ty
<
'tcx
>
{
debug!
(
"xform_self_ty(self_ty={}, substs={})"
,
method
.fty.sig
.0
.inputs
[
0
]
.repr
(
self
.tcx
()),
debug!
(
"xform_self_ty(impl_ty={}, self_ty={}, substs={})"
,
impl_ty
.repr
(
self
.tcx
()),
method
.fty.sig
.0
.inputs
.get
(
0
)
.repr
(
self
.tcx
()),
substs
.repr
(
self
.tcx
()));
assert
!
(
!
substs
.has_escaping_regions
());
...
...
@@ -1063,6 +1106,11 @@ fn xform_self_ty(&self,
// if there are any.
assert_eq!
(
substs
.types
.len
(
subst
::
FnSpace
),
0
);
assert_eq!
(
substs
.regions
()
.len
(
subst
::
FnSpace
),
0
);
if
self
.mode
==
Mode
::
Path
{
return
impl_ty
;
}
let
placeholder
;
let
mut
substs
=
substs
;
if
...
...
@@ -1094,9 +1142,10 @@ fn xform_self_ty(&self,
xform_self_ty
}
fn
impl_substs
(
&
self
,
impl_def_id
:
ast
::
DefId
)
->
subst
::
Substs
<
'tcx
>
/// Get the type of an impl and generate substitutions with placeholders.
fn
impl_ty_and_substs
(
&
self
,
impl_def_id
:
ast
::
DefId
)
->
(
Ty
<
'tcx
>
,
subst
::
Substs
<
'tcx
>
)
{
let
impl_pty
=
ty
::
lookup_item_type
(
self
.tcx
(),
impl_def_id
);
...
...
@@ -1108,7 +1157,8 @@ fn impl_substs(&self,
impl_pty
.generics.regions
.map
(
|
_
|
ty
::
ReStatic
);
// see erase_late_bound_regions() for an expl of why 'static
subst
::
Substs
::
new
(
type_vars
,
region_placeholders
)
let
substs
=
subst
::
Substs
::
new
(
type_vars
,
region_placeholders
);
(
impl_pty
.ty
,
substs
)
}
/// Replace late-bound-regions bound by `value` with `'static` using
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
fe4f9b8e
...
...
@@ -82,9 +82,10 @@
use
self
::
IsBinopAssignment
::
*
;
use
self
::
TupleArgumentsFlag
::
*
;
use
astconv
::{
self
,
ast_region_to_region
,
ast_ty_to_ty
,
AstConv
};
use
astconv
::{
self
,
ast_region_to_region
,
ast_ty_to_ty
,
AstConv
,
PathParamMode
};
use
check
::
_
match
::
pat_ctxt
;
use
fmt_macros
::{
Parser
,
Piece
,
Position
};
use
middle
::
astconv_util
::{
check_path_args
,
NO_TPS
,
NO_REGIONS
};
use
middle
::{
const_eval
,
def
};
use
middle
::
infer
;
use
middle
::
mem_categorization
as
mc
;
...
...
@@ -1598,26 +1599,11 @@ fn instantiate_struct_literal_ty(&self,
let
ty
::
TypeScheme
{
generics
,
ty
:
decl_ty
}
=
ty
::
lookup_item_type
(
tcx
,
did
);
let
wants_params
=
generics
.has_type_params
(
TypeSpace
)
||
generics
.has_region_params
(
TypeSpace
);
let
needs_defaults
=
wants_params
&&
path
.segments
.iter
()
.all
(|
s
|
s
.parameters
.is_empty
());
let
substs
=
if
needs_defaults
{
let
tps
=
self
.infcx
()
.next_ty_vars
(
generics
.types
.len
(
TypeSpace
));
let
rps
=
self
.infcx
()
.region_vars_for_defs
(
path
.span
,
generics
.regions
.get_slice
(
TypeSpace
));
Substs
::
new_type
(
tps
,
rps
)
}
else
{
astconv
::
ast_path_substs_for_ty
(
self
,
self
,
path
.span
,
&
generics
,
path
.segments
.last
()
.unwrap
())
};
let
substs
=
astconv
::
ast_path_substs_for_ty
(
self
,
self
,
path
.span
,
PathParamMode
::
Optional
,
&
generics
,
path
.segments
.last
()
.unwrap
());
let
ty
=
self
.instantiate_type_scheme
(
path
.span
,
&
substs
,
&
decl_ty
);
...
...
@@ -3604,21 +3590,57 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
};
fcx
.write_ty
(
id
,
oprnd_t
);
}
ast
::
ExprPath
(
ref
path
)
=>
{
let
defn
=
lookup_def
(
fcx
,
path
.span
,
id
);
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
defn
);
instantiate_path
(
fcx
,
path
,
scheme
,
&
predicates
,
None
,
defn
,
expr
.span
,
expr
.id
);
ast
::
ExprPath
(
ref
path
)
|
ast
::
ExprQPath
(
ast
::
QPath
{
ref
path
,
..
})
=>
{
let
opt_self_ty
=
if
let
ast
::
ExprQPath
(
ref
qpath
)
=
expr
.node
{
Some
(
fcx
.to_ty
(
&*
qpath
.self_type
))
}
else
{
None
};
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
constrain_path_type_parameters
(
fcx
,
expr
);
}
ast
::
ExprQPath
(
ref
qpath
)
=>
{
let
self_ty
=
fcx
.to_ty
(
&*
qpath
.self_type
);
let
defn
=
lookup_def
(
fcx
,
expr
.span
,
id
);
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
defn
);
instantiate_path
(
fcx
,
&
qpath
.path
,
scheme
,
&
predicates
,
Some
(
self_ty
),
defn
,
expr
.span
,
expr
.id
);
// Helpers to avoid keeping the RefCell borrow for too long.
let
get_def
=
|
&
:|
tcx
.def_map
.borrow
()
.get
(
&
id
)
.cloned
();
let
get_partial_def
=
|
&
:|
tcx
.partial_def_map
.borrow
()
.get
(
&
id
)
.cloned
();
if
let
Some
(
def
)
=
get_def
()
{
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
def
);
instantiate_path
(
fcx
,
&
path
.segments
,
scheme
,
&
predicates
,
None
,
def
,
expr
.span
,
id
);
}
else
if
let
Some
(
partial
)
=
get_partial_def
()
{
let
mut
def
=
partial
.base_type
;
let
ty_segments
=
path
.segments
.init
();
let
ty_assoc_num
=
partial
.extra_associated_types
as
usize
;
let
base_ty_end
=
ty_segments
.len
()
-
ty_assoc_num
;
let
ty
=
astconv
::
finish_resolving_def_to_ty
(
fcx
,
fcx
,
expr
.span
,
PathParamMode
::
Optional
,
&
mut
def
,
opt_self_ty
,
&
ty_segments
[
..
base_ty_end
],
&
ty_segments
[
base_ty_end
..
]);
let
method_segment
=
path
.segments
.last
()
.unwrap
();
let
method_name
=
method_segment
.identifier.name
;
match
method
::
resolve_ufcs
(
fcx
,
expr
.span
,
method_name
,
ty
,
id
)
{
Ok
(
def
)
=>
{
// Write back the new resolution.
tcx
.def_map
.borrow_mut
()
.insert
(
id
,
def
);
let
(
scheme
,
predicates
)
=
type_scheme_and_predicates_for_def
(
fcx
,
expr
.span
,
def
);
instantiate_path
(
fcx
,
slice
::
ref_slice
(
method_segment
),
scheme
,
&
predicates
,
Some
(
ty
),
def
,
expr
.span
,
id
);
}
Err
(
error
)
=>
{
method
::
report_error
(
fcx
,
expr
.span
,
ty
,
method_name
,
expr
,
error
);
fcx
.write_error
(
id
);
}
}
}
else
{
tcx
.sess
.span_bug
(
expr
.span
,
&
format!
(
"unbound path {}"
,
expr
.repr
(
tcx
))[])
}
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
...
...
@@ -4641,7 +4663,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def
::
DefForeignMod
(
..
)
|
def
::
DefUse
(
..
)
|
def
::
DefRegion
(
..
)
|
def
::
DefTyParamBinder
(
..
)
|
def
::
DefLabel
(
..
)
|
def
::
DefSelfTy
(
..
)
=>
{
fcx
.ccx.tcx.sess
.span_bug
(
sp
,
&
format!
(
"expected value, found {:?}"
,
defn
));
...
...
@@ -4652,15 +4673,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
pub
fn
instantiate_path
<
'a
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'a
,
'tcx
>
,
path
:
&
ast
::
Path
,
segments
:
&
[
ast
::
PathSegment
]
,
type_scheme
:
TypeScheme
<
'tcx
>
,
type_predicates
:
&
ty
::
GenericPredicates
<
'tcx
>
,
opt_self_ty
:
Option
<
Ty
<
'tcx
>>
,
def
:
def
::
Def
,
span
:
Span
,
node_id
:
ast
::
NodeId
)
{
debug!
(
"instantiate_path(path={}, def={}, node_id={}, type_scheme={})"
,
path
.repr
(
fcx
.tcx
())
,
debug!
(
"instantiate_path(path={
:?
}, def={}, node_id={}, type_scheme={})"
,
segments
,
def
.repr
(
fcx
.tcx
()),
node_id
,
type_scheme
.repr
(
fcx
.tcx
()));
...
...
@@ -4724,7 +4745,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
//
// The first step then is to categorize the segments appropriately.
assert
!
(
path
.segments
.len
()
>=
1
);
assert
!
(
segments
.len
()
>=
1
);
// In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory.
let
mut
require_type_space
=
opt_self_ty
.is_some
();
let
mut
segment_spaces
:
Vec
<
_
>
;
match
def
{
// Case 1 and 1b. Reference to a *type* or *enum variant*.
...
...
@@ -4738,7 +4763,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def
::
DefTyParam
(
..
)
=>
{
// Everything but the final segment should have no
// parameters at all.
segment_spaces
=
repeat
(
None
)
.take
(
path
.
segments
.len
()
-
1
)
.collect
();
segment_spaces
=
repeat
(
None
)
.take
(
segments
.len
()
-
1
)
.collect
();
segment_spaces
.push
(
Some
(
subst
::
TypeSpace
));
}
...
...
@@ -4746,14 +4771,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def
::
DefFn
(
..
)
|
def
::
DefConst
(
..
)
|
def
::
DefStatic
(
..
)
=>
{
segment_spaces
=
repeat
(
None
)
.take
(
path
.
segments
.len
()
-
1
)
.collect
();
segment_spaces
=
repeat
(
None
)
.take
(
segments
.len
()
-
1
)
.collect
();
segment_spaces
.push
(
Some
(
subst
::
FnSpace
));
}
// Case 3. Reference to a method.
def
::
DefMethod
(
_
,
providence
)
=>
{
assert
!
(
path
.segments
.len
()
>=
2
);
match
providence
{
def
::
FromTrait
(
trait_did
)
=>
{
callee
::
check_legal_trait_for_method_call
(
fcx
.ccx
,
span
,
trait_did
)
...
...
@@ -4761,9 +4784,16 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def
::
FromImpl
(
_
)
=>
{}
}
segment_spaces
=
repeat
(
None
)
.take
(
path
.segments
.len
()
-
2
)
.collect
();
segment_spaces
.push
(
Some
(
subst
::
TypeSpace
));
segment_spaces
.push
(
Some
(
subst
::
FnSpace
));
if
segments
.len
()
>=
2
{
segment_spaces
=
repeat
(
None
)
.take
(
segments
.len
()
-
2
)
.collect
();
segment_spaces
.push
(
Some
(
subst
::
TypeSpace
));
segment_spaces
.push
(
Some
(
subst
::
FnSpace
));
}
else
{
// `<T>::method` will end up here, and so can `T::method`.
assert
!
(
opt_self_ty
.is_some
());
require_type_space
=
false
;
segment_spaces
=
vec!
[
Some
(
subst
::
FnSpace
)];
}
}
// Other cases. Various nonsense that really shouldn't show up
...
...
@@ -4776,10 +4806,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
def
::
DefRegion
(
..
)
|
def
::
DefLabel
(
..
)
|
def
::
DefUpvar
(
..
)
=>
{
segment_spaces
=
repeat
(
None
)
.take
(
path
.
segments
.len
())
.collect
();
segment_spaces
=
repeat
(
None
)
.take
(
segments
.len
())
.collect
();
}
}
assert_eq!
(
segment_spaces
.len
(),
path
.
segments
.len
());
assert_eq!
(
segment_spaces
.len
(),
segments
.len
());
debug!
(
"segment_spaces={:?}"
,
segment_spaces
);
...
...
@@ -4793,16 +4823,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// provided (if any) into their appropriate spaces. We'll also report
// errors if type parameters are provided in an inappropriate place.
let
mut
substs
=
Substs
::
empty
();
for
(
opt_space
,
segment
)
in
segment_spaces
.iter
()
.zip
(
path
.
segments
.iter
())
{
for
(
opt_space
,
segment
)
in
segment_spaces
.iter
()
.zip
(
segments
.iter
())
{
match
*
opt_space
{
None
=>
{
report_error_if_segment_contains_type_parameters
(
fcx
,
segment
);
check_path_args
(
fcx
.tcx
(),
slice
::
ref_slice
(
segment
),
NO_TPS
|
NO_REGIONS
);
}
Some
(
space
)
=>
{
push_explicit_parameters_from_segment_to_substs
(
fcx
,
space
,
path
.
span
,
span
,
type_defs
,
region_defs
,
segment
,
...
...
@@ -4824,7 +4855,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// a problem.
for
&
space
in
&
ParamSpace
::
all
()
{
adjust_type_parameters
(
fcx
,
span
,
space
,
type_defs
,
opt_self_ty
.is_some
()
,
&
mut
substs
);
require_type_space
,
&
mut
substs
);
assert_eq!
(
substs
.types
.len
(
space
),
type_defs
.len
(
space
));
adjust_region_parameters
(
fcx
,
span
,
space
,
region_defs
,
&
mut
substs
);
...
...
@@ -4851,23 +4882,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fcx
.write_substs
(
node_id
,
ty
::
ItemSubsts
{
substs
:
substs
});
return
;
fn
report_error_if_segment_contains_type_parameters
(
fcx
:
&
FnCtxt
,
segment
:
&
ast
::
PathSegment
)
{
for
typ
in
&
segment
.parameters
.types
()
{
span_err!
(
fcx
.tcx
()
.sess
,
typ
.span
,
E0085
,
"type parameters may not appear here"
);
break
;
}
for
lifetime
in
&
segment
.parameters
.lifetimes
()
{
span_err!
(
fcx
.tcx
()
.sess
,
lifetime
.span
,
E0086
,
"lifetime parameters may not appear here"
);
break
;
}
}
/// Finds the parameters that the user provided and adds them to `substs`. If too many
/// parameters are provided, then reports an error and clears the output vector.
///
...
...
src/librustc_typeck/collect.rs
浏览文件 @
fe4f9b8e
...
...
@@ -1684,8 +1684,8 @@ fn is_param(ccx: &CollectCtxt,
->
bool
{
match
ast_ty
.node
{
ast
::
TyPath
(
_
,
id
)
=>
{
match
ccx
.tcx.def_map
.borrow
()[
id
]
{
ast
::
TyPath
(
_
)
=>
{
match
ccx
.tcx.def_map
.borrow
()[
ast_ty
.
id
]
{
def
::
DefTyParam
(
s
,
i
,
_
,
_
)
=>
{
space
==
s
&&
index
==
i
}
...
...
src/test/compile-fail/issue-3973.rs
浏览文件 @
fe4f9b8e
...
...
@@ -30,7 +30,5 @@ fn to_string(&self) -> String {
fn
main
()
{
let
p
=
Point
::
new
(
0.0
,
0.0
);
//~^ ERROR unresolved name `Point::new`
//~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
println!
(
"{}"
,
p
.to_string
());
}
src/test/run-pass/const-polymorphic-paths.rs
浏览文件 @
fe4f9b8e
...
...
@@ -77,18 +77,27 @@ impl<T> Size for T {}
// , (vec![b'f', b'o', b'o'], u8_as_i8);
// Trait static methods.
bool
::
size
,
fn
()
->
uint
,
();
<
bool
as
Size
>
::
size
,
fn
()
->
uint
,
();
Default
::
default
,
fn
()
->
int
,
();
int
::
default
,
fn
()
->
int
,
();
<
int
as
Default
>
::
default
,
fn
()
->
int
,
();
Rand
::
rand
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
int
::
rand
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
<
int
as
Rand
>
::
rand
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
Rand
::
rand
::
<
DummyRng
>
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
int
::
rand
::
<
DummyRng
>
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
<
int
as
Rand
>
::
rand
::
<
DummyRng
>
,
fn
(
&
mut
DummyRng
)
->
int
,
(
&
mut
dummy_rng
());
// Trait non-static methods.
Clone
::
clone
,
fn
(
&
int
)
->
int
,
(
&
5
);
int
::
clone
,
fn
(
&
int
)
->
int
,
(
&
5
);
<
int
as
Clone
>
::
clone
,
fn
(
&
int
)
->
int
,
(
&
5
);
FromIterator
::
from_iter
,
fn
(
OptionIter
<
int
>
)
->
Vec
<
int
>
,
(
Some
(
5
)
.into_iter
());
Vec
::
from_iter
,
fn
(
OptionIter
<
int
>
)
->
Vec
<
int
>
,
(
Some
(
5
)
.into_iter
());
<
Vec
<
_
>
as
FromIterator
<
_
>>
::
from_iter
,
fn
(
OptionIter
<
int
>
)
->
Vec
<
int
>
,
(
Some
(
5
)
.into_iter
());
<
Vec
<
int
>
as
FromIterator
<
_
>>
::
from_iter
,
fn
(
OptionIter
<
int
>
)
->
Vec
<
int
>
,
...
...
@@ -97,9 +106,14 @@ impl<T> Size for T {}
(
Some
(
5
)
.into_iter
());
<
Vec
<
int
>
as
FromIterator
<
_
>>
::
from_iter
::
<
OptionIter
<
int
>>
,
fn
(
OptionIter
<
int
>
)
->
Vec
<
int
>
,
(
Some
(
5
)
.into_iter
());
Add
::
add
,
fn
(
i32
,
i32
)
->
i32
,
(
5
,
6
);
i32
::
add
,
fn
(
i32
,
i32
)
->
i32
,
(
5
,
6
);
<
i32
as
Add
<
_
>>
::
add
,
fn
(
i32
,
i32
)
->
i32
,
(
5
,
6
);
<
i32
as
Add
<
i32
>>
::
add
,
fn
(
i32
,
i32
)
->
i32
,
(
5
,
6
);
String
::
into_cow
,
fn
(
String
)
->
Cow
<
'static
,
str
>
,
(
"foo"
.to_string
());
<
String
as
IntoCow
<
_
>>
::
into_cow
,
fn
(
String
)
->
Cow
<
'static
,
str
>
,
(
"foo"
.to_string
());
<
String
as
IntoCow
<
'static
,
_
>>
::
into_cow
,
fn
(
String
)
->
Cow
<
'static
,
str
>
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录