summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp122
1 files changed, 101 insertions, 21 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index e8e0f65c..04cb6f17 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -37,7 +37,7 @@ struct Context
{
public:
virtual void fmt(::std::ostream& os) const = 0;
- virtual bool revisit(Context& context) = 0;
+ virtual bool revisit(Context& context, bool is_fallback) = 0;
};
struct Binding
@@ -3790,24 +3790,26 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
void fmt(::std::ostream& os) const override {
os << "MatchErgonomicsRevisit { " << m_pattern << " : " << m_outer_ty << " }";
}
- bool revisit(Context& context) override {
- TRACE_FUNCTION_F("Match ergonomics - " << m_pattern << " : " << m_outer_ty);
- return this->revisit_inner(context, m_pattern, m_outer_ty, m_outer_mode);
+ bool revisit(Context& context, bool is_fallback_mode) override {
+ TRACE_FUNCTION_F("Match ergonomics - " << m_pattern << " : " << m_outer_ty << (is_fallback_mode ? " (fallback)": ""));
+ return this->revisit_inner_real(context, m_pattern, m_outer_ty, m_outer_mode, is_fallback_mode);
}
// TODO: Recurse into inner patterns, creating new revisitors?
// - OR, could just recurse on it.
//
// Recusring incurs costs on every iteration, but is less expensive the first time around
// New revisitors are cheaper when inferrence takes multiple iterations, but takes longer first time.
- bool revisit_inner(Context& context, ::HIR::Pattern& pattern, const ::HIR::TypeRef& type, ::HIR::PatternBinding::Type binding_mode) const {
- if( !revisit_inner_real(context, pattern, type, binding_mode) )
+ bool revisit_inner(Context& context, ::HIR::Pattern& pattern, const ::HIR::TypeRef& type, ::HIR::PatternBinding::Type binding_mode) const
+ {
+ if( !revisit_inner_real(context, pattern, type, binding_mode, false) )
{
DEBUG("Add revisit for " << pattern << " : " << type << "(mode = " << (int)binding_mode << ")");
context.add_revisit_adv( box$(( MatchErgonomicsRevisit { sp, type.clone(), pattern, binding_mode } )) );
}
return true;
}
- bool revisit_inner_real(Context& context, ::HIR::Pattern& pattern, const ::HIR::TypeRef& type, ::HIR::PatternBinding::Type binding_mode) const {
+ bool revisit_inner_real(Context& context, ::HIR::Pattern& pattern, const ::HIR::TypeRef& type, ::HIR::PatternBinding::Type binding_mode, bool is_fallback) const
+ {
TRACE_FUNCTION_F(pattern << " : " << type);
// Binding applies to the raw input type (not after dereferencing)
@@ -3837,7 +3839,72 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
DEBUG("- " << n_deref << " derefs of class " << bt << " to get " << *ty_p);
if( ty_p->m_data.is_Infer() ) {
// Still pure infer, can't do anything
- // - What if it's an literal?
+ // - What if it's a literal?
+
+ if( n_deref == 0 && is_fallback )
+ {
+ ::HIR::TypeRef possible_type;
+ // TODO: Get a potential type from the pattern, and set as a possibility.
+ // - Note, this is only if no derefs were applied
+ TU_MATCH_HDR( (pattern.m_data), { )
+ TU_ARM(pattern.m_data, Any, pe) {
+ // No type information.
+ }
+ TU_ARM(pattern.m_data, Value, pe) {
+ // TODO: Get type info
+ }
+ TU_ARM(pattern.m_data, Range, pe) {
+ // TODO: Get type info (same as Value)
+ }
+ TU_ARM(pattern.m_data, Box, pe) {
+ // TODO: Get type info (Box<_>)
+ }
+ TU_ARM(pattern.m_data, Ref, pe) {
+ BUG(sp, "Match ergonomics - & pattern");
+ }
+ TU_ARM(pattern.m_data, Tuple, e) {
+ // TODO: Get type info `(T, U, ...)`
+ }
+ TU_ARM(pattern.m_data, SplitTuple, pe) {
+ // Can't get type information, tuple size is unkown
+ }
+ TU_ARM(pattern.m_data, Slice, e) {
+ // Can be either a [T] or [T; n]. Can't provide a hint
+ }
+ TU_ARM(pattern.m_data, SplitSlice, pe) {
+ // Can be either a [T] or [T; n]. Can't provide a hint
+ }
+ TU_ARM(pattern.m_data, StructValue, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, StructTuple, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, Struct, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, EnumValue, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ TU_ARM(pattern.m_data, EnumTuple, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ TU_ARM(pattern.m_data, EnumStruct, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ }
+ if( possible_type != ::HIR::TypeRef() )
+ {
+ DEBUG("Possible equate " << possible_type);
+ context.equate_types( sp, *ty_p, possible_type );
+ }
+ }
// TODO: Visit all inner bindings and disable coercion fallbacks on them.
MatchErgonomicsRevisit::disable_possibilities_on_bindings(sp, context, pattern);
@@ -4360,7 +4427,7 @@ void Context::handle_pattern_direct_inner(const Span& sp, ::HIR::Pattern& pat, c
void fmt(::std::ostream& os) const override {
os << "SplitTuplePatRevisit { " << m_outer_ty << " = (" << m_leading_tys << ", ..., " << m_trailing_tys << ") }";
}
- bool revisit(Context& context) override {
+ bool revisit(Context& context, bool is_fallback) override {
const auto& ty = context.get_type(m_outer_ty);
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Infer, te,
return false;
@@ -4414,7 +4481,7 @@ void Context::handle_pattern_direct_inner(const Span& sp, ::HIR::Pattern& pat, c
{}
void fmt(::std::ostream& os) const override { os << "SlicePatRevisit { " << inner << ", " << type << ", " << size; }
- bool revisit(Context& context) override {
+ bool revisit(Context& context, bool is_fallback) override {
const auto& ty = context.get_type(type);
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te,
context.equate_types(sp, *te.inner, inner);
@@ -4489,7 +4556,7 @@ void Context::handle_pattern_direct_inner(const Span& sp, ::HIR::Pattern& pat, c
{}
void fmt(::std::ostream& os) const override { os << "SplitSlice inner=" << inner << ", outer=" << type << ", binding="<<var_ty<<", " << min_size; }
- bool revisit(Context& context) override {
+ bool revisit(Context& context, bool is_fallback) override {
const auto& ty = context.get_type(this->type);
if( ty.m_data.is_Infer() )
return false;
@@ -6881,12 +6948,6 @@ namespace {
static Span _span;
const auto& sp = _span;
- if( ! ivar_ent.has_rules() ) {
- // No rules, don't do anything (and don't print)
- DEBUG(i << ": No rules");
- return false;
- }
-
if( honour_disable && (ivar_ent.force_no_to || ivar_ent.force_no_from) )
{
DEBUG(i << ": forced unknown");
@@ -6898,9 +6959,18 @@ namespace {
const auto& ty_l = context.m_ivars.get_type(ty_l_ivar);
if( ty_l != ty_l_ivar ) {
- DEBUG("- IVar " << i << " had possibilities, but was known to be " << ty_l);
- // Completely clear by reinitialising
- ivar_ent = Context::IVarPossible();
+ if( ivar_ent.has_rules() )
+ {
+ DEBUG("- IVar " << i << " had possibilities, but was known to be " << ty_l);
+ // Completely clear by reinitialising
+ ivar_ent = Context::IVarPossible();
+ }
+ return false;
+ }
+
+ if( ! ivar_ent.has_rules() ) {
+ // No rules, don't do anything (and don't print)
+ DEBUG(i << ": No rules");
return false;
}
@@ -7096,7 +7166,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
for(size_t i = 0; i < len; i ++)
{
auto& ent = *context.adv_revisits[i];
- adv_revisit_remove_list.push_back( ent.revisit(context) );
+ adv_revisit_remove_list.push_back( ent.revisit(context, /*is_fallback=*/false) );
}
for(size_t i = len; i --;)
{
@@ -7234,6 +7304,16 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
}
} // `if peek_changed` (ivar possibilities #2)
+ if( !context.m_ivars.peek_changed() )
+ {
+ size_t len = context.adv_revisits.size();
+ for(size_t i = 0; i < len; i ++)
+ {
+ auto& ent = *context.adv_revisits[i];
+ ent.revisit(context, /*is_fallback=*/true);
+ }
+ }
+
// Finally. If nothing changed, apply ivar defaults
if( !context.m_ivars.peek_changed() )
{