1
1
use super :: {
2
+ ConstEvalFailure ,
3
+ EvaluationResult ,
2
4
FulfillmentError ,
3
5
FulfillmentErrorCode ,
4
6
MismatchedProjectionTypes ,
7
+ ObjectSafetyViolation ,
5
8
Obligation ,
6
9
ObligationCause ,
7
10
ObligationCauseCode ,
8
11
OnUnimplementedDirective ,
9
12
OnUnimplementedNote ,
10
13
OutputTypeParameterMismatch ,
11
- TraitNotObjectSafe ,
12
- ConstEvalFailure ,
14
+ Overflow ,
13
15
PredicateObligation ,
14
16
SelectionContext ,
15
17
SelectionError ,
16
- ObjectSafetyViolation ,
17
- Overflow ,
18
+ TraitNotObjectSafe ,
18
19
} ;
19
20
20
21
use crate :: hir;
@@ -35,7 +36,7 @@ use crate::util::nodemap::{FxHashMap, FxHashSet};
35
36
use errors:: { Applicability , DiagnosticBuilder } ;
36
37
use std:: fmt;
37
38
use syntax:: ast;
38
- use syntax:: symbol:: sym;
39
+ use syntax:: symbol:: { sym, kw } ;
39
40
use syntax_pos:: { DUMMY_SP , Span , ExpnKind } ;
40
41
41
42
impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
@@ -657,19 +658,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
657
658
span,
658
659
E0277 ,
659
660
"{}" ,
660
- message. unwrap_or_else( ||
661
- format!( "the trait bound `{}` is not satisfied{}" ,
662
- trait_ref. to_predicate( ) , post_message)
663
- ) ) ;
661
+ message. unwrap_or_else( || format!(
662
+ "the trait bound `{}` is not satisfied{}" ,
663
+ trait_ref. to_predicate( ) ,
664
+ post_message,
665
+ ) ) ) ;
664
666
665
667
let explanation =
666
668
if obligation. cause . code == ObligationCauseCode :: MainFunctionType {
667
669
"consider using `()`, or a `Result`" . to_owned ( )
668
670
} else {
669
- format ! ( "{}the trait `{}` is not implemented for `{}`" ,
670
- pre_message,
671
- trait_ref,
672
- trait_ref. self_ty( ) )
671
+ format ! (
672
+ "{}the trait `{}` is not implemented for `{}`" ,
673
+ pre_message,
674
+ trait_ref,
675
+ trait_ref. self_ty( ) ,
676
+ )
673
677
} ;
674
678
675
679
if let Some ( ref s) = label {
@@ -686,6 +690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
686
690
}
687
691
688
692
self . suggest_borrow_on_unsized_slice ( & obligation. cause . code , & mut err) ;
693
+ self . suggest_fn_call ( & obligation, & mut err, & trait_ref) ;
689
694
self . suggest_remove_reference ( & obligation, & mut err, & trait_ref) ;
690
695
self . suggest_semicolon_removal ( & obligation, & mut err, span, & trait_ref) ;
691
696
@@ -953,6 +958,57 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
953
958
}
954
959
}
955
960
961
+ fn suggest_fn_call (
962
+ & self ,
963
+ obligation : & PredicateObligation < ' tcx > ,
964
+ err : & mut DiagnosticBuilder < ' tcx > ,
965
+ trait_ref : & ty:: Binder < ty:: TraitRef < ' tcx > > ,
966
+ ) {
967
+ let self_ty = trait_ref. self_ty ( ) ;
968
+ match self_ty. sty {
969
+ ty:: FnDef ( def_id, _) => {
970
+ // We tried to apply the bound to an `fn`. Check whether calling it would evaluate
971
+ // to a type that *would* satisfy the trait binding. If it would, suggest calling
972
+ // it: `bar(foo)` -> `bar(foo)`. This case is *very* likely to be hit if `foo` is
973
+ // `async`.
974
+ let output_ty = self_ty. fn_sig ( self . tcx ) . output ( ) ;
975
+ let new_trait_ref = ty:: TraitRef {
976
+ def_id : trait_ref. def_id ( ) ,
977
+ substs : self . tcx . mk_substs_trait ( output_ty. skip_binder ( ) , & [ ] ) ,
978
+ } ;
979
+ let obligation = Obligation :: new (
980
+ obligation. cause . clone ( ) ,
981
+ obligation. param_env ,
982
+ new_trait_ref. to_predicate ( ) ,
983
+ ) ;
984
+ match self . evaluate_obligation ( & obligation) {
985
+ Ok ( EvaluationResult :: EvaluatedToOk ) |
986
+ Ok ( EvaluationResult :: EvaluatedToOkModuloRegions ) |
987
+ Ok ( EvaluationResult :: EvaluatedToAmbig ) => {
988
+ if let Some ( hir:: Node :: Item ( hir:: Item {
989
+ ident,
990
+ node : hir:: ItemKind :: Fn ( .., body_id) ,
991
+ ..
992
+ } ) ) = self . tcx . hir ( ) . get_if_local ( def_id) {
993
+ let body = self . tcx . hir ( ) . body ( * body_id) ;
994
+ err. help ( & format ! (
995
+ "use parentheses to call the function: `{}({})`" ,
996
+ ident,
997
+ body. params. iter( )
998
+ . map( |arg| match & arg. pat. node {
999
+ hir:: PatKind :: Binding ( _, _, ident, None )
1000
+ if ident. name != kw:: SelfLower => ident. to_string( ) ,
1001
+ _ => "_" . to_string( ) ,
1002
+ } ) . collect:: <Vec <_>>( ) . join( ", " ) ) ) ;
1003
+ }
1004
+ }
1005
+ _ => { }
1006
+ }
1007
+ }
1008
+ _ => { }
1009
+ }
1010
+ }
1011
+
956
1012
/// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
957
1013
/// suggest removing these references until we reach a type that implements the trait.
958
1014
fn suggest_remove_reference (
@@ -1535,25 +1591,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1535
1591
err. note ( "only the last element of a tuple may have a dynamically sized type" ) ;
1536
1592
}
1537
1593
ObligationCauseCode :: ProjectionWf ( data) => {
1538
- err. note ( & format ! ( "required so that the projection `{}` is well-formed" ,
1539
- data) ) ;
1594
+ err. note ( & format ! (
1595
+ "required so that the projection `{}` is well-formed" ,
1596
+ data,
1597
+ ) ) ;
1540
1598
}
1541
1599
ObligationCauseCode :: ReferenceOutlivesReferent ( ref_ty) => {
1542
- err. note ( & format ! ( "required so that reference `{}` does not outlive its referent" ,
1543
- ref_ty) ) ;
1600
+ err. note ( & format ! (
1601
+ "required so that reference `{}` does not outlive its referent" ,
1602
+ ref_ty,
1603
+ ) ) ;
1544
1604
}
1545
1605
ObligationCauseCode :: ObjectTypeBound ( object_ty, region) => {
1546
- err. note ( & format ! ( "required so that the lifetime bound of `{}` for `{}` \
1547
- is satisfied",
1548
- region, object_ty) ) ;
1606
+ err. note ( & format ! (
1607
+ "required so that the lifetime bound of `{}` for `{}` is satisfied" ,
1608
+ region,
1609
+ object_ty,
1610
+ ) ) ;
1549
1611
}
1550
1612
ObligationCauseCode :: ItemObligation ( item_def_id) => {
1551
1613
let item_name = tcx. def_path_str ( item_def_id) ;
1552
1614
let msg = format ! ( "required by `{}`" , item_name) ;
1553
1615
1554
1616
if let Some ( sp) = tcx. hir ( ) . span_if_local ( item_def_id) {
1555
1617
let sp = tcx. sess . source_map ( ) . def_span ( sp) ;
1556
- err. span_note ( sp, & msg) ;
1618
+ err. span_label ( sp, & msg) ;
1557
1619
} else {
1558
1620
err. note ( & msg) ;
1559
1621
}
0 commit comments