diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-17 16:02:23 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-17 16:02:23 +0800 |
commit | 5b8b5da9ac7ca950cc700e6a27f7897e4b753c18 (patch) | |
tree | ccc60456cf487e9a8a6fb6d03d0771a1952b7193 | |
parent | d8371fadef66162230b8610a255739f6bb7dca4d (diff) | |
download | mrust-5b8b5da9ac7ca950cc700e6a27f7897e4b753c18.tar.gz |
HIR Typecheck Expr - Handle revisit in SplitSlice
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 74 |
1 files changed, 55 insertions, 19 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 1a320bdf..f2d2dabe 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -192,6 +192,7 @@ struct Context // - Add a pattern binding (forcing the type to match) void add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type); + void add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type); void add_var(unsigned int index, const ::std::string& name, ::HIR::TypeRef type); const ::HIR::TypeRef& get_var(const Span& sp, unsigned int idx) const; @@ -3262,27 +3263,31 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const } } } + +void Context::add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type) +{ + assert( pb.is_valid() ); + switch( pb.m_type ) + { + case ::HIR::PatternBinding::Type::Move: + this->add_var( pb.m_slot, pb.m_name, mv$(type) ); + break; + case ::HIR::PatternBinding::Type::Ref: + this->add_var( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, mv$(type)) ); + break; + case ::HIR::PatternBinding::Type::MutRef: + this->add_var( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, mv$(type)) ); + break; + } +} + // NOTE: Mutates the pattern to add ivars to contained paths void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type) { TRACE_FUNCTION_F("pat = " << pat << ", type = " << type); if( pat.m_binding.is_valid() ) { - const auto& pb = pat.m_binding; - - assert( pb.is_valid() ); - switch( pb.m_type ) - { - case ::HIR::PatternBinding::Type::Move: - this->add_var( pb.m_slot, pb.m_name, type.clone() ); - break; - case ::HIR::PatternBinding::Type::Ref: - this->add_var( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, type.clone()) ); - break; - case ::HIR::PatternBinding::Type::MutRef: - this->add_var( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, type.clone()) ); - break; - } + this->add_binding_inner(sp, pat.m_binding, type.clone()); // TODO: Bindings aren't allowed within another binding } @@ -3471,9 +3476,11 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type unsigned int min_len = e.leading.size() + e.trailing.size(); const auto& ty = this->get_type(type); TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te, + // Slice - Fetch inner and set new variable also be a slice + // - TODO: Better new variable handling. inner = te.inner->clone(); if( e.extra_bind.is_valid() ) { - this->add_var( e.extra_bind.m_slot, e.extra_bind.m_name, ty.clone() ); + this->add_binding_inner( sp, e.extra_bind, ty.clone() ); } ) else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, te, @@ -3484,7 +3491,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type unsigned extra_len = te.size_val - min_len; if( e.extra_bind.is_valid() ) { - this->add_var( e.extra_bind.m_slot, e.extra_bind.m_name, ::HIR::TypeRef::new_array(inner.clone(), extra_len) ); + this->add_binding_inner( sp, e.extra_bind, ::HIR::TypeRef::new_array(inner.clone(), extra_len) ); } ) else if( ty.m_data.is_Infer() ) { @@ -3492,15 +3499,18 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type ::HIR::TypeRef var_ty; if( e.extra_bind.is_valid() ) { var_ty = this->m_ivars.new_ivar_tr(); - this->add_var( e.extra_bind.m_slot, e.extra_bind.m_name, var_ty.clone() ); + this->add_binding_inner( sp, e.extra_bind, var_ty.clone() ); } struct SplitSlicePatRevisit: public Revisitor { Span sp; + // Inner type ::HIR::TypeRef inner; + // Outer ivar (should be either Slice or Array) ::HIR::TypeRef type; + // Binding type (if not default value) ::HIR::TypeRef var_ty; unsigned int min_size; @@ -3510,7 +3520,33 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type void fmt(::std::ostream& os) const override { os << "SplitSlice inner=" << inner << ", outer=" << type << ", binding="<<var_ty<<", " << min_size; } bool revisit(Context& context) override { - TODO(sp, "SplitSlicePatRevisit"); + const auto& ty = context.get_type(this->type); + if( ty.m_data.is_Infer() ) + return false; + + // Slice - Equate inners + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te, + context.equate_types(this->sp, this->inner, *te.inner); + if( this->var_ty != ::HIR::TypeRef() ) { + context.equate_types(this->sp, this->var_ty, ty); + } + ) + // Array - Equate inners and check size + else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, te, + context.equate_types(this->sp, this->inner, *te.inner); + if( te.size_val < this->min_size ) { + ERROR(sp, E0000, "Slice pattern on an array smaller than the pattern"); + } + unsigned extra_len = te.size_val - this->min_size; + + if( this->var_ty != ::HIR::TypeRef() ) { + context.equate_types(this->sp, this->var_ty, ::HIR::TypeRef::new_array(this->inner.clone(), extra_len) ); + } + ) + else { + ERROR(sp, E0000, "Slice pattern on non-array/-slice - " << ty); + } + return true; } }; // Callback |