// Copyright (C) 2020-2026 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#include "rust-ast-validation.h"
#include "rust-common.h"
#include "rust-diagnostics.h"
#include "rust-item.h"
#include "rust-keyword-values.h"

namespace Rust {

void
ASTValidation::visit (AST::Lifetime &lifetime)
{
  auto name = lifetime.get_lifetime_name ();
  auto valid = std::set<std::string>{"static", "_"};
  auto &keywords = Values::Keywords::keywords;

  if (valid.find (name) == valid.end ()
      && keywords.find (name) != keywords.end ())
    rust_error_at (lifetime.get_locus (), "lifetimes cannot use keyword names");

  AST::ContextualASTVisitor::visit (lifetime);
}

void
ASTValidation::visit (AST::LoopLabel &label)
{
  auto name = label.get_lifetime ().get_lifetime_name ();
  auto lifetime_name = '\'' + name;
  auto &keywords = Values::Keywords::keywords;
  if (keywords.find (name) != keywords.end ())
    rust_error_at (label.get_lifetime ().get_locus (), "invalid label name %qs",
		   lifetime_name.c_str ());

  // WARNING: Do not call ContextualASTVisitor, we don't want to visit the
  // lifetime
  // Maybe we should refactor LoopLabel instead ?
}

void
ASTValidation::visit (AST::ConstantItem &const_item)
{
  if (!const_item.has_expr () && ctx.peek () != Kind::TRAIT)
    {
      rust_error_at (const_item.get_locus (),
		     "associated constant in %<impl%> without body");
    }
  AST::ContextualASTVisitor::visit (const_item);
}

void
ASTValidation::visit (AST::Union &item)
{
  if (item.get_variants ().empty ())
    rust_error_at (item.get_locus (), "unions cannot have zero fields");

  AST::ContextualASTVisitor::visit (item);
}

void
ASTValidation::visit (AST::Function &function)
{
  const auto &qualifiers = function.get_qualifiers ();
  if (qualifiers.is_default () && ctx.peek () != Kind::INHERENT_IMPL
      && ctx.peek () != Kind::TRAIT_IMPL)
    rust_error_at (
      function.get_locus (),
      "%<default%> is only allowed on items within %<impl%> blocks");
  if (qualifiers.is_async () && qualifiers.is_const ())
    rust_error_at (function.get_locus (),
		   "functions cannot be both %<const%> and %<async%>");

  if (qualifiers.is_const ()
      && (ctx.peek () == Kind::TRAIT_IMPL || ctx.peek () == Kind::TRAIT))
    rust_error_at (function.get_locus (), ErrorCode::E0379,
		   "functions in traits cannot be declared %<const%>");

  // may change soon
  if (qualifiers.is_async ()
      && (ctx.peek () == Kind::TRAIT_IMPL || ctx.peek () == Kind::TRAIT))
    rust_error_at (function.get_locus (), ErrorCode::E0706,
		   "functions in traits cannot be declared %<async%>");

  // if not an associated function but has a self parameter
  if (ctx.peek () != Kind::TRAIT && ctx.peek () != Kind::TRAIT_IMPL
      && ctx.peek () != Kind::INHERENT_IMPL && function.has_self_param ())
    rust_error_at (
      function.get_self_param ().get_locus (),
      "%<self%> parameter is only allowed in associated functions");

  if (function.is_external ())
    {
      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 (),
		       "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);
	      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");
	    }
	}
    }

  else
    {
      if (!function.has_body ())
	{
	  if (ctx.peek () == Kind::INHERENT_IMPL
	      || ctx.peek () == Kind::TRAIT_IMPL)
	    rust_error_at (function.get_locus (),
			   "associated function in %<impl%> without body");
	  else if (ctx.peek () != Kind::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);
}

void
ASTValidation::visit (AST::Trait &trait)
{
  if (trait.is_auto ())
    {
      if (trait.has_generics ())
	rust_error_at (trait.get_generic_params ()[0]->get_locus (),
		       ErrorCode::E0567,
		       "auto traits cannot have generic parameters");
      if (trait.has_type_param_bounds ())
	rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (),
		       ErrorCode::E0568,
		       "auto traits cannot have super traits");
      if (trait.has_trait_items ())
	{
	  rust_error_at (trait.get_identifier ().get_locus (), ErrorCode::E0380,
			 "auto traits cannot have methods or associated items");
	  for (const auto &item : trait.get_trait_items ())
	    Error::Hint (item->get_locus (), "remove this item").emit ();
	}
    }

  AST::ContextualASTVisitor::visit (trait);
}

void
ASTValidation::visit (AST::Module &module)
{
  if (module.get_unsafety () == Unsafety::Unsafe)
    rust_error_at (module.get_locus (), "module cannot be declared unsafe");

  AST::ContextualASTVisitor::visit (module);
}

} // namespace Rust
