1
1
use super :: {
2
- Obligation , ObligationCause , ObligationCauseCode , PredicateObligation , SelectionContext ,
2
+ DefIdOrName , Obligation , ObligationCause , ObligationCauseCode , PredicateObligation ,
3
+ SelectionContext ,
3
4
} ;
4
5
5
6
use crate :: autoderef:: Autoderef ;
6
7
use crate :: infer:: InferCtxt ;
7
8
use crate :: traits:: normalize_to;
8
9
10
+ use hir:: def:: CtorOf ;
9
11
use hir:: HirId ;
10
12
use rustc_data_structures:: fx:: FxHashSet ;
11
13
use rustc_data_structures:: stack:: ensure_sufficient_stack;
@@ -812,28 +814,87 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
812
814
err : & mut Diagnostic ,
813
815
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
814
816
) -> bool {
815
- // Skipping binder here, remapping below
816
- let self_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
817
+ if let ty:: PredicateKind :: Trait ( trait_pred) = obligation. predicate . kind ( ) . skip_binder ( )
818
+ && Some ( trait_pred. def_id ( ) ) == self . tcx . lang_items ( ) . sized_trait ( )
819
+ {
820
+ // Don't suggest calling to turn an unsized type into a sized type
821
+ return false ;
822
+ }
817
823
818
- let ( def_id, inputs, output, kind) = match * self_ty. kind ( ) {
819
- ty:: Closure ( def_id, substs) => {
820
- let sig = substs. as_closure ( ) . sig ( ) ;
821
- ( def_id, sig. inputs ( ) . map_bound ( |inputs| & inputs[ 1 ..] ) , sig. output ( ) , "closure" )
824
+ // This is duplicated from `extract_callable_info` in typeck, which
825
+ // relies on autoderef, so we can't use it here.
826
+ let found = trait_pred. self_ty ( ) . skip_binder ( ) . peel_refs ( ) ;
827
+ let Some ( ( def_id_or_name, output, inputs) ) = ( match * found. kind ( )
828
+ {
829
+ ty:: FnPtr ( fn_sig) => {
830
+ Some ( ( DefIdOrName :: Name ( "function pointer" ) , fn_sig. output ( ) , fn_sig. inputs ( ) ) )
822
831
}
823
832
ty:: FnDef ( def_id, _) => {
824
- let sig = self_ty. fn_sig ( self . tcx ) ;
825
- (
826
- def_id,
827
- sig. inputs ( ) ,
828
- sig. output ( ) ,
829
- match self . tcx . def_kind ( def_id) {
830
- DefKind :: Ctor ( ..) => "constructor" ,
831
- _ => "function" ,
832
- } ,
833
- )
833
+ let fn_sig = found. fn_sig ( self . tcx ) ;
834
+ Some ( ( DefIdOrName :: DefId ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) ) )
834
835
}
835
- _ => return false ,
836
- } ;
836
+ ty:: Closure ( def_id, substs) => {
837
+ let fn_sig = substs. as_closure ( ) . sig ( ) ;
838
+ Some ( (
839
+ DefIdOrName :: DefId ( def_id) ,
840
+ fn_sig. output ( ) ,
841
+ fn_sig. inputs ( ) . map_bound ( |inputs| & inputs[ 1 ..] ) ,
842
+ ) )
843
+ }
844
+ ty:: Opaque ( def_id, substs) => {
845
+ self . tcx . bound_item_bounds ( def_id) . subst ( self . tcx , substs) . iter ( ) . find_map ( |pred| {
846
+ if let ty:: PredicateKind :: Projection ( proj) = pred. kind ( ) . skip_binder ( )
847
+ && Some ( proj. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
848
+ // args tuple will always be substs[1]
849
+ && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
850
+ {
851
+ Some ( (
852
+ DefIdOrName :: DefId ( def_id) ,
853
+ pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
854
+ pred. kind ( ) . rebind ( args. as_slice ( ) ) ,
855
+ ) )
856
+ } else {
857
+ None
858
+ }
859
+ } )
860
+ }
861
+ ty:: Dynamic ( data, _, ty:: Dyn ) => {
862
+ data. iter ( ) . find_map ( |pred| {
863
+ if let ty:: ExistentialPredicate :: Projection ( proj) = pred. skip_binder ( )
864
+ && Some ( proj. item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
865
+ // for existential projection, substs are shifted over by 1
866
+ && let ty:: Tuple ( args) = proj. substs . type_at ( 0 ) . kind ( )
867
+ {
868
+ Some ( (
869
+ DefIdOrName :: Name ( "trait object" ) ,
870
+ pred. rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
871
+ pred. rebind ( args. as_slice ( ) ) ,
872
+ ) )
873
+ } else {
874
+ None
875
+ }
876
+ } )
877
+ }
878
+ ty:: Param ( _) => {
879
+ obligation. param_env . caller_bounds ( ) . iter ( ) . find_map ( |pred| {
880
+ if let ty:: PredicateKind :: Projection ( proj) = pred. kind ( ) . skip_binder ( )
881
+ && Some ( proj. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
882
+ && proj. projection_ty . self_ty ( ) == found
883
+ // args tuple will always be substs[1]
884
+ && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
885
+ {
886
+ Some ( (
887
+ DefIdOrName :: Name ( "type parameter" ) ,
888
+ pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
889
+ pred. kind ( ) . rebind ( args. as_slice ( ) ) ,
890
+ ) )
891
+ } else {
892
+ None
893
+ }
894
+ } )
895
+ }
896
+ _ => None ,
897
+ } ) else { return false ; } ;
837
898
let output = self . replace_bound_vars_with_fresh_vars (
838
899
obligation. cause . span ,
839
900
LateBoundRegionConversionTime :: FnCall ,
@@ -859,7 +920,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
859
920
// Get the name of the callable and the arguments to be used in the suggestion.
860
921
let hir = self . tcx . hir ( ) ;
861
922
862
- let msg = format ! ( "use parentheses to call the {}" , kind) ;
923
+ let msg = match def_id_or_name {
924
+ DefIdOrName :: DefId ( def_id) => match self . tcx . def_kind ( def_id) {
925
+ DefKind :: Ctor ( CtorOf :: Struct , _) => {
926
+ "use parentheses to instantiate this tuple struct" . to_string ( )
927
+ }
928
+ DefKind :: Ctor ( CtorOf :: Variant , _) => {
929
+ "use parentheses to instantiate this tuple variant" . to_string ( )
930
+ }
931
+ kind => format ! ( "use parentheses to call this {}" , kind. descr( def_id) ) ,
932
+ } ,
933
+ DefIdOrName :: Name ( name) => format ! ( "use parentheses to call this {name}" ) ,
934
+ } ;
863
935
864
936
let args = inputs
865
937
. map ( |ty| {
@@ -872,31 +944,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
872
944
. collect :: < Vec < _ > > ( )
873
945
. join ( ", " ) ;
874
946
875
- let name = match hir. get_if_local ( def_id) {
876
- Some ( hir:: Node :: Expr ( hir:: Expr {
877
- kind : hir:: ExprKind :: Closure ( hir:: Closure { fn_decl_span, .. } ) ,
878
- ..
879
- } ) ) => {
880
- err. span_label ( * fn_decl_span, "consider calling this closure" ) ;
881
- let Some ( name) = self . get_closure_name ( def_id, err, & msg) else {
882
- return false ;
883
- } ;
884
- name. to_string ( )
885
- }
886
- Some ( hir:: Node :: Item ( hir:: Item { ident, kind : hir:: ItemKind :: Fn ( ..) , .. } ) ) => {
887
- err. span_label ( ident. span , "consider calling this function" ) ;
888
- ident. to_string ( )
889
- }
890
- Some ( hir:: Node :: Ctor ( ..) ) => {
891
- let name = self . tcx . def_path_str ( def_id) ;
892
- err. span_label (
893
- self . tcx . def_span ( def_id) ,
894
- format ! ( "consider calling the constructor for `{}`" , name) ,
895
- ) ;
896
- name
897
- }
898
- _ => return false ,
899
- } ;
900
947
if matches ! ( obligation. cause. code( ) , ObligationCauseCode :: FunctionArgumentObligation { .. } )
901
948
&& obligation. cause . span . can_be_used_for_suggestions ( )
902
949
{
@@ -910,7 +957,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
910
957
format ! ( "({args})" ) ,
911
958
Applicability :: HasPlaceholders ,
912
959
) ;
913
- } else {
960
+ } else if let DefIdOrName :: DefId ( def_id) = def_id_or_name {
961
+ let name = match hir. get_if_local ( def_id) {
962
+ Some ( hir:: Node :: Expr ( hir:: Expr {
963
+ kind : hir:: ExprKind :: Closure ( hir:: Closure { fn_decl_span, .. } ) ,
964
+ ..
965
+ } ) ) => {
966
+ err. span_label ( * fn_decl_span, "consider calling this closure" ) ;
967
+ let Some ( name) = self . get_closure_name ( def_id, err, & msg) else {
968
+ return false ;
969
+ } ;
970
+ name. to_string ( )
971
+ }
972
+ Some ( hir:: Node :: Item ( hir:: Item { ident, kind : hir:: ItemKind :: Fn ( ..) , .. } ) ) => {
973
+ err. span_label ( ident. span , "consider calling this function" ) ;
974
+ ident. to_string ( )
975
+ }
976
+ Some ( hir:: Node :: Ctor ( ..) ) => {
977
+ let name = self . tcx . def_path_str ( def_id) ;
978
+ err. span_label (
979
+ self . tcx . def_span ( def_id) ,
980
+ format ! ( "consider calling the constructor for `{}`" , name) ,
981
+ ) ;
982
+ name
983
+ }
984
+ _ => return false ,
985
+ } ;
914
986
err. help ( & format ! ( "{msg}: `{name}({args})`" ) ) ;
915
987
}
916
988
true
0 commit comments