Skip to content

Commit bc39aab

Browse files
committed
Fix ICE that occurs when an associated const is ambiguous.
Also change several error messages to refer to "items" rather than "methods", since associated items that require resolution during type checking are not always methods.
1 parent dde68d4 commit bc39aab

32 files changed

+147
-114
lines changed

src/librustc_typeck/check/method/mod.rs

+35-35
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ use middle::def;
1818
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
1919
use middle::subst;
2020
use middle::traits;
21-
use middle::ty::*;
22-
use middle::ty;
21+
use middle::ty::{self, AsPredicate, ToPolyTraitRef};
2322
use middle::infer;
2423
use util::ppaux::Repr;
2524

@@ -64,7 +63,7 @@ type ItemIndex = usize; // just for doc purposes
6463
pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
6564
span: Span,
6665
method_name: ast::Name,
67-
self_ty: Ty<'tcx>,
66+
self_ty: ty::Ty<'tcx>,
6867
call_expr_id: ast::NodeId)
6968
-> bool
7069
{
@@ -94,11 +93,11 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9493
pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9594
span: Span,
9695
method_name: ast::Name,
97-
self_ty: Ty<'tcx>,
98-
supplied_method_types: Vec<Ty<'tcx>>,
96+
self_ty: ty::Ty<'tcx>,
97+
supplied_method_types: Vec<ty::Ty<'tcx>>,
9998
call_expr: &'tcx ast::Expr,
10099
self_expr: &'tcx ast::Expr)
101-
-> Result<MethodCallee<'tcx>, MethodError>
100+
-> Result<ty::MethodCallee<'tcx>, MethodError>
102101
{
103102
debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})",
104103
method_name.repr(fcx.tcx()),
@@ -117,9 +116,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
117116
self_expr: Option<&ast::Expr>,
118117
m_name: ast::Name,
119118
trait_def_id: DefId,
120-
self_ty: Ty<'tcx>,
121-
opt_input_types: Option<Vec<Ty<'tcx>>>)
122-
-> Option<MethodCallee<'tcx>>
119+
self_ty: ty::Ty<'tcx>,
120+
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
121+
-> Option<ty::MethodCallee<'tcx>>
123122
{
124123
lookup_in_trait_adjusted(fcx, span, self_expr, m_name, trait_def_id,
125124
0, false, self_ty, opt_input_types)
@@ -141,9 +140,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
141140
trait_def_id: DefId,
142141
autoderefs: usize,
143142
unsize: bool,
144-
self_ty: Ty<'tcx>,
145-
opt_input_types: Option<Vec<Ty<'tcx>>>)
146-
-> Option<MethodCallee<'tcx>>
143+
self_ty: ty::Ty<'tcx>,
144+
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
145+
-> Option<ty::MethodCallee<'tcx>>
147146
{
148147
debug!("lookup_in_trait_adjusted(self_ty={}, self_expr={}, m_name={}, trait_def_id={})",
149148
self_ty.repr(fcx.tcx()),
@@ -188,7 +187,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
188187
// Trait must have a method named `m_name` and it should not have
189188
// type parameters or early-bound regions.
190189
let tcx = fcx.tcx();
191-
let (method_num, method_ty) = trait_method(tcx, trait_def_id, m_name).unwrap();
190+
let (method_num, method_ty) = trait_item(tcx, trait_def_id, m_name)
191+
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
192+
.unwrap();
192193
assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
193194
assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
194195

@@ -290,10 +291,10 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
290291
}
291292
}
292293

293-
let callee = MethodCallee {
294-
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
295-
method_num: method_num,
296-
impl_def_id: None}),
294+
let callee = ty::MethodCallee {
295+
origin: ty::MethodTypeParam(ty::MethodParam{trait_ref: trait_ref.clone(),
296+
method_num: method_num,
297+
impl_def_id: None}),
297298
ty: fty,
298299
substs: trait_ref.substs.clone()
299300
};
@@ -306,7 +307,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
306307
pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
307308
span: Span,
308309
method_name: ast::Name,
309-
self_ty: Ty<'tcx>,
310+
self_ty: ty::Ty<'tcx>,
310311
expr_id: ast::NodeId)
311312
-> Result<(def::Def, LastPrivate), MethodError>
312313
{
@@ -324,41 +325,40 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
324325
_ => def::FromTrait(pick.item.container().id())
325326
};
326327
let def_result = match pick.item {
327-
ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
328-
ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance),
329-
ImplOrTraitItem::TypeTraitItem(..) => {
328+
ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
329+
ty::ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance),
330+
ty::ImplOrTraitItem::TypeTraitItem(..) => {
330331
fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type");
331332
}
332333
};
333334
Ok((def_result, lp))
334335
}
335336

336337

