Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
439c3128
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,发现更多精彩内容 >>
提交
439c3128
编写于
12月 21, 2016
作者:
B
bors
浏览文件
操作
浏览文件
下载
差异文件
Auto merge of #38099 - GuillaumeGomez:cast_suggestions, r=nikomatsakis
Cast suggestions r? @nikomatsakis
上级
92d46006
28e2c6af
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
401 addition
and
100 deletion
+401
-100
src/librustc/infer/mod.rs
src/librustc/infer/mod.rs
+3
-2
src/librustc/ty/sty.rs
src/librustc/ty/sty.rs
+1
-0
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/_match.rs
+1
-1
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/autoderef.rs
+8
-0
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/demand.rs
+67
-4
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/mod.rs
+9
-4
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/probe.rs
+201
-84
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+3
-3
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/mod.rs
+1
-1
src/librustc_typeck/lib.rs
src/librustc_typeck/lib.rs
+1
-1
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+4
-0
src/test/ui/span/coerce-suggestions.rs
src/test/ui/span/coerce-suggestions.rs
+47
-0
src/test/ui/span/coerce-suggestions.stderr
src/test/ui/span/coerce-suggestions.stderr
+55
-0
未找到文件。
src/librustc/infer/mod.rs
浏览文件 @
439c3128
...
...
@@ -1367,9 +1367,10 @@ pub fn report_mismatched_types(&self,
cause
:
&
ObligationCause
<
'tcx
>
,
expected
:
Ty
<
'tcx
>
,
actual
:
Ty
<
'tcx
>
,
err
:
TypeError
<
'tcx
>
)
{
err
:
TypeError
<
'tcx
>
)
->
DiagnosticBuilder
<
'tcx
>
{
let
trace
=
TypeTrace
::
types
(
cause
,
true
,
expected
,
actual
);
self
.report_and_explain_type_error
(
trace
,
&
err
)
.emit
();
self
.report_and_explain_type_error
(
trace
,
&
err
)
}
pub
fn
report_conflicting_default_types
(
&
self
,
...
...
src/librustc/ty/sty.rs
浏览文件 @
439c3128
...
...
@@ -543,6 +543,7 @@ pub struct ProjectionTy<'tcx> {
pub
struct
BareFnTy
<
'tcx
>
{
pub
unsafety
:
hir
::
Unsafety
,
pub
abi
:
abi
::
Abi
,
/// Signature (inputs and output) of this function type.
pub
sig
:
PolyFnSig
<
'tcx
>
,
}
...
...
src/librustc_typeck/check/_match.rs
浏览文件 @
439c3128
...
...
@@ -481,7 +481,7 @@ pub fn check_match(&self,
}
else
{
(
result_ty
,
arm_ty
)
};
self
.report_mismatched_types
(
&
cause
,
expected
,
found
,
e
);
self
.report_mismatched_types
(
&
cause
,
expected
,
found
,
e
)
.emit
()
;
self
.tcx.types.err
}
};
...
...
src/librustc_typeck/check/autoderef.rs
浏览文件 @
439c3128
...
...
@@ -131,10 +131,18 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
Some
(
self
.fcx
.resolve_type_vars_if_possible
(
&
normalized
.value
))
}
/// Returns the final type, generating an error if it is an
/// unresolved inference variable.
pub
fn
unambiguous_final_ty
(
&
self
)
->
Ty
<
'tcx
>
{
self
.fcx
.structurally_resolved_type
(
self
.span
,
self
.cur_ty
)
}
/// Returns the final type we ended up with, which may well be an
/// inference variable (we will resolve it first, if possible).
pub
fn
maybe_ambiguous_final_ty
(
&
self
)
->
Ty
<
'tcx
>
{
self
.fcx
.resolve_type_vars_if_possible
(
&
self
.cur_ty
)
}
pub
fn
finalize
<
'b
,
I
>
(
self
,
pref
:
LvaluePreference
,
exprs
:
I
)
where
I
:
IntoIterator
<
Item
=
&
'b
hir
::
Expr
>
{
...
...
src/librustc_typeck/check/demand.rs
浏览文件 @
439c3128
...
...
@@ -14,8 +14,13 @@
use
rustc
::
infer
::{
InferOk
};
use
rustc
::
traits
::
ObligationCause
;
use
syntax_pos
::
Span
;
use
syntax
::
ast
;
use
syntax_pos
::{
self
,
Span
};
use
rustc
::
hir
;
use
rustc
::
hir
::
def
::
Def
;
use
rustc
::
ty
::{
self
,
AssociatedItem
};
use
super
::
method
::
probe
;
impl
<
'a
,
'gcx
,
'tcx
>
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
// Requires that the two types unify, and prints an error message if
...
...
@@ -27,7 +32,7 @@ pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
self
.register_predicates
(
obligations
);
},
Err
(
e
)
=>
{
self
.report_mismatched_types
(
&
cause
,
expected
,
actual
,
e
);
self
.report_mismatched_types
(
&
cause
,
expected
,
actual
,
e
)
.emit
()
;
}
}
}
...
...
@@ -46,7 +51,7 @@ pub fn demand_eqtype_with_origin(&self,
self
.register_predicates
(
obligations
);
},
Err
(
e
)
=>
{
self
.report_mismatched_types
(
cause
,
expected
,
actual
,
e
);
self
.report_mismatched_types
(
cause
,
expected
,
actual
,
e
)
.emit
()
;
}
}
}
...
...
@@ -57,7 +62,65 @@ pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty
if
let
Err
(
e
)
=
self
.try_coerce
(
expr
,
checked_ty
,
expected
)
{
let
cause
=
self
.misc
(
expr
.span
);
let
expr_ty
=
self
.resolve_type_vars_with_obligations
(
checked_ty
);
self
.report_mismatched_types
(
&
cause
,
expected
,
expr_ty
,
e
);
let
mode
=
probe
::
Mode
::
MethodCall
;
let
suggestions
=
self
.probe_for_return_type
(
syntax_pos
::
DUMMY_SP
,
mode
,
expected
,
checked_ty
,
ast
::
DUMMY_NODE_ID
);
let
mut
err
=
self
.report_mismatched_types
(
&
cause
,
expected
,
expr_ty
,
e
);
if
suggestions
.len
()
>
0
{
err
.help
(
&
format!
(
"here are some functions which
\
might fulfill your needs:
\n
- {}"
,
self
.get_best_match
(
&
suggestions
)));
};
err
.emit
();
}
}
fn
format_method_suggestion
(
&
self
,
method
:
&
AssociatedItem
)
->
String
{
format!
(
".{}({})"
,
method
.name
,
if
self
.has_no_input_arg
(
method
)
{
""
}
else
{
"..."
})
}
fn
display_suggested_methods
(
&
self
,
methods
:
&
[
AssociatedItem
])
->
String
{
methods
.iter
()
.take
(
5
)
.map
(|
method
|
self
.format_method_suggestion
(
&*
method
))
.collect
::
<
Vec
<
String
>>
()
.join
(
"
\n
- "
)
}
fn
get_best_match
(
&
self
,
methods
:
&
[
AssociatedItem
])
->
String
{
let
no_argument_methods
:
Vec
<
_
>
=
methods
.iter
()
.filter
(|
ref
x
|
self
.has_no_input_arg
(
&*
x
))
.map
(|
x
|
x
.clone
())
.collect
();
if
no_argument_methods
.len
()
>
0
{
self
.display_suggested_methods
(
&
no_argument_methods
)
}
else
{
self
.display_suggested_methods
(
&
methods
)
}
}
// This function checks if the method isn't static and takes other arguments than `self`.
fn
has_no_input_arg
(
&
self
,
method
:
&
AssociatedItem
)
->
bool
{
match
method
.def
()
{
Def
::
Method
(
def_id
)
=>
{
match
self
.tcx
.item_type
(
def_id
)
.sty
{
ty
::
TypeVariants
::
TyFnDef
(
_
,
_
,
fty
)
=>
{
fty
.sig
.skip_binder
()
.inputs
()
.len
()
==
1
}
_
=>
false
,
}
}
_
=>
false
,
}
}
}
src/librustc_typeck/check/method/mod.rs
浏览文件 @
439c3128
...
...
@@ -30,9 +30,11 @@
pub
use
self
::
suggest
::
AllTraitsVec
;
mod
confirm
;
mod
probe
;
pub
mod
probe
;
mod
suggest
;
use
self
::
probe
::
IsSuggestion
;
pub
enum
MethodError
<
'tcx
>
{
// Did not find an applicable method, but we did find various near-misses that may work.
NoMatch
(
NoMatchData
<
'tcx
>
),
...
...
@@ -91,7 +93,8 @@ pub fn method_exists(&self,
allow_private
:
bool
)
->
bool
{
let
mode
=
probe
::
Mode
::
MethodCall
;
match
self
.probe_method
(
span
,
mode
,
method_name
,
self_ty
,
call_expr_id
)
{
match
self
.probe_for_name
(
span
,
mode
,
method_name
,
IsSuggestion
(
false
),
self_ty
,
call_expr_id
)
{
Ok
(
..
)
=>
true
,
Err
(
NoMatch
(
..
))
=>
false
,
Err
(
Ambiguity
(
..
))
=>
true
,
...
...
@@ -130,7 +133,8 @@ pub fn lookup_method(&self,
let
mode
=
probe
::
Mode
::
MethodCall
;
let
self_ty
=
self
.resolve_type_vars_if_possible
(
&
self_ty
);
let
pick
=
self
.probe_method
(
span
,
mode
,
method_name
,
self_ty
,
call_expr
.id
)
?
;
let
pick
=
self
.probe_for_name
(
span
,
mode
,
method_name
,
IsSuggestion
(
false
),
self_ty
,
call_expr
.id
)
?
;
if
let
Some
(
import_id
)
=
pick
.import_id
{
self
.tcx.used_trait_imports
.borrow_mut
()
.insert
(
import_id
);
...
...
@@ -328,7 +332,8 @@ pub fn resolve_ufcs(&self,
expr_id
:
ast
::
NodeId
)
->
Result
<
Def
,
MethodError
<
'tcx
>>
{
let
mode
=
probe
::
Mode
::
Path
;
let
pick
=
self
.probe_method
(
span
,
mode
,
method_name
,
self_ty
,
expr_id
)
?
;
let
pick
=
self
.probe_for_name
(
span
,
mode
,
method_name
,
IsSuggestion
(
false
),
self_ty
,
expr_id
)
?
;
if
let
Some
(
import_id
)
=
pick
.import_id
{
self
.tcx.used_trait_imports
.borrow_mut
()
.insert
(
import_id
);
...
...
src/librustc_typeck/check/method/probe.rs
浏览文件 @
439c3128
...
...
@@ -16,12 +16,12 @@
use
check
::
FnCtxt
;
use
hir
::
def_id
::
DefId
;
use
hir
::
def
::
Def
;
use
rustc
::
infer
::
InferOk
;
use
rustc
::
ty
::
subst
::{
Subst
,
Substs
};
use
rustc
::
traits
::{
self
,
ObligationCause
};
use
rustc
::
ty
::{
self
,
Ty
,
ToPolyTraitRef
,
TraitRef
,
TypeFoldable
};
use
rustc
::
infer
::
type_variable
::
TypeVariableOrigin
;
use
rustc
::
util
::
nodemap
::
FxHashSet
;
use
rustc
::
infer
::{
self
,
InferOk
};
use
syntax
::
ast
;
use
syntax_pos
::
Span
;
use
rustc
::
hir
;
...
...
@@ -32,11 +32,24 @@
use
self
::
CandidateKind
::
*
;
pub
use
self
::
PickKind
::
*
;
pub
enum
LookingFor
<
'tcx
>
{
/// looking for methods with the given name; this is the normal case
MethodName
(
ast
::
Name
),
/// looking for methods that return a given type; this is used to
/// assemble suggestions
ReturnType
(
Ty
<
'tcx
>
),
}
/// Boolean flag used to indicate if this search is for a suggestion
/// or not. If true, we can allow ambiguity and so forth.
pub
struct
IsSuggestion
(
pub
bool
);
struct
ProbeContext
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
span
:
Span
,
mode
:
Mode
,
item_name
:
ast
::
Name
,
looking_for
:
LookingFor
<
'tcx
>
,
steps
:
Rc
<
Vec
<
CandidateStep
<
'tcx
>>>
,
opt_simplified_steps
:
Option
<
Vec
<
ty
::
fast_reject
::
SimplifiedType
>>
,
inherent_candidates
:
Vec
<
Candidate
<
'tcx
>>
,
...
...
@@ -144,18 +157,72 @@ pub enum Mode {
}
impl
<
'a
,
'gcx
,
'tcx
>
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
pub
fn
probe_method
(
&
self
,
span
:
Span
,
mode
:
Mode
,
item_name
:
ast
::
Name
,
self_ty
:
Ty
<
'tcx
>
,
scope_expr_id
:
ast
::
NodeId
)
->
PickResult
<
'tcx
>
{
/// This is used to offer suggestions to users. It returns methods
/// that could have been called which have the desired return
/// type. Some effort is made to rule out methods that, if called,
/// would result in an error (basically, the same criteria we
/// would use to decide if a method is a plausible fit for
/// ambiguity purposes).
pub
fn
probe_for_return_type
(
&
self
,
span
:
Span
,
mode
:
Mode
,
return_type
:
Ty
<
'tcx
>
,
self_ty
:
Ty
<
'tcx
>
,
scope_expr_id
:
ast
::
NodeId
)
->
Vec
<
ty
::
AssociatedItem
>
{
debug!
(
"probe(self_ty={:?}, return_type={}, scope_expr_id={})"
,
self_ty
,
return_type
,
scope_expr_id
);
let
method_names
=
self
.probe_op
(
span
,
mode
,
LookingFor
::
ReturnType
(
return_type
),
IsSuggestion
(
true
),
self_ty
,
scope_expr_id
,
|
probe_cx
|
Ok
(
probe_cx
.candidate_method_names
()))
.unwrap_or
(
vec!
[]);
method_names
.iter
()
.flat_map
(|
&
method_name
|
{
match
self
.probe_for_name
(
span
,
mode
,
method_name
,
IsSuggestion
(
true
),
self_ty
,
scope_expr_id
)
{
Ok
(
pick
)
=>
Some
(
pick
.item
),
Err
(
_
)
=>
None
,
}
})
.collect
()
}
pub
fn
probe_for_name
(
&
self
,
span
:
Span
,
mode
:
Mode
,
item_name
:
ast
::
Name
,
is_suggestion
:
IsSuggestion
,
self_ty
:
Ty
<
'tcx
>
,
scope_expr_id
:
ast
::
NodeId
)
->
PickResult
<
'tcx
>
{
debug!
(
"probe(self_ty={:?}, item_name={}, scope_expr_id={})"
,
self_ty
,
item_name
,
scope_expr_id
);
self
.probe_op
(
span
,
mode
,
LookingFor
::
MethodName
(
item_name
),
is_suggestion
,
self_ty
,
scope_expr_id
,
|
probe_cx
|
probe_cx
.pick
())
}
fn
probe_op
<
OP
,
R
>
(
&
'a
self
,
span
:
Span
,
mode
:
Mode
,
looking_for
:
LookingFor
<
'tcx
>
,
is_suggestion
:
IsSuggestion
,
self_ty
:
Ty
<
'tcx
>
,
scope_expr_id
:
ast
::
NodeId
,
op
:
OP
)
->
Result
<
R
,
MethodError
<
'tcx
>>
where
OP
:
FnOnce
(
ProbeContext
<
'a
,
'gcx
,
'tcx
>
)
->
Result
<
R
,
MethodError
<
'tcx
>>
{
// FIXME(#18741) -- right now, creating the steps involves evaluating the
// `*` operator, which registers obligations that then escape into
// the global fulfillment context and thus has global
...
...
@@ -164,7 +231,7 @@ pub fn probe_method(&self,
// think cause spurious errors. Really though this part should
// take place in the `self.probe` below.
let
steps
=
if
mode
==
Mode
::
MethodCall
{
match
self
.create_steps
(
span
,
self_ty
)
{
match
self
.create_steps
(
span
,
self_ty
,
is_suggestion
)
{
Some
(
steps
)
=>
steps
,
None
=>
{
return
Err
(
MethodError
::
NoMatch
(
NoMatchData
::
new
(
Vec
::
new
(),
...
...
@@ -207,14 +274,19 @@ pub fn probe_method(&self,
// that we create during the probe process are removed later
self
.probe
(|
_
|
{
let
mut
probe_cx
=
ProbeContext
::
new
(
self
,
span
,
mode
,
item_name
,
steps
,
opt_simplified_steps
);
ProbeContext
::
new
(
self
,
span
,
mode
,
looking_for
,
steps
,
opt_simplified_steps
);
probe_cx
.assemble_inherent_candidates
();
probe_cx
.assemble_extension_candidates_for_traits_in_scope
(
scope_expr_id
)
?
;
probe_cx
.pick
(
)
op
(
probe_cx
)
})
}
fn
create_steps
(
&
self
,
span
:
Span
,
self_ty
:
Ty
<
'tcx
>
)
->
Option
<
Vec
<
CandidateStep
<
'tcx
>>>
{
fn
create_steps
(
&
self
,
span
:
Span
,
self_ty
:
Ty
<
'tcx
>
,
is_suggestion
:
IsSuggestion
)
->
Option
<
Vec
<
CandidateStep
<
'tcx
>>>
{
// FIXME: we don't need to create the entire steps in one pass
let
mut
autoderef
=
self
.autoderef
(
span
,
self_ty
);
...
...
@@ -228,8 +300,22 @@ fn create_steps(&self, span: Span, self_ty: Ty<'tcx>) -> Option<Vec<CandidateSte
})
.collect
();
let
final_ty
=
autoderef
.
un
ambiguous_final_ty
();
let
final_ty
=
autoderef
.
maybe_
ambiguous_final_ty
();
match
final_ty
.sty
{
ty
::
TyInfer
(
ty
::
TyVar
(
_
))
=>
{
// Ended in an inference variable. If we are doing
// a real method lookup, this is a hard error (it's an
// ambiguity and we can't make progress).
if
!
is_suggestion
.0
{
let
t
=
self
.structurally_resolved_type
(
span
,
final_ty
);
assert_eq!
(
t
,
self
.tcx.types.err
);
return
None
}
else
{
// If we're just looking for suggestions,
// though, ambiguity is no big thing, we can
// just ignore it.
}
}
ty
::
TyArray
(
elem_ty
,
_
)
=>
{
let
dereferences
=
steps
.len
()
-
1
;
...
...
@@ -253,7 +339,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn
new
(
fcx
:
&
'a
FnCtxt
<
'a
,
'gcx
,
'tcx
>
,
span
:
Span
,
mode
:
Mode
,
item_name
:
ast
::
Name
,
looking_for
:
LookingFor
<
'tcx
>
,
steps
:
Vec
<
CandidateStep
<
'tcx
>>
,
opt_simplified_steps
:
Option
<
Vec
<
ty
::
fast_reject
::
SimplifiedType
>>
)
->
ProbeContext
<
'a
,
'gcx
,
'tcx
>
{
...
...
@@ -261,7 +347,7 @@ fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
fcx
:
fcx
,
span
:
span
,
mode
:
mode
,
item_name
:
item_name
,
looking_for
:
looking_for
,
inherent_candidates
:
Vec
::
new
(),
extension_candidates
:
Vec
::
new
(),
impl_dups
:
FxHashSet
(),
...
...
@@ -410,44 +496,40 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
debug!
(
"assemble_inherent_impl_probe {:?}"
,
impl_def_id
);
let
item
=
match
self
.associated
_item
(
impl_def_id
)
{
Some
(
m
)
=>
m
,
None
=>
{
return
;
}
// No method with correct name on this impl
};
for
item
in
self
.impl_or_trait
_item
(
impl_def_id
)
{
if
!
self
.has_applicable_self
(
&
item
)
{
// No receiver declared. Not a candidate.
self
.record_static_candidate
(
ImplSource
(
impl_def_id
))
;
continue
}
if
!
self
.has_applicable_self
(
&
item
)
{
// No receiver declared. Not a candidate.
return
self
.record_static_candidate
(
ImplSource
(
impl_def_id
));
}
if
!
item
.vis
.is_accessible_from
(
self
.body_id
,
&
self
.tcx.map
)
{
self
.private_candidate
=
Some
(
item
.def
());
continue
}
if
!
item
.vis
.is_accessible_from
(
self
.body_id
,
&
self
.tcx.map
)
{
self
.private_candidate
=
Some
(
item
.def
());
return
;
}
let
(
impl_ty
,
impl_substs
)
=
self
.impl_ty_and_substs
(
impl_def_id
);
let
impl_ty
=
impl_ty
.subst
(
self
.tcx
,
impl_substs
);
let
(
impl_ty
,
impl_substs
)
=
self
.impl_ty_and_substs
(
impl_def_id
);
let
impl_ty
=
impl_ty
.subst
(
self
.tcx
,
impl_substs
);
// Determine the receiver type that the method itself expects.
let
xform_self_ty
=
self
.xform_self_ty
(
&
item
,
impl_ty
,
impl_substs
);
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
let
cause
=
traits
::
ObligationCause
::
misc
(
self
.span
,
self
.body_id
);
let
mut
selcx
=
&
mut
traits
::
SelectionContext
::
new
(
self
.fcx
);
let
traits
::
Normalized
{
value
:
xform_self_ty
,
obligations
}
=
traits
::
normalize
(
selcx
,
cause
,
&
xform_self_ty
);
debug!
(
"assemble_inherent_impl_probe: xform_self_ty = {:?}"
,
xform_self_ty
);
self
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
item
:
item
,
kind
:
InherentImplCandidate
(
impl_substs
,
obligations
),
import_id
:
self
.import_id
,
});
// Determine the receiver type that the method itself expects.
let
xform_self_ty
=
self
.xform_self_ty
(
&
item
,
impl_ty
,
impl_substs
);
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
let
cause
=
traits
::
ObligationCause
::
misc
(
self
.span
,
self
.body_id
);
let
mut
selcx
=
&
mut
traits
::
SelectionContext
::
new
(
self
.fcx
);
let
traits
::
Normalized
{
value
:
xform_self_ty
,
obligations
}
=
traits
::
normalize
(
selcx
,
cause
,
&
xform_self_ty
);
debug!
(
"assemble_inherent_impl_probe: xform_self_ty = {:?}"
,
xform_self_ty
);
self
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
item
:
item
,
kind
:
InherentImplCandidate
(
impl_substs
,
obligations
),
import_id
:
self
.import_id
,
});
}
}
fn
assemble_inherent_candidates_from_object
(
&
mut
self
,
...
...
@@ -540,17 +622,12 @@ fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand
let
tcx
=
self
.tcx
;
for
bound_trait_ref
in
traits
::
transitive_bounds
(
tcx
,
bounds
)
{
let
item
=
match
self
.associated_item
(
bound_trait_ref
.def_id
())
{
Some
(
v
)
=>
v
,
None
=>
{
continue
;
for
item
in
self
.impl_or_trait_item
(
bound_trait_ref
.def_id
())
{
if
!
self
.has_applicable_self
(
&
item
)
{
self
.record_static_candidate
(
TraitSource
(
bound_trait_ref
.def_id
()));
}
else
{
mk_cand
(
self
,
bound_trait_ref
,
item
);
}
};
if
!
self
.has_applicable_self
(
&
item
)
{
self
.record_static_candidate
(
TraitSource
(
bound_trait_ref
.def_id
()));
}
else
{
mk_cand
(
self
,
bound_trait_ref
,
item
);
}
}
}
...
...
@@ -584,36 +661,45 @@ fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodE
Ok
(())
}
pub
fn
matches_return_type
(
&
self
,
method
:
&
ty
::
AssociatedItem
,
expected
:
ty
::
Ty
<
'tcx
>
)
->
bool
{
match
method
.def
()
{
Def
::
Method
(
def_id
)
=>
{
let
fty
=
self
.tcx
.item_type
(
def_id
)
.fn_sig
();
self
.probe
(|
_
|
{
let
substs
=
self
.fresh_substs_for_item
(
self
.span
,
method
.def_id
);
let
output
=
fty
.output
()
.subst
(
self
.tcx
,
substs
);
let
(
output
,
_
)
=
self
.replace_late_bound_regions_with_fresh_var
(
self
.span
,
infer
::
FnCall
,
&
output
);
self
.can_sub_types
(
output
,
expected
)
.is_ok
()
})
}
_
=>
false
,
}
}
fn
assemble_extension_candidates_for_trait
(
&
mut
self
,
trait_def_id
:
DefId
)
->
Result
<
(),
MethodError
<
'tcx
>>
{
debug!
(
"assemble_extension_candidates_for_trait(trait_def_id={:?})"
,
trait_def_id
);
// Check whether `trait_def_id` defines a method with suitable name:
let
maybe_item
=
self
.tcx
.associated_items
(
trait_def_id
)
.find
(|
item
|
item
.name
==
self
.item_name
);
let
item
=
match
maybe_item
{
Some
(
i
)
=>
i
,
None
=>
{
return
Ok
(());
for
item
in
self
.impl_or_trait_item
(
trait_def_id
)
{
// Check whether `trait_def_id` defines a method with suitable name:
if
!
self
.has_applicable_self
(
&
item
)
{
debug!
(
"method has inapplicable self"
);
self
.record_static_candidate
(
TraitSource
(
trait_def_id
));
continue
;
}
};
// Check whether `trait_def_id` defines a method with suitable name:
if
!
self
.has_applicable_self
(
&
item
)
{
debug!
(
"method has inapplicable self"
);
self
.record_static_candidate
(
TraitSource
(
trait_def_id
));
return
Ok
(());
}
self
.assemble_extension_candidates_for_trait_impls
(
trait_def_id
,
item
.clone
());
self
.assemble_extension_candidates_for_trait_impls
(
trait_def_id
,
item
.clone
())
;
self
.assemble_closure_candidates
(
trait_def_id
,
item
.clone
())
?
;
self
.assemble_closure_candidates
(
trait_def_id
,
item
.clone
())
?
;
self
.assemble_projection_candidates
(
trait_def_id
,
item
.clone
())
;
self
.assemble_projection_candidates
(
trait_def_id
,
item
.clone
());
self
.assemble_where_clause_candidates
(
trait_def_id
,
item
.clone
());
self
.assemble_where_clause_candidates
(
trait_def_id
,
item
.clone
());
}
Ok
(())
}
...
...
@@ -833,10 +919,30 @@ fn assemble_where_clause_candidates(&mut self,
}
}
fn
candidate_method_names
(
&
self
)
->
Vec
<
ast
::
Name
>
{
let
mut
set
=
FxHashSet
();
let
mut
names
:
Vec
<
_
>
=
self
.inherent_candidates
.iter
()
.chain
(
&
self
.extension_candidates
)
.map
(|
candidate
|
candidate
.item.name
)
.filter
(|
&
name
|
set
.insert
(
name
))
.collect
();
// sort them by the name so we have a stable result
names
.sort_by_key
(|
n
|
n
.as_str
());
names
}
///////////////////////////////////////////////////////////////////////////
// THE ACTUAL SEARCH
fn
pick
(
mut
self
)
->
PickResult
<
'tcx
>
{
assert
!
(
match
self
.looking_for
{
LookingFor
::
MethodName
(
_
)
=>
true
,
LookingFor
::
ReturnType
(
_
)
=>
false
,
});
if
let
Some
(
r
)
=
self
.pick_core
()
{
return
r
;
}
...
...
@@ -855,6 +961,7 @@ fn pick(mut self) -> PickResult<'tcx> {
let
out_of_scope_traits
=
match
self
.pick_core
()
{
Some
(
Ok
(
p
))
=>
vec!
[
p
.item.container
.id
()],
//Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(),
Some
(
Err
(
MethodError
::
Ambiguity
(
v
)))
=>
{
v
.into_iter
()
.map
(|
source
|
{
...
...
@@ -1257,10 +1364,20 @@ fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
self
.tcx
.erase_late_bound_regions
(
value
)
}
/// Find item with name `item_name` defined in impl/trait `def_id`
/// and return it, or `None`, if no such item was defined there.
fn
associated_item
(
&
self
,
def_id
:
DefId
)
->
Option
<
ty
::
AssociatedItem
>
{
self
.fcx
.associated_item
(
def_id
,
self
.item_name
)
/// Find the method with the appropriate name (or return type, as the case may be).
fn
impl_or_trait_item
(
&
self
,
def_id
:
DefId
)
->
Vec
<
ty
::
AssociatedItem
>
{
match
self
.looking_for
{
LookingFor
::
MethodName
(
name
)
=>
{
self
.fcx
.associated_item
(
def_id
,
name
)
.map_or
(
Vec
::
new
(),
|
x
|
vec!
[
x
])
}
LookingFor
::
ReturnType
(
return_ty
)
=>
{
self
.tcx
.associated_items
(
def_id
)
.map
(|
did
|
self
.tcx
.associated_item
(
did
.def_id
))
.filter
(|
m
|
self
.matches_return_type
(
m
,
return_ty
))
.collect
()
}
}
}
}
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
439c3128
...
...
@@ -2986,7 +2986,7 @@ fn check_then_else(&self,
}
}
Err
(
e
)
=>
{
self
.report_mismatched_types
(
&
cause
,
expected_ty
,
found_ty
,
e
);
self
.report_mismatched_types
(
&
cause
,
expected_ty
,
found_ty
,
e
)
.emit
()
;
self
.tcx.types.err
}
}
...
...
@@ -3697,7 +3697,7 @@ fn check_expr_kind(&self,
match
result
{
Ok
(
ty
)
=>
ctxt
.unified
=
ty
,
Err
(
err
)
=>
{
self
.report_mismatched_types
(
&
cause
,
ctxt
.unified
,
e_ty
,
err
);
self
.report_mismatched_types
(
&
cause
,
ctxt
.unified
,
e_ty
,
err
)
.emit
()
;
}
}
...
...
@@ -3880,7 +3880,7 @@ fn check_expr_kind(&self,
match
result
{
Ok
(
ty
)
=>
unified
=
ty
,
Err
(
e
)
=>
{
self
.report_mismatched_types
(
&
cause
,
unified
,
e_ty
,
e
);
self
.report_mismatched_types
(
&
cause
,
unified
,
e_ty
,
e
)
.emit
()
;
}
}
}
...
...
src/librustc_typeck/coherence/mod.rs
浏览文件 @
439c3128
...
...
@@ -356,7 +356,7 @@ fn check_implementations_of_coerce_unsized(&self) {
infcx
.report_mismatched_types
(
&
cause
,
mk_ptr
(
mt_b
.ty
),
target
,
ty
::
error
::
TypeError
::
Mutability
);
ty
::
error
::
TypeError
::
Mutability
)
.emit
()
;
}
(
mt_a
.ty
,
mt_b
.ty
,
unsize_trait
,
None
)
};
...
...
src/librustc_typeck/lib.rs
浏览文件 @
439c3128
...
...
@@ -185,7 +185,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
true
}
Err
(
err
)
=>
{
infcx
.report_mismatched_types
(
cause
,
expected
,
actual
,
err
);
infcx
.report_mismatched_types
(
cause
,
expected
,
actual
,
err
)
.emit
()
;
false
}
}
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
439c3128
...
...
@@ -304,6 +304,7 @@ pub fn new() -> Features {
// Allows using `Self` and associated types in struct expressions and patterns.
(
active
,
more_struct_aliases
,
"1.14.0"
,
Some
(
37544
)),
// Allows #[link(..., cfg(..))]
(
active
,
link_cfg
,
"1.14.0"
,
Some
(
37406
)),
...
...
@@ -314,6 +315,9 @@ pub fn new() -> Features {
// Allows #[target_feature(...)]
(
active
,
target_feature
,
"1.15.0"
,
None
),
// Allow safe suggestions for potential type conversions.
(
active
,
safe_suggestion
,
"1.0.0"
,
Some
(
37384
)),
);
declare_features!
(
...
...
src/test/ui/span/coerce-suggestions.rs
0 → 100644
浏览文件 @
439c3128
// Copyright 2016 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.
#![feature(box_syntax)]
fn
test
(
_
x
:
&
mut
String
)
{}
fn
test2
(
_
x
:
&
mut
i32
)
{}
fn
main
()
{
let
x
:
usize
=
String
::
new
();
//~^ ERROR E0308
//~| NOTE expected usize, found struct `std::string::String`
//~| NOTE expected type `usize`
//~| NOTE found type `std::string::String`
//~| HELP here are some functions which might fulfill your needs:
let
x
:
&
str
=
String
::
new
();
//~^ ERROR E0308
//~| NOTE expected &str, found struct `std::string::String`
//~| NOTE expected type `&str`
//~| NOTE found type `std::string::String`
//~| HELP try with `&String::new()`
let
y
=
String
::
new
();
test
(
&
y
);
//~^ ERROR E0308
//~| NOTE types differ in mutability
//~| NOTE expected type `&mut std::string::String`
//~| NOTE found type `&std::string::String`
//~| HELP try with `&mut y`
test2
(
&
y
);
//~^ ERROR E0308
//~| NOTE types differ in mutability
//~| NOTE expected type `&mut i32`
//~| NOTE found type `&std::string::String`
let
f
;
f
=
box
f
;
//~^ ERROR E0308
//~| NOTE cyclic type of infinite size
//~| NOTE expected type `_`
//~| NOTE found type `Box<_>`
}
src/test/ui/span/coerce-suggestions.stderr
0 → 100644
浏览文件 @
439c3128
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:17:20
|
17 | let x: usize = String::new();
| ^^^^^^^^^^^^^ expected usize, found struct `std::string::String`
|
= note: expected type `usize`
= note: found type `std::string::String`
= help: here are some functions which might fulfill your needs:
- .capacity()
- .len()
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:23:19
|
23 | let x: &str = String::new();
| ^^^^^^^^^^^^^ expected &str, found struct `std::string::String`
|
= note: expected type `&str`
= note: found type `std::string::String`
= help: here are some functions which might fulfill your needs:
- .as_str()
- .trim()
- .trim_left()
- .trim_right()
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:30:10
|
30 | test(&y);
| ^^ types differ in mutability
|
= note: expected type `&mut std::string::String`
= note: found type `&std::string::String`
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:36:11
|
36 | test2(&y);
| ^^ types differ in mutability
|
= note: expected type `&mut i32`
= note: found type `&std::string::String`
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:42:9
|
42 | f = box f;
| ^^^^^ cyclic type of infinite size
|
= note: expected type `_`
= note: found type `Box<_>`
error: aborting due to 5 previous errors
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录