Skip to content

Commit 25a2d13

Browse files
Allow multiple suggestions
1 parent dac8883 commit 25a2d13

File tree

3 files changed

+106
-53
lines changed

3 files changed

+106
-53
lines changed

src/librustc/infer/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,7 +1367,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13671367
cause: &ObligationCause<'tcx>,
13681368
expected: Ty<'tcx>,
13691369
actual: Ty<'tcx>,
1370-
err: TypeError<'tcx>) -> DiagnosticBuilder<'tcx> {
1370+
err: TypeError<'tcx>)
1371+
-> DiagnosticBuilder<'tcx> {
13711372
let trace = TypeTrace::types(cause, true, expected, actual);
13721373
self.report_and_explain_type_error(trace, &err)
13731374
}

src/librustc_typeck/check/demand.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
8181
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
8282
format!(".{}({})",
8383
method.name,
84-
if self.has_not_input_arg(method) {
84+
if self.has_no_input_arg(method) {
8585
""
8686
} else {
8787
"..."
@@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9999
fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
100100
let no_argument_methods: Vec<_> =
101101
methods.iter()
102-
.filter(|ref x| self.has_not_input_arg(&*x))
102+
.filter(|ref x| self.has_no_input_arg(&*x))
103103
.map(|x| x.clone())
104104
.collect();
105105
if no_argument_methods.len() > 0 {
@@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
110110
}
111111

112112
// This function checks if the method isn't static and takes other arguments than `self`.
113-
fn has_not_input_arg(&self, method: &AssociatedItem) -> bool {
113+
fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
114114
match method.def() {
115115
Def::Method(def_id) => {
116116
match self.tcx.item_type(def_id).sty {

src/librustc_typeck/check/method/probe.rs

Lines changed: 101 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ pub enum LookingFor<'tcx> {
3737
ReturnType(Ty<'tcx>),
3838
}
3939

40+
impl<'tcx> LookingFor<'tcx> {
41+
pub fn is_method_name(&self) -> bool {
42+
match *self {
43+
LookingFor::MethodName(_) => true,
44+
_ => false,
45+
}
46+
}
47+
48+
pub fn is_return_type(&self) -> bool {
49+
match *self {
50+
LookingFor::ReturnType(_) => true,
51+
_ => false,
52+
}
53+
}
54+
}
55+
4056
struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
4157
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
4258
span: Span,
@@ -468,44 +484,81 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
468484

469485
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
470486

471-
let item = match self.impl_or_trait_item(impl_def_id) {
472-
Some(m) => m,
473-
None => {
487+
let items = self.impl_or_trait_item(impl_def_id);
488+
if items.len() < 1 {
489+
return // No method with correct name on this impl
490+
}
491+
492+
if self.looking_for.is_method_name() {
493+
let item = items[0];
494+
495+
if !self.has_applicable_self(&item) {
496+
// No receiver declared. Not a candidate.
497+
return self.record_static_candidate(ImplSource(impl_def_id));
498+
}
499+
500+
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
501+
self.private_candidate = Some(item.def());
474502
return;
475-
} // No method with correct name on this impl
476-
};
503+
}
477504

478-
if !self.has_applicable_self(&item) {
479-
// No receiver declared. Not a candidate.
480-
return self.record_static_candidate(ImplSource(impl_def_id));
481-
}
505+
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
506+
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
482507

483-
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
484-
self.private_candidate = Some(item.def());
485-
return;
486-
}
508+
// Determine the receiver type that the method itself expects.
509+
let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
487510

488-
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
489-
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
490-
491-
// Determine the receiver type that the method itself expects.
492-
let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
493-
494-
// We can't use normalize_associated_types_in as it will pollute the
495-
// fcx's fulfillment context after this probe is over.
496-
let cause = traits::ObligationCause::misc(self.span, self.body_id);
497-
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
498-
let traits::Normalized { value: xform_self_ty, obligations } =
499-
traits::normalize(selcx, cause, &xform_self_ty);
500-
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
501-
xform_self_ty);
502-
503-
self.inherent_candidates.push(Candidate {
504-
xform_self_ty: xform_self_ty,
505-
item: item,
506-
kind: InherentImplCandidate(impl_substs, obligations),
507-
import_id: self.import_id,
508-
});
511+
// We can't use normalize_associated_types_in as it will pollute the
512+
// fcx's fulfillment context after this probe is over.
513+
let cause = traits::ObligationCause::misc(self.span, self.body_id);
514+
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
515+
let traits::Normalized { value: xform_self_ty, obligations } =
516+
traits::normalize(selcx, cause, &xform_self_ty);
517+
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
518+
xform_self_ty);
519+
520+
self.inherent_candidates.push(Candidate {
521+
xform_self_ty: xform_self_ty,
522+
item: item,
523+
kind: InherentImplCandidate(impl_substs, obligations),
524+
import_id: self.import_id,
525+
});
526+
} else {
527+
for item in items {
528+
if !self.has_applicable_self(&item) {
529+
// No receiver declared. Not a candidate.
530+
self.record_static_candidate(ImplSource(impl_def_id));
531+
continue
532+
}
533+
534+
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
535+
self.private_candidate = Some(item.def());
536+
continue
537+
}
538+
539+
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
540+
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
541+
542+
// Determine the receiver type that the method itself expects.
543+
let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
544+
545+
// We can't use normalize_associated_types_in as it will pollute the
546+
// fcx's fulfillment context after this probe is over.
547+
let cause = traits::ObligationCause::misc(self.span, self.body_id);
548+
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
549+
let traits::Normalized { value: xform_self_ty, obligations } =
550+
traits::normalize(selcx, cause, &xform_self_ty);
551+
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
552+
xform_self_ty);
553+
554+
self.inherent_candidates.push(Candidate {
555+
xform_self_ty: xform_self_ty,
556+
item: item,
557+
kind: InherentImplCandidate(impl_substs, obligations),
558+
import_id: self.import_id,
559+
});
560+
}
561+
}
509562
}
510563

