Skip to content

Commit 1b5b639

Browse files
committed
Auto merge of #25065 - quantheory:fix_associated_const_ambiguity_message, r=nikomatsakis
This fixes #24922 and #25017, and reduces the number of error messages that talk about "methods" when associated constants rather than methods are involved. I will admit that I haven't thought very carefully about the error messages. My goal has been to make more of the messages technically correct in all situations, and to avoid ICEs. But in some cases we could probably talk specifically about "methods" rather than "items".
2 parents e539424 + b4bbf3a commit 1b5b639

36 files changed

+191
-150
lines changed

src/librustc_resolve/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2528,15 +2528,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
25282528
// If anything ends up here entirely resolved,
25292529
// it's an error. If anything ends up here
25302530
// partially resolved, that's OK, because it may
2531-
// be a `T::CONST` that typeck will resolve to
2532-
// an inherent impl.
2531+
// be a `T::CONST` that typeck will resolve.
25332532
if path_res.depth == 0 {
25342533
self.resolve_error(
25352534
path.span,
25362535
&format!("`{}` is not an enum variant, struct or const",
25372536
token::get_ident(
25382537
path.segments.last().unwrap().identifier)));
25392538
} else {
2539+
let const_name = path.segments.last().unwrap()
2540+
.identifier.name;
2541+
let traits = self.get_traits_containing_item(const_name);
2542+
self.trait_map.insert(pattern.id, traits);
25402543
self.record_def(pattern.id, path_res);
25412544
}
25422545
}

src/librustc_typeck/check/method/mod.rs

+36-37
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ use middle::def;
1616
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
1717
use middle::subst;
1818
use middle::traits;
19-
use middle::ty::*;
20-
use middle::ty;
19+
use middle::ty::{self, AsPredicate, ToPolyTraitRef};
2120
use middle::infer;
2221
use util::ppaux::Repr;
2322

24-
use std::rc::Rc;
2523
use syntax::ast::DefId;
2624
use syntax::ast;
2725
use syntax::codemap::Span;
@@ -39,7 +37,7 @@ pub enum MethodError {
3937
// Did not find an applicable method, but we did find various
4038
// static methods that may apply, as well as a list of
4139
// not-in-scope traits which may work.
42-
NoMatch(Vec<CandidateSource>, Vec<ast::DefId>),
40+
NoMatch(Vec<CandidateSource>, Vec<ast::DefId>, probe::Mode),
4341

4442
// Multiple methods might apply.
4543
Ambiguity(Vec<CandidateSource>),
@@ -62,7 +60,7 @@ type ItemIndex = usize; // just for doc purposes
6260
pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
6361
span: Span,
6462
method_name: ast::Name,
65-
self_ty: Ty<'tcx>,
63+
self_ty: ty::Ty<'tcx>,
6664
call_expr_id: ast::NodeId)
6765
-> bool
6866
{
@@ -92,11 +90,11 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9290
pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9391
span: Span,
9492
method_name: ast::Name,
95-
self_ty: Ty<'tcx>,
96-
supplied_method_types: Vec<Ty<'tcx>>,
93+
self_ty: ty::Ty<'tcx>,
94+
supplied_method_types: Vec<ty::Ty<'tcx>>,
9795
call_expr: &'tcx ast::Expr,
9896
self_expr: &'tcx ast::Expr)
99-
-> Result<MethodCallee<'tcx>, MethodError>
97+
-> Result<ty::MethodCallee<'tcx>, MethodError>
10098
{
10199
debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})",
102100
method_name.repr(fcx.tcx()),
@@ -115,9 +113,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
115113
self_expr: Option<&ast::Expr>,
116114
m_name: ast::Name,
117115
trait_def_id: DefId,
118-
self_ty: Ty<'tcx>,
119-
opt_input_types: Option<Vec<Ty<'tcx>>>)
120-
-> Option<MethodCallee<'tcx>>
116+
self_ty: ty::Ty<'tcx>,
117+
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
118+
-> Option<ty::MethodCallee<'tcx>>
121119
{
122120
lookup_in_trait_adjusted(fcx, span, self_expr, m_name, trait_def_id,
123121
0, false, self_ty, opt_input_types)
@@ -139,9 +137,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
139137
trait_def_id: DefId,
140138
autoderefs: usize,
141139
unsize: bool,
142-
self_ty: Ty<'tcx>,
143-
opt_input_types: Option<Vec<Ty<'tcx>>>)
144-
-> Option<MethodCallee<'tcx>>
140+
self_ty: ty::Ty<'tcx>,
141+
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
142+
-> Option<ty::MethodCallee<'tcx>>
145143
{
146144
debug!("lookup_in_trait_adjusted(self_ty={}, self_expr={}, m_name={}, trait_def_id={})",
147145
self_ty.repr(fcx.tcx()),
@@ -186,7 +184,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
186184
// Trait must have a method named `m_name` and it should not have
187185
// type parameters or early-bound regions.
188186
let tcx = fcx.tcx();
189-
let (method_num, method_ty) = trait_method(tcx, trait_def_id, m_name).unwrap();
187+
let (method_num, method_ty) = trait_item(tcx, trait_def_id, m_name)
188+
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
189+
.unwrap();
190190
assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
191191
assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
192192

@@ -288,10 +288,10 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
288288
}
289289
}
290290

291-
let callee = MethodCallee {
292-
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
293-
method_num: method_num,
294-
impl_def_id: None}),
291+
let callee = ty::MethodCallee {
292+
origin: ty::MethodTypeParam(ty::MethodParam{trait_ref: trait_ref.clone(),
293+
method_num: method_num,
294+
impl_def_id: None}),
295295
ty: fty,
296296
substs: trait_ref.substs.clone()
297297
};
@@ -304,7 +304,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
304304
pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
305305
span: Span,
306306
method_name: ast::Name,
307-
self_ty: Ty<'tcx>,
307+
self_ty: ty::Ty<'tcx>,
308308
expr_id: ast::NodeId)
309309
-> Result<(def::Def, LastPrivate), MethodError>
310310
{
@@ -322,41 +322,40 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
322322
_ => def::FromTrait(pick.item.container().id())
323323
};
324324
let def_result = match pick.item {
325-
ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
326-
ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance),
327-
ImplOrTraitItem::TypeTraitItem(..) => {
325+
ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
326+
ty::ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance),
327+
ty::ImplOrTraitItem::TypeTraitItem(..) => {
328328
fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type");
329329
}
330330
};
331331
Ok((def_result, lp))
332332
}
333333

