gccrs: Refactor TypeResolution to be a simple query based system

This patch refactors the type resolution system to introduce a new
interface

  bool query_type (HirId, TyTy::BaseType** result)

This is needed in order to properly support forward declared items. Our
name resolution system has two parts:

  1. Toplevel scan
  2. Item resolution

The toplevel scan gathers all the nesseacry 'names' into their respective
namespace by doing a full toplevel scan and generate canonical paths for
each item. The second pass is responsible for drilling down into each
structure or function to resolve each field or variable etc. This means
our name resolution system supports forward decalred items but our type
resolution system did not.

This patch removes the toplevel scan from our type resolution pass which
is not able to handle all cases such as a function with return type and
the type is decalred after the fact or a type alias to a type declared
after the fact. The name resolution mappings are resolved so when errors
occured here we got errors such as unable to lookup HirId 1234, which meant
yes we have 'resolved' this reference to this HirId but we are unable to
find any type information for it. This means we needed a new way to figure
out the type in a query based way.

This is where the new query_type inferface comes in so when we have an
HirId we want to resolve the mappings class allows us to figure out what
item this is such as:

  1. HIR::Item (normal HIR::Function, Struct, TypeAlias, ...)
  2. HIR::ImplItem (function, constant, ... within an impl-block)
  3. HIR::ImplBlock (Self type on an impl-block)
  4. HIR::ExternalItem (extern-block item)

The mappings class allows us to simply lookup these HIR nodes and then
call the relevant resolver class to compute the type. This patch does not
add support for self-referencial types but is the starting point to be able
to support such types.

Fixes #1455

gcc/rust/ChangeLog:

	* Make-lang.in: Remove `rust-hir-typecheck-toplevel` object and add
	`rust-hir-path-probe` one.
	* typecheck/rust-hir-dot-operator.cc (MethodResolver::MethodResolver):
	Remove no longer used `context` and `mapping` fields, and use new
	`query_type` API.
	(MethodResolver::MethodResolver): Likewise.
	(MethodResolver::select): Use new `query_type` API.
	* typecheck/rust-hir-path-probe.h: New header.
	* typecheck/rust-hir-path-probe.cc: New file.
	* typecheck/rust-hir-dot-operator.h (class MethodResolver): Remove no
	longer used `context` and `mapping` fields, and use new `query_type` API.
	* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::query_type): New function.
	* typecheck/rust-hir-type-check-base.h: Declare `query_type` function.
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Add debug print.
	* typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::Resolve):
	Refactor and make use of new query system.
	(TypeCheckTopLevelExternItem::Resolve): Likewise.
	(TypeCheckTopLevelExternItem::visit): Likewise.
	(TypeCheckTopLevelImplItem::visit): Likewise.
	(TypeCheckImplItem::visit): Likewise.
	(TypeCheckImplItem::TypeCheckImplItem): Likewise.
	(TypeCheckImplItem::Resolve): Likewise.
	(TypeCheckImplItemWithTrait::visit): Likewise.
	* typecheck/rust-hir-type-check-implitem.h (class TypeCheckTopLevelImplItem): Likewise.
	(class TypeCheckImplItemWithTrait): Likewise.
	* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::TypeCheckItem): Likewise.
	(TypeCheckItem::Resolve): Likewise.
	(TypeCheckItem::ResolveImplItem): Likewise.
	(TypeCheckItem::ResolveImplBlockSelf): Likewise.
	(TypeCheckItem::visit): Likewise.
	(TypeCheckItem::resolve_impl_item): Likewise.
	(TypeCheckItem::resolve_impl_block_substitutions): Likewise.
	(TypeCheckItem::resolve_impl_block_self): Likewise.
	* typecheck/rust-hir-type-check-item.h: Likewise.
	* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): Likewise.
	(TypeCheckExpr::resolve_segments): Likewise.
	* typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Likewise.
	* typecheck/rust-hir-type-check-stmt.h: Likewise.
	* typecheck/rust-hir-type-check-type.cc (TypeCheckType::Resolve): Likewise.
	(TypeCheckType::visit): Likewise.
	(TypeCheckType::resolve_root_path): Likewise.
	* typecheck/rust-hir-type-check.cc (TypeResolution::Resolve): Likewise.
	* typecheck/rust-hir-type-check.h: Likewise.
	* typecheck/rust-substitution-mapper.h: Likewise.
	* typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Likewise.
	(TypeCheckBase::get_predicate_from_bound): Likewise.
	(TypeBoundsMappings::add_bound): Likewise.
	* typecheck/rust-tyty-cmp.h: Likewise.
	* typecheck/rust-tyty.h: Likewise.
	* typecheck/rust-tyty.cc (SubstitutionRef::infer_substitions): Likewise.
	(ParamType::resolve): Do not infinite loop anymore.
	* util/rust-hir-map.h: Add new `hirImplBlockTypeMappings` and
	declare `lookup_impl_block_type`.
	* util/rust-hir-map.cc (Mappings::insert_hir_impl_block): Use new
	`hirImplBlockTypeMappings`
	(Mappings::lookup_impl_block_type): New function.

gcc/testsuite/ChangeLog:

	* rust/compile/const_generics_5.rs: Fix assertions.
	* rust/compile/unconstrained_type_param.rs: Add more assertions.
This commit is contained in:
Philip Herron
2023-01-16 12:36:53 +01:00
committed by Arthur Cohen
parent 11a37f8950
commit 104cc28553
27 changed files with 953 additions and 790 deletions

View File

@@ -116,7 +116,6 @@ GRS_OBJS = \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
rust/rust-hir-type-check-toplevel.o \
rust/rust-hir-type-check-item.o \
rust/rust-hir-type-check-type.o \
rust/rust-hir-type-check-struct.o \
@@ -126,6 +125,7 @@ GRS_OBJS = \
rust/rust-hir-type-check-enumitem.o \
rust/rust-hir-type-check-implitem.o \
rust/rust-hir-dot-operator.o \
rust/rust-hir-path-probe.o \
rust/rust-coercion.o \
rust/rust-casts.o \
rust/rust-hir-type-check-base.o \

View File

@@ -25,8 +25,7 @@ namespace Resolver {
MethodResolver::MethodResolver (bool autoderef_flag,
const HIR::PathIdentSegment &segment_name)
: AutoderefCycle (autoderef_flag), mappings (Analysis::Mappings::get ()),
context (TypeCheckContext::get ()), segment_name (segment_name),
: AutoderefCycle (autoderef_flag), segment_name (segment_name),
try_result (MethodCandidate::get_error ())
{}
@@ -80,8 +79,9 @@ MethodResolver::select (const TyTy::BaseType &receiver)
return true;
TyTy::BaseType *ty = nullptr;
if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
if (!query_type (func->get_mappings ().get_hirid (), &ty))
return true;
rust_assert (ty != nullptr);
if (ty->get_kind () == TyTy::TypeKind::ERROR)
return true;
@@ -127,7 +127,7 @@ MethodResolver::select (const TyTy::BaseType &receiver)
continue;
TyTy::BaseType *ty = nullptr;
if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
if (!query_type (func->get_mappings ().get_hirid (), &ty))
continue;
if (ty->get_kind () == TyTy::TypeKind::ERROR)
continue;

View File

@@ -37,7 +37,7 @@ struct MethodCandidate
bool is_error () const { return candidate.is_error (); }
};
class MethodResolver : protected AutoderefCycle
class MethodResolver : private TypeCheckBase, protected AutoderefCycle
{
public:
struct predicate_candidate
@@ -63,10 +63,6 @@ protected:
bool select (const TyTy::BaseType &receiver) override;
private:
// context info
Analysis::Mappings *mappings;
TypeCheckContext *context;
// search
const HIR::PathIdentSegment &segment_name;
std::vector<MethodResolver::predicate_candidate> predicate_items;

View File

@@ -0,0 +1,46 @@
// 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-hir-path-probe.h"
#include "rust-hir-type-check-item.h"
namespace Rust {
namespace Resolver {
void
PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl)
{
current_impl = impl;
HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
TyTy::BaseType *impl_block_ty = nullptr;
if (!query_type (impl_ty_id, &impl_block_ty))
return;
if (!receiver->can_eq (impl_block_ty, false))
{
if (!impl_block_ty->can_eq (receiver, false))
return;
}
// lets visit the impl_item
item->accept_vis (*this);
}
} // namespace Resolver
} // namespace Rust

