diff options
author | John Hodge <tpg@mutabah.net> | 2018-11-03 22:08:03 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-11-03 22:08:03 +0800 |
commit | 76757341622b747074be74cc75aa5f4f51665f15 (patch) | |
tree | e0c7562fc49810c81b915636ad56121508a88970 | |
parent | f31020b3f3aeb299e68af9c4790bb591dcfc2aca (diff) | |
download | mrust-76757341622b747074be74cc75aa5f4f51665f15.tar.gz |
HIR Typecheck - Fixing holes from 1.29 compiler_builtins
-rw-r--r-- | src/hir/hir.cpp | 2 | ||||
-rw-r--r-- | src/hir/type.cpp | 60 | ||||
-rw-r--r-- | src/hir_typeck/expr_check.cpp | 4 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 7 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 260 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/impl_ref.cpp | 19 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 5 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 6 |
9 files changed, 205 insertions, 159 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 9f9bc1c3..fb0cdbd3 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -344,7 +344,7 @@ bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_reso { // NOTE: Don't return any impls when the type is an unbouned ivar. Wouldn't be able to pick anything anyway // TODO: For `Unbound`, it could be valid, if the target is a generic. - if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { + if( /*is_unbounded_infer(type) ||*/ TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { return false; } return matches_type_int(m_params, m_type, type, ty_res, true); diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 6f826111..434d471b 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -58,8 +58,8 @@ namespace HIR { void ::HIR::TypeRef::fmt(::std::ostream& os) const { - TU_MATCH(::HIR::TypeRef::Data, (m_data), (e), - (Infer, + TU_MATCH_HDR( (m_data), { ) + TU_ARM(m_data, Infer, e) { os << "_"; if( e.index != ~0u || e.ty_class != ::HIR::InferClass::None ) { os << "/*"; @@ -73,14 +73,14 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const } os << "*/"; } - ), - (Diverge, + } + TU_ARM(m_data, Diverge, e) { os << "!"; - ), - (Primitive, + } + TU_ARM(m_data, Primitive, e) { os << e; - ), - (Path, + } + TU_ARM(m_data, Path, e) { os << e.path; TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), (Unbound, os << "/*?*/";), @@ -89,8 +89,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const (Union, os << "/*U*/";), (Enum, os << "/*E*/";) ) - ), - (Generic, + } + TU_ARM(m_data, Generic, e) { os << e.name << "/*"; if( e.binding == 0xFFFF ) os << ""; @@ -103,8 +103,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const else os << e.binding; os << "*/"; - ), - (TraitObject, + } + TU_ARM(m_data, TraitObject, e) { os << "dyn ("; if( e.m_trait.m_path != ::HIR::GenericPath() ) { @@ -115,8 +115,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const if( e.m_lifetime != LifetimeRef::new_static() ) os << "+" << e.m_lifetime; os << ")"; - ), - (ErasedType, + } + TU_ARM(m_data, ErasedType, e) { os << "impl "; for(const auto& tr : e.m_traits) { if( &tr != &e.m_traits[0] ) @@ -126,25 +126,25 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const if( e.m_lifetime != LifetimeRef::new_static() ) os << "+ '" << e.m_lifetime; os << "/*" << e.m_origin << "#" << e.m_index << "*/"; - ), - (Array, + } + TU_ARM(m_data, Array, e) { os << "[" << *e.inner << "; "; if( e.size_val != ~0u ) os << e.size_val; else os << "/*sz*/"; os << "]"; - ), - (Slice, + } + TU_ARM(m_data, Slice, e) { os << "[" << *e.inner << "]"; - ), - (Tuple, + } + TU_ARM(m_data, Tuple, e) { os << "("; for(const auto& t : e) os << t << ", "; os << ")"; - ), - (Borrow, + } + TU_ARM(m_data, Borrow, e) { switch(e.type) { case ::HIR::BorrowType::Shared: os << "&"; break; @@ -152,8 +152,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const case ::HIR::BorrowType::Owned: os << "&move "; break; } os << *e.inner; - ), - (Pointer, + } + TU_ARM(m_data, Pointer, e) { switch(e.type) { case ::HIR::BorrowType::Shared: os << "*const "; break; @@ -161,8 +161,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const case ::HIR::BorrowType::Owned: os << "*move "; break; } os << *e.inner; - ), - (Function, + } + TU_ARM(m_data, Function, e) { if( e.is_unsafe ) { os << "unsafe "; } @@ -173,8 +173,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const for(const auto& t : e.m_arg_types) os << t << ", "; os << ") -> " << *e.m_rettype; - ), - (Closure, + } + TU_ARM(m_data, Closure, e) { os << "closure["<<e.node<<"]"; /* os << "("; @@ -182,8 +182,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const os << t << ", "; os << ") -> " << *e.m_rettype; */ - ) - ) + } + } } bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 8a199557..6d2feaba 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -177,8 +177,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->get_lang_item_path(node.span(), lang_item); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index e7748115..a236c818 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -846,8 +846,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item); @@ -5294,7 +5294,6 @@ namespace { auto out_ty_o = impl.get_type(v.name.c_str()); if( out_ty_o == ::HIR::TypeRef() ) { - //BUG(sp, "Getting associated type '" << v.name << "' which isn't in " << v.trait << " (" << ty << ")"); out_ty_o = ::HIR::TypeRef(::HIR::Path( v.impl_ty.clone(), ::HIR::GenericPath(v.trait, v.params.clone()), v.name, ::HIR::PathParams() )); } out_ty_o = context.m_resolve.expand_associated_types(sp, mv$(out_ty_o)); @@ -5450,6 +5449,8 @@ namespace { if( TU_TEST1(impl_ty.m_data, Infer, .is_lit() == false) ) { DEBUG("Unbounded ivar, waiting - TODO: Add possibility " << impl_ty << " == " << possible_impl_ty); + context.possible_equate_type_coerce_to(impl_ty.m_data.as_Infer().index, possible_impl_ty); + context.possible_equate_type_coerce_from(impl_ty.m_data.as_Infer().index, possible_impl_ty); return false; } // Only one possible impl diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 6860de41..4d3ea82d 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -914,8 +914,8 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params); ), (ErasedType, + ASSERT_BUG(Span(), le.m_origin != ::HIR::SimplePath(), "Erased type with unset origin"); return H::compare_path(*this, le.m_origin, re.m_origin); - //TODO(Span(), "ErasedType"); ), (Tuple, return type_list_equal(*this, le, re); @@ -932,12 +932,17 @@ void TraitResolution::prep_indexes() static Span sp_AAA; const Span& sp = sp_AAA; + // TODO: Create a list of all known type rules in this scope (recursively) + // - What if there's recursive bounds (e.g. on ATYs) + auto add_equality = [&](::HIR::TypeRef long_ty, ::HIR::TypeRef short_ty){ DEBUG("[prep_indexes] ADD " << long_ty << " => " << short_ty); // TODO: Sort the two types by "complexity" (most of the time long >= short) this->m_type_equalities.insert(::std::make_pair( mv$(long_ty), mv$(short_ty) )); }; + // Obtain type equality bounds. + // TODO: Also flatten the bounds list into known trait bounds? this->iterate_bounds([&](const auto& b)->bool { if(const auto* bep = b.opt_TraitBound()) { @@ -1047,6 +1052,31 @@ bool TraitResolution::iterate_bounds( ::std::function<bool(const ::HIR::GenericB } return false; } +bool TraitResolution::iterate_bounds_traits(const Span& sp, ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::TraitPath& trait)> cb) const +{ + // Iterate all bounds, finding trait + return this->iterate_bounds([&](const auto& gb) { + if( const auto* be = gb.opt_TraitBound() ) + { + // TODO: Type filter (to avoid the cost of checking parent bounds) + if( cb(be->type, be->trait) ) + return true; + + assert(be->trait.m_trait_ptr); + const auto& trait_ref = *be->trait.m_trait_ptr; + auto monomorph_cb = monomorphise_type_get_cb(sp, &be->type, &be->trait.m_path.m_params, nullptr, nullptr); + for(const auto& parent_tp : trait_ref.m_all_parent_traits) + { + ::HIR::TraitPath tp_mono_o; + const auto& tp_mono = (monomorphise_traitpath_needed(parent_tp) ? tp_mono_o = monomorphise_traitpath_with(sp, parent_tp, monomorph_cb, false) : parent_tp); + // TODO: Monomorphise the bound + if( cb(be->type, tp_mono) ) + return true; + } + } + return false; + }); +} bool TraitResolution::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function<bool(const ::HIR::TraitPath&)> cb) const { ::HIR::GenericPath trait_path; @@ -2241,136 +2271,127 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple ) ) -#if 0 - if( m_ivars.get_type(type).m_data.is_Infer() ) - return false; - if( TU_TEST1(m_ivars.get_type(type).m_data, Path, .binding.is_Unbound()) ) - return false; -#endif + // NOTE: Even if the type is completely unknown (infer or unbound UFCS), search the bound list. // TODO: A bound can imply something via its associated types. How deep can this go? // E.g. `T: IntoIterator<Item=&u8>` implies `<T as IntoIterator>::IntoIter : Iterator<Item=&u8>` - return this->iterate_bounds([&](const auto& b)->bool { - DEBUG(b); - if( b.is_TraitBound() ) - { - const auto& e = b.as_TraitBound(); - const auto& b_params = e.trait.m_path.m_params; + // > Would maybe want a list of all explicit and implied bounds instead. + return this->iterate_bounds_traits(sp, [&](const auto& bound_ty, const ::HIR::TraitPath& bound_trait)->bool { + const auto& b_params = bound_trait.m_path.m_params; - auto cmp = e.type .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer()); - DEBUG("cmp = " << cmp); - if( cmp == ::HIR::Compare::Unequal ) - return false; + auto cmp = bound_ty .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer()); + DEBUG("cmp = " << cmp); + if( cmp == ::HIR::Compare::Unequal ) + return false; - if( e.trait.m_path.m_path == trait ) { - // Check against `params` - DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params); - auto ord = cmp; - ord &= this->compare_pp(sp, b_params, params); - if( ord == ::HIR::Compare::Unequal ) - return false; - if( ord == ::HIR::Compare::Fuzzy ) { - DEBUG("Fuzzy match"); - } - DEBUG("[find_trait_impls_bound] Match " << b); - // Hand off to the closure, and return true if it does - // TODO: The type bounds are only the types that are specified. - if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) { - return true; - } + if( bound_trait.m_path.m_path == trait ) { + // Check against `params` + DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params); + auto ord = cmp; + ord &= this->compare_pp(sp, b_params, params); + if( ord == ::HIR::Compare::Unequal ) + return false; + if( ord == ::HIR::Compare::Fuzzy ) { + DEBUG("Fuzzy match"); + } + DEBUG("[find_trait_impls_bound] Match " << bound_ty << " : " << bound_trait); + // Hand off to the closure, and return true if it does + // TODO: The type bounds are only the types that are specified. + auto b = bound_trait.clone(); + if( callback( ImplRef(bound_ty.clone(), mv$(b.m_path.m_params), mv$(b.m_type_bounds)), ord) ) { + return true; } + } - // TODO: Allow fuzzy equality? - if( cmp == ::HIR::Compare::Equal ) - { - // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set - // - XXX: This is actually wrong (false-positive) in many cases. FIXME - bool rv = this->find_named_trait_in_trait(sp, - trait,params, - *e.trait.m_trait_ptr, e.trait.m_path.m_path,e.trait.m_path.m_params, - type, - [&](const auto& ty, const auto& params, const auto& assoc) { - // TODO: Avoid duplicating this map every time - ::std::map< ::std::string,::HIR::TypeRef> assoc2; - for(const auto& i : assoc) { + // TODO: Allow fuzzy equality? + if( cmp == ::HIR::Compare::Equal ) + { + // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set + // - XXX: This is actually wrong (false-positive) in many cases. FIXME + bool rv = this->find_named_trait_in_trait(sp, + trait,params, + *bound_trait.m_trait_ptr, bound_trait.m_path.m_path,bound_trait.m_path.m_params, + type, + [&](const auto& ty, const auto& params, const auto& assoc) { + // TODO: Avoid duplicating this map every time + ::std::map< ::std::string,::HIR::TypeRef> assoc2; + for(const auto& i : assoc) { + assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); + } + for(const auto& i : bound_trait.m_type_bounds) { + // TODO: Only include from above when needed + //if( des_trait_ref.m_types.count(i.first) ) { assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); - } - for(const auto& i : e.trait.m_type_bounds) { - // TODO: Only include from above when needed - //if( des_trait_ref.m_types.count(i.first) ) { - assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); - //} - } - return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal ); - }); - if( rv ) { - return true; - } + //} + } + return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal ); + }); + if( rv ) { + return true; } + } - // If the input type is an associated type controlled by this trait bound, check for added bounds. - // TODO: This just checks a single layer, but it's feasable that there could be multiple layers - if( assoc_info && e.trait.m_path.m_path == assoc_info->trait.m_path && e.type == *assoc_info->type ) - { - // Check the trait params - auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params); - if( ord == ::HIR::Compare::Fuzzy ) { - //TODO(sp, "Handle fuzzy matches searching for associated type bounds"); - } - else if( ord == ::HIR::Compare::Unequal ) { - return false; - } - auto outer_ord = ord; + // If the input type is an associated type controlled by this trait bound, check for added bounds. + // TODO: This just checks a single layer, but it's feasable that there could be multiple layers + if( assoc_info && bound_trait.m_path.m_path == assoc_info->trait.m_path && bound_ty == *assoc_info->type ) + { + // Check the trait params + auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params); + if( ord == ::HIR::Compare::Fuzzy ) { + //TODO(sp, "Handle fuzzy matches searching for associated type bounds"); + } + else if( ord == ::HIR::Compare::Unequal ) { + return false; + } + auto outer_ord = ord; - const auto& trait_ref = *e.trait.m_trait_ptr; - const auto& at = trait_ref.m_types.at(assoc_info->item); - for(const auto& bound : at.m_trait_bounds) { - if( bound.m_path.m_path == trait ) - { - auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { - const auto& ge = gt.m_data.as_Generic(); - if( ge.binding == 0xFFFF ) { - return *assoc_info->type; - } - else { - if( ge.binding >= assoc_info->trait.m_params.m_types.size() ) - BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range"); - return assoc_info->trait.m_params.m_types[ge.binding]; - } - }; - - DEBUG("- Found an associated type bound for this trait via another bound"); - ::HIR::Compare ord = outer_ord; - if( monomorphise_pathparams_needed(bound.m_path.m_params) ) { - // TODO: Use a compare+callback method instead - auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false); - ord &= this->compare_pp(sp, b_params_mono, params); + const auto& trait_ref = *bound_trait.m_trait_ptr; + const auto& at = trait_ref.m_types.at(assoc_info->item); + for(const auto& bound : at.m_trait_bounds) { + if( bound.m_path.m_path == trait ) + { + auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& { + const auto& ge = gt.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + return *assoc_info->type; } else { - ord &= this->compare_pp(sp, bound.m_path.m_params, params); - } - if( ord == ::HIR::Compare::Unequal ) - return false; - if( ord == ::HIR::Compare::Fuzzy ) { - DEBUG("Fuzzy match"); + if( ge.binding >= assoc_info->trait.m_params.m_types.size() ) + BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range"); + return assoc_info->trait.m_params.m_types[ge.binding]; } + }; - auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false); - // - Expand associated types - for(auto& ty : tp_mono.m_type_bounds) { - ty.second = this->expand_associated_types(sp, mv$(ty.second)); - } - DEBUG("- tp_mono = " << tp_mono); - // TODO: Instead of using `type` here, build the real type - if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) { - return true; - } + DEBUG("- Found an associated type bound for this trait via another bound"); + ::HIR::Compare ord = outer_ord; + if( monomorphise_pathparams_needed(bound.m_path.m_params) ) { + // TODO: Use a compare+callback method instead + auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false); + ord &= this->compare_pp(sp, b_params_mono, params); + } + else { + ord &= this->compare_pp(sp, bound.m_path.m_params, params); + } + if( ord == ::HIR::Compare::Unequal ) + return false; + if( ord == ::HIR::Compare::Fuzzy ) { + DEBUG("Fuzzy match"); + } + + auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false); + // - Expand associated types + for(auto& ty : tp_mono.m_type_bounds) { + ty.second = this->expand_associated_types(sp, mv$(ty.second)); + } + DEBUG("- tp_mono = " << tp_mono); + // TODO: Instead of using `type` here, build the real type + if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) { + return true; } } } - - return false; } + return false; }); } @@ -3843,7 +3864,8 @@ bool TraitResolution::find_method(const Span& sp, // 2. Compare the receiver of the above to this type and the bound. if(const auto* self_ty = check_method_receiver(sp, *fcn_ptr, ty, access)) { - if( self_ty->m_data.is_Infer() ) + // If the type is an unbounded ivar, don't check. + if( TU_TEST1(self_ty->m_data, Infer, .is_lit() == false) ) return false; // TODO: Do a fuzzy match here? auto cmp = self_ty->compare_with_placeholders(sp, e.type, cb_infer); @@ -3864,7 +3886,17 @@ bool TraitResolution::find_method(const Span& sp, } else if( cmp == ::HIR::Compare::Fuzzy ) { - TODO(sp, "Fuzzy match checking bounded method - " << *self_ty << " != " << e.type); + DEBUG("Fuzzy match checking bounded method - " << *self_ty << " != " << e.type); + + // Found the method, return the UFCS path for it + possibilities.push_back(::std::make_pair( borrow_type, + ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ + box$( self_ty->clone() ), + mv$(final_trait_path), + method_name, + {} + }) ) )); + rv = true; } else { diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 7868b93f..cb95c94f 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -201,6 +201,7 @@ public: /// Iterate over in-scope bounds (function then top) bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const; + bool iterate_bounds_traits(const Span& sp, ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::TraitPath& trait)> cb) const; bool iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function<bool(const ::HIR::TraitPath&)> cb) const; typedef ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl; diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp index e8966b38..d2dc9fe6 100644 --- a/src/hir_typeck/impl_ref.cpp +++ b/src/hir_typeck/impl_ref.cpp @@ -219,8 +219,8 @@ bool ImplRef::type_is_specialisable(const char* name) const ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x) { - TU_MATCH(ImplRef::Data, (x.m_data), (e), - (TraitImpl, + TU_MATCH_HDR( (x.m_data), { ) + TU_ARM(x.m_data, TraitImpl, e) { if( e.impl == nullptr ) { os << "none"; } @@ -258,13 +258,16 @@ bool ImplRef::type_is_specialisable(const char* name) const } os << "}"; } - ), - (BoundedPtr, + } + TU_ARM(x.m_data, BoundedPtr, e) { + assert(e.type); + assert(e.trait_args); + assert(e.assoc); os << "bound (ptr) " << *e.type << " : ?" << *e.trait_args << " + {" << *e.assoc << "}"; - ), - (Bounded, + } + TU_ARM(x.m_data, Bounded, e) { os << "bound " << e.type << " : ?" << e.trait_args << " + {"<<e.assoc<<"}"; - ) - ) + } + } return os; } diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index bcc9eb3d..93dc6980 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -116,8 +116,11 @@ #define TU_IFLET(CLASS, VAR, TAG, NAME, ...) if(VAR.tag() == CLASS::TAG_##TAG) { auto& NAME = VAR.as_##TAG(); (void)&NAME; __VA_ARGS__ } +#define TU_MATCH_HDR(VARS, brace) TU_MATCH_HDR_(::std::remove_reference<decltype(TU_FIRST VARS)>::type, VARS, brace) +#define TU_MATCH_HDR_(CLASS, VARS, brace) switch( (TU_FIRST VARS).tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used"); + // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) +#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false) //#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST) #define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST) diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 86bbdddc..1bbafcd2 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1776,6 +1776,9 @@ namespace { }; TU_MATCHA( (lit), (e), (Invalid, m_of << "/* INVALID */"; ), + (Defer, + MIR_BUG(*m_mir_res, "Defer literal encountered"); + ), (List, m_of << "{"; if( ty.m_data.is_Array() ) @@ -5285,6 +5288,9 @@ namespace { (Invalid, m_of << "/* INVALID */"; ), + (Defer, + MIR_BUG(*m_mir_res, "Defer literal encountered"); + ), (List, if( ty.m_data.is_Array() ) { |