11use super :: {
2- Obligation , ObligationCause , ObligationCauseCode , PredicateObligation , SelectionContext ,
2+ DefIdOrName , Obligation , ObligationCause , ObligationCauseCode , PredicateObligation ,
3+ SelectionContext ,
34} ;
45
56use crate :: autoderef:: Autoderef ;
67use crate :: infer:: InferCtxt ;
78use crate :: traits:: normalize_to;
89
10+ use hir:: def:: CtorOf ;
911use hir:: HirId ;
1012use rustc_data_structures:: fx:: FxHashSet ;
1113use rustc_data_structures:: stack:: ensure_sufficient_stack;
@@ -812,28 +814,87 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
812814 err : & mut Diagnostic ,
813815 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
814816 ) -> 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+ }
817823
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 ( ) ) )
822831 }
823832 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 ( ) ) )
834835 }
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 ; } ;
837898 let output = self . replace_bound_vars_with_fresh_vars (
838899 obligation. cause . span ,
839900 LateBoundRegionConversionTime :: FnCall ,
@@ -859,7 +920,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
859920 // Get the name of the callable and the arguments to be used in the suggestion.
860921 let hir = self . tcx . hir ( ) ;
861922
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+ } ;
863935
864936 let args = inputs
865937 . map ( |ty| {
@@ -872,31 +944,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
872944 . collect :: < Vec < _ > > ( )
873945 . join ( ", " ) ;
874946
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- } ;
900947 if matches ! ( obligation. cause. code( ) , ObligationCauseCode :: FunctionArgumentObligation { .. } )
901948 && obligation. cause . span . can_be_used_for_suggestions ( )
902949 {
@@ -910,7 +957,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
910957 format ! ( "({args})" ) ,
911958 Applicability :: HasPlaceholders ,
912959 ) ;
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+ } ;
914986 err. help ( & format ! ( "{msg}: `{name}({args})`" ) ) ;
915987 }
916988 true
0 commit comments