summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/expr_cs.cpp71
1 files changed, 54 insertions, 17 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 47b83356..abca0507 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -221,7 +221,7 @@ static void fix_param_count(const Span& sp, Context& context, const ::HIR::TypeR
namespace {
- void apply_bounds_as_rules(Context& context, const Span& sp, const ::HIR::GenericParams& params_def, t_cb_generic monomorph_cb)
+ void apply_bounds_as_rules(Context& context, const Span& sp, const ::HIR::GenericParams& params_def, t_cb_generic monomorph_cb, bool is_impl_level)
{
for(const auto& bound : params_def.m_bounds)
{
@@ -264,6 +264,15 @@ namespace {
)
)
}
+
+ for(size_t i = 0; i < params_def.m_types.size(); i++)
+ {
+ if( params_def.m_types[i].m_is_sized )
+ {
+ ::HIR::TypeRef ty("", (is_impl_level ? 0 : 256) + i);
+ context.require_sized(sp, monomorph_cb(ty));
+ }
+ }
}
bool visit_call_populate_cache(Context& context, const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache) __attribute__((warn_unused_result));
@@ -374,7 +383,7 @@ namespace {
cache.m_arg_types.push_back( monomorphise_type_with(sp, fcn.m_return, monomorph_cb, false) );
// --- Apply bounds by adding them to the associated type ruleset
- apply_bounds_as_rules(context, sp, *cache.m_fcn_params, cache.m_monomorph_cb);
+ apply_bounds_as_rules(context, sp, *cache.m_fcn_params, cache.m_monomorph_cb, /*is_impl_level=*/false);
return true;
}
@@ -497,7 +506,7 @@ namespace {
};
// Add trait bounds for all impl and function bounds
- apply_bounds_as_rules(context, sp, impl_ptr->m_params, cache.m_monomorph_cb);
+ apply_bounds_as_rules(context, sp, impl_ptr->m_params, cache.m_monomorph_cb, /*is_impl_level=*/true);
// Equate `Self` and `impl_ptr->m_type` (after monomorph)
{
@@ -1256,7 +1265,7 @@ namespace {
}
// Convert bounds on the type into rules
- apply_bounds_as_rules(context, node.span(), *generics, monomorph_cb);
+ apply_bounds_as_rules(context, node.span(), *generics, monomorph_cb, /*is_impl_level=*/true);
auto _ = this->push_inner_coerce_scoped(true);
for( auto& val : node.m_values ) {
@@ -1283,7 +1292,7 @@ namespace {
auto monomorph_cb = monomorphise_type_get_cb(node.span(), &ty, &node.m_path.m_params, nullptr);
// Convert bounds on the type into rules
- apply_bounds_as_rules(context, node.span(), unm.m_params, monomorph_cb);
+ apply_bounds_as_rules(context, node.span(), unm.m_params, monomorph_cb, /*is_impl_level=*/true);
auto it = ::std::find_if(unm.m_variants.begin(), unm.m_variants.end(), [&](const auto& v)->bool{ return v.first == node.m_variant_name; });
assert(it != unm.m_variants.end());
@@ -1589,7 +1598,7 @@ namespace {
}
// Apply bounds
- apply_bounds_as_rules(this->context, sp, f.m_params, monomorph_cb);
+ apply_bounds_as_rules(this->context, sp, f.m_params, monomorph_cb, /*is_impl_level=*/false);
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
DEBUG("> " << node.m_path << " = " << ty);
@@ -1610,7 +1619,7 @@ namespace {
{
ft.m_arg_types.push_back( monomorphise_type(sp, s.m_params, e.m_params, arg.ent) );
}
- //apply_bounds_as_rules(this->context, sp, s.m_params, monomorph_cb);
+ //apply_bounds_as_rules(this->context, sp, s.m_params, monomorph_cb, /*is_impl_level=*/true);
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
this->context.equate_types(sp, node.m_res_type, ty);
@@ -1638,7 +1647,7 @@ namespace {
{
ft.m_arg_types.push_back( monomorphise_type(sp, enm.m_params, e.m_params, arg.ent) );
}
- //apply_bounds_as_rules(this->context, sp, enm.m_params, monomorph_cb);
+ //apply_bounds_as_rules(this->context, sp, enm.m_params, monomorph_cb, /*is_impl_level=*/true);
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
this->context.equate_types(sp, node.m_res_type, ty);
@@ -1695,7 +1704,7 @@ namespace {
};
for(const auto& arg : ie.m_args)
ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
- apply_bounds_as_rules(this->context, sp, ie.m_params, monomorph_cb);
+ apply_bounds_as_rules(this->context, sp, ie.m_params, monomorph_cb, /*is_impl_level=*/false);
auto ty = ::HIR::TypeRef(mv$(ft));
this->context.equate_types(node.span(), node.m_res_type, ty);
@@ -1804,8 +1813,8 @@ namespace {
};
// Bounds (both impl and fn)
- apply_bounds_as_rules(this->context, sp, impl_ptr->m_params, monomorph_cb);
- apply_bounds_as_rules(this->context, sp, fcn_ptr->m_params, monomorph_cb);
+ apply_bounds_as_rules(this->context, sp, impl_ptr->m_params, monomorph_cb, /*is_impl_level=*/true);
+ apply_bounds_as_rules(this->context, sp, fcn_ptr->m_params, monomorph_cb, /*is_impl_level=*/false);
::HIR::FunctionType ft {
fcn_ptr->m_unsafe, fcn_ptr->m_abi,
@@ -1826,7 +1835,7 @@ namespace {
::HIR::TypeRef tmp;
const auto& ty = ( monomorphise_type_needed(const_ptr->m_type) ? tmp = monomorphise_type_with(sp, const_ptr->m_type, monomorph_cb) : const_ptr->m_type );
- apply_bounds_as_rules(this->context, sp, impl_ptr->m_params, monomorph_cb);
+ apply_bounds_as_rules(this->context, sp, impl_ptr->m_params, monomorph_cb, /*is_impl_level=*/true);
this->context.equate_types(node.span(), node.m_res_type, ty);
}
)
@@ -4222,10 +4231,8 @@ void fix_param_count_(const Span& sp, Context& context, const ::HIR::TypeRef& se
{
if( params.m_types.size() == param_defs.m_types.size() ) {
// Nothing to do, all good
- return ;
}
-
- if( params.m_types.size() > param_defs.m_types.size() ) {
+ else if( params.m_types.size() > param_defs.m_types.size() ) {
ERROR(sp, E0000, "Too many type parameters passed to " << path);
}
else {
@@ -4352,6 +4359,13 @@ namespace {
return CoerceResult::Equality;
}
+ // Can't Unsize to a known-Sized type.
+ if( dst.m_data.is_Infer() && dst.m_data.as_Infer().index < context.m_ivars_sized.size() && context.m_ivars_sized.at( dst.m_data.as_Infer().index ) )
+ {
+ DEBUG("Can't unsize to known-Sized type");
+ return CoerceResult::Equality;
+ }
+
// Handle ivars specially
if(dst.m_data.is_Infer() && src.m_data.is_Infer())
{
@@ -4757,6 +4771,8 @@ namespace {
if( TU_TEST1(src.m_data, Infer, .is_lit()) ) {
return CoerceResult::Equality;
}
+
+ // TODO: If the destination is bounded to be Sized, equate and return.
// If both sides are `_`, then can't know about coerce yet
if( dst.m_data.is_Infer() && src.m_data.is_Infer() ) {
// Add possibilities both ways
@@ -6183,12 +6199,13 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
{
// Check the possible equations
DEBUG("--- IVar possibilities");
- for(unsigned int i = 0; i < context.possible_ivar_vals.size(); i ++ )
+ for(unsigned int i = context.possible_ivar_vals.size(); i --; )
+ //for(unsigned int i = 0; i < context.possible_ivar_vals.size(); i ++ )
{
if( check_ivar_poss(context, i, context.possible_ivar_vals[i]) ) {
static Span sp;
assert( context.possible_ivar_vals[i].has_rules() );
- // TODO: Disable all metioned ivars in the possibilities
+ // Disable all metioned ivars in the possibilities
for(const auto& ty : context.possible_ivar_vals[i].types_coerce_to)
context.equate_types_from_shadow(sp,ty);
for(const auto& ty : context.possible_ivar_vals[i].types_unsize_to)
@@ -6197,6 +6214,26 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
context.equate_types_to_shadow(sp,ty);
for(const auto& ty : context.possible_ivar_vals[i].types_unsize_from)
context.equate_types_to_shadow(sp,ty);
+
+ // Also disable inferrence (for this pass) for all ivars in affected bounds
+ for(const auto& la : context.link_assoc)
+ {
+ bool found = false;
+ auto cb = [&](const auto& t) { return TU_TEST1(t.m_data, Infer, .index == i); };
+ if( la.left_ty != ::HIR::TypeRef() )
+ found |= visit_ty_with( la.left_ty, cb );
+ found |= visit_ty_with( la.impl_ty, cb );
+ for(const auto& t : la.params.m_types)
+ found |= visit_ty_with( t, cb );
+ if( found )
+ {
+ if(la.left_ty != ::HIR::TypeRef())
+ context.equate_types_shadow(sp, la.left_ty, false);
+ context.equate_types_shadow(sp, la.impl_ty, false);
+ for(const auto& t : la.params.m_types)
+ context.equate_types_shadow(sp, t, false);
+ }
+ }
}
else {
//assert( !context.m_ivars.peek_changed() );