@@ -81,6 +81,7 @@ use rustc_errors::ErrorGuaranteed;
8181use rustc_errors:: { pluralize, struct_span_code_err, Diag } ;
8282use rustc_hir:: def_id:: { DefId , LocalDefId } ;
8383use rustc_hir:: intravisit:: Visitor ;
84+ use rustc_hir:: Mutability ;
8485use rustc_index:: bit_set:: BitSet ;
8586use rustc_infer:: infer:: error_reporting:: ObligationCauseExt as _;
8687use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
@@ -91,10 +92,11 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
9192use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
9293use rustc_middle:: ty:: { GenericArgs , GenericArgsRef } ;
9394use rustc_session:: parse:: feature_err;
94- use rustc_span:: symbol:: { kw, Ident } ;
95- use rustc_span:: { self , def_id:: CRATE_DEF_ID , BytePos , Span , Symbol , DUMMY_SP } ;
95+ use rustc_span:: symbol:: { kw, sym , Ident } ;
96+ use rustc_span:: { def_id:: CRATE_DEF_ID , BytePos , Span , Symbol , DUMMY_SP } ;
9697use rustc_target:: abi:: VariantIdx ;
9798use rustc_target:: spec:: abi:: Abi ;
99+ use rustc_trait_selection:: infer:: InferCtxtExt ;
98100use rustc_trait_selection:: traits:: error_reporting:: suggestions:: ReturnsVisitor ;
99101use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
100102use rustc_trait_selection:: traits:: ObligationCtxt ;
@@ -466,14 +468,64 @@ fn fn_sig_suggestion<'tcx>(
466468 )
467469}
468470
469- pub fn ty_kind_suggestion ( ty : Ty < ' _ > ) -> Option < & ' static str > {
471+ pub fn ty_kind_suggestion < ' tcx > ( ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Option < String > {
472+ // Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`.
473+ // FIXME: deduplicate the above.
474+ let implements_default = |ty| {
475+ let Some ( default_trait) = tcx. get_diagnostic_item ( sym:: Default ) else {
476+ return false ;
477+ } ;
478+ let infcx = tcx. infer_ctxt ( ) . build ( ) ;
479+ infcx
480+ . type_implements_trait ( default_trait, [ ty] , ty:: ParamEnv :: reveal_all ( ) )
481+ . must_apply_modulo_regions ( )
482+ } ;
470483 Some ( match ty. kind ( ) {
471- ty:: Bool => "true" ,
472- ty:: Char => "'a'" ,
473- ty:: Int ( _) | ty:: Uint ( _) => "42" ,
474- ty:: Float ( _) => "3.14159" ,
475- ty:: Error ( _) | ty:: Never => return None ,
476- _ => "value" ,
484+ ty:: Never | ty:: Error ( _) => return None ,
485+ ty:: Bool => "false" . to_string ( ) ,
486+ ty:: Char => "\' x\' " . to_string ( ) ,
487+ ty:: Int ( _) | ty:: Uint ( _) => "42" . into ( ) ,
488+ ty:: Float ( _) => "3.14159" . into ( ) ,
489+ ty:: Slice ( _) => "[]" . to_string ( ) ,
490+ ty:: Adt ( def, _) if Some ( def. did ( ) ) == tcx. get_diagnostic_item ( sym:: Vec ) => {
491+ "vec![]" . to_string ( )
492+ }
493+ ty:: Adt ( def, _) if Some ( def. did ( ) ) == tcx. get_diagnostic_item ( sym:: String ) => {
494+ "String::new()" . to_string ( )
495+ }
496+ ty:: Adt ( def, args) if def. is_box ( ) => {
497+ format ! ( "Box::new({})" , ty_kind_suggestion( args[ 0 ] . expect_ty( ) , tcx) ?)
498+ }
499+ ty:: Adt ( def, _) if Some ( def. did ( ) ) == tcx. get_diagnostic_item ( sym:: Option ) => {
500+ "None" . to_string ( )
501+ }
502+ ty:: Adt ( def, args) if Some ( def. did ( ) ) == tcx. get_diagnostic_item ( sym:: Result ) => {
503+ format ! ( "Ok({})" , ty_kind_suggestion( args[ 0 ] . expect_ty( ) , tcx) ?)
504+ }
505+ ty:: Adt ( _, _) if implements_default ( ty) => "Default::default()" . to_string ( ) ,
506+ ty:: Ref ( _, ty, mutability) => {
507+ if let ( ty:: Str , Mutability :: Not ) = ( ty. kind ( ) , mutability) {
508+ "\" \" " . to_string ( )
509+ } else {
510+ let Some ( ty) = ty_kind_suggestion ( * ty, tcx) else {
511+ return None ;
512+ } ;
513+ format ! ( "&{}{ty}" , mutability. prefix_str( ) )
514+ }
515+ }
516+ ty:: Array ( ty, len) => format ! (
517+ "[{}; {}]" ,
518+ ty_kind_suggestion( * ty, tcx) ?,
519+ len. eval_target_usize( tcx, ty:: ParamEnv :: reveal_all( ) ) ,
520+ ) ,
521+ ty:: Tuple ( tys) => format ! (
522+ "({})" ,
523+ tys. iter( )
524+ . map( |ty| ty_kind_suggestion( ty, tcx) )
525+ . collect:: <Option <Vec <String >>>( ) ?
526+ . join( ", " )
527+ ) ,
528+ _ => "value" . to_string ( ) ,
477529 } )
478530}
479531
@@ -511,7 +563,7 @@ fn suggestion_signature<'tcx>(
511563 }
512564 ty:: AssocKind :: Const => {
513565 let ty = tcx. type_of ( assoc. def_id ) . instantiate_identity ( ) ;
514- let val = ty_kind_suggestion ( ty) . unwrap_or ( "todo!()" ) ;
566+ let val = ty_kind_suggestion ( ty, tcx ) . unwrap_or_else ( || "value" . to_string ( ) ) ;
515567 format ! ( "const {}: {} = {};" , assoc. name, ty, val)
516568 }
517569 }
0 commit comments