self.unify_receivers(self_ty, method_sig.inputs()[0]);
// Add any trait/regions obligations specified on the method's type parameters.
- let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
- self.add_obligations(method_ty, all_substs, &method_predicates);
+ // We won't add these if we encountered an illegal sized bound, so that we can use
+ // a custom error in that case.
+ if !rerun {
+ let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
+ self.add_obligations(method_ty, all_substs, &method_predicates);
+ }
// Create the final `MethodCallee`.
let callee = MethodCallee {
// Found an applicable method, but it is not visible.
PrivateMatch(Def),
+
+ // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
+ // forgotten to import a trait.
+ IllegalSizedBound(Vec<DefId>),
}
// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
Err(Ambiguity(..)) => true,
Err(ClosureAmbiguity(..)) => true,
Err(PrivateMatch(..)) => allow_private,
+ Err(IllegalSizedBound(..)) => true,
}
}
self_ty,
call_expr,
ProbeScope::AllTraits) {
+
+ // If we find a different result the caller probably forgot to import a trait.
Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
- Err(MethodError::Ambiguity(ref sources)) => {
+ Err(Ambiguity(ref sources)) => {
sources.iter()
.filter_map(|source| {
match *source {
// Note: this cannot come from an inherent impl,
- // because the first probe succeeded.
+ // because the first probing succeeded.
ImplSource(def) => self.tcx.trait_id_of_impl(def),
TraitSource(_) => None,
}
_ => Vec::new(),
};
- // If we find a different result, the caller probably forgot to import a trait.
- // We span an error with an appropriate help message.
- if !candidates.is_empty() {
- let error = MethodError::NoMatch(
- NoMatchData::new(Vec::new(), Vec::new(), candidates, probe::Mode::MethodCall)
- );
- self.report_method_error(span,
- self_ty,
- segment.name,
- Some(self_expr),
- error,
- None);
- }
+ return Err(IllegalSizedBound(candidates));
}
Ok(result.callee)
let msg = format!("{} `{}` is private", def.kind_name(), item_name);
self.tcx.sess.span_err(span, &msg);
}
+
+ MethodError::IllegalSizedBound(candidates) => {
+ let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
+ let mut err = self.sess().struct_span_err(span, &msg);
+ if !candidates.is_empty() {
+ let help = format!("{an}other candidate{s} {were} found in the following \
+ trait{s}, perhaps add a `use` for {one_of_them}:",
+ an = if candidates.len() == 1 {"an" } else { "" },
+ s = if candidates.len() == 1 { "" } else { "s" },
+ were = if candidates.len() == 1 { "was" } else { "were" },
+ one_of_them = if candidates.len() == 1 {
+ "it"
+ } else {
+ "one_of_them"
+ });
+ self.suggest_use_candidates(&mut err, help, candidates);
+ }
+ err.emit();
+ }
+ }
+ }
+
+ fn suggest_use_candidates(&self,
+ err: &mut DiagnosticBuilder,
+ mut msg: String,
+ candidates: Vec<DefId>) {
+ let limit = if candidates.len() == 5 { 5 } else { 4 };
+ for (i, trait_did) in candidates.iter().take(limit).enumerate() {
+ msg.push_str(&format!("\ncandidate #{}: `use {};`",
+ i + 1,
+ self.tcx.item_path_str(*trait_did)));
+ }
+ if candidates.len() > limit {
+ msg.push_str(&format!("\nand {} others", candidates.len() - limit));
}
+ err.note(&msg[..]);
}
fn suggest_traits_to_import(&self,
candidates.sort();
candidates.dedup();
err.help("items from traits can only be used if the trait is in scope");
- let mut msg = format!("the following {traits_are} implemented but not in scope, \
- perhaps add a `use` for {one_of_them}:",
- traits_are = if candidates.len() == 1 {
- "trait is"
- } else {
- "traits are"
- },
- one_of_them = if candidates.len() == 1 {
- "it"
- } else {
- "one of them"
- });
-
- let limit = if candidates.len() == 5 { 5 } else { 4 };
- for (i, trait_did) in candidates.iter().take(limit).enumerate() {
- msg.push_str(&format!("\ncandidate #{}: `use {};`",
- i + 1,
- self.tcx.item_path_str(*trait_did)));
- }
- if candidates.len() > limit {
- msg.push_str(&format!("\nand {} others", candidates.len() - limit));
- }
- err.note(&msg[..]);
-
+ let msg = format!("the following {traits_are} implemented but not in scope, \
+ perhaps add a `use` for {one_of_them}:",
+ traits_are = if candidates.len() == 1 {
+ "trait is"
+ } else {
+ "traits are"
+ },
+ one_of_them = if candidates.len() == 1 {
+ "it"
+ } else {
+ "one of them"
+ });
+
+ self.suggest_use_candidates(err, msg, candidates);
return;
}
+++ /dev/null
-// 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.
-
-mod private {
- pub trait Future {
- fn wait(&self) where Self: Sized;
- }
-
- impl Future for Box<Future> {
- fn wait(&self) { }
- }
-}
-
-//use private::Future;
-
-fn bar(arg: Box<private::Future>) {
- arg.wait();
- //~^ ERROR no method named `wait` found for type `std::boxed::Box<private::Future + 'static>`
- //~| the following trait is implemented but not in scope
- //~| ERROR the trait bound `private::Future + 'static: std::marker::Sized` is not satisfied
- //~| `private::Future + 'static` does not have a constant size known at compile-time
-}
-
-fn main() {
-
-}
--- /dev/null
+// 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.
+
+mod private {
+ pub trait Future {
+ fn wait(&self) where Self: Sized;
+ }
+
+ impl Future for Box<Future> {
+ fn wait(&self) { }
+ }
+}
+
+//use private::Future;
+
+fn bar(arg: Box<private::Future>) {
+ arg.wait();
+ //~^ ERROR the `wait` method cannot be invoked on a trait object
+ //~| another candidate was found in the following trait, perhaps add a `use` for it:
+}
+
+fn main() {
+
+}
--- /dev/null
+error: the `wait` method cannot be invoked on a trait object
+ --> $DIR/issue-35976.rs:24:9
+ |
+24 | arg.wait();
+ | ^^^^
+ |
+ = note: another candidate was found in the following trait, perhaps add a `use` for it:
+ candidate #1: `use private::Future;`
+
+error: aborting due to previous error
+