337-
/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
338-
/// index (or `None`, if no such method).
339-
fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
340-
trait_def_id: ast::DefId,
341-
method_name: ast::Name)
342-
-> Option<(usize, Rc<ty::Method<'tcx>>)>
338+
/// Find item with name `item_name` defined in `trait_def_id` and return it, along with its
339+
/// index (or `None`, if no such item).
340+
fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
341+
trait_def_id: ast::DefId,
342+
item_name: ast::Name)
343+
-> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
343344
{
344345
let trait_items = ty::trait_items(tcx, trait_def_id);
345346
trait_items
346347
.iter()
347348
.enumerate()
348-
.find(|&(_, ref item)| item.name() == method_name)
349-
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
349+
.find(|&(_, ref item)| item.name() == item_name)
350+
.map(|(num, item)| (num, (*item).clone()))
350351
}
351352

352-
fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
353-
impl_def_id: ast::DefId,
354-
method_name: ast::Name)
355-
-> Option<Rc<ty::Method<'tcx>>>
353+
fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
354+
impl_def_id: ast::DefId,
355+
item_name: ast::Name)
356+
-> Option<ty::ImplOrTraitItem<'tcx>>
356357
{
357358
let impl_items = tcx.impl_items.borrow();
358359
let impl_items = impl_items.get(&impl_def_id).unwrap();
359360
impl_items
360361
.iter()
361362
.map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
362-
.find(|m| m.name() == method_name)
363-
.and_then(|item| item.as_opt_method())
363+
.find(|m| m.name() == item_name)
364364
}

src/librustc_typeck/check/method/suggest.rs

+31-31
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Give useful errors and suggestions to users when a method can't be
11+
//! Give useful errors and suggestions to users when an item can't be
1212
//! found or is otherwise invalid.
1313
1414
use CrateCtxt;
@@ -27,12 +27,12 @@ use syntax::print::pprust;
2727
use std::cell;
2828
use std::cmp::Ordering;
2929

30-
use super::{MethodError, CandidateSource, impl_method, trait_method};
30+
use super::{MethodError, CandidateSource, impl_item, trait_item};
3131

