Refactor all coercion type calls into a single coercion_site function
In order to fully support coercion sites we need a single place in order to implement the logic. This refactors all the coercion calls to have a single TypeCheckBase::coercion_site(lhs, rhs, location). Eventually we will do something similar for unifications and casts so we can improve our diagnostics.
This commit is contained in:
parent
ffb419d6a4
commit
2dc902baa1
|
@ -106,6 +106,7 @@ GRS_OBJS = \
|
|||
rust/rust-pub-restricted-visitor.o \
|
||||
rust/rust-privacy-reporter.o \
|
||||
rust/rust-tyty.o \
|
||||
rust/rust-tyty-call.o \
|
||||
rust/rust-tyctx.o \
|
||||
rust/rust-tyty-bounds.o \
|
||||
rust/rust-hir-type-check-util.o \
|
||||
|
|
|
@ -327,5 +327,12 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus)
|
|||
return repr;
|
||||
}
|
||||
|
||||
TyTy::BaseType *
|
||||
TypeCheckBase::coercion_site (TyTy::BaseType *lhs, TyTy::BaseType *rhs,
|
||||
Location)
|
||||
{
|
||||
return lhs->coerce (rhs);
|
||||
}
|
||||
|
||||
} // namespace Resolver
|
||||
} // namespace Rust
|
||||
|
|
|
@ -39,6 +39,9 @@ public:
|
|||
|
||||
virtual ~TypeCheckBase () {}
|
||||
|
||||
static TyTy::BaseType *coercion_site (TyTy::BaseType *lhs,
|
||||
TyTy::BaseType *rhs, Location locus);
|
||||
|
||||
protected:
|
||||
TypeCheckBase ()
|
||||
: mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()),
|
||||
|
|
|
@ -380,7 +380,7 @@ public:
|
|||
auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
|
||||
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
|
||||
|
||||
lhs->coerce (rhs);
|
||||
coercion_site (lhs, rhs, expr.get_locus ());
|
||||
}
|
||||
|
||||
void visit (HIR::CompoundAssignmentExpr &expr) override
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
if (specified_ty != nullptr && init_expr_ty != nullptr)
|
||||
{
|
||||
// FIXME use this result and look at the regressions
|
||||
specified_ty->coerce (init_expr_ty);
|
||||
coercion_site (specified_ty, init_expr_ty, stmt.get_locus ());
|
||||
context->insert_type (stmt_pattern.get_pattern_mappings (),
|
||||
specified_ty);
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
|
|||
{
|
||||
TyTy::BaseType *base_resolved
|
||||
= TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
|
||||
struct_def
|
||||
= (TyTy::ADTType *) struct_path_resolved->coerce (base_resolved);
|
||||
struct_def = static_cast<TyTy::ADTType *> (
|
||||
struct_path_resolved->coerce (base_resolved));
|
||||
if (struct_def == nullptr)
|
||||
{
|
||||
rust_fatal_error (struct_expr.struct_base->base_struct->get_locus (),
|
||||
|
@ -221,7 +221,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
|
|||
}
|
||||
|
||||
TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
|
||||
resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
|
||||
resolved_field_value_expr
|
||||
= coercion_site (field_type->get_field_type (), value, field.get_locus ());
|
||||
if (resolved_field_value_expr != nullptr)
|
||||
{
|
||||
fields_assigned.insert (field.field_name);
|
||||
|
@ -250,7 +251,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
|
|||
}
|
||||
|
||||
TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
|
||||
resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
|
||||
resolved_field_value_expr
|
||||
= coercion_site (field_type->get_field_type (), value, field.get_locus ());
|
||||
if (resolved_field_value_expr != nullptr)
|
||||
{
|
||||
fields_assigned.insert (field_name);
|
||||
|
@ -284,7 +286,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
|
|||
field.get_locus ());
|
||||
TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr);
|
||||
|
||||
resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
|
||||
resolved_field_value_expr
|
||||
= coercion_site (field_type->get_field_type (), value, field.get_locus ());
|
||||
if (resolved_field_value_expr != nullptr)
|
||||
|
||||
{
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
// Copyright (C) 2020-2022 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-tyty-call.h"
|
||||
#include "rust-hir-type-check-expr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace TyTy {
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (ADTType &type)
|
||||
{
|
||||
rust_assert (!variant.is_error ());
|
||||
if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
|
||||
{
|
||||
rust_error_at (
|
||||
call.get_locus (),
|
||||
"expected function, tuple struct or tuple variant, found struct %<%s%>",
|
||||
type.get_name ().c_str ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.num_params () != variant.num_fields ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) variant.num_fields ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
StructFieldType *field = variant.get_field_at_index (i);
|
||||
BaseType *field_tyty = field->get_field_type ();
|
||||
|
||||
BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (arg->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"failed to resolve argument type");
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = field_tyty->coerce (arg);
|
||||
if (res->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delete res;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
resolved = type.clone ();
|
||||
}
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (FnType &type)
|
||||
{
|
||||
type.monomorphize ();
|
||||
if (call.num_params () != type.num_params ())
|
||||
{
|
||||
if (type.is_varadic ())
|
||||
{
|
||||
if (call.num_params () < type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
// it might be a varadic function
|
||||
if (i < type.num_params ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto resolved_argument_type
|
||||
= fnparam.second->coerce (argument_expr_tyty);
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
type.monomorphize ();
|
||||
resolved = type.get_return_type ()->clone ();
|
||||
}
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (FnPtr &type)
|
||||
{
|
||||
if (call.num_params () != type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
auto resolved_argument_type
|
||||
= Resolver::TypeCheckBase::coercion_site (fnparam, argument_expr_tyty,
|
||||
argument->get_locus ());
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
resolved = type.get_return_type ()->monomorphized_clone ();
|
||||
}
|
||||
|
||||
// method call checker
|
||||
|
||||
void
|
||||
TypeCheckMethodCallExpr::visit (FnType &type)
|
||||
{
|
||||
type.get_self_type ()->unify (adjusted_self);
|
||||
|
||||
// +1 for the receiver self
|
||||
size_t num_args_to_call = call.num_params () + 1;
|
||||
if (num_args_to_call != type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 1;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
auto resolved_argument_type
|
||||
= Resolver::TypeCheckBase::coercion_site (fnparam.second,
|
||||
argument_expr_tyty,
|
||||
argument->get_locus ());
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != num_args_to_call)
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
type.monomorphize ();
|
||||
|
||||
resolved = type.get_return_type ()->monomorphized_clone ();
|
||||
}
|
||||
|
||||
} // namespace TyTy
|
||||
} // namespace Rust
|
|
@ -3205,243 +3205,5 @@ DynamicObjectType::get_object_items () const
|
|||
return items;
|
||||
}
|
||||
|
||||
// rust-tyty-call.h
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (ADTType &type)
|
||||
{
|
||||
rust_assert (!variant.is_error ());
|
||||
if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
|
||||
{
|
||||
rust_error_at (
|
||||
call.get_locus (),
|
||||
"expected function, tuple struct or tuple variant, found struct %<%s%>",
|
||||
type.get_name ().c_str ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.num_params () != variant.num_fields ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) variant.num_fields ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
StructFieldType *field = variant.get_field_at_index (i);
|
||||
BaseType *field_tyty = field->get_field_type ();
|
||||
|
||||
BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (arg->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"failed to resolve argument type");
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = field_tyty->coerce (arg);
|
||||
if (res->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delete res;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
resolved = type.clone ();
|
||||
}
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (FnType &type)
|
||||
{
|
||||
type.monomorphize ();
|
||||
if (call.num_params () != type.num_params ())
|
||||
{
|
||||
if (type.is_varadic ())
|
||||
{
|
||||
if (call.num_params () < type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
// it might be a varadic function
|
||||
if (i < type.num_params ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto resolved_argument_type
|
||||
= fnparam.second->coerce (argument_expr_tyty);
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
type.monomorphize ();
|
||||
resolved = type.get_return_type ()->clone ();
|
||||
}
|
||||
|
||||
void
|
||||
TypeCheckCallExpr::visit (FnPtr &type)
|
||||
{
|
||||
if (call.num_params () != type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
auto resolved_argument_type = fnparam->coerce (argument_expr_tyty);
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != call.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
resolved = type.get_return_type ()->monomorphized_clone ();
|
||||
}
|
||||
|
||||
// method call checker
|
||||
|
||||
void
|
||||
TypeCheckMethodCallExpr::visit (FnType &type)
|
||||
{
|
||||
type.get_self_type ()->unify (adjusted_self);
|
||||
|
||||
// +1 for the receiver self
|
||||
size_t num_args_to_call = call.num_params () + 1;
|
||||
if (num_args_to_call != type.num_params ())
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) call.num_params (),
|
||||
(unsigned long) type.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 1;
|
||||
for (auto &argument : call.get_arguments ())
|
||||
{
|
||||
auto fnparam = type.param_at (i);
|
||||
auto argument_expr_tyty
|
||||
= Resolver::TypeCheckExpr::Resolve (argument.get ());
|
||||
if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (
|
||||
argument->get_locus (),
|
||||
"failed to resolve type for argument expr in CallExpr");
|
||||
return;
|
||||
}
|
||||
|
||||
auto resolved_argument_type = fnparam.second->coerce (argument_expr_tyty);
|
||||
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
|
||||
{
|
||||
rust_error_at (argument->get_locus (),
|
||||
"Type Resolution failure on parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
context->insert_type (argument->get_mappings (), argument_expr_tyty);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != num_args_to_call)
|
||||
{
|
||||
rust_error_at (call.get_locus (),
|
||||
"unexpected number of arguments %lu expected %lu",
|
||||
(unsigned long) i, (unsigned long) call.num_params ());
|
||||
return;
|
||||
}
|
||||
|
||||
type.monomorphize ();
|
||||
|
||||
resolved = type.get_return_type ()->monomorphized_clone ();
|
||||
}
|
||||
|
||||
} // namespace TyTy
|
||||
} // namespace Rust
|
||||
|
|
Loading…
Reference in New Issue