View File

@@ -195,7 +195,7 @@ public:
{
HirId tyid = alias.get_mappings ().get_hirid ();
TyTy::BaseType *ty = nullptr;
bool ok = context->lookup_type (tyid, &ty);
bool ok = query_type (tyid, &ty);
rust_assert (ok);
PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
@@ -214,7 +214,7 @@ public:
{
HirId tyid = constant.get_mappings ().get_hirid ();
TyTy::BaseType *ty = nullptr;
bool ok = context->lookup_type (tyid, &ty);
bool ok = query_type (tyid, &ty);
rust_assert (ok);
PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
@@ -233,7 +233,7 @@ public:
{
HirId tyid = function.get_mappings ().get_hirid ();
TyTy::BaseType *ty = nullptr;
bool ok = context->lookup_type (tyid, &ty);
bool ok = query_type (tyid, &ty);
rust_assert (ok);
PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
@@ -272,23 +272,7 @@ protected:
}
void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl)
{
current_impl = impl;
HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
TyTy::BaseType *impl_block_ty = nullptr;
if (!context->lookup_type (impl_ty_id, &impl_block_ty))
return;
if (!receiver->can_eq (impl_block_ty, false))
{
if (!impl_block_ty->can_eq (receiver, false))
return;
}
// lets visit the impl_item
item->accept_vis (*this);
}
HIR::ImplBlock *impl);
void
process_associated_trait_for_candidates (const TraitReference *trait_ref,

View File

@@ -17,8 +17,10 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-base.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-coercion.h"
#include "rust-casts.h"
@@ -37,6 +39,13 @@ TypeCheckBase::check_for_unconstrained (
const TyTy::SubstitutionArgumentMappings &constraint_b,
const TyTy::BaseType *reference)
{
bool check_result = false;
bool check_completed
= context->have_checked_for_unconstrained (reference->get_ref (),
&check_result);
if (check_completed)
return check_result;
std::set<HirId> symbols_to_constrain;
std::map<HirId, Location> symbol_to_location;
for (const auto &p : params_to_constrain)
@@ -86,6 +95,10 @@ TypeCheckBase::check_for_unconstrained (
unconstrained = true;
}
}
context->insert_unconstrained_check_marker (reference->get_ref (),
unconstrained);
return unconstrained;
}
@@ -479,5 +492,68 @@ TypeCheckBase::resolve_generic_params (
}
}
bool
TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
{
if (context->lookup_type (reference, result))
return true;
HIR::Item *item = mappings->lookup_hir_item (reference);
if (item != nullptr)
{
rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
*result = TypeCheckItem::Resolve (*item);
return true;
}
HirId parent_impl_id = UNKNOWN_HIRID;
HIR::ImplItem *impl_item
= mappings->lookup_hir_implitem (reference, &parent_impl_id);
if (impl_item != nullptr)
{
HIR::ImplBlock *impl_block
= mappings->lookup_hir_impl_block (parent_impl_id);
rust_assert (impl_block != nullptr);
// found an impl item
rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to",
reference);
*result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
return true;
}
// is it an impl_type?
HIR::ImplBlock *impl_block_by_type = nullptr;
bool found_impl_block_type
= mappings->lookup_impl_block_type (reference, &impl_block_by_type);
if (found_impl_block_type)
{
*result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
return true;
}
// is it an extern item?
HirId parent_extern_block_id = UNKNOWN_HIRID;
HIR::ExternalItem *extern_item
= mappings->lookup_hir_extern_item (reference, &parent_extern_block_id);
if (extern_item != nullptr)
{
HIR::ExternBlock *block
= mappings->lookup_hir_extern_block (parent_extern_block_id);
rust_assert (block != nullptr);
*result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
return true;
}
// more?
Location possible_locus = mappings->lookup_location (reference);
rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
reference);
return false;
}
} // namespace Resolver
} // namespace Rust

View File

@@ -69,6 +69,8 @@ protected:
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions);
bool query_type (HirId reference, TyTy::BaseType **result);
Analysis::Mappings *mappings;
Resolver *resolver;
TypeCheckContext *context;

View File