511564
fn assemble_inherent_candidates_from_object(&mut self,
@@ -598,12 +651,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
598651

599652
let tcx = self.tcx;
600653
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
601-
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
602-
Some(v) => v,
603-
None => {
604-
continue;
605-
}
606-
};
654+
let items = self.impl_or_trait_item(bound_trait_ref.def_id());
655+
if items.len() < 1 {
656+
continue
657+
}
658+
let item = items[0];
607659

608660
if !self.has_applicable_self(&item) {
609661
self.record_static_candidate(TraitSource(bound_trait_ref.def_id()));
@@ -665,12 +717,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
665717
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
666718
trait_def_id);
667719

668-
let item = match self.impl_or_trait_item(trait_def_id) {
669-
Some(i) => i,
670-
None => {
671-
return Ok(());
672-
}
673-
};
720+
let items = self.impl_or_trait_item(trait_def_id);
721+
if items.len() < 1 {
722+
return Ok(());
723+
}
724+
let item = items[0];
674725

675726
// Check whether `trait_def_id` defines a method with suitable name:
676727
if !self.has_applicable_self(&item) {
@@ -1351,16 +1402,17 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
13511402
}
13521403

13531404
/// Find the method with the appropriate name (or return type, as the case may be).
1354-
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
1405+
fn impl_or_trait_item(&self, def_id: DefId) -> Vec<ty::AssociatedItem> {
13551406
match self.looking_for {
13561407
LookingFor::MethodName(name) => {
1357-
self.fcx.associated_item(def_id, name)
1408+
self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x])
13581409
}
13591410
LookingFor::ReturnType(return_ty) => {
13601411
self.tcx
13611412
.associated_items(def_id)
13621413
.map(|did| self.tcx.associated_item(did.def_id))
1363-
.find(|m| self.matches_return_type(m, return_ty))
1414+
.filter(|m| self.matches_return_type(m, return_ty))
1415+
.collect()
13641416
}
13651417
}
13661418
}

0 commit comments

Comments
 (0)