Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(revision 54643)
+++ src/wp-includes/user.php	(working copy)
@@ -34,6 +34,9 @@
 	if ( empty( $credentials ) ) {
 		$credentials = array(); // Back-compat for plugins passing an empty string.
 
+		$credentials['user_login']    = '';
+		$credentials['user_password'] = '';
+
 		if ( ! empty( $_POST['log'] ) ) {
 			$credentials['user_login'] = wp_unslash( $_POST['log'] );
 		}
Index: tests/phpunit/tests/auth.php
===================================================================
--- tests/phpunit/tests/auth.php	(revision 54643)
+++ tests/phpunit/tests/auth.php	(working copy)
@@ -429,6 +429,25 @@
 	}
 
 	/**
+	 * Tests that PHP 8.1 "passing null to non-nullable" deprecation notices
+	 * are not thrown when `user_login` and `user_password` parameters are empty.
+	 *
+	 * The notices that we should not see:
+	 * `Deprecated: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated`.
+	 * `Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated`.
+	 *
+	 * @ticket 56850
+	 */
+	public function test_wp_signon_does_not_throw_deprecation_notices_with_default_parameters() {
+		$error = wp_signon();
+		$this->assertWPError( $error, 'The result should be an instance of WP_Error.' );
+
+		$error_codes = $error->get_error_codes();
+		$this->assertContains( 'empty_username', $error_codes, 'The "empty_username" error code should be present.' );
+		$this->assertContains( 'empty_password', $error_codes, 'The "empty_password" error code should be present.' );
+	}
+
+	/**
 	 * HTTP Auth headers are used to determine the current user.
 	 *
 	 * @ticket 42790