334334

335-
/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
336-
/// index (or `None`, if no such method).
337-
fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
338-
trait_def_id: ast::DefId,
339-
method_name: ast::Name)
340-
-> Option<(usize, Rc<ty::Method<'tcx>>)>
335+
/// Find item with name `item_name` defined in `trait_def_id` and return it, along with its
336+
/// index (or `None`, if no such item).
337+
fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
338+
trait_def_id: ast::DefId,
339+
item_name: ast::Name)
340+
-> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
341341
{
342342
let trait_items = ty::trait_items(tcx, trait_def_id);
343343
trait_items
344344
.iter()
345345
.enumerate()
346-
.find(|&(_, ref item)| item.name() == method_name)
347-
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
346+
.find(|&(_, ref item)| item.name() == item_name)
347+
.map(|(num, item)| (num, (*item).clone()))
348348
}
349349

350-
fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
351-
impl_def_id: ast::DefId,
352-
method_name: ast::Name)
353-
-> Option<Rc<ty::Method<'tcx>>>
350+
fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
351+
impl_def_id: ast::DefId,
352+
item_name: ast::Name)
353+
-> Option<ty::ImplOrTraitItem<'tcx>>
354354
{
355355
let impl_items = tcx.impl_items.borrow();
356356
let impl_items = impl_items.get(&impl_def_id).unwrap();
357357
impl_items
358358
.iter()
359359
.map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
360-
.find(|m| m.name() == method_name)
361-
.and_then(|item| item.as_opt_method())
360+
.find(|m| m.name() == item_name)
362361
}

src/librustc_typeck/check/method/probe.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
136136
let steps = if mode == Mode::MethodCall {
137137
match create_steps(fcx, span, self_ty) {
138138
Some(steps) => steps,
139-
None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
139+
None => return Err(MethodError::NoMatch(Vec::new(), Vec::new(), mode)),
140140
}
141141
} else {
142142
vec![CandidateStep {
@@ -866,7 +866,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
866866
}
867867
}
868868
}).collect(),
869-
Some(Err(MethodError::NoMatch(_, others))) => {
869+
Some(Err(MethodError::NoMatch(_, others, _))) => {
870870
assert!(others.is_empty());
871871
vec![]
872872
}
@@ -877,7 +877,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
877877
None => vec![],
878878
};
879879

880-
Err(MethodError::NoMatch(static_candidates, out_of_scope_traits))
880+
Err(MethodError::NoMatch(static_candidates, out_of_scope_traits, self.mode))
881881
}
882882

883883
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {

0 commit comments

Comments
 (0)