Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
cb08cb8a
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,发现更多精彩内容 >>
提交
cb08cb8a
编写于
4月 22, 2014
作者:
K
Kevin Butler
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Provide a note if method lookup fails and there are static definitions with the same name.
上级
b5d6b073
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
200 addition
and
35 deletion
+200
-35
src/librustc/middle/resolve.rs
src/librustc/middle/resolve.rs
+21
-19
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/method.rs
+58
-11
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/mod.rs
+17
-5
src/test/compile-fail/issue-7575.rs
src/test/compile-fail/issue-7575.rs
+80
-0
src/test/run-pass/issue-7575.rs
src/test/run-pass/issue-7575.rs
+24
-0
未找到文件。
src/librustc/middle/resolve.rs
浏览文件 @
cb08cb8a
...
...
@@ -16,7 +16,7 @@
use
middle
::
lang_items
::
LanguageItems
;
use
middle
::
lint
::{
UnnecessaryQualification
,
UnusedImports
};
use
middle
::
pat_util
::
pat_bindings
;
use
util
::
nodemap
::{
NodeMap
,
DefIdSet
,
FnvHash
Set
};
use
util
::
nodemap
::{
NodeMap
,
DefIdSet
,
FnvHash
Map
};
use
syntax
::
ast
::
*
;
use
syntax
::
ast
;
...
...
@@ -821,7 +821,7 @@ fn Resolver<'a>(session: &'a Session,
graph_root
:
graph_root
,
method_
set
:
RefCell
::
new
(
FnvHashSet
::
new
()),
method_
map
:
RefCell
::
new
(
FnvHashMap
::
new
()),
structs
:
HashSet
::
new
(),
unresolved_imports
:
0
,
...
...
@@ -860,7 +860,7 @@ struct Resolver<'a> {
graph_root
:
NameBindings
,
method_
set
:
RefCell
<
FnvHashSet
<
(
Name
,
DefId
)
>>
,
method_
map
:
RefCell
<
FnvHashMap
<
(
Name
,
DefId
),
ast
::
ExplicitSelf_
>>
,
structs
:
HashSet
<
DefId
>
,
// The number of imports that are currently unresolved.
...
...
@@ -1371,10 +1371,8 @@ fn build_reduced_graph_for_item(&mut self,
ty_m
.span
);
method_name_bindings
.define_value
(
def
,
ty_m
.span
,
true
);
// Add it to the trait info if not static.
if
ty_m
.explicit_self.node
!=
SelfStatic
{
self
.method_set
.borrow_mut
()
.insert
((
ident
.name
,
def_id
));
}
self
.method_map
.borrow_mut
()
.insert
((
ident
.name
,
def_id
),
ty_m
.explicit_self.node
);
}
name_bindings
.define_type
(
DefTrait
(
def_id
),
sp
,
is_public
);
...
...
@@ -1660,10 +1658,8 @@ fn handle_external_def(&mut self,
trait method '{}'"
,
token
::
get_ident
(
method_name
));
// Add it to the trait info if not static.
if
explicit_self
!=
SelfStatic
{
self
.method_set
.borrow_mut
()
.insert
((
method_name
.name
,
def_id
));
}
self
.method_map
.borrow_mut
()
.insert
((
method_name
.name
,
def_id
),
explicit_self
);
if
is_exported
{
self
.external_exports
.insert
(
method_def_id
);
}
...
...
@@ -4718,10 +4714,16 @@ fn resolve_module_relative_path(&mut self,
match
containing_module
.kind
.get
()
{
TraitModuleKind
|
ImplModuleKind
=>
{
match
containing_module
.def_id
.get
()
{
Some
(
def_id
)
if
self
.method_set
.borrow
()
.contains
(
&
(
ident
.name
,
def_id
))
=>
{
debug!
(
"containing module was a trait or impl
\
Some
(
def_id
)
=>
{
match
self
.method_map
.borrow
()
.find
(
&
(
ident
.name
,
def_id
))
{
Some
(
x
)
if
*
x
==
SelfStatic
=>
(),
None
=>
(),
_
=>
{
debug!
(
"containing module was a trait or impl
\
and name was a method -> not resolved"
);
return
None
;
return
None
;
}
}
},
_
=>
(),
}
...
...
@@ -5110,9 +5112,9 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
// Look for the current trait.
match
self
.current_trait_refs
{
Some
(
ref
trait_def_ids
)
=>
{
let
method_
set
=
self
.method_set
.borrow
();
let
method_
map
=
self
.method_map
.borrow
();
for
&
trait_def_id
in
trait_def_ids
.iter
()
{
if
method_
set
.contains
(
&
(
name
,
trait_def_id
))
{
if
method_
map
.contains_key
(
&
(
name
,
trait_def_id
))
{
add_trait_info
(
&
mut
found_traits
,
trait_def_id
,
name
);
}
}
...
...
@@ -5126,7 +5128,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
self
.populate_module_if_necessary
(
&
search_module
);
{
let
method_
set
=
self
.method_set
.borrow
();
let
method_
map
=
self
.method_map
.borrow
();
for
(
_
,
child_names
)
in
search_module
.children
.borrow
()
.iter
()
{
let
def
=
match
child_names
.def_for_namespace
(
TypeNS
)
{
Some
(
def
)
=>
def
,
...
...
@@ -5136,7 +5138,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
DefTrait
(
trait_def_id
)
=>
trait_def_id
,
_
=>
continue
,
};
if
method_
set
.contains
(
&
(
name
,
trait_def_id
))
{
if
method_
map
.contains_key
(
&
(
name
,
trait_def_id
))
{
add_trait_info
(
&
mut
found_traits
,
trait_def_id
,
name
);
}
}
...
...
@@ -5152,7 +5154,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
Some
(
DefTrait
(
trait_def_id
))
=>
trait_def_id
,
Some
(
..
)
|
None
=>
continue
,
};
if
self
.method_
set
.borrow
()
.contains
(
&
(
name
,
did
))
{
if
self
.method_
map
.borrow
()
.contains_key
(
&
(
name
,
did
))
{
add_trait_info
(
&
mut
found_traits
,
did
,
name
);
self
.used_imports
.insert
((
import
.type_id
,
TypeNS
));
}
...
...
src/librustc/middle/typeck/check/method.rs
浏览文件 @
cb08cb8a
...
...
@@ -118,6 +118,12 @@ pub enum AutoderefReceiverFlag {
DontAutoderefReceiver
,
}
#[deriving(Eq)]
pub
enum
StaticMethodsFlag
{
ReportStaticMethods
,
IgnoreStaticMethods
,
}
pub
fn
lookup
<
'a
>
(
fcx
:
&
'a
FnCtxt
<
'a
>
,
...
...
@@ -129,7 +135,8 @@ pub fn lookup<'a>(
supplied_tps
:
&
'a
[
ty
::
t
],
// The list of types X, Y, ... .
deref_args
:
check
::
DerefArgs
,
// Whether we autopointer first.
check_traits
:
CheckTraitsFlag
,
// Whether we check traits only.
autoderef_receiver
:
AutoderefReceiverFlag
)
autoderef_receiver
:
AutoderefReceiverFlag
,
report_statics
:
StaticMethodsFlag
)
->
Option
<
MethodCallee
>
{
let
mut
lcx
=
LookupContext
{
fcx
:
fcx
,
...
...
@@ -143,6 +150,7 @@ pub fn lookup<'a>(
deref_args
:
deref_args
,
check_traits
:
check_traits
,
autoderef_receiver
:
autoderef_receiver
,
report_statics
:
report_statics
,
};
debug!
(
"method lookup(self_ty={}, expr={}, self_expr={})"
,
...
...
@@ -173,7 +181,8 @@ pub fn lookup_in_trait<'a>(
trait_did
:
DefId
,
// The trait to limit the lookup to.
self_ty
:
ty
::
t
,
// The type of `a`.
supplied_tps
:
&
'a
[
ty
::
t
],
// The list of types X, Y, ... .
autoderef_receiver
:
AutoderefReceiverFlag
)
autoderef_receiver
:
AutoderefReceiverFlag
,
report_statics
:
StaticMethodsFlag
)
->
Option
<
MethodCallee
>
{
let
mut
lcx
=
LookupContext
{
fcx
:
fcx
,
...
...
@@ -187,6 +196,7 @@ pub fn lookup_in_trait<'a>(
deref_args
:
check
::
DoDerefArgs
,
check_traits
:
CheckTraitsOnly
,
autoderef_receiver
:
autoderef_receiver
,
report_statics
:
report_statics
,
};
debug!
(
"method lookup_in_trait(self_ty={}, self_expr={})"
,
...
...
@@ -197,8 +207,6 @@ pub fn lookup_in_trait<'a>(
lcx
.search
(
self_ty
)
}
// Determine the index of a method in the list of all methods belonging
// to a trait and its supertraits.
fn
get_method_index
(
tcx
:
&
ty
::
ctxt
,
...
...
@@ -301,6 +309,7 @@ struct LookupContext<'a> {
deref_args
:
check
::
DerefArgs
,
check_traits
:
CheckTraitsFlag
,
autoderef_receiver
:
AutoderefReceiverFlag
,
report_statics
:
StaticMethodsFlag
,
}
/**
...
...
@@ -661,7 +670,17 @@ fn push_candidates_from_impl(&mut self,
impl_did
:
DefId
,
impl_methods
:
&
[
DefId
],
is_extension
:
bool
)
{
if
!
self
.impl_dups
.insert
(
impl_did
)
{
let
did
=
if
self
.report_statics
==
ReportStaticMethods
{
// we only want to report each base trait once
match
ty
::
impl_trait_ref
(
self
.tcx
(),
impl_did
)
{
Some
(
trait_ref
)
=>
trait_ref
.def_id
,
None
=>
impl_did
}
}
else
{
impl_did
};
if
!
self
.impl_dups
.insert
(
did
)
{
return
;
// already visited
}
...
...
@@ -1018,6 +1037,25 @@ fn consider_candidates(&self, rcvr_ty: ty::t,
return
None
;
}
if
self
.report_statics
==
ReportStaticMethods
{
// lookup should only be called with ReportStaticMethods if a regular lookup failed
assert
!
(
relevant_candidates
.iter
()
.all
(|
c
|
c
.method_ty.explicit_self
==
SelfStatic
));
self
.tcx
()
.sess
.fileline_note
(
self
.span
,
"found defined static methods, maybe a `self` is missing?"
);
for
(
idx
,
candidate
)
in
relevant_candidates
.iter
()
.enumerate
()
{
self
.report_candidate
(
idx
,
&
candidate
.origin
);
}
// return something so we don't get errors for every mutability
return
Some
(
MethodCallee
{
origin
:
relevant_candidates
.get
(
0
)
.origin
,
ty
:
ty
::
mk_err
(),
substs
:
substs
::
empty
()
});
}
if
relevant_candidates
.len
()
>
1
{
self
.tcx
()
.sess
.span_err
(
self
.span
,
...
...
@@ -1305,7 +1343,7 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
return
match
candidate
.method_ty.explicit_self
{
SelfStatic
=>
{
debug!
(
"(is relevant?) explicit self is static"
);
false
self
.report_statics
==
ReportStaticMethods
}
SelfValue
=>
{
...
...
@@ -1391,11 +1429,20 @@ fn mutability_matches(self_mutbl: ast::Mutability,
fn
report_candidate
(
&
self
,
idx
:
uint
,
origin
:
&
MethodOrigin
)
{
match
*
origin
{
MethodStatic
(
impl_did
)
=>
{
// If it is an instantiated default method, use the original
// default method for error reporting.
let
did
=
match
provided_source
(
self
.tcx
(),
impl_did
)
{
None
=>
impl_did
,
Some
(
did
)
=>
did
let
did
=
if
self
.report_statics
==
ReportStaticMethods
{
// If we're reporting statics, we want to report the trait
// definition if possible, rather than an impl
match
ty
::
trait_method_of_method
(
self
.tcx
(),
impl_did
)
{
None
=>
{
debug!
(
"(report candidate) No trait method found"
);
impl_did
},
Some
(
trait_did
)
=>
{
debug!
(
"(report candidate) Found trait ref"
);
trait_did
}
}
}
else
{
// If it is an instantiated default method, use the original
// default method for error reporting.
match
provided_source
(
self
.tcx
(),
impl_did
)
{
None
=>
impl_did
,
Some
(
did
)
=>
did
}
};
self
.report_static_candidate
(
idx
,
did
)
}
...
...
src/librustc/middle/typeck/check/mod.rs
浏览文件 @
cb08cb8a
...
...
@@ -97,6 +97,7 @@
use
middle
::
typeck
::
check
::
method
::{
AutoderefReceiverFlag
};
use
middle
::
typeck
::
check
::
method
::{
CheckTraitsAndInherentMethods
};
use
middle
::
typeck
::
check
::
method
::{
DontAutoderefReceiver
};
use
middle
::
typeck
::
check
::
method
::{
IgnoreStaticMethods
,
ReportStaticMethods
};
use
middle
::
typeck
::
check
::
regionmanip
::
replace_late_bound_regions_in_fn_sig
;
use
middle
::
typeck
::
check
::
regionmanip
::
relate_free_regions
;
use
middle
::
typeck
::
check
::
vtable
::
VtableContext
;
...
...
@@ -1360,7 +1361,7 @@ fn try_overloaded_deref(fcx: &FnCtxt,
(
PreferMutLvalue
,
Some
(
trait_did
))
=>
{
method
::
lookup_in_trait
(
fcx
,
span
,
base_expr
.map
(|
x
|
&*
x
),
token
::
intern
(
"deref_mut"
),
trait_did
,
base_ty
,
[],
DontAutoderefReceiver
)
base_ty
,
[],
DontAutoderefReceiver
,
IgnoreStaticMethods
)
}
_
=>
None
};
...
...
@@ -1370,7 +1371,7 @@ fn try_overloaded_deref(fcx: &FnCtxt,
(
None
,
Some
(
trait_did
))
=>
{
method
::
lookup_in_trait
(
fcx
,
span
,
base_expr
.map
(|
x
|
&*
x
),
token
::
intern
(
"deref"
),
trait_did
,
base_ty
,
[],
DontAutoderefReceiver
)
base_ty
,
[],
DontAutoderefReceiver
,
IgnoreStaticMethods
)
}
(
method
,
_
)
=>
method
};
...
...
@@ -1956,7 +1957,7 @@ fn check_method_call(fcx: &FnCtxt,
expr_t
,
tps
.as_slice
(),
DontDerefArgs
,
CheckTraitsAndInherentMethods
,
AutoderefReceiver
)
{
AutoderefReceiver
,
IgnoreStaticMethods
)
{
Some
(
method
)
=>
{
let
method_ty
=
method
.ty
;
let
method_call
=
MethodCall
::
expr
(
expr
.id
);
...
...
@@ -1976,6 +1977,15 @@ fn check_method_call(fcx: &FnCtxt,
// Add error type for the result
fcx
.write_error
(
expr
.id
);
// Check for potential static matches (missing self parameters)
method
::
lookup
(
fcx
,
expr
,
rcvr
,
method_name
.node.name
,
expr_t
,
tps
.as_slice
(),
DontDerefArgs
,
CheckTraitsAndInherentMethods
,
DontAutoderefReceiver
,
ReportStaticMethods
);
ty
::
mk_err
()
}
};
...
...
@@ -2040,7 +2050,8 @@ fn lookup_op_method(fcx: &FnCtxt,
let
method
=
match
trait_did
{
Some
(
trait_did
)
=>
{
method
::
lookup_in_trait
(
fcx
,
op_ex
.span
,
Some
(
&*
args
[
0
]),
opname
,
trait_did
,
self_t
,
[],
autoderef_receiver
)
trait_did
,
self_t
,
[],
autoderef_receiver
,
IgnoreStaticMethods
)
}
None
=>
None
};
...
...
@@ -2348,7 +2359,8 @@ fn check_field(fcx: &FnCtxt,
tps
.as_slice
(),
DontDerefArgs
,
CheckTraitsAndInherentMethods
,
AutoderefReceiver
)
{
AutoderefReceiver
,
IgnoreStaticMethods
)
{
Some
(
_
)
=>
{
fcx
.type_error_message
(
expr
.span
,
...
...
src/test/compile-fail/issue-7575.rs
0 → 100644
浏览文件 @
cb08cb8a
// Copyright 2014 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.
trait
CtxtFn
{
fn
f8
(
self
,
uint
)
->
uint
;
fn
f9
(
uint
)
->
uint
;
//~ NOTE candidate #
}
trait
OtherTrait
{
fn
f9
(
uint
)
->
uint
;
//~ NOTE candidate #
}
trait
UnusedTrait
{
// This should never show up as a candidate
fn
f9
(
uint
)
->
uint
;
}
impl
CtxtFn
for
uint
{
fn
f8
(
self
,
i
:
uint
)
->
uint
{
i
*
4u
}
fn
f9
(
i
:
uint
)
->
uint
{
i
*
4u
}
}
impl
OtherTrait
for
uint
{
fn
f9
(
i
:
uint
)
->
uint
{
i
*
8u
}
}
struct
MyInt
(
int
);
impl
MyInt
{
fn
fff
(
i
:
int
)
->
int
{
//~ NOTE candidate #1 is `MyInt::fff`
i
}
}
trait
ManyImplTrait
{
fn
is_str
()
->
bool
{
//~ NOTE candidate #1 is
false
}
}
impl
ManyImplTrait
for
~
str
{
fn
is_str
()
->
bool
{
true
}
}
impl
ManyImplTrait
for
uint
{}
impl
ManyImplTrait
for
int
{}
impl
ManyImplTrait
for
char
{}
impl
ManyImplTrait
for
MyInt
{}
fn
no_param_bound
(
u
:
uint
,
m
:
MyInt
)
->
uint
{
u
.f8
(
42
)
+
u
.f9
(
342
)
+
m
.fff
(
42
)
//~^ ERROR type `uint` does not implement any method in scope named `f9`
//~^^ NOTE found defined static methods, maybe a `self` is missing?
//~^^^ ERROR type `MyInt` does not implement any method in scope named `fff`
//~^^^^ NOTE found defined static methods, maybe a `self` is missing?
}
fn
param_bound
<
T
:
ManyImplTrait
>
(
t
:
T
)
->
bool
{
t
.is_str
()
//~^ ERROR type `T` does not implement any method in scope named `is_str`
//~^^ NOTE found defined static methods, maybe a `self` is missing?
}
fn
main
()
{
}
\ No newline at end of file
src/test/run-pass/issue-7575.rs
0 → 100644
浏览文件 @
cb08cb8a
// Copyright 2014 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.
trait
Foo
{
fn
new
()
->
bool
{
false
}
}
trait
Bar
{
fn
new
(
&
self
)
->
bool
{
true
}
}
impl
Bar
for
int
{}
impl
Foo
for
int
{}
fn
main
()
{
assert
!
(
1
i
.new
());
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录