@@ -12,7 +12,7 @@ use crate::check::fatally_break_rust;
12
12
use crate :: check:: report_unexpected_variant_res;
13
13
use crate :: check:: Needs ;
14
14
use crate :: check:: TupleArgumentsFlag :: DontTupleArguments ;
15
- use crate :: check:: method:: SelfSource ;
15
+ use crate :: check:: method:: { probe , SelfSource , MethodError } ;
16
16
use crate :: util:: common:: ErrorReported ;
17
17
use crate :: util:: nodemap:: FxHashMap ;
18
18
use crate :: astconv:: AstConv as _;
@@ -29,6 +29,7 @@ use rustc::hir::def::{CtorKind, Res, DefKind};
29
29
use rustc:: hir:: ptr:: P ;
30
30
use rustc:: infer;
31
31
use rustc:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
32
+ use rustc:: middle:: lang_items;
32
33
use rustc:: mir:: interpret:: GlobalId ;
33
34
use rustc:: ty;
34
35
use rustc:: ty:: adjustment:: {
@@ -775,35 +776,80 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
775
776
// no need to check for bot/err -- callee does that
776
777
let rcvr_t = self . structurally_resolved_type ( args[ 0 ] . span , rcvr_t) ;
777
778
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) {
783
780
Ok ( method) => {
784
781
self . write_method_call ( expr. hir_id , method) ;
785
782
Ok ( method)
786
783
}
787
784
Err ( error) => {
788
785
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) ;
795
787
}
796
788
Err ( ( ) )
797
789
}
798
790
} ;
799
791
800
792
// 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
+ }
807
853
}
808
854
809
855
fn check_expr_cast (
@@ -1466,8 +1512,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1466
1512
let struct_variant_def = def. non_enum_variant ( ) ;
1467
1513
let field_names = self . available_field_names ( struct_variant_def) ;
1468
1514
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
+ ) ) ;
1471
1519
}
1472
1520
}
1473
1521
}
0 commit comments