diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index bf70ca5d96f..f5a97b0d350 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -122,23 +122,61 @@ ASTValidation::visit (AST::Function &function)
       function.get_self_param ()->get_locus (),
       "%<self%> parameter is only allowed in associated functions");
 
-  if (!function.has_body ())
+  if (function.is_external ())
     {
-      if (context.back () == Context::INHERENT_IMPL
-	  || context.back () == Context::TRAIT_IMPL)
+      if (function.has_body ())
+	rust_error_at (function.get_locus (), "cannot have a body");
+
+      auto &params = function.get_function_params ();
+
+      if (params.size () == 1 && function.is_variadic ())
 	rust_error_at (function.get_locus (),
-		       "associated function in %<impl%> without body");
-      else if (context.back () != Context::TRAIT)
-	rust_error_at (function.get_locus (), "free function without a body");
+		       "C-variadic function must be declared with at least one "
+		       "named argument");
+
+      for (auto it = params.begin (); it != params.end (); it++)
+	{
+	  if (it->get ()->is_variadic () && it + 1 != params.end ())
+	    rust_error_at (
+	      it->get ()->get_locus (),
+	      "%<...%> must be the last argument of a C-variadic function");
+
+	  // if functional parameter
+	  if (!it->get ()->is_self () && !it->get ()->is_variadic ())
+	    {
+	      auto param = static_cast<AST::FunctionParam *> (it->get ());
+	      auto kind = param->get_pattern ()->get_pattern_kind ();
+
+	      if (kind != AST::Pattern::Kind::Identifier
+		  && kind != AST::Pattern::Kind::Wildcard)
+		rust_error_at (it->get ()->get_locus (), ErrorCode::E0130,
+			       "pattern not allowed in foreign function");
+	    }
+	}
     }
 
-  auto &function_params = function.get_function_params ();
-  for (auto it = function_params.begin (); it != function_params.end (); it++)
+  else
     {
-      if (it->get ()->is_variadic ())
-	rust_error_at (it->get ()->get_locus (),
-		       "only foreign or %<unsafe extern \"C\"%> functions may "
-		       "be C-variadic");
+      if (!function.has_body ())
+	{
+	  if (context.back () == Context::INHERENT_IMPL
+	      || context.back () == Context::TRAIT_IMPL)
+	    rust_error_at (function.get_locus (),
+			   "associated function in %<impl%> without body");
+	  else if (context.back () != Context::TRAIT)
+	    rust_error_at (function.get_locus (),
+			   "free function without a body");
+	}
+      auto &function_params = function.get_function_params ();
+      for (auto it = function_params.begin (); it != function_params.end ();
+	   it++)
+	{
+	  if (it->get ()->is_variadic ())
+	    rust_error_at (
+	      it->get ()->get_locus (),
+	      "only foreign or %<unsafe extern \"C\"%> functions may "
+	      "be C-variadic");
+	}
     }
 
   AST::ContextualASTVisitor::visit (function);
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 9d9722e9714..c8a87a11766 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2908,7 +2908,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::Function>
 Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
-					    AST::AttrVec outer_attrs)
+					    AST::AttrVec outer_attrs,
+					    bool is_external)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
   // Get qualifiers for function if they exist
@@ -2992,7 +2993,7 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
 		       std::move (generic_params), std::move (function_params),
 		       std::move (return_type), std::move (where_clause),
 		       std::move (body), std::move (vis),
-		       std::move (outer_attrs), locus));
+		       std::move (outer_attrs), locus, false, is_external));
 }
 
 // Parses function or method qualifiers (i.e. const, unsafe, and extern).
@@ -6166,6 +6167,7 @@ Parser<ManagedTokenSource>::parse_external_item ()
     case FN_KW:
       return parse_external_function_item (std::move (vis),
 					   std::move (outer_attrs));
+
     case TYPE:
       return parse_external_type_item (std::move (vis),
 				       std::move (outer_attrs));
@@ -10474,8 +10476,7 @@ Parser<ManagedTokenSource>::parse_pattern ()
     {
       lexer.skip_token ();
       alts.push_back (parse_pattern_no_alt ());
-    }
-  while (lexer.peek_token ()->get_id () == PIPE);
+  } while (lexer.peek_token ()->get_id () == PIPE);
 
   /* alternates */
   return std::unique_ptr<AST::Pattern> (
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 8c8bf96eb8d..cdddfa6dff9 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -253,7 +253,8 @@ private:
   parse_use_decl (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr<AST::UseTree> parse_use_tree ();
   std::unique_ptr<AST::Function> parse_function (AST::Visibility vis,
-						 AST::AttrVec outer_attrs);
+						 AST::AttrVec outer_attrs,
+						 bool is_external = false);
   AST::FunctionQualifiers parse_function_qualifiers ();
   std::vector<std::unique_ptr<AST::GenericParam>>
   parse_generic_params_in_angles ();