@@ -188,6 +188,9 @@ TypeCheckExpr::visit (HIR::CallExpr &expr)
return;
}
rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}",
function_tyty->get_name ().c_str ());
TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node ();
if (function_tyty->get_kind () == TyTy::TypeKind::ADT)
{

View File

@@ -32,12 +32,21 @@ TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
: TypeCheckBase (), parent (parent)
{}
void
TyTy::BaseType *
TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem *item,
const HIR::ExternBlock &parent)
{
// is it already resolved?
auto context = TypeCheckContext::get ();
TyTy::BaseType *resolved = nullptr;
bool already_resolved
= context->lookup_type (item->get_mappings ().get_hirid (), &resolved);
if (already_resolved)
return resolved;
TypeCheckTopLevelExternItem resolver (parent);
item->accept_vis (resolver);
return resolver.resolved;
}
void
@@ -47,6 +56,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item)
= TypeCheckType::Resolve (item.get_item_type ().get ());
context->insert_type (item.get_mappings (), actual_type);
resolved = actual_type;
}
void
@@ -142,79 +152,40 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
ret_type, std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
resolved = fnType;
}
TypeCheckTopLevelImplItem::TypeCheckTopLevelImplItem (
TyTy::BaseType *self,
TypeCheckImplItem::TypeCheckImplItem (
HIR::ImplBlock *parent, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
: TypeCheckBase (), self (self), substitutions (substitutions)
: TypeCheckBase (), parent (parent), self (self),
substitutions (substitutions)
{}
void
TypeCheckTopLevelImplItem::Resolve (
HIR::ImplItem *item, TyTy::BaseType *self,
TyTy::BaseType *
TypeCheckImplItem::Resolve (
HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
{
TypeCheckTopLevelImplItem resolver (self, substitutions);
// is it already resolved?
auto context = TypeCheckContext::get ();
TyTy::BaseType *resolved = nullptr;
bool already_resolved
= context->lookup_type (item->get_impl_mappings ().get_hirid (), &resolved);
if (already_resolved)
return resolved;
// resolve
TypeCheckImplItem resolver (parent, self, substitutions);
item->accept_vis (resolver);
return resolver.result;
}
void
TypeCheckTopLevelImplItem::visit (HIR::TypeAlias &alias)
{
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ().get ());
context->insert_type (alias.get_mappings (), actual_type);
for (auto &where_clause_item : alias.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
}
void
TypeCheckTopLevelImplItem::visit (HIR::ConstantItem &constant)
{
TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
TyTy::BaseType *unified = unify_site (
constant.get_mappings ().get_hirid (),
TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
constant.get_locus ());
context->insert_type (constant.get_mappings (), unified);
}
void
TypeCheckTopLevelImplItem::visit (HIR::Function &function)
TypeCheckImplItem::visit (HIR::Function &function)
{
if (function.has_generics ())
{
for (auto &generic_param : function.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
resolve_generic_params (function.get_generic_params (), substitutions);
for (auto &where_clause_item : function.get_where_clause ().get_items ())
{
@@ -328,41 +299,10 @@ TypeCheckTopLevelImplItem::visit (HIR::Function &function)
std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
}
TypeCheckImplItem::TypeCheckImplItem (HIR::ImplBlock *parent,
TyTy::BaseType *self)
: TypeCheckBase (), parent (parent), self (self)
{}
void
TypeCheckImplItem::Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item,
TyTy::BaseType *self)
{
TypeCheckImplItem resolver (parent, self);
item->accept_vis (resolver);
}
void
TypeCheckImplItem::visit (HIR::Function &function)
{
TyTy::BaseType *lookup;
if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
{
rust_error_at (function.get_locus (), "failed to lookup function type");
return;
}
if (lookup->get_kind () != TyTy::TypeKind::FNDEF)
{
rust_error_at (function.get_locus (),
"found invalid type for function [%s]",
lookup->as_string ().c_str ());
return;
}
result = fnType;
// need to get the return type from this
TyTy::FnType *resolve_fn_type = static_cast<TyTy::FnType *> (lookup);
TyTy::FnType *resolve_fn_type = fnType;
auto expected_ret_tyty = resolve_fn_type->get_return_type ();
context->push_return_type (TypeCheckContextItem (parent, &function),
expected_ret_tyty);
@@ -383,20 +323,41 @@ TypeCheckImplItem::visit (HIR::Function &function)
}
void
TypeCheckImplItem::visit (HIR::ConstantItem &const_item)
{}
TypeCheckImplItem::visit (HIR::ConstantItem &constant)
{
TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
TyTy::BaseType *unified = unify_site (
constant.get_mappings ().get_hirid (),
TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
constant.get_locus ());
context->insert_type (constant.get_mappings (), unified);
result = unified;
}
void
TypeCheckImplItem::visit (HIR::TypeAlias &type_alias)
{}
TypeCheckImplItem::visit (HIR::TypeAlias &alias)
{
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ().get ());
context->insert_type (alias.get_mappings (), actual_type);
result = actual_type;
for (auto &where_clause_item : alias.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
}
TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
HIR::ImplBlock *parent, TyTy::BaseType *self,
TyTy::TypeBoundPredicate &trait_reference,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
: TypeCheckImplItem (parent, self), trait_reference (trait_reference),
: TypeCheckBase (), trait_reference (trait_reference),
resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
substitutions (substitutions)
parent (parent), self (self), substitutions (substitutions)
{
rust_assert (is_trait_impl_block ());
}
@@ -417,10 +378,8 @@ void
TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
{
// normal resolution of the item
TypeCheckImplItem::visit (constant);
TyTy::BaseType *lookup;
if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup))
return;
TyTy::BaseType *lookup
= TypeCheckImplItem::Resolve (parent, &constant, self, substitutions);
// map the impl item to the associated trait item
const auto tref = trait_reference.get ();
@@ -468,10 +427,8 @@ void
TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
{
// normal resolution of the item
TypeCheckImplItem::visit (type);
TyTy::BaseType *lookup;
if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
return;
TyTy::BaseType *lookup
= TypeCheckImplItem::Resolve (parent, &type, self, substitutions);
// map the impl item to the associated trait item
const auto tref = trait_reference.get ();
@@ -528,11 +485,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
void
TypeCheckImplItemWithTrait::visit (HIR::Function &function)
{
// we get the error checking from the base method here
TypeCheckImplItem::visit (function);
TyTy::BaseType *lookup;
if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
return;
// normal resolution of the item
TyTy::BaseType *lookup
= TypeCheckImplItem::Resolve (parent, &function, self, substitutions);
// map the impl item to the associated trait item
const auto tref = trait_reference.get ();

View File

@@ -28,7 +28,8 @@ class TypeCheckTopLevelExternItem : public TypeCheckBase,
public HIR::HIRExternalItemVisitor
{
public:
static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent);
static TyTy::BaseType *Resolve (HIR::ExternalItem *item,
const HIR::ExternBlock &parent);
void visit (HIR::ExternalStaticItem &item) override;
void visit (HIR::ExternalFunctionItem &function) override;
@@ -37,47 +38,33 @@ private:
TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent);
const HIR::ExternBlock &parent;
};
class TypeCheckTopLevelImplItem : public TypeCheckBase,
public HIR::HIRImplVisitor
{
public:
static void
Resolve (HIR::ImplItem *item, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions);
void visit (HIR::TypeAlias &alias) override;
void visit (HIR::ConstantItem &constant) override;
void visit (HIR::Function &function) override;
private:
TypeCheckTopLevelImplItem (
TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions);
TyTy::BaseType *self;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
TyTy::BaseType *resolved;
};
class TypeCheckImplItem : public TypeCheckBase, public HIR::HIRImplVisitor
{
public:
static void Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item,
TyTy::BaseType *self);
static TyTy::BaseType *
Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions);
void visit (HIR::Function &function) override;
void visit (HIR::ConstantItem &const_item) override;
void visit (HIR::TypeAlias &type_alias) override;
protected:
TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self);
TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions);
HIR::ImplBlock *parent;
TyTy::BaseType *self;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
TyTy::BaseType *result;
};
class TypeCheckImplItemWithTrait : public TypeCheckImplItem
class TypeCheckImplItemWithTrait : public TypeCheckBase,
public HIR::HIRImplVisitor
{
public:
static TyTy::TypeBoundPredicateItem
@@ -105,6 +92,9 @@ private:
TyTy::TypeBoundPredicate &trait_reference;
TyTy::TypeBoundPredicateItem resolved_trait_item;
HIR::ImplBlock *parent;
TyTy::BaseType *self;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
};

View File

@@ -16,59 +16,466 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-item.h"
#include "rust-hir-full.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check-enumitem.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-stmt.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-pattern.h"
#include "rust-hir-trait-resolve.h"
namespace Rust {
namespace Resolver {
TypeCheckItem::TypeCheckItem () : TypeCheckBase () {}
TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
void
TyTy::BaseType *
TypeCheckItem::Resolve (HIR::Item &item)
{
// is it already resolved?
auto context = TypeCheckContext::get ();
TyTy::BaseType *resolved = nullptr;
bool already_resolved
= context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
if (already_resolved)
return resolved;
rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
TypeCheckItem resolver;
vis_item.accept_vis (resolver);
return resolver.infered;
}
TyTy::BaseType *
TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
{
TypeCheckItem resolver;
return resolver.resolve_impl_item (impl_block, item);
}
TyTy::BaseType *
TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
{
TypeCheckItem resolver;
bool failed_flag = false;
std::vector<TyTy::SubstitutionParamMapping> substitutions
= resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
if (failed_flag)
{
return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
}
return resolver.resolve_impl_block_self (impl_block);
}
void
TypeCheckItem::visit (HIR::TypeAlias &alias)
{
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ().get ());
context->insert_type (alias.get_mappings (), actual_type);
for (auto &where_clause_item : alias.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
infered = actual_type;
}
void
TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
resolve_generic_params (struct_decl.get_generic_params (), substitutions);
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
std::vector<TyTy::StructFieldType *> fields;
size_t idx = 0;
for (auto &field : struct_decl.get_fields ())
{
TyTy::BaseType *field_type
= TypeCheckType::Resolve (field.get_field_type ().get ());
TyTy::StructFieldType *ty_field
= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
std::to_string (idx), field_type,
field.get_locus ());
fields.push_back (ty_field);
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
idx++;
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok = mappings->lookup_canonical_path (
struct_decl.get_mappings ().get_nodeid (), &canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, struct_decl.get_locus ()};
// its a single variant ADT
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields)));
// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
TyTy::ADTType::ReprOptions repr
= parse_repr_options (attrs, struct_decl.get_locus ());
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
struct_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::TUPLE_STRUCT,
std::move (variants), std::move (substitutions), repr);
context->insert_type (struct_decl.get_mappings (), type);
infered = type;
}
void
TypeCheckItem::visit (HIR::StructStruct &struct_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
resolve_generic_params (struct_decl.get_generic_params (), substitutions);
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
std::vector<TyTy::StructFieldType *> fields;
for (auto &field : struct_decl.get_fields ())
{
TyTy::BaseType *field_type
= TypeCheckType::Resolve (field.get_field_type ().get ());
TyTy::StructFieldType *ty_field
= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
field.get_field_name (), field_type,
field.get_locus ());
fields.push_back (ty_field);
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok = mappings->lookup_canonical_path (
struct_decl.get_mappings ().get_nodeid (), &canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, struct_decl.get_locus ()};
// its a single variant ADT
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
TyTy::ADTType::ReprOptions repr
= parse_repr_options (attrs, struct_decl.get_locus ());
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
struct_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::STRUCT_STRUCT,
std::move (variants), std::move (substitutions), repr);
context->insert_type (struct_decl.get_mappings (), type);
infered = type;
}
void
TypeCheckItem::visit (HIR::Enum &enum_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (enum_decl.has_generics ())
resolve_generic_params (enum_decl.get_generic_params (), substitutions);
std::vector<TyTy::VariantDef *> variants;
int64_t discriminant_value = 0;
for (auto &variant : enum_decl.get_variants ())
{
TyTy::VariantDef *field_type
= TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
discriminant_value++;
variants.push_back (field_type);
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, enum_decl.get_locus ()};
// multi variant ADT
TyTy::BaseType *type
= new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
enum_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::ENUM, std::move (variants),
std::move (substitutions));
context->insert_type (enum_decl.get_mappings (), type);
infered = type;
}
void
TypeCheckItem::visit (HIR::Union &union_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (union_decl.has_generics ())
resolve_generic_params (union_decl.get_generic_params (), substitutions);
for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
std::vector<TyTy::StructFieldType *> fields;
for (auto &variant : union_decl.get_variants ())
{
TyTy::BaseType *variant_type
= TypeCheckType::Resolve (variant.get_field_type ().get ());
TyTy::StructFieldType *ty_variant
= new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
variant.get_field_name (), variant_type,
variant.get_locus ());
fields.push_back (ty_variant);
context->insert_type (variant.get_mappings (),
ty_variant->get_field_type ());
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, union_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
TyTy::BaseType *type
= new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
union_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::UNION, std::move (variants),
std::move (substitutions));
context->insert_type (union_decl.get_mappings (), type);
infered = type;
}
void
TypeCheckItem::visit (HIR::StaticItem &var)
{
TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
TyTy::BaseType *unified
= coercion_site (var.get_mappings ().get_hirid (),
TyTy::TyWithLocation (type, var.get_type ()->get_locus ()),
TyTy::TyWithLocation (expr_type,
var.get_expr ()->get_locus ()),
var.get_locus ());
context->insert_type (var.get_mappings (), unified);
infered = unified;
}
void
TypeCheckItem::visit (HIR::ConstantItem &constant)
{
TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
TyTy::BaseType *unified = unify_site (
constant.get_mappings ().get_hirid (),
TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
constant.get_locus ());
context->insert_type (constant.get_mappings (), unified);
infered = unified;
}
void
TypeCheckItem::visit (HIR::ImplBlock &impl_block)
{
bool failed_flag = false;
std::vector<TyTy::SubstitutionParamMapping> substitutions
= resolve_impl_block_substitutions (impl_block, failed_flag);
if (failed_flag)
{
infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
return;
}
TyTy::BaseType *self = resolve_impl_block_self (impl_block);
// resolve each impl_item
for (auto &impl_item : impl_block.get_impl_items ())
{
TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self,
substitutions);
}
// validate the impl items
validate_trait_impl_block (impl_block, self, substitutions);
}
TyTy::BaseType *
TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
HIR::ImplItem &item)
{
bool failed_flag = false;
std::vector<TyTy::SubstitutionParamMapping> substitutions
= resolve_impl_block_substitutions (impl_block, failed_flag);
if (failed_flag)
{
return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
}
TyTy::BaseType *self = resolve_impl_block_self (impl_block);
return TypeCheckImplItem::Resolve (&impl_block, &item, self, substitutions);
}
void
TypeCheckItem::visit (HIR::Function &function)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
resolve_generic_params (function.get_generic_params (), substitutions);
for (auto &where_clause_item : function.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
TyTy::BaseType *ret_type = nullptr;
if (!function.has_function_return_type ())
ret_type
= TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
else
{
auto resolved
= TypeCheckType::Resolve (function.get_return_type ().get ());
if (resolved->get_kind () == TyTy::TypeKind::ERROR)
{
rust_error_at (function.get_locus (),
"failed to resolve return type");
return;
}
ret_type = resolved->clone ();
ret_type->set_ref (
function.get_return_type ()->get_mappings ().get_hirid ());
}
std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params;
for (auto &param : function.get_function_params ())
{
// get the name as well required for later on
auto param_tyty = TypeCheckType::Resolve (param.get_type ());
params.push_back (
std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (),
param_tyty));
context->insert_type (param.get_mappings (), param_tyty);
TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
}
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, function.get_locus ()};
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
function.get_mappings ().get_defid (),
function.get_function_name (), ident,
TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST,
std::move (params), ret_type,
std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
// need to get the return type from this
TyTy::FnType *resolved_fn_type = fnType;
auto expected_ret_tyty = resolved_fn_type->get_return_type ();
context->push_return_type (TypeCheckContextItem (&function),
expected_ret_tyty);
auto block_expr_ty
= TypeCheckExpr::Resolve (function.get_definition ().get ());
Location fn_return_locus = function.has_function_return_type ()
? function.get_return_type ()->get_locus ()
: function.get_locus ();
coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
TyTy::TyWithLocation (block_expr_ty),
function.get_definition ()->get_locus ());
context->pop_return_type ();
infered = fnType;
}
void
TypeCheckItem::visit (HIR::Module &module)
{
for (auto &item : module.get_items ())
TypeCheckItem::Resolve (*item.get ());
}
void
TypeCheckItem::visit (HIR::Trait &trait)
{
TraitResolver::Resolve (trait);
}
void
TypeCheckItem::visit (HIR::ExternBlock &extern_block)
{
for (auto &item : extern_block.get_extern_items ())
{
TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block);
}
}
std::vector<TyTy::SubstitutionParamMapping>
TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
bool &failure_flag)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (impl_block.has_generics ())
{
for (auto &generic_param : impl_block.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
resolve_generic_params (impl_block.get_generic_params (), substitutions);
case HIR::GenericParam::GenericKind::TYPE: {
TyTy::BaseType *l = nullptr;
bool ok = context->lookup_type (
generic_param->get_mappings ().get_hirid (), &l);
if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
{
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param),
static_cast<TyTy::ParamType *> (l)));
}
}
break;
}
}
for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
{
ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
}
auto specified_bound = TyTy::TypeBoundPredicate::error ();
@@ -84,14 +491,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
specified_bound = get_predicate_from_bound (*ref.get ());
}
TyTy::BaseType *self = nullptr;
if (!context->lookup_type (
impl_block.get_type ()->get_mappings ().get_hirid (), &self))
{
rust_error_at (impl_block.get_locus (),
"failed to resolve Self for ImplBlock");
return;
}
TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ());
// inherit the bounds
if (!specified_bound.is_error ())
@@ -103,20 +503,35 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
const TyTy::SubstitutionArgumentMappings impl_constraints
= GetUsedSubstArgs::From (self);
bool impl_block_has_unconstrained_typarams
= check_for_unconstrained (substitutions, trait_constraints,
impl_constraints, self);
if (impl_block_has_unconstrained_typarams)
return;
failure_flag = check_for_unconstrained (substitutions, trait_constraints,
impl_constraints, self);
return substitutions;
}
void
TypeCheckItem::validate_trait_impl_block (
HIR::ImplBlock &impl_block, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> &substitutions)
{
auto specified_bound = TyTy::TypeBoundPredicate::error ();
TraitReference *trait_reference = &TraitReference::error_node ();
if (impl_block.has_trait_ref ())
{
std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
trait_reference = TraitResolver::Resolve (*ref.get ());
rust_assert (!trait_reference->is_error ());
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
specified_bound = get_predicate_from_bound (*ref.get ());
}
// validate the impl items
bool is_trait_impl_block = !trait_reference->is_error ();
std::vector<const TraitItemReference *> trait_item_refs;
for (auto &impl_item : impl_block.get_impl_items ())
{
if (!is_trait_impl_block)
TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self);
else
if (!specified_bound.is_error ())
{
auto trait_item_ref
= TypeCheckImplItemWithTrait::Resolve (&impl_block,
@@ -128,7 +543,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
}
bool impl_block_missing_trait_items
= is_trait_impl_block
= !specified_bound.is_error ()
&& trait_reference->size () != trait_item_refs.size ();
if (impl_block_missing_trait_items)
{
@@ -187,55 +602,10 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
}
}
void
TypeCheckItem::visit (HIR::Function &function)
TyTy::BaseType *
TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
{
TyTy::BaseType *lookup;
if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
{
rust_error_at (function.get_locus (), "failed to lookup function type");
return;
}
if (lookup->get_kind () != TyTy::TypeKind::FNDEF)
{
rust_error_at (function.get_locus (),
"found invalid type for function [%s]",
lookup->as_string ().c_str ());
return;
}
// need to get the return type from this
TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (lookup);
auto expected_ret_tyty = resolved_fn_type->get_return_type ();
context->push_return_type (TypeCheckContextItem (&function),
expected_ret_tyty);
auto block_expr_ty
= TypeCheckExpr::Resolve (function.get_definition ().get ());
Location fn_return_locus = function.has_function_return_type ()
? function.get_return_type ()->get_locus ()
: function.get_locus ();
coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
TyTy::TyWithLocation (block_expr_ty),
function.get_definition ()->get_locus ());
context->pop_return_type ();
}
void
TypeCheckItem::visit (HIR::Module &module)
{
for (auto &item : module.get_items ())
TypeCheckItem::Resolve (*item.get ());
}
void
TypeCheckItem::visit (HIR::Trait &trait)
{
TraitResolver::Resolve (trait);
return TypeCheckType::Resolve (impl_block.get_type ().get ());
}
} // namespace Resolver

