Skip to content

Commit

Permalink
HIR Typecheck - Integrate matching/resolution of value generics
Browse files Browse the repository at this point in the history
  • Loading branch information
thepowersgang committed Jan 6, 2024
1 parent 733e87d commit 7be37db
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 115 deletions.
6 changes: 3 additions & 3 deletions src/hir/hir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ class TypeImpl

bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
return matches_type(tr, ResolvePlaceholdersNop());
}
};

Expand Down Expand Up @@ -579,7 +579,7 @@ class TraitImpl

bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
return matches_type(tr, ResolvePlaceholdersNop());
}

bool more_specific_than(const TraitImpl& x) const;
Expand All @@ -598,7 +598,7 @@ class MarkerImpl

bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
return matches_type(tr, ResolvePlaceholdersNop());
}
};

Expand Down
8 changes: 4 additions & 4 deletions src/hir/hir_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace {
bool matches_type_int(const ::HIR::TypeRef& left, const ::HIR::TypeRef& right_in, ::HIR::t_cb_resolve_type ty_res, bool expand_generic)
{
assert(! left.data().is_Infer() );
const auto& right = (right_in.data().is_Infer() ? ty_res(right_in) : right_in);
const auto& right = (right_in.data().is_Infer() ? ty_res.get_type(Span(), right_in) : right_in);
if( right_in.data().is_Generic() )
expand_generic = false;

Expand Down Expand Up @@ -823,7 +823,7 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl&
// TODO: Detect `impl<T> Foo<T> for Bar<T>` vs `impl<T> Foo<&T> for Bar<T>`
// > Create values for impl params from the type, then check if the trait params are compatible
// > Requires two lists, and telling which one to use by the end
auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; };
auto cb_ident = ResolvePlaceholdersNop();
bool is_reversed = false;
ImplTyMatcher matcher;
matcher.reinit(this->m_params);
Expand Down Expand Up @@ -926,10 +926,10 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl&
}
else {
// Search the crate for an impl
bool rv = crate.find_trait_impls(trait.m_path.m_path, ty, [](const auto&t)->const auto&{ return t; }, [&](const ::HIR::TraitImpl& ti)->bool {
auto cb_ident = ResolvePlaceholdersNop();
bool rv = crate.find_trait_impls(trait.m_path.m_path, ty, cb_ident, [&](const ::HIR::TraitImpl& ti)->bool {
DEBUG("impl" << ti.m_params.fmt_args() << " " << trait.m_path.m_path << ti.m_trait_args << " for " << ti.m_type << ti.m_params.fmt_bounds());

auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; };
ImplTyMatcher matcher;
matcher.reinit(ti.m_params);
// 1. Triple-check the type matches (and get generics)
Expand Down
5 changes: 2 additions & 3 deletions src/hir/inherent_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void HIR::InherentCache::Inner::insert(const Span& sp, const HIR::TypeRef& cur_t
}
void HIR::InherentCache::Inner::find(const Span& sp, const HIR::TypeRef& cur_ty_act, t_cb_resolve_type ty_res, InherentCache::inner_callback_t& cb) const
{
const auto& cur_ty = ty_res(cur_ty_act);
const auto& cur_ty = ty_res.get_type(sp, cur_ty_act);
m_byvalue.iterate(cur_ty, cb);

const Inner* inner = nullptr;
Expand Down Expand Up @@ -202,7 +202,6 @@ void HIR::InherentCache::insert_all(const Span& sp, const HIR::TypeImpl& impl, c
void HIR::InherentCache::find(const Span& sp, const RcString& name, const HIR::TypeRef& ty, t_cb_resolve_type ty_res, callback_t cb) const
{
TRACE_FUNCTION_F(name << ", " << ty);
auto cb_resolve = [](const HIR::TypeRef& t)->const HIR::TypeRef& { return t; };
// Callback that ensures that a potential impl fully matches the required receiver type
inner_callback_t inner_cb = [&](const HIR::TypeRef& rough_self_ty, const HIR::TypeImpl& impl) {
DEBUG("- " << rough_self_ty);
Expand All @@ -224,7 +223,7 @@ void HIR::InherentCache::find(const Span& sp, const RcString& name, const HIR::T
} getself;

if( fcn.m_receiver == HIR::Function::Receiver::Custom ) {
if( fcn.m_receiver_type.match_test_generics(sp, ty, cb_resolve, getself) ) {
if( fcn.m_receiver_type.match_test_generics(sp, ty, ResolvePlaceholdersNop(), getself) ) {
ASSERT_BUG(sp, getself.detected_self_ty, "Unable to determine receiver type when matching " << fcn.m_receiver_type << " and " << ty);
cb(*getself.detected_self_ty, impl);
}
Expand Down
4 changes: 4 additions & 0 deletions src/hir/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ ::HIR::Compare HIR::PathParams::match_test_generics_fuzz(const Span& sp, const P
return Compare::Unequal;
}
else {
// TODO: Look up the the ivars?
if( this->m_values[i].is_Infer() ) {
return Compare::Fuzzy;
}
if( this->m_values[i] != x.m_values[i] ) {
return Compare::Unequal;
}
Expand Down
8 changes: 4 additions & 4 deletions src/hir/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,8 @@ ::HIR::Compare HIR::TypeRef::match_test_generics_fuzz(const Span& sp, const ::HI
if( const auto* e = data().opt_Generic() ) {
return callback.match_ty(*e, x_in, resolve_placeholder);
}
const auto& v = (this->data().is_Infer() ? resolve_placeholder(*this) : *this);
const auto& x = (x_in.data().is_Infer() || x_in.data().is_Generic() ? resolve_placeholder(x_in) : x_in);
const auto& v = (this->data().is_Infer() ? resolve_placeholder.get_type(sp, *this) : *this);
const auto& x = (x_in.data().is_Infer() || x_in.data().is_Generic() ? resolve_placeholder.get_type(sp, x_in) : x_in);
TRACE_FUNCTION_F(*this << ", " << x_in << " -- " << v << ", " << x);
// If `x` is an ivar - This can be a fuzzy match.
if(const auto* xep = x.data().opt_Infer())
Expand Down Expand Up @@ -1059,9 +1059,9 @@ ::HIR::TypeRef HIR::TypeRef::clone_shallow() const
::HIR::Compare HIR::TypeRef::compare_with_placeholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const
{
//TRACE_FUNCTION_F(*this << " ?= " << x);
const auto& left = (data().is_Infer() || data().is_Generic() ? resolve_placeholder(*this) : *this);
const auto& left = (data().is_Infer() || data().is_Generic() ? resolve_placeholder.get_type(sp, *this) : *this);
//const auto& left = *this;
const auto& right = (x.data().is_Infer() ? resolve_placeholder(x) : (x.data().is_Generic() ? resolve_placeholder(x) : x));
const auto& right = (x.data().is_Infer() || x.data().is_Generic()) ? resolve_placeholder.get_type(sp, x) : x;

// If the two types are the same ivar, return equal
if( left.data().is_Infer() && left == right ) {
Expand Down
12 changes: 11 additions & 1 deletion src/hir/type_ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,17 @@ enum Compare {
Unequal,
};

typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type;
class ResolvePlaceholders {
public:
virtual const ::HIR::TypeRef& get_type(const Span& sp, const HIR::TypeRef& ty) const = 0;
virtual const ::HIR::ConstGeneric& get_val(const Span& sp, const HIR::ConstGeneric& v) const = 0;
};
class ResolvePlaceholdersNop: public ResolvePlaceholders {
const ::HIR::TypeRef& get_type(const Span& sp, const HIR::TypeRef& ty) const { return ty; }
const ::HIR::ConstGeneric& get_val(const Span& sp, const HIR::ConstGeneric& v) const { return v; }
};
//typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type;
typedef const ResolvePlaceholders& t_cb_resolve_type;

class MatchGenerics
{
Expand Down
4 changes: 2 additions & 2 deletions src/hir_conv/resolve_ufcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ namespace resolve_ufcs {
{
auto& e = pd.as_UfcsUnknown();
TRACE_FUNCTION_F(e.type);
return m_crate.find_type_impls(e.type, [&](const auto& t)->const auto& { return t; }, [&](const auto& impl) {
return m_crate.find_type_impls(e.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) {
DEBUG("- matched inherent impl" << impl.m_params.fmt_args() << " " << impl.m_type);
// Search for item in this block
switch( pc )
Expand Down Expand Up @@ -887,7 +887,7 @@ namespace resolve_ufcs {
BUG(sp, "UfcsUnknown still in pattern value - " << pat);
}
TU_ARMA(UfcsInherent, pe) {
bool rv = m_crate.find_type_impls(pe.type, [&](const auto& t)->const auto& { return t; }, [&](const auto& impl) {
bool rv = m_crate.find_type_impls(pe.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) {
DEBUG("- matched inherent impl" << impl.m_params.fmt_args() << " " << impl.m_type);
// Search for item in this block
auto it = impl.m_constants.find(pe.item);
Expand Down
2 changes: 1 addition & 1 deletion src/hir_typeck/expr_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ namespace {
TU_ARMA(UfcsInherent, e) {
// - Locate function (and impl block)
const ::HIR::TypeImpl* impl_ptr = nullptr;
m_resolve.m_crate.find_type_impls(e.type, [&](const auto& ty)->const ::HIR::TypeRef& { return ty; },
m_resolve.m_crate.find_type_impls(e.type, HIR::ResolvePlaceholdersNop(),
[&](const auto& impl) {
DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type);
auto it = impl.m_methods.find(e.item);
Expand Down
71 changes: 40 additions & 31 deletions src/hir_typeck/expr_cs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1959,33 +1959,6 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
set_ivar(l_t, r_t);
}
else {
auto equality_constgeneric = [&](const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr) {
const auto& l = this->m_ivars.get_value(rl);
const auto& r = this->m_ivars.get_value(rr);
if( l != r ) {
DEBUG(l << " != " << r);
if(l.is_Infer()) {
if(r.is_Infer()) {
// Unify ivars
this->m_ivars.ivar_val_unify(l.as_Infer().index, r.as_Infer().index);
}
else {
this->m_ivars.set_ivar_val_to(l.as_Infer().index, r.clone());
}
}
else {
if(r.is_Infer()) {
this->m_ivars.set_ivar_val_to(r.as_Infer().index, l.clone());
}
else {
ERROR(sp, E0000, "Value mismatch between " << l << " and " << r);
}
}
}
else {
DEBUG(l << " == " << r);
}
};
// Helper function for Path and TraitObject
auto equality_typeparams = [&](const ::HIR::PathParams& l, const ::HIR::PathParams& r) {
if( l.m_types.size() != r.m_types.size() ) {
Expand All @@ -2001,7 +1974,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
}
for(unsigned int i = 0; i < l.m_values.size(); i ++)
{
equality_constgeneric(l.m_values[i], r.m_values[i]);
this->equate_values(sp, l.m_values[i], r.m_values[i]);
}
};

Expand Down Expand Up @@ -2126,15 +2099,15 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
if( !l_e.size.is_Unevaluated() ) {
assert(l_e.size.is_Known());
assert(r_e.size.is_Unevaluated());
equality_constgeneric(HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(l_e.size.as_Known())), r_e.size.as_Unevaluated());
this->equate_values(sp, HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(l_e.size.as_Known())), r_e.size.as_Unevaluated());
}
else if( !r_e.size.is_Unevaluated() ) {
assert(l_e.size.is_Unevaluated());
assert(r_e.size.is_Known());
equality_constgeneric(l_e.size.as_Unevaluated(), HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(r_e.size.as_Known())));
this->equate_values(sp, l_e.size.as_Unevaluated(), HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(r_e.size.as_Known())));
}
else {
equality_constgeneric(l_e.size.as_Unevaluated(), r_e.size.as_Unevaluated());
this->equate_values(sp, l_e.size.as_Unevaluated(), r_e.size.as_Unevaluated());
}
}
else {
Expand Down Expand Up @@ -2194,6 +2167,35 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
}
}

void Context::equate_values(const Span& sp, const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr)
{
const auto& l = this->m_ivars.get_value(rl);
const auto& r = this->m_ivars.get_value(rr);
if( l != r ) {
DEBUG(l << " != " << r);
if(l.is_Infer()) {
if(r.is_Infer()) {
// Unify ivars
this->m_ivars.ivar_val_unify(l.as_Infer().index, r.as_Infer().index);
}
else {
this->m_ivars.set_ivar_val_to(l.as_Infer().index, r.clone());
}
}
else {
if(r.is_Infer()) {
this->m_ivars.set_ivar_val_to(r.as_Infer().index, l.clone());
}
else {
ERROR(sp, E0000, "Value mismatch between " << l << " and " << r);
}
}
}
else {
DEBUG(l << " == " << r);
}
}

void Context::add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type)
{
assert( pb.is_valid() );
Expand Down Expand Up @@ -5206,6 +5208,10 @@ namespace {
{
context.equate_types(sp, v.params.m_types[i], itp.m_types[i]);
}
for(unsigned int i = 0; i < v.params.m_values.size(); i ++)
{
context.equate_values(sp, v.params.m_values[i], itp.m_values[i]);
}
return true;
}
else {
Expand Down Expand Up @@ -5421,6 +5427,9 @@ namespace {
for( unsigned int i = 0; i < possible_params.m_types.size(); i ++ ) {
context.equate_types(sp, v.params.m_types[i], possible_params.m_types[i]);
}
for( unsigned int i = 0; i < possible_params.m_values.size(); i ++ ) {
context.equate_values(sp, v.params.m_values[i], possible_params.m_values[i]);
}
// - Obtain the bounds required for this impl and add those as trait bounds to check/equate
if( const auto* ep = best_impl.m_data.opt_TraitImpl() )
{
Expand Down
3 changes: 3 additions & 0 deletions src/hir_typeck/expr_cs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ struct Context
// - Equate a type to an associated type (if name == "", no equation is done, but trait is searched)
void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::HIR::PathParams params, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op=false);

// Equate const generics (values)
void equate_values(const Span& sp, const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr);

/// Adds a `ty: Sized` bound to the contained ivars.
void require_sized(const Span& sp, const ::HIR::TypeRef& ty);

Expand Down
4 changes: 4 additions & 0 deletions src/hir_typeck/expr_cs__enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ namespace typecheck
{
}

void visit_path_params(::HIR::PathParams& pp)
{
this->context.m_ivars.add_ivars_params(pp);
}
void visit_type(::HIR::TypeRef& ty)
{
this->context.add_ivars(ty);
Expand Down
Loading

0 comments on commit 7be37db

Please sign in to comment.