@@ -12,7 +12,7 @@ use crate::check::fatally_break_rust;
1212use crate::check::report_unexpected_variant_res;
1313use crate::check::Needs;
1414use crate::check::TupleArgumentsFlag::DontTupleArguments;
15- use crate::check::method::SelfSource;
15+ use crate::check::method::{probe, SelfSource, MethodError} ;
1616use crate::util::common::ErrorReported;
1717use crate::util::nodemap::FxHashMap;
1818use crate::astconv::AstConv as _;
@@ -29,6 +29,7 @@ use rustc::hir::def::{CtorKind, Res, DefKind};
2929use rustc::hir::ptr::P;
3030use rustc::infer;
3131use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
32+ use rustc::middle::lang_items;
3233use rustc::mir::interpret::GlobalId;
3334use rustc::ty;
3435use rustc::ty::adjustment::{
@@ -775,35 +776,80 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
775776 // no need to check for bot/err -- callee does that
776777 let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
777778
778- let method = match self.lookup_method(rcvr_t,
779- segment,
780- span,
781- expr,
782- rcvr) {
779+ let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) {
783780 Ok(method) => {
784781 self.write_method_call(expr.hir_id, method);
785782 Ok(method)
786783 }
787784 Err(error) => {
788785 if segment.ident.name != kw::Invalid {
789- self.report_method_error(span,
790- rcvr_t,
791- segment.ident,
792- SelfSource::MethodCall(rcvr),
793- error,
794- Some(args));
786+ self.report_extended_method_error(segment, span, args, rcvr_t, error);
795787 }
796788 Err(())
797789 }
798790 };
799791
800792 // Call the generic checker.
801- self.check_method_argument_types(span,
802- expr.span,
803- method,
804- &args[1..],
805- DontTupleArguments,
806- expected)
793+ self.check_method_argument_types(
794+ span,
795+ expr.span,
796+ method,
797+ &args[1..],
798+ DontTupleArguments,
799+ expected,
800+ )
801+ }
802+
803+ fn report_extended_method_error(
804+ &self,
805+ segment: &hir::PathSegment,
806+ span: Span,
807+ args: &'tcx [hir::Expr],
808+ rcvr_t: Ty<'tcx>,
809+ error: MethodError<'tcx>
810+ ) {
811+ let rcvr = &args[0];
812+ let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
813+ if let Ok(pick) = self.lookup_probe(
814+ span,
815+ segment.ident,
816+ new_rcvr_t,
817+ rcvr,
818+ probe::ProbeScope::AllTraits,
819+ ) {
820+ err.span_label(
821+ pick.item.ident.span,
822+ &format!("the method is available for `{}` here", new_rcvr_t),
823+ );
824+ }
825+ };
826+
827+ if let Some(mut err) = self.report_method_error(
828+ span,
829+ rcvr_t,
830+ segment.ident,
831+ SelfSource::MethodCall(rcvr),
832+ error,
833+ Some(args),
834+ ) {
835+ if let ty::Adt(..) = rcvr_t.sty {
836+ // Try alternative arbitrary self types that could fulfill this call.
837+ // FIXME: probe for all types that *could* be arbitrary self-types, not
838+ // just this whitelist.
839+ let box_rcvr_t = self.tcx.mk_box(rcvr_t);
840+ try_alt_rcvr(&mut err, box_rcvr_t);
841+ let pin_rcvr_t = self.tcx.mk_lang_item(
842+ rcvr_t,
843+ lang_items::PinTypeLangItem,
844+ );
845+ try_alt_rcvr(&mut err, pin_rcvr_t);
846+ let arc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Arc);
847+ try_alt_rcvr(&mut err, arc_rcvr_t);
848+ let rc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Rc);
849+ try_alt_rcvr(&mut err, rc_rcvr_t);
850+ }
851+ err.emit();
852+ }
807853 }
808854
809855 fn check_expr_cast(
@@ -1466,8 +1512,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14661512 let struct_variant_def = def.non_enum_variant();
14671513 let field_names = self.available_field_names(struct_variant_def);
14681514 if !field_names.is_empty() {
1469- err.note(&format!("available fields are: {}",
1470- self.name_series_display(field_names)));
1515+ err.note(&format!(
1516+ "available fields are: {}",
1517+ self.name_series_display(field_names),
1518+ ));
14711519 }
14721520 }
14731521 }
0 commit comments