View File

@@ -27,29 +27,48 @@ namespace Resolver {
class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor
{
public:
static void Resolve (HIR::Item &item);
static TyTy::BaseType *Resolve (HIR::Item &item);
static TyTy::BaseType *ResolveImplItem (HIR::ImplBlock &impl_block,
HIR::ImplItem &item);
static TyTy::BaseType *ResolveImplBlockSelf (HIR::ImplBlock &impl_block);
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::Function &function) override;
void visit (HIR::Module &module) override;
void visit (HIR::Trait &trait) override;
// FIXME - get rid of toplevel pass
void visit (HIR::TypeAlias &alias) override{};
void visit (HIR::TupleStruct &struct_decl) override{};
void visit (HIR::StructStruct &struct_decl) override{};
void visit (HIR::Enum &enum_decl) override{};
void visit (HIR::Union &union_decl) override{};
void visit (HIR::StaticItem &var) override{};
void visit (HIR::ConstantItem &constant) override{};
void visit (HIR::ExternBlock &extern_block) override{};
void visit (HIR::Function &function) override;
void visit (HIR::TypeAlias &alias) override;
void visit (HIR::TupleStruct &struct_decl) override;
void visit (HIR::StructStruct &struct_decl) override;
void visit (HIR::Enum &enum_decl) override;
void visit (HIR::Union &union_decl) override;
void visit (HIR::StaticItem &var) override;
void visit (HIR::ConstantItem &constant) override;
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Trait &trait_block) override;
// nothing to do
void visit (HIR::ExternCrate &crate) override {}
void visit (HIR::UseDeclaration &use_decl) override {}
protected:
std::vector<TyTy::SubstitutionParamMapping>
resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
bool &failure_flag);
void validate_trait_impl_block (
HIR::ImplBlock &impl_block, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> &substitutions);
TyTy::BaseType *resolve_impl_item (HIR::ImplBlock &impl_block,
HIR::ImplItem &item);
TyTy::BaseType *resolve_impl_block_self (HIR::ImplBlock &impl_block);
private:
TypeCheckItem ();
TyTy::BaseType *infered;
};
} // namespace Resolver

