@@ -13,6 +13,7 @@ use rustc_hir::{
13
13
use rustc_hir_analysis:: astconv:: AstConv ;
14
14
use rustc_infer:: traits:: { self , StatementAsExpression } ;
15
15
use rustc_middle:: lint:: in_external_macro;
16
+ use rustc_middle:: ty:: print:: with_no_trimmed_paths;
16
17
use rustc_middle:: ty:: {
17
18
self , suggest_constraining_type_params, Binder , DefIdTree , IsSuggestable , ToPredicate , Ty ,
18
19
TypeVisitable ,
@@ -704,10 +705,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
704
705
}
705
706
}
706
707
hir:: FnRetTy :: Return ( ty) => {
708
+ let span = ty. span ;
709
+
710
+ if let hir:: TyKind :: OpaqueDef ( item_id, ..) = ty. kind
711
+ && let hir:: Node :: Item ( hir:: Item {
712
+ kind : hir:: ItemKind :: OpaqueTy ( op_ty) ,
713
+ ..
714
+ } ) = self . tcx . hir ( ) . get ( item_id. hir_id ( ) )
715
+ && let hir:: OpaqueTy {
716
+ bounds : [ bound] , ..
717
+ } = op_ty
718
+ && let hir:: GenericBound :: LangItemTrait (
719
+ hir:: LangItem :: Future , _, _, generic_args) = bound
720
+ && let hir:: GenericArgs { bindings : [ ty_binding] , .. } = generic_args
721
+ && let hir:: TypeBinding { kind, .. } = ty_binding
722
+ && let hir:: TypeBindingKind :: Equality { term } = kind
723
+ && let hir:: Term :: Ty ( term_ty) = term {
724
+ // Check if async function's return type was omitted.
725
+ // Don't emit suggestions if the found type is `impl Future<...>`.
726
+ debug ! ( "suggest_missing_return_type: found = {:?}" , found) ;
727
+ if found. is_suggestable ( self . tcx , false ) {
728
+ if term_ty. span . is_empty ( ) {
729
+ err. subdiagnostic ( AddReturnTypeSuggestion :: Add { span, found : found. to_string ( ) } ) ;
730
+ return true ;
731
+ } else {
732
+ err. subdiagnostic ( ExpectedReturnTypeLabel :: Other { span, expected } ) ;
733
+ }
734
+ }
735
+ }
736
+
707
737
// Only point to return type if the expected type is the return type, as if they
708
738
// are not, the expectation must have been caused by something else.
709
739
debug ! ( "suggest_missing_return_type: return type {:?} node {:?}" , ty, ty. kind) ;
710
- let span = ty. span ;
711
740
let ty = self . astconv ( ) . ast_ty_to_ty ( ty) ;
712
741
debug ! ( "suggest_missing_return_type: return type {:?}" , ty) ;
713
742
debug ! ( "suggest_missing_return_type: expected type {:?}" , ty) ;
@@ -1244,6 +1273,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1244
1273
}
1245
1274
}
1246
1275
1276
+ /// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
1277
+ /// pass in a literal 0 to an raw pointer.
1278
+ #[ instrument( skip( self , err) ) ]
1279
+ pub ( crate ) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg (
1280
+ & self ,
1281
+ err : & mut Diagnostic ,
1282
+ expr : & hir:: Expr < ' _ > ,
1283
+ expected_ty : Ty < ' tcx > ,
1284
+ ) -> bool {
1285
+ // Expected type needs to be a raw pointer.
1286
+ let ty:: RawPtr ( ty:: TypeAndMut { mutbl, .. } ) = expected_ty. kind ( ) else {
1287
+ return false ;
1288
+ } ;
1289
+
1290
+ // Provided expression needs to be a literal `0`.
1291
+ let ExprKind :: Lit ( Spanned {
1292
+ node : rustc_ast:: LitKind :: Int ( 0 , _) ,
1293
+ span,
1294
+ } ) = expr. kind else {
1295
+ return false ;
1296
+ } ;
1297
+
1298
+ // We need to find a null pointer symbol to suggest
1299
+ let null_sym = match mutbl {
1300
+ hir:: Mutability :: Not => sym:: ptr_null,
1301
+ hir:: Mutability :: Mut => sym:: ptr_null_mut,
1302
+ } ;
1303
+ let Some ( null_did) = self . tcx . get_diagnostic_item ( null_sym) else {
1304
+ return false ;
1305
+ } ;
1306
+ let null_path_str = with_no_trimmed_paths ! ( self . tcx. def_path_str( null_did) ) ;
1307
+
1308
+ // We have satisfied all requirements to provide a suggestion. Emit it.
1309
+ err. span_suggestion (
1310
+ span,
1311
+ format ! ( "if you meant to create a null pointer, use `{null_path_str}()`" ) ,
1312
+ null_path_str + "()" ,
1313
+ Applicability :: MachineApplicable ,
1314
+ ) ;
1315
+
1316
+ true
1317
+ }
1318
+
1247
1319
pub ( crate ) fn suggest_associated_const (
1248
1320
& self ,
1249
1321
err : & mut Diagnostic ,
0 commit comments