3232
pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3333
span: Span,
3434
rcvr_ty: Ty<'tcx>,
35-
method_name: ast::Name,
35+
item_name: ast::Name,
3636
rcvr_expr: Option<&ast::Expr>,
3737
error: MethodError)
3838
{
@@ -44,26 +44,26 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4444
match error {
4545
MethodError::NoMatch(static_sources, out_of_scope_traits) => {
4646
let cx = fcx.tcx();
47-
let method_ustring = method_name.user_string(cx);
47+
let item_ustring = item_name.user_string(cx);
4848

4949
fcx.type_error_message(
5050
span,
5151
|actual| {
5252
format!("type `{}` does not implement any \
53-
method in scope named `{}`",
53+
item in scope named `{}`",
5454
actual,
55-
method_ustring)
55+
item_ustring)
5656
},
5757
rcvr_ty,
5858
None);
5959

60-
// If the method has the name of a field, give a help note
60+
// If the item has the name of a field, give a help note
6161
if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
6262
let fields = ty::lookup_struct_fields(cx, did);
63-
if fields.iter().any(|f| f.name == method_name) {
63+
if fields.iter().any(|f| f.name == item_name) {
6464
cx.sess.span_note(span,
6565
&format!("use `(s.{0})(...)` if you meant to call the \
66-
function stored in the `{0}` field", method_ustring));
66+
function stored in the `{0}` field", item_ustring));
6767
}
6868
}
6969

@@ -72,25 +72,25 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7272
span,
7373
"found defined static methods, maybe a `self` is missing?");
7474

75-
report_candidates(fcx, span, method_name, static_sources);
75+
report_candidates(fcx, span, item_name, static_sources);
7676
}
7777

78-
suggest_traits_to_import(fcx, span, rcvr_ty, method_name,
78+
suggest_traits_to_import(fcx, span, rcvr_ty, item_name,
7979
rcvr_expr, out_of_scope_traits)
8080
}
8181

8282
MethodError::Ambiguity(sources) => {
8383
span_err!(fcx.sess(), span, E0034,
84-
"multiple applicable methods in scope");
84+
"multiple applicable items in scope");
8585

86-
report_candidates(fcx, span, method_name, sources);
86+
report_candidates(fcx, span, item_name, sources);
8787
}
8888

8989
MethodError::ClosureAmbiguity(trait_def_id) => {
9090
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
9191
invoked on this closure as we have not yet inferred what \
9292
kind of closure it is",
93-
method_name.user_string(fcx.tcx()),
93+
item_name.user_string(fcx.tcx()),
9494
ty::item_path_str(fcx.tcx(), trait_def_id));
9595
let msg = if let Some(callee) = rcvr_expr {
9696
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
@@ -104,19 +104,19 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
104104

105105
fn report_candidates(fcx: &FnCtxt,
106106
span: Span,
107-
method_name: ast::Name,
107+
item_name: ast::Name,
108108
mut sources: Vec<CandidateSource>) {
109109
sources.sort();
110110
sources.dedup();
111111

112112
for (idx, source) in sources.iter().enumerate() {
113113
match *source {
114114
CandidateSource::ImplSource(impl_did) => {
115-
// Provide the best span we can. Use the method, if local to crate, else
116-
// the impl, if local to crate (method may be defaulted), else the call site.
117-
let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap();
115+
// Provide the best span we can. Use the item, if local to crate, else
116+
// the impl, if local to crate (item may be defaulted), else the call site.
117+
let item = impl_item(fcx.tcx(), impl_did, item_name).unwrap();
118118
let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
119-
let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span);
119+
let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span);
120120

121121
let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty;
122122

@@ -127,16 +127,16 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
127127
trait_ref.def_id)),
128128
};
129129

130-
span_note!(fcx.sess(), method_span,
130+
span_note!(fcx.sess(), item_span,
131131
"candidate #{} is defined in an impl{} for the type `{}`",
132132
idx + 1,
133133
insertion,
134134
impl_ty.user_string(fcx.tcx()));
135135
}
136136
CandidateSource::TraitSource(trait_did) => {
137-
let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap();
138-
let method_span = fcx.tcx().map.def_id_span(method.def_id, span);
139-
span_note!(fcx.sess(), method_span,
137+
let (_, item) = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
138+
let item_span = fcx.tcx().map.def_id_span(item.def_id(), span);
139+
span_note!(fcx.sess(), item_span,
140140
"candidate #{} is defined in the trait `{}`",
141141
idx + 1,
142142
ty::item_path_str(fcx.tcx(), trait_did));
@@ -152,19 +152,19 @@ pub type AllTraitsVec = Vec<TraitInfo>;
152152
fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
153153
span: Span,
154154
rcvr_ty: Ty<'tcx>,
155-
method_name: ast::Name,
155+
item_name: ast::Name,
156156
rcvr_expr: Option<&ast::Expr>,
157157
valid_out_of_scope_traits: Vec<ast::DefId>)
158158
{
159159
let tcx = fcx.tcx();
160-
let method_ustring = method_name.user_string(tcx);
160+
let item_ustring = item_name.user_string(tcx);
161161

162162
if !valid_out_of_scope_traits.is_empty() {
163163
let mut candidates = valid_out_of_scope_traits;
164164
candidates.sort();
165165
candidates.dedup();
166166
let msg = format!(
167-
"methods from traits can only be called if the trait is in scope; \
167+
"items from traits can only be used if the trait is in scope; \
168168
the following {traits_are} implemented but not in scope, \
169169
perhaps add a `use` for {one_of_them}:",
170170
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
@@ -185,7 +185,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
185185
let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr);
186186

187187
// there's no implemented traits, so lets suggest some traits to
188-
// implement, by finding ones that have the method name, and are
188+
// implement, by finding ones that have the item name, and are
189189
// legal to implement.
190190
let mut candidates = all_traits(fcx.ccx)
191191
.filter(|info| {
@@ -196,7 +196,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
196196
// implementing a trait would be legal but is rejected
197197
// here).
198198
(type_is_local || ast_util::is_local(info.def_id))
199-
&& trait_method(tcx, info.def_id, method_name).is_some()
199+
&& trait_item(tcx, info.def_id, item_name).is_some()
200200
})
201201
.collect::<Vec<_>>();
202202

@@ -209,12 +209,12 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
209209
// of a type parameter: suggest adding a trait bound rather
210210
// than implementing.
211211
let msg = format!(
212-
"methods from traits can only be called if the trait is implemented and in scope; \
213-
the following {traits_define} a method `{name}`, \
212+
"items from traits can only be used if the trait is implemented and in scope; \
213+
the following {traits_define} an item `{name}`, \
214214
perhaps you need to implement {one_of_them}:",
215215
traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
216216
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
217-
name = method_ustring);
217+
name = item_ustring);
218218

219219
fcx.sess().fileline_help(span, &msg[..]);
220220

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(associated_consts)]
12+
13+
trait Foo {
14+
const ID: i32;
15+
}
16+
17+
trait Bar {
18+
const ID: i32;
19+
}
20+
21+
impl Foo for i32 {
22+
const ID: i32 = 1;
23+
}
24+
25+
impl Bar for i32 {
26+
const ID: i32 = 3;
27+
}
28+
29+
const X: i32 = <i32>::ID; //~ ERROR E0034
30+
31+
fn main() {
32+
assert_eq!(1, X);
33+
}

src/test/compile-fail/auto-ref-slice-plus-ref.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ fn main() {
1515
// vectors to slices then automatically create a self reference.
1616

1717
let mut a = vec!(0);
18-
a.test_mut(); //~ ERROR does not implement any method in scope named `test_mut`
19-
a.test(); //~ ERROR does not implement any method in scope named `test`
18+
a.test_mut(); //~ ERROR does not implement any item in scope named `test_mut`
19+
a.test(); //~ ERROR does not implement any item in scope named `test`
2020

21-
([1]).test(); //~ ERROR does not implement any method in scope named `test`
22-
(&[1]).test(); //~ ERROR does not implement any method in scope named `test`
21+
([1]).test(); //~ ERROR does not implement any item in scope named `test`
22+
(&[1]).test(); //~ ERROR does not implement any item in scope named `test`
2323
}
2424

2525
trait MyIter {

0 commit comments

Comments
 (0)