View File

@@ -235,7 +235,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
}
TyTy::BaseType *lookup = nullptr;
if (!context->lookup_type (ref, &lookup))
if (!query_type (ref, &lookup))
{
if (is_root)
{
@@ -383,7 +383,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
HirId impl_ty_id
= associated_impl_block->get_type ()->get_mappings ().get_hirid ();
TyTy::BaseType *impl_block_ty = nullptr;
bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
bool ok = query_type (impl_ty_id, &impl_block_ty);
rust_assert (ok);
if (impl_block_ty->needs_generic_substitutions ())

View File

@@ -22,6 +22,7 @@
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-enumitem.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check-pattern.h"
namespace Rust {
@@ -138,379 +139,75 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
}
}
void
TypeCheckStmt::visit (HIR::TypePath &path)
{
infered = TypeCheckType::Resolve (&path);
}
void
TypeCheckStmt::visit (HIR::QualifiedPathInType &path)
{
infered = TypeCheckType::Resolve (&path);
}
void
TypeCheckStmt::visit (HIR::TupleStruct &struct_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
{
for (auto &generic_param : struct_decl.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
std::vector<TyTy::StructFieldType *> fields;
size_t idx = 0;
for (auto &field : struct_decl.get_fields ())
{
TyTy::BaseType *field_type
= TypeCheckType::Resolve (field.get_field_type ().get ());
TyTy::StructFieldType *ty_field
= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
std::to_string (idx), field_type,
field.get_locus ());
fields.push_back (ty_field);
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
idx++;
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok = mappings->lookup_canonical_path (
struct_decl.get_mappings ().get_nodeid (), &canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, struct_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields)));
// Process #[repr(...)] attribute, if any
const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
TyTy::ADTType::ReprOptions repr
= parse_repr_options (attrs, struct_decl.get_locus ());
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
struct_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::TUPLE_STRUCT,
std::move (variants), std::move (substitutions), repr);
context->insert_type (struct_decl.get_mappings (), type);
infered = type;
infered = TypeCheckItem::Resolve (struct_decl);
}
void
TypeCheckStmt::visit (HIR::Enum &enum_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (enum_decl.has_generics ())
{
for (auto &generic_param : enum_decl.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
std::vector<TyTy::VariantDef *> variants;
int64_t discriminant_value = 0;
for (auto &variant : enum_decl.get_variants ())
{
TyTy::VariantDef *field_type
= TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
discriminant_value++;
variants.push_back (field_type);
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, enum_decl.get_locus ()};
TyTy::BaseType *type
= new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
enum_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::ENUM, std::move (variants),
std::move (substitutions));
context->insert_type (enum_decl.get_mappings (), type);
infered = type;
infered = TypeCheckItem::Resolve (enum_decl);
}
void
TypeCheckStmt::visit (HIR::StructStruct &struct_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
{
for (auto &generic_param : struct_decl.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
std::vector<TyTy::StructFieldType *> fields;
for (auto &field : struct_decl.get_fields ())
{
TyTy::BaseType *field_type
= TypeCheckType::Resolve (field.get_field_type ().get ());
TyTy::StructFieldType *ty_field
= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
field.get_field_name (), field_type,
field.get_locus ());
fields.push_back (ty_field);
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok = mappings->lookup_canonical_path (
struct_decl.get_mappings ().get_nodeid (), &canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, struct_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
// Process #[repr(...)] attribute, if any
const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
TyTy::ADTType::ReprOptions repr
= parse_repr_options (attrs, struct_decl.get_locus ());
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
struct_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::STRUCT_STRUCT,
std::move (variants), std::move (substitutions), repr);
context->insert_type (struct_decl.get_mappings (), type);
infered = type;
infered = TypeCheckItem::Resolve (struct_decl);
}
void
TypeCheckStmt::visit (HIR::Union &union_decl)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (union_decl.has_generics ())
{
for (auto &generic_param : union_decl.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
std::vector<TyTy::StructFieldType *> fields;
for (auto &variant : union_decl.get_variants ())
{
TyTy::BaseType *variant_type
= TypeCheckType::Resolve (variant.get_field_type ().get ());
TyTy::StructFieldType *ty_variant
= new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
variant.get_field_name (), variant_type,
variant.get_locus ());
fields.push_back (ty_variant);
context->insert_type (variant.get_mappings (),
ty_variant->get_field_type ());
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, union_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
variants.push_back (new TyTy::VariantDef (
union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (),
ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
TyTy::BaseType *type
= new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
mappings->get_next_hir_id (),
union_decl.get_identifier (), ident,
TyTy::ADTType::ADTKind::UNION, std::move (variants),
std::move (substitutions));
context->insert_type (union_decl.get_mappings (), type);
infered = type;
infered = TypeCheckItem::Resolve (union_decl);
}
void
TypeCheckStmt::visit (HIR::Function &function)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
for (auto &generic_param : function.get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
{
case HIR::GenericParam::GenericKind::LIFETIME:
case HIR::GenericParam::GenericKind::CONST:
// FIXME: Skipping Lifetime and Const completely until better
// handling.
break;
infered = TypeCheckItem::Resolve (function);
}
case HIR::GenericParam::GenericKind::TYPE: {
auto param_type
= TypeResolveGenericParam::Resolve (generic_param.get ());
context->insert_type (generic_param->get_mappings (),
param_type);
void
TypeCheckStmt::visit (HIR::Module &module)
{
infered = TypeCheckItem::Resolve (module);
}
substitutions.push_back (TyTy::SubstitutionParamMapping (
static_cast<HIR::TypeParam &> (*generic_param), param_type));
}
break;
}
}
}
void
TypeCheckStmt::visit (HIR::TypeAlias &type_alias)
{
infered = TypeCheckItem::Resolve (type_alias);
}
TyTy::BaseType *ret_type = nullptr;
if (!function.has_function_return_type ())
ret_type
= TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
else
{
auto resolved
= TypeCheckType::Resolve (function.get_return_type ().get ());
if (resolved == nullptr)
{
rust_error_at (function.get_locus (),
"failed to resolve return type");
return;
}
void
TypeCheckStmt::visit (HIR::StaticItem &static_item)
{
infered = TypeCheckItem::Resolve (static_item);
}
ret_type = resolved->clone ();
ret_type->set_ref (
function.get_return_type ()->get_mappings ().get_hirid ());
}
void
TypeCheckStmt::visit (HIR::Trait &trait)
{
infered = TypeCheckItem::Resolve (trait);
}
std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
for (auto &param : function.get_function_params ())
{
// get the name as well required for later on
auto param_tyty = TypeCheckType::Resolve (param.get_type ());
params.push_back (
std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (),
param_tyty));
context->insert_type (param.get_mappings (), param_tyty);
TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
}
// get the path
const CanonicalPath *canonical_path = nullptr;
bool ok
= mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
&canonical_path);
rust_assert (ok);
RustIdent ident{*canonical_path, function.get_locus ()};
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
function.get_mappings ().get_defid (),
function.get_function_name (), ident,
TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST,
std::move (params), ret_type,
std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
TyTy::FnType *resolved_fn_type = fnType;
auto expected_ret_tyty = resolved_fn_type->get_return_type ();
context->push_return_type (TypeCheckContextItem (&function),
expected_ret_tyty);
auto block_expr_ty
= TypeCheckExpr::Resolve (function.get_definition ().get ());
context->pop_return_type ();
Location fn_return_locus = function.has_function_return_type ()
? function.get_return_type ()->get_locus ()
: function.get_locus ();
coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
TyTy::TyWithLocation (block_expr_ty),
function.get_definition ()->get_locus ());
infered = fnType;
void
TypeCheckStmt::visit (HIR::ImplBlock &impl)
{
infered = TypeCheckItem::Resolve (impl);
}
} // namespace Resolver

View File

@@ -40,50 +40,32 @@ public:
void visit (HIR::StructStruct &struct_decl) override;
void visit (HIR::Union &union_decl) override;
void visit (HIR::Function &function) override;
void visit (HIR::Module &module) override;
void visit (HIR::TypeAlias &type_alias) override;
void visit (HIR::StaticItem &static_item) override;
void visit (HIR::Trait &trait) override;
void visit (HIR::ImplBlock &impl) override;
void visit (HIR::TypePath &path) override;
void visit (HIR::QualifiedPathInType &path) override;
void visit (HIR::EnumItemTuple &) override
{ /* TODO? */
}
void visit (HIR::EnumItemStruct &) override
{ /* TODO? */
}
void visit (HIR::EnumItem &item) override
{ /* TODO? */
}
void visit (HIR::EnumItemDiscriminant &) override
{ /* TODO? */
}
// FIXME
// this seems like it should not be part of this visitor
void visit (HIR::TypePathSegmentFunction &segment) override
{ /* TODO? */
}
void visit (HIR::TypePath &path) override
{ /* TODO? */
}
void visit (HIR::QualifiedPathInType &path) override
{ /* TODO? */
}
void visit (HIR::Module &module) override
{ /* TODO? */
}
void visit (HIR::ExternCrate &crate) override
{ /* TODO? */
}
void visit (HIR::UseDeclaration &use_decl) override
{ /* TODO? */
}
void visit (HIR::TypeAlias &type_alias) override
{ /* TODO? */
}
void visit (HIR::StaticItem &static_item) override
{ /* TODO? */
}
void visit (HIR::Trait &trait) override
{ /* TODO? */
}
void visit (HIR::ImplBlock &impl) override
{ /* TODO? */
{
gcc_unreachable ();
}
// nothing to do for these
void visit (HIR::ExternCrate &crate) override {}
void visit (HIR::UseDeclaration &use_decl) override {}
// nothing to do for these as they are taken care of by the
// hir-type-check-enumitem.h
void visit (HIR::EnumItemTuple &) override {}
void visit (HIR::EnumItemStruct &) override {}
void visit (HIR::EnumItem &) override {}
void visit (HIR::EnumItemDiscriminant &) override {}
private:
TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {}

View File

@@ -48,6 +48,14 @@ TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
TyTy::BaseType *
TypeCheckType::Resolve (HIR::Type *type)
{
// is it already resolved?
auto context = TypeCheckContext::get ();
TyTy::BaseType *resolved = nullptr;
bool already_resolved
= context->lookup_type (type->get_mappings ().get_hirid (), &resolved);
if (already_resolved)
return resolved;
TypeCheckType resolver (type->get_mappings ().get_hirid ());
type->accept_vis (resolver);
rust_assert (resolver.translated != nullptr);
@@ -103,77 +111,29 @@ TypeCheckType::visit (HIR::TupleType &tuple)
void
TypeCheckType::visit (HIR::TypePath &path)
{
// lookup the Node this resolves to
NodeId ref;
auto nid = path.get_mappings ().get_nodeid ();
bool is_fully_resolved = resolver->lookup_resolved_type (nid, &ref);
// this can happen so we need to look up the root then resolve the
// remaining segments if possible
size_t offset = 0;
NodeId resolved_node_id = UNKNOWN_NODEID;
TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id);
if (root->get_kind () == TyTy::TypeKind::ERROR)
return;
TyTy::BaseType *lookup = nullptr;
if (!is_fully_resolved)
{
// this can happen so we need to look up the root then resolve the
// remaining segments if possible
size_t offset = 0;
NodeId resolved_node_id = UNKNOWN_NODEID;
TyTy::BaseType *root
= resolve_root_path (path, &offset, &resolved_node_id);
rust_assert (root != nullptr);
if (root->get_kind () == TyTy::TypeKind::ERROR)
return;
translated
= resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
path.get_segments (), offset, root,
path.get_mappings (), path.get_locus ());
return;
}
HirId hir_lookup;
if (!context->lookup_type_by_node_id (ref, &hir_lookup))
{
rust_error_at (path.get_locus (), "failed to lookup HIR %d for node '%s'",
ref, path.as_string ().c_str ());
return;
}
if (!context->lookup_type (hir_lookup, &lookup))
{
rust_error_at (path.get_locus (), "failed to lookup HIR TyTy");
return;
}
TyTy::BaseType *path_type = lookup->clone ();
TyTy::BaseType *path_type = root->clone ();
path_type->set_ref (path.get_mappings ().get_hirid ());
context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
HIR::TypePathSegment *final_seg = path.get_final_segment ().get ();
HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg);
bool is_big_self = final_seg->is_ident_only ()
&& (final_seg->as_string ().compare ("Self") == 0);
if (path_type->needs_generic_substitutions ())
{
if (is_big_self)
{
translated = path_type;
return;
}
translated = SubstMapper::Resolve (path_type, path.get_locus (), &args);
}
else if (!args.is_empty ())
{
rust_error_at (path.get_locus (),
"TypePath %s declares generic arguments but "
"the type %s does not have any",
path.as_string ().c_str (),
path_type->as_string ().c_str ());
}
else
bool fully_resolved = offset >= path.get_segments ().size ();
if (fully_resolved)
{
translated = path_type;
return;
}
translated
= resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
path.get_segments (), offset, path_type,
path.get_mappings (), path.get_locus ());
}
void
@@ -389,7 +349,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
}
TyTy::BaseType *lookup = nullptr;
if (!context->lookup_type (ref, &lookup))
if (!query_type (ref, &lookup))
{
if (is_root)
{
@@ -428,14 +388,22 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
if (!lookup->can_substitute ())
{
rust_error_at (seg->get_locus (),
"substitutions not supported for %s",
rust_error_at (path.get_locus (),
"TypePath %s declares generic arguments but the "
"type %s does not have any",
path.as_string ().c_str (),
lookup->as_string ().c_str ());
return new TyTy::ErrorType (lookup->get_ref ());
}
lookup = SubstMapper::Resolve (lookup, path.get_locus (),
&generic_segment->get_generic_args ());
}
else if (lookup->needs_generic_substitutions ())
{
HIR::GenericArgs empty
= HIR::GenericArgs::create_empty (path.get_locus ());
lookup = SubstMapper::Resolve (lookup, path.get_locus (), &empty);
}
*root_resolved_node_id = ref_node_id;
*offset = *offset + 1;
@@ -531,7 +499,7 @@ TypeCheckType::resolve_segments (
context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
if (tyseg->needs_generic_substitutions ())
{
Location locus = segments.back ()->get_locus ();
// Location locus = segments.back ()->get_locus ();
if (!prev_segment->needs_generic_substitutions ())
{
auto used_args_in_prev_segment
@@ -540,10 +508,6 @@ TypeCheckType::resolve_segments (
tyseg
= SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment);
}
else
{
tyseg = SubstMapper::InferSubst (tyseg, locus);
}
if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (expr_id);

View File

@@ -18,7 +18,6 @@
#include "rust-hir-type-check.h"
#include "rust-hir-full.h"
#include "rust-hir-type-check-toplevel.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-pattern.h"
@@ -35,7 +34,7 @@ void
TypeResolution::Resolve (HIR::Crate &crate)
{
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
TypeCheckTopLevel::Resolve (*it->get ());
TypeCheckItem::Resolve (*it->get ());
if (saw_errors ())
return;
@@ -44,12 +43,6 @@ TypeResolution::Resolve (HIR::Crate &crate)
if (saw_errors ())
return;
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
TypeCheckItem::Resolve (*it->get ());
if (saw_errors ())
return;
auto mappings = Analysis::Mappings::get ();
auto context = TypeCheckContext::get ();

View File

@@ -337,6 +337,41 @@ public:
return true;
}
void insert_unconstrained_check_marker (HirId id, bool status)
{
unconstrained[id] = status;
}
bool have_checked_for_unconstrained (HirId id, bool *result)
{
auto it = unconstrained.find (id);
bool found = it != unconstrained.end ();
if (!found)
return false;
*result = it->second;
return true;
}
void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate)
{
auto it = predicates.find (id);
rust_assert (it == predicates.end ());
predicates.insert ({id, predicate});
}
bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
{
auto it = predicates.find (id);
bool found = it != predicates.end ();
if (!found)
return false;
*result = it->second;
return true;
}
private:
TypeCheckContext ();
@@ -365,6 +400,12 @@ private:
// variants
std::map<HirId, HirId> variants;
// unconstrained type-params check
std::map<HirId, bool> unconstrained;
// predicates
std::map<HirId, TyTy::TypeBoundPredicate> predicates;
};
class TypeResolution

View File

@@ -102,7 +102,7 @@ public:
if (!have_generic_args ())
{
TyTy::BaseType *substs = type.infer_substitions (locus);
rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
concrete = static_cast<TyTy::ProjectionType *> (substs);
}
else

View File

@@ -18,6 +18,7 @@
#include "rust-hir-type-bounds.h"
#include "rust-hir-trait-resolve.h"
#include "rust-hir-type-check-item.h"
namespace Rust {
namespace Resolver {
@@ -33,11 +34,8 @@ TypeBoundsProbe::scan ()
if (!impl->has_trait_ref ())
return true;
TyTy::BaseType *impl_type = nullptr;
bool ok
= context->lookup_type (impl->get_type ()->get_mappings ().get_hirid (),
&impl_type);
if (!ok)
TyTy::BaseType *impl_type = TypeCheckItem::ResolveImplBlockSelf (*impl);
if (impl_type->get_kind () == TyTy::TypeKind::ERROR)
return true;
if (!receiver->can_eq (impl_type, false))
@@ -69,6 +67,13 @@ TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
TyTy::TypeBoundPredicate
TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
{
TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
bool already_resolved
= context->lookup_predicate (type_path.get_mappings ().get_hirid (),
&lookup);
if (already_resolved)
return lookup;
TraitReference *trait = resolve_trait_path (type_path);
if (trait->is_error ())
return TyTy::TypeBoundPredicate::error ();
@@ -94,6 +99,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
predicate.apply_generic_arguments (&args);
}
context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
predicate);
return predicate;
}
@@ -470,6 +477,13 @@ TypeBoundsMappings::raw_bounds_as_name () const
void
TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
{
for (auto &bound : specified_bounds)
{
bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
if (same_trait_ref_p)
return;
}
specified_bounds.push_back (predicate);
}

View File

@@ -1358,6 +1358,8 @@ public:
// generic arguments
void visit (const ParamType &) override { ok = true; }
void visit (const TupleType &) override { ok = true; }
void visit (const InferType &) override { ok = true; }
void visit (const FnType &) override { ok = true; }

View File

@@ -208,9 +208,6 @@ void
BaseType::inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
{
// FIXME
// 1. This needs to union the bounds
// 2. Do some checking for trait polarity to ensure compatibility
for (auto &bound : specified_bounds)
{
add_bound (bound);
@@ -754,6 +751,40 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
return SubstitutionArgumentMappings (mappings, args.get_locus ());
}
BaseType *
SubstitutionRef::infer_substitions (Location locus)
{
std::vector<SubstitutionArg> args;
std::map<std::string, BaseType *> argument_mappings;
for (auto &p : get_substs ())
{
if (p.needs_substitution ())
{
const std::string &symbol = p.get_param_ty ()->get_symbol ();
auto it = argument_mappings.find (symbol);
bool have_mapping = it != argument_mappings.end ();
if (have_mapping)
{
args.push_back (SubstitutionArg (&p, it->second));
}
else
{
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
argument_mappings[symbol] = infer_var.get_tyty ();
}
}
else
{
args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
}
}
SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
return handle_substitions (std::move (infer_arguments));
}
SubstitutionArgumentMappings
SubstitutionRef::adjust_mappings_for_this (
SubstitutionArgumentMappings &mappings)
@@ -2479,7 +2510,13 @@ ParamType::resolve () const
break;
TyVar v (rr->get_ty_ref ());
r = v.get_tyty ();
BaseType *n = v.get_tyty ();
// fix infinite loop
if (r == n)
break;
r = n;
}
if (r->get_kind () == TypeKind::PARAM && (r->get_ref () == r->get_ty_ref ()))

View File

@@ -960,37 +960,7 @@ public:
solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
// TODO comment
BaseType *infer_substitions (Location locus)
{
std::vector<SubstitutionArg> args;
std::map<std::string, BaseType *> argument_mappings;
for (auto &p : get_substs ())
{
if (p.needs_substitution ())
{
const std::string &symbol = p.get_param_ty ()->get_symbol ();
auto it = argument_mappings.find (symbol);
if (it == argument_mappings.end ())
{
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
argument_mappings[symbol] = infer_var.get_tyty ();
}
else
{
args.push_back (SubstitutionArg (&p, it->second));
}
}
else
{
args.push_back (
SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
}
}
SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
return handle_substitions (std::move (infer_arguments));
}
BaseType *infer_substitions (Location locus);
// TODO comment
bool monomorphize ();
@@ -1059,6 +1029,8 @@ public:
bool contains_associated_types () const;
DefId get_id () const { return reference; }
private:
DefId reference;
Location locus;

View File

@@ -419,7 +419,9 @@ Mappings::insert_hir_impl_block (HIR::ImplBlock *item)
auto id = item->get_mappings ().get_hirid ();
rust_assert (lookup_hir_impl_block (id) == nullptr);
HirId impl_type_id = item->get_type ()->get_mappings ().get_hirid ();
hirImplBlockMappings[id] = item;
hirImplBlockTypeMappings[impl_type_id] = item;
insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
}
@@ -433,6 +435,17 @@ Mappings::lookup_hir_impl_block (HirId id)
return it->second;
}
bool
Mappings::lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block)
{
auto it = hirImplBlockTypeMappings.find (id);
if (it == hirImplBlockTypeMappings.end ())
return false;
*impl_block = it->second;
return true;
}
void
Mappings::insert_module (HIR::Module *module)
{

View File

@@ -123,6 +123,7 @@ public:
void insert_hir_impl_block (HIR::ImplBlock *item);
HIR::ImplBlock *lookup_hir_impl_block (HirId id);
bool lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block);
void insert_module (HIR::Module *module);
HIR::Module *lookup_module (HirId id);
@@ -314,6 +315,7 @@ private:
std::map<HirId, HIR::SelfParam *> hirSelfParamMappings;
std::map<HirId, HIR::ImplBlock *> hirImplItemsToImplMappings;
std::map<HirId, HIR::ImplBlock *> hirImplBlockMappings;
std::map<HirId, HIR::ImplBlock *> hirImplBlockTypeMappings;
std::map<HirId, HIR::TraitItem *> hirTraitItemMappings;
std::map<HirId, HIR::ExternBlock *> hirExternBlockMappings;
std::map<HirId, std::pair<HIR::ExternalItem *, HirId>> hirExternItemMappings;

View File

@@ -1,12 +1,15 @@
// bogus errors but shows the type checking system needs to support const
// generics with defaults
struct Foo<const N: usize = { 14 }>;
const M: usize = 15;
type N = Foo<3>;
type N = Foo<3>; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
fn main() {
let _: Foo<15> = Foo;
let _: Foo<{ M }> = Foo;
let _: Foo<M> = Foo;
// bogus error, but it means the above const generic gets disambiguated properly
let _: Foo<15> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
let _: Foo<{ M }> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
let _: Foo<M> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
let _: Foo<N> = Foo; // { dg-error "TypePath Foo<N> declares generic arguments but the type Foo{Foo {}} does not have any" }
}

View File

@@ -9,4 +9,6 @@ impl<X, Y> Foo<X> {
fn main() {
let a = Foo::test();
// { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-1 }
// { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
}