From 3a3f95d0c0b64ae2c5c702a50f6d26a35931bf48 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 14 May 2017 23:21:46 +0800 Subject: HIR Typecheck - Fix (hopefully) typeck errors in new libcollections --- src/hir_typeck/expr_cs.cpp | 72 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 10 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 12819251..52af3924 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -4986,8 +4986,28 @@ namespace { else { // No equivalence added } - // - Fall through and search for the impl - DEBUG("- Unsize, no ivar equivalence"); + + // TODO: If this was a compiler-inserted bound (from a coercion rule), then do deref checks +#if 0 + { + ::HIR::TypeRef tmp_ty; + const ::HIR::TypeRef* ty_ptr = &src_ty; + while( (ty_ptr = context.m_resolve.autoderef(sp, *ty_ptr, tmp_ty)) ) + { + const auto& cur_ty = context.m_ivars.get_type(*ty_ptr); + if( cur_ty.m_data.is_Infer() ) { + break; + } + auto cmp = dst_ty.compare_with_placeholders(sp, cur_ty, context.m_ivars.callback_resolve_infer()); + if( cmp != ::HIR::Compare::Unequal ) + { + // TODO: This is a deref coercion, so what can actually be done? + TODO(sp, "Handle Unsize with deref - " << src_ty << " -> " << dst_ty); + } + } + } +#endif + DEBUG("- Unsize, no deref or ivar"); } if( v.trait == context.m_crate.get_lang_item_path(sp, "coerce_unsized") ) { @@ -5052,7 +5072,7 @@ namespace { // > This makes `let v: usize = !0;` work without special cases auto cmp2 = v.left_ty.compare_with_placeholders(sp, out_ty, context.m_ivars.callback_resolve_infer()); if( cmp2 == ::HIR::Compare::Unequal ) { - DEBUG("- (fail) known result can't match (" << context.m_ivars.fmt_type(v.left_ty) << " and " << context.m_ivars.fmt_type(out_ty) << ")"); + DEBUG("[check_associated] - (fail) known result can't match (" << context.m_ivars.fmt_type(v.left_ty) << " and " << context.m_ivars.fmt_type(out_ty) << ")"); return false; } // if solid or fuzzy, leave as-is @@ -5071,9 +5091,10 @@ namespace { } else { count += 1; - DEBUG("- (possible) " << impl); + DEBUG("[check_associated] - (possible) " << impl); if( possible_impl_ty == ::HIR::TypeRef() ) { + DEBUG("[check_associated] First - " << impl); possible_impl_ty = impl.get_impl_type(); possible_params = impl.get_trait_params(); best_impl = mv$(impl); @@ -5084,27 +5105,33 @@ namespace { // NOTE: `overlaps_with` (should be) reflective else if( impl.overlaps_with(best_impl) ) { - DEBUG("- overlaps with " << best_impl); + DEBUG("[check_associated] - Overlaps with existing - " << best_impl); + // if not more specific than the existing best, ignore. if( ! impl.more_specific_than(best_impl) ) { - possible_impl_ty = impl.get_impl_type(); - possible_params = impl.get_trait_params(); - best_impl = mv$(impl); + // Ignore + DEBUG("[check_associated] - Less specific than existing"); count -= 1; } + // If the existing best is not more specific than the new one, use the new one else if( ! best_impl.more_specific_than(impl) ) { - // Ignore + DEBUG("[check_associated] - More specific than existing - " << impl); + possible_impl_ty = impl.get_impl_type(); + possible_params = impl.get_trait_params(); + best_impl = mv$(impl); count -= 1; } else { - DEBUG("> Neither is more specific. Error?"); + // Supposedly, `more_specific_than` should be reflexive... + DEBUG("[check_associated] > Neither is more specific. Error?"); } } else { // Disjoint impls. + DEBUG("[check_associated] Disjoint impl -" << impl); } #endif @@ -5680,6 +5707,31 @@ namespace { // TODO: Monomorphise this type replacing mentions of the current ivar with the replacement? +#if 0 // NOTE: The following shouldn't happen + if( bound.trait == context.m_crate.get_lang_item_path(sp, "unsize") /* && bound.is_from_coerce*/ ) + { + bool possible = false; + + ::HIR::TypeRef tmp_ty; + const ::HIR::TypeRef* ty_ptr = &new_ty; + while( (ty_ptr = context.m_resolve.autoderef(sp, *ty_ptr, tmp_ty)) ) + { + const auto& cur_ty = context.get_type(*ty_ptr); + if( cur_ty.m_data.is_Infer() ) { + break; + } + auto cmp = ty_l.compare_with_placeholders(sp, cur_ty, context.m_ivars.callback_resolve_infer()); + if( cmp != ::HIR::Compare::Unequal ) + { + possible = true; + break; + } + } + if( possible ) + continue ; + } +#endif + // Search for any trait impl that could match this, bool has = context.m_resolve.find_trait_impls(sp, bound.trait, bound.params, new_ty, [&](const auto , auto){return true;}); if( !has ) { -- cgit v1.2.3 From 8436f719096c37de5828608df3bc881809678037 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 15 May 2017 15:21:16 +0800 Subject: HIR Typecheck - Handling of implicit Sized bound when searching for impls --- src/hir_typeck/expr_check.cpp | 3 ++ src/hir_typeck/helpers.cpp | 101 ++++++++++++++++++++++++++++++++++-------- src/hir_typeck/helpers.hpp | 2 + 3 files changed, 88 insertions(+), 18 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 614d52f4..9e369e61 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -748,6 +748,9 @@ namespace { cache.m_monomorph_cb = mv$(monomorph_cb); // Bounds + for(size_t i = 0; i < cache.m_fcn_params->m_types.size(); i ++) + { + } for(const auto& bound : cache.m_fcn_params->m_bounds) { TU_MATCH(::HIR::GenericBound, (bound), (be), diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 60210867..e257d154 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1078,25 +1078,13 @@ bool TraitResolution::find_trait_impls(const Span& sp, const auto& trait_indexmut = this->m_crate.get_lang_item_path(sp, "index_mut"); if( trait == lang_Sized ) { - TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (e), - ( - // Any unknown - it's sized - ), - (Primitive, - if( e == ::HIR::CoreType::Str ) - return false; - ), - (Slice, - return false; - ), - (Path, - // ... TODO (Search the innards or bounds) - ), - (TraitObject, + auto cmp = type_is_sized(sp, type); + if( cmp != ::HIR::Compare::Unequal ) { + return callback( ImplRef(&type, &null_params, &null_assoc), cmp ); + } + else { return false; - ) - ) - return callback( ImplRef(&type, &null_params, &null_assoc), ::HIR::Compare::Equal ); + } } if( trait == lang_Copy ) { @@ -2813,6 +2801,23 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ) } + for(size_t i = 0; i < impl_params_def.m_types.size(); i ++) + { + if( impl_params_def.m_types.at(i).m_is_sized ) + { + if( impl_params[i] ) { + auto cmp = type_is_sized(sp, *impl_params[i]); + if( cmp == ::HIR::Compare::Unequal ) + { + return ::HIR::Compare::Unequal; + } + } + else { + // TODO: Set match to fuzzy? + } + } + } + return match; } @@ -2909,6 +2914,66 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa return false; } +::HIR::Compare TraitResolution::type_is_sized(const Span& sp, const ::HIR::TypeRef& type) const +{ + TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (e), + ( + // Any unknown - it's sized + ), + (Infer, + switch(e.ty_class) + { + case ::HIR::InferClass::Integer: + case ::HIR::InferClass::Float: + return ::HIR::Compare::Equal; + default: + return ::HIR::Compare::Fuzzy; + } + ), + (Primitive, + if( e == ::HIR::CoreType::Str ) + return ::HIR::Compare::Unequal; + ), + (Slice, + return ::HIR::Compare::Unequal; + ), + (Path, + // ... TODO (Search the innards or bounds) + TU_MATCHA( (e.binding), (pb), + (Unbound, + // + ), + (Opaque, + // TODO: Check bounds + ), + (Enum, + // HAS to be Sized + ), + (Union, + // Pretty sure unions are Sized + ), + (Struct, + // Possibly not sized + switch( pb->m_markings.dst_type ) + { + case ::HIR::TraitMarkings::DstType::None: + break; + case ::HIR::TraitMarkings::DstType::Possible: + // TODO: Check sized-ness of the unsized param/field + break; + case ::HIR::TraitMarkings::DstType::Slice: + case ::HIR::TraitMarkings::DstType::TraitObject: + return ::HIR::Compare::Unequal; + } + ) + ) + ), + (TraitObject, + return ::HIR::Compare::Unequal; + ) + ) + return ::HIR::Compare::Equal; +} ::HIR::Compare TraitResolution::type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const { const auto& type = this->m_ivars.get_type(ty); diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index b7e6ca38..d715905c 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -265,7 +265,9 @@ public: bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, AllowedReceivers ar, ::HIR::GenericPath& out_path) const; bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; + ::HIR::Compare type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const; ::HIR::Compare type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const; + // If `new_type_callback` is populated, it will be called with the actual/possible dst_type // If `infer_callback` is populated, it will be called when either side is an ivar ::HIR::Compare can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty, const ::HIR::TypeRef& src_ty, ::std::function new_type_callback) const { -- cgit v1.2.3 From 08c7a7e2cb1b8b137a252edf0c615cd81477adf8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 15 May 2017 16:19:51 +0800 Subject: HIR Typecheck - Fix greedily picking the most specific impl when typechecking --- src/hir_typeck/expr_cs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 52af3924..7c73644d 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -5109,17 +5109,17 @@ namespace { // if not more specific than the existing best, ignore. if( ! impl.more_specific_than(best_impl) ) { - // Ignore DEBUG("[check_associated] - Less specific than existing"); + // NOTE: This picks the _least_ specific impl + possible_impl_ty = impl.get_impl_type(); + possible_params = impl.get_trait_params(); + best_impl = mv$(impl); count -= 1; } // If the existing best is not more specific than the new one, use the new one else if( ! best_impl.more_specific_than(impl) ) { DEBUG("[check_associated] - More specific than existing - " << impl); - possible_impl_ty = impl.get_impl_type(); - possible_params = impl.get_trait_params(); - best_impl = mv$(impl); count -= 1; } else -- cgit v1.2.3 From 52f6e3d1c2fa705a5160219b764ec508da338fa8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 16 May 2017 21:02:20 +0800 Subject: HIR Typecheck - Tweaks --- src/hir_typeck/expr_cs.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 7c73644d..605df162 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1208,7 +1208,7 @@ namespace { } des_ty = &des_ty_cache; } - this->equate_types_inner_coerce(node.span(), *des_ty, val.second); + this->context.equate_types_coerce(node.span(), *des_ty, val.second); } // Convert bounds on the type into rules @@ -3466,7 +3466,8 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type context.equate_types(sp, type, ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::TypeRef(::HIR::CoreType::Str) )); ), (ByteString, - context.equate_types(sp, type, ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::TypeRef::new_slice(::HIR::CoreType::U8) )); + // NOTE: Matches both &[u8] and &[u8; N], so doesn't provide type information + // TODO: Check the type. ), (Named, // TODO: Get type of the value and equate it -- cgit v1.2.3 From 1b8e9e01a8ebce42e8ad3dca101180430b28c947 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 26 May 2017 14:22:00 +0800 Subject: HIR Typecheck - Handle struct syntax for unit structs --- src/hir_typeck/expr_check.cpp | 8 ++++++++ src/hir_typeck/expr_cs.cpp | 23 +++++++++++++++++++++-- src/mir/from_hir.cpp | 8 ++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 9e369e61..d0fe6a5d 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -473,6 +473,14 @@ namespace { TODO(sp, "Union in StructLiteral"); ), (Struct, + if( e->m_data.is_Unit() ) + { + ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like struct"); + ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like struct"); + return ; + } + + ASSERT_BUG(node.span(), e->m_data.is_Named(), "StructLiteral not pointing to a braced struct, instead " << e->m_data.tag_str() << " - " << ty); fields_ptr = &e->m_data.as_Named(); ) ) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 605df162..5c69e20b 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1162,6 +1162,14 @@ namespace { TODO(node.span(), "StructLiteral of a union - " << ty); ), (Struct, + if( e->m_data.is_Unit() ) + { + ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like struct"); + ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like struct"); + return ; + } + + ASSERT_BUG(node.span(), e->m_data.is_Named(), "StructLiteral not pointing to a braced struct, instead " << e->m_data.tag_str() << " - " << ty); fields_ptr = &e->m_data.as_Named(); generics = &e->m_params; ) @@ -4200,7 +4208,7 @@ namespace { //} context.possible_equate_type_unsize_to(r_e.index, ty_dst); context.possible_equate_type_unsize_from(l_e.index, ty_src); - DEBUG("- Infer, add possibility"); + DEBUG("- Both infer, add possibility"); return false; } @@ -4232,8 +4240,16 @@ namespace { return true; } + // If the source can't unsize, equate + if( const auto* te = ty_src.m_data.opt_Slice() ) + { + (void)te; + context.equate_types(sp, ty_dst, ty_src); + return true; + } + context.possible_equate_type_unsize_from(l_e.index, ty_src); - DEBUG("- Infer, add possibility"); + DEBUG("- Dest infer, add possibility"); return false; ) @@ -4781,12 +4797,15 @@ namespace { } // TODO: Can this can unsize as well as convert to raw? + // - It _can_ unsize, TODO: context.equate_types(sp, *l_e.inner, *s_e.inner); // Add downcast auto span = node_ptr->span(); node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst.clone() )); node_ptr->m_res_type = ty_dst.clone(); + // TODO: Add a coerce of src->&dst_inner + context.m_ivars.mark_change(); return true; ) diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index cb9b5771..6b756952 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2091,6 +2091,14 @@ namespace { BUG(node.span(), "_StructLiteral Union"); ), (Struct, + if(e->m_data.is_Unit()) { + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + node.m_path.clone(), + variant_index, + {} + }) ); + return ; + } fields_ptr = &e->m_data.as_Named(); ) ) -- cgit v1.2.3 From 1ca60578426833dfcfda6ecfa7ef67e31f5d6a85 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 26 May 2017 14:52:11 +0800 Subject: Typecheck Expr - Fix a place where literals can become trait objects --- Makefile | 6 ++---- src/hir_typeck/expr_cs.cpp | 31 ++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src/hir_typeck') diff --git a/Makefile b/Makefile index cec1790b..67f25c5d 100644 --- a/Makefile +++ b/Makefile @@ -396,16 +396,13 @@ DISABLED_TESTS += run-pass/issue-7784 # PartialEq impl and deref DISABLED_TESTS += run-pass/traits-issue-26339 # ^ DISABLED_TESTS += run-pass/builtin-superkinds-self-type # ^ DISABLED_TESTS += run-pass/intrinsic-move-val # ^ -DISABLED_TESTS += run-pass/issue-9951 # Trait impled for i32 -DISABLED_TESTS += run-pass/trait-default-method-xc # ^ -DISABLED_TESTS += run-pass/trait-impl # ^ +DISABLED_TESTS += run-pass/trait-default-method-xc # Trait impled for i32 DISABLED_TESTS += run-pass/issue-11205 # ^ DISABLED_TESTS += run-pass/mir_coercions # Coercion to unsafe fn DISABLED_TESTS += run-pass/typeck-fn-to-unsafe-fn-ptr # ^ DISABLED_TESTS += run-pass/unsafe-coercion # ^ DISABLED_TESTS += run-pass/mir_misc_casts # Cast fn to *const isize DISABLED_TESTS += run-pass/never-result # ! not correctly unifiying -DISABLED_TESTS += run-pass/reachable-unnameable-items # assert Struct::is_Named() DISABLED_TESTS += run-pass/self-impl # Unable to infer DISABLED_TESTS += run-pass/trait-copy-guessing # ^ DISABLED_TESTS += run-pass/issue-20575 # ^ @@ -711,6 +708,7 @@ DISABLED_TESTS += run-pass/unwind-resource DISABLED_TESTS += run-pass/unwind-unique DISABLED_TESTS += run-pass/vector-sort-panic-safe DISABLED_TESTS += run-pass/dynamic-drop +DISABLED_TESTS += run-pass/reachable-unnameable-items # - Misc DISABLED_TESTS += run-pass/issue-16671 # Blocks forever DISABLED_TESTS += run-pass/issue-13027 # Infinite loop (match?) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 5c69e20b..ac2cf511 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -4214,16 +4214,29 @@ namespace { // If the source is '_', we can't know yet TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Infer, r_e, - // TODO: If the source is a literal, and the destination isn't a TraitObject, equate. - // - Except if it's known to be a primitive - //if( r_e.ty_class != ::HIR::InferClass::None ) { - // context.equate_types(sp, ty_dst, ty_src); - // return true; - //} - context.possible_equate_type_unsize_to(r_e.index, ty_dst); - DEBUG("- Infer, add possibility"); - return false; + // No avaliable information, add a possible unsize + if( r_e.ty_class == ::HIR::InferClass::None || r_e.ty_class == ::HIR::InferClass::Diverge ) + { + // Possibility + context.possible_equate_type_unsize_to(r_e.index, ty_dst); + DEBUG("- Infer, add possibility"); + return false; + } + // Destination is infer, fall through to next TU_IFLET + else if( ty_dst.m_data.is_Infer() ) + { + } + // Destination is a TraitObject, fall through to doing an impl search + else if( ty_dst.m_data.is_TraitObject() ) + { + } + // Otherwise, they have to be equal + else + { + context.equate_types(sp, ty_dst, ty_src); + return true; + } ) TU_IFLET(::HIR::TypeRef::Data, ty_dst.m_data, Infer, l_e, -- cgit v1.2.3 From f56c30f45738698fc791f5e33d7203c9421b121b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 28 May 2017 12:16:43 +0800 Subject: Typecheck Expressions - Fix some places where ivars don't have indexes --- Makefile | 11 +++-------- src/hir_typeck/expr_cs.cpp | 2 ++ src/hir_typeck/helpers.cpp | 11 ++++++++++- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'src/hir_typeck') diff --git a/Makefile b/Makefile index 67f25c5d..3c164dcb 100644 --- a/Makefile +++ b/Makefile @@ -413,14 +413,8 @@ DISABLED_TESTS += run-pass/variadic-ffi # variadics not supported DISABLED_TESTS += run-pass/weird-exprs # Line 17, let _ = return; result type DISABLED_TESTS += run-pass/where-for-self # Failed deref coercion? DISABLED_TESTS += run-pass/union/union-backcomp # ? discarded value? -# - Typecheck - `_` type with no ivar index assigned -DISABLED_TESTS += run-pass/coerce-expect-unsized -DISABLED_TESTS += run-pass/coerce-unify-return -DISABLED_TESTS += run-pass/issue-23485 -DISABLED_TESTS += run-pass/issue-26805 -DISABLED_TESTS += run-pass/match-vec-alternatives -DISABLED_TESTS += run-pass/pure-sum -DISABLED_TESTS += run-pass/struct-aliases +DISABLED_TESTS += run-pass/coerce-expect-unsized # Can't infer ivar in associated +DISABLED_TESTS += run-pass/issue-26805 # ^ # - Lazy (Typecheck - Leftover rules) DISABLED_TESTS += run-pass/regions-infer-borrow-scope-addr-of # Didn't unify literal ivar DISABLED_TESTS += run-pass/swap-2 # ^ @@ -449,6 +443,7 @@ DISABLED_TESTS += run-pass/mir_build_match_comparisons # - ^ DISABLED_TESTS += run-pass/issue-18352 # - ^ DISABLED_TESTS += run-pass/issue-13620 # - Todo in cleanup of dependency DISABLED_TESTS += run-pass/vec-matching-fold # todo: Match SplitSlice with tailing (rule gen) +DISABLED_TESTS += run-pass/match-vec-alternatives # & DISABLED_TESTS += run-pass/issue-17877 # - SplitSlice + array DISABLED_TESTS += run-pass/vec-matching-fixed # ^ DISABLED_TESTS += run-pass/vec-tail-matching # SplitSlice destructure array diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index ac2cf511..5597b022 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1061,6 +1061,7 @@ namespace { for( auto& val : node.m_args ) { this->context.add_ivars( val->m_res_type ); } + this->context.m_ivars.add_ivars_params(node.m_path.m_params); // - Create ivars in path, and set result type const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path); @@ -1131,6 +1132,7 @@ namespace { void visit(::HIR::ExprNode_StructLiteral& node) override { TRACE_FUNCTION_F(&node << " " << node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]"); + this->add_ivars_generic_path(node.span(), node.m_path); for( auto& val : node.m_values ) { this->context.add_ivars( val.second->m_res_type ); } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index e257d154..b60b03c8 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -468,6 +468,8 @@ void HMTypeInferrence::add_ivars(::HIR::TypeRef& type) (TraitObject, // Iterate all paths this->add_ivars_params(e.m_trait.m_path.m_params); + for(auto& aty : e.m_trait.m_type_bounds) + this->add_ivars(aty.second); for(auto& marker : e.m_markers) this->add_ivars_params(marker.m_params); ), @@ -2142,7 +2144,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple if( e.trait.m_path.m_path == trait ) { // Check against `params` - DEBUG("Checking " << params << " vs " << b_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 ) @@ -2150,6 +2152,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple 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) ) { @@ -3361,6 +3364,12 @@ const ::HIR::TypeRef* TraitResolution::autoderef(const Span& sp, const ::HIR::Ty else { bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "deref"), ::HIR::PathParams {}, ty, [&](auto impls, auto match) { tmp_type = impls.get_type("Target"); + if( tmp_type == ::HIR::TypeRef() ) + { + tmp_type = ::HIR::Path( ty.clone(), this->m_crate.get_lang_item_path(sp, "deref"), "Target" ); + tmp_type.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); + } + DEBUG("Deref " << ty << " into " << tmp_type); return true; }); if( succ ) { -- cgit v1.2.3 From 6f45483d70b7da92adec01ab67f5c7450c421801 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 2 Jun 2017 12:12:59 +0800 Subject: Tweaks to handling of struct patterns --- src/hir_conv/bind.cpp | 30 +++++++++++++++++------------- src/hir_typeck/expr_cs.cpp | 23 ++++++++++++++++++++--- src/parse/root.cpp | 4 ++++ 3 files changed, 41 insertions(+), 16 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index c7a0829a..cf443eb6 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -248,37 +248,41 @@ namespace { (Struct, const auto& str = get_struct_ptr(sp, m_crate, e.path); if(str.m_data.is_Named() ) { - e.binding = &str; } else if( str.m_data.is_Unit() && e.sub_patterns.size() == 0 ) { - e.binding = &str; + } + else if( str.m_data.is_Tuple() && str.m_data.as_Tuple().empty() && e.sub_patterns.size() == 0 ) { } else { - ERROR(sp, E0000, "Struct pattern on field-less struct " << e.path); + ERROR(sp, E0000, "Struct pattern `" << pat << "` on field-less struct " << e.path); } + e.binding = &str; ), (EnumTuple, auto p = get_enum_ptr(sp, m_crate, e.path); const auto& var = p.first->m_variants[p.second].second; - TU_IFLET(::HIR::Enum::Variant, var, Tuple, _, - e.binding_ptr = p.first; - e.binding_idx = p.second; - ) + if( var.is_Tuple() ) { + } else { ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); } + e.binding_ptr = p.first; + e.binding_idx = p.second; ), (EnumStruct, auto p = get_enum_ptr(sp, m_crate, e.path); const auto& var = p.first->m_variants[p.second].second; - TU_IFLET(::HIR::Enum::Variant, var, Struct, _, - // All good - e.binding_ptr = p.first; - e.binding_idx = p.second; - ) + if( var.is_Struct() ) { + } + else if( var.is_Unit() && e.sub_patterns.empty() ) { + } + else if( var.is_Tuple() && var.as_Tuple().empty() && e.sub_patterns.empty() ) { + } else { - ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); + ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); } + e.binding_ptr = p.first; + e.binding_idx = p.second; ) ) } diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 5597b022..fb56abc4 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1157,6 +1157,12 @@ namespace { const auto& enm = *e; auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; }); assert(it != enm.m_variants.end()); + if( it->second.is_Unit() || it->second.is_Value() || it->second.is_Tuple() ) { + ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like variant"); + ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like variant"); + return ; + } + ASSERT_BUG(node.span(), it->second.is_Struct(), "_StructLiteral for non-struct variant - " << node.m_path); fields_ptr = &it->second.as_Struct(); generics = &enm.m_params; ), @@ -1164,10 +1170,14 @@ namespace { TODO(node.span(), "StructLiteral of a union - " << ty); ), (Struct, - if( e->m_data.is_Unit() ) + if( e->m_data.is_Unit() || e->m_data.is_Tuple() ) { ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like struct"); - ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like struct"); + + if( node.m_base_value ) { + auto _ = this->push_inner_coerce_scoped(false); + node.m_base_value->visit( *this ); + } return ; } @@ -3817,10 +3827,14 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type this->add_ivars_params( e.path.m_params ); this->equate_types( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); + if( e.sub_patterns.empty() ) + return ; + assert(e.binding); const auto& str = *e.binding; + // - assert check from earlier pass - assert( str.m_data.is_Named() ); + ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct"); const auto& sd = str.m_data.as_Named(); const auto& params = e.path.m_params; @@ -3893,6 +3907,9 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type this->equate_types( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); } + if( e.sub_patterns.empty() ) + return ; + assert(e.binding_ptr); const auto& enm = *e.binding_ptr; const auto& var = enm.m_variants[e.binding_idx].second; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2dc2ffc4..5f8ed0a3 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -824,6 +824,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) CHECK_TOK(tok, TOK_IDENT); ::std::string name = mv$(tok.str()); + // Tuple-like variants if( GET_TOK(tok, lex) == TOK_PAREN_OPEN ) { ::std::vector types; @@ -850,6 +851,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) GET_TOK(tok, lex); variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) ); } + // Struct-like variants else if( tok.type() == TOK_BRACE_OPEN ) { ::std::vector<::AST::StructItem> fields; @@ -880,12 +882,14 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) ); } + // Value variants else if( tok.type() == TOK_EQUAL ) { auto node = Parse_Expr(lex); variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) ); GET_TOK(tok, lex); } + // Unit variants else { variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), ::AST::Expr()) ); -- cgit v1.2.3 From 4102dd960cdbd1a3c377ed8d02d0ee47f3ee9d92 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 3 Jun 2017 11:56:08 +0800 Subject: HIR Typecheck - Validate traits after typecheck --- src/hir_expand/closures.cpp | 1 + src/hir_typeck/expr_check.cpp | 61 ++++++++--- src/hir_typeck/static.cpp | 237 +++++++++++++++++++++++++++++++++++++++++- src/hir_typeck/static.hpp | 2 + src/mir/mir_builder.cpp | 2 + 5 files changed, 286 insertions(+), 17 deletions(-) (limited to 'src/hir_typeck') diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 180ed89a..5b4fd722 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -151,6 +151,7 @@ namespace { if( binding_it->second != ::HIR::ValueUsage::Move ) { auto bt = (binding_it->second == ::HIR::ValueUsage::Mutate ? ::HIR::BorrowType::Unique : ::HIR::BorrowType::Shared); + visit_type(m_replacement->m_res_type); m_replacement->m_res_type = ::HIR::TypeRef::new_borrow( bt, mv$(m_replacement->m_res_type) ); m_replacement = NEWNODE(node.m_res_type.clone(), Deref, node.span(), mv$(m_replacement)); } diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index d0fe6a5d..66fdcb14 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -22,12 +22,15 @@ namespace { const ::HIR::TypeRef& ret_type; ::std::vector< const ::HIR::TypeRef*> closure_ret_types; + ::HIR::SimplePath m_lang_Index; + public: ExprVisitor_Validate(const StaticTraitResolve& res, const t_args& args, const ::HIR::TypeRef& ret_type): m_resolve(res), //m_args(args), ret_type(ret_type) { + m_lang_Index = m_resolve.m_crate.get_lang_item_path_opt("index"); } void visit_root(::HIR::ExprPtr& node_ptr) @@ -255,8 +258,7 @@ namespace { { TRACE_FUNCTION_F(&node << " ... [ ... ]"); check_associated_type(node.span(), - node.m_res_type, - this->get_lang_item_path(node.span(), "index"), { node.m_index->m_res_type.clone() }, node.m_value->m_res_type, "Target" + node.m_res_type, m_lang_Index, { node.m_index->m_res_type.clone() }, node.m_value->m_res_type, "Target" ); node.m_value->visit( *this ); @@ -333,7 +335,10 @@ namespace { const auto& src_ty = node.m_value->m_res_type; const auto& dst_ty = node.m_res_type; - if( src_ty.m_data.is_Borrow() && dst_ty.m_data.is_Borrow() ) + if( src_ty == dst_ty ) + { + } + else if( src_ty.m_data.is_Borrow() && dst_ty.m_data.is_Borrow() ) { const auto& se = src_ty.m_data.as_Borrow(); const auto& de = dst_ty.m_data.as_Borrow(); @@ -363,10 +368,20 @@ namespace { void visit(::HIR::ExprNode_Deref& node) override { TRACE_FUNCTION_F(&node << " *..."); - check_associated_type(node.span(), - node.m_res_type, - this->get_lang_item_path(node.span(), "deref"), {}, node.m_value->m_res_type, "Target" - ); + const auto& ty = node.m_value->m_res_type; + + if( ty.m_data.is_Pointer() ) { + check_types_equal(node.span(), node.m_res_type, *ty.m_data.as_Pointer().inner); + } + else if( ty.m_data.is_Borrow() ) { + check_types_equal(node.span(), node.m_res_type, *ty.m_data.as_Borrow().inner); + } + else { + check_associated_type(node.span(), + node.m_res_type, + this->get_lang_item_path(node.span(), "deref"), {}, node.m_value->m_res_type, "Target" + ); + } node.m_value->visit( *this ); } @@ -768,7 +783,10 @@ namespace { ), (TraitBound, auto real_type = monomorphise_type_with(sp, be.type, cache.m_monomorph_cb); + m_resolve.expand_associated_types(sp, real_type); auto real_trait = monomorphise_genericpath_with(sp, be.trait.m_path, cache.m_monomorph_cb, false); + for(auto& t : real_trait.m_params.m_types) + m_resolve.expand_associated_types(sp, t); DEBUG("Bound " << be.type << ": " << be.trait); DEBUG("= (" << real_type << ": " << real_trait << ")"); const auto& trait_params = real_trait.m_params; @@ -783,6 +801,7 @@ namespace { ASSERT_BUG(sp, has_ty, "Type " << assoc.first << " not found in chain of " << real_trait); auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true); + m_resolve.expand_associated_types(sp, other_ty); check_associated_type(sp, other_ty, type_trait_path.m_path, type_trait_path.m_params, real_type, assoc.first.c_str()); } @@ -1047,10 +1066,29 @@ namespace { const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& ity, const char* name ) const { - // TODO: Actually check. - #if 0 - bool found = m_resolve.find_impl(sp, trait, ¶ms, ity, [&](auto impl, bool fuzzy){ - + if( trait == m_lang_Index && ity.m_data.is_Array() ) { + if(name) + { + if( res != *ity.m_data.as_Array().inner ) { + ERROR(sp, E0000, "Associated type on " << trait << params << " for " << ity << " doesn't match - " << res << " != " << *ity.m_data.as_Array().inner); + } + } + return ; + } + bool found = m_resolve.find_impl(sp, trait, ¶ms, ity, [&](auto impl, bool fuzzy) { + if( name ) + { + auto atyv = impl.get_type(name); + m_resolve.expand_associated_types(sp, atyv); + if( atyv == ::HIR::TypeRef() ) + { + // TODO: Check that `res` is ::name + } + else if( res != atyv ) + { + ERROR(sp, E0000, "Associated type on " << trait << params << " for " << ity << " doesn't match - " << res << " != " << atyv); + } + } return true; }); @@ -1058,7 +1096,6 @@ namespace { { ERROR(sp, E0000, "Cannot find an impl of " << trait << params << " for " << ity); } - #endif } const ::HIR::SimplePath& get_lang_item_path(const Span& sp, const char* name) const diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 83299909..b46567fd 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -109,11 +109,13 @@ bool StaticTraitResolve::find_impl( return found_cb( ImplRef(&type, &null_params, &null_assoc), false ); } } - //else if( trait_path == m_lang_Unsize ) { - // if( true ) { - // return found_cb( ImplRef(&type, &null_params, &null_assoc), false ); - // } - //} + else if( trait_path == m_lang_Unsize ) { + ASSERT_BUG(sp, trait_params, "TODO: Support no params for Unzie"); + const auto& dst_ty = trait_params->m_types.at(0); + if( this->can_unsize(sp, dst_ty, type) ) { + return found_cb( ImplRef(&type, trait_params, &null_assoc), false ); + } + } } // --- MAGIC IMPLS --- @@ -1177,6 +1179,43 @@ bool StaticTraitResolve::iterate_bounds( ::std::function cb) const +{ + const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path); + ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item); + const auto& aty_def = trait_ref.m_types.find(pe.item)->second; + + for(const auto& bound : aty_def.m_trait_bounds) + { + if( cb(bound) ) + return true; + } + // Search `::Name` bounds on the trait itself + for(const auto& bound : trait_ref.m_params.m_bounds) + { + if( ! bound.is_TraitBound() ) continue ; + const auto& be = bound.as_TraitBound(); + + if( ! be.type.m_data.is_Path() ) continue ; + if( ! be.type.m_data.as_Path().binding.is_Opaque() ) continue ; + + const auto& be_type_pe = be.type.m_data.as_Path().path.m_data.as_UfcsKnown(); + if( *be_type_pe.type != ::HIR::TypeRef("Self", 0xFFFF) ) + continue ; + if( be_type_pe.trait.m_path != pe.trait.m_path ) + continue ; + if( be_type_pe.item != pe.item ) + continue ; + + if( cb(be.trait) ) + return true; + } + + return false; +} + // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- @@ -1408,6 +1447,194 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) throw ""; } +bool StaticTraitResolve::can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty, const ::HIR::TypeRef& src_ty) const +{ + TRACE_FUNCTION_F(dst_ty << " <- " << src_ty); + + ASSERT_BUG(sp, !dst_ty.m_data.is_Infer(), "_ seen after inferrence - " << dst_ty); + ASSERT_BUG(sp, !src_ty.m_data.is_Infer(), "_ seen after inferrence - " << src_ty); + + { + //ASSERT_BUG(sp, dst_ty != src_ty, "Equal types for can_unsize - " << dst_ty << " <-" << src_ty ); + if( dst_ty == src_ty ) + return true; + } + + { + bool found_bound = this->iterate_bounds([&](const auto& gb){ + if(!gb.is_TraitBound()) + return false; + const auto& be = gb.as_TraitBound(); + if(be.trait.m_path.m_path != m_lang_Unsize) + return false; + const auto& be_dst = be.trait.m_path.m_params.m_types.at(0); + + if( src_ty != be.type ) return false; + if( dst_ty != be_dst ) return false; + return true; + }); + if( found_bound ) + { + return ::HIR::Compare::Equal; + } + } + + // Associated types, check the bounds in the trait. + if( src_ty.m_data.is_Path() && src_ty.m_data.as_Path().path.m_data.is_UfcsKnown() ) + { + const auto& pe = src_ty.m_data.as_Path().path.m_data.as_UfcsKnown(); + auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr); + auto found_bound = this->iterate_aty_bounds(sp, pe, [&](const ::HIR::TraitPath& bound) { + if( bound.m_path.m_path != m_lang_Unsize ) + return false; + const auto& be_dst_tpl = bound.m_path.m_params.m_types.at(0); + ::HIR::TypeRef tmp_ty; + const auto& be_dst = (monomorphise_type_needed(be_dst_tpl) ? tmp_ty = monomorphise_type_with(sp, be_dst_tpl, monomorph_cb) : be_dst_tpl); + + if( dst_ty != be_dst ) return false; + return true; + }); + if( found_bound ) + { + return true; + } + } + + // Struct<..., T, ...>: Unsize> + if( dst_ty.m_data.is_Path() && src_ty.m_data.is_Path() ) + { + bool dst_is_unsizable = dst_ty.m_data.as_Path().binding.is_Struct() && dst_ty.m_data.as_Path().binding.as_Struct()->m_markings.can_unsize; + bool src_is_unsizable = src_ty.m_data.as_Path().binding.is_Struct() && src_ty.m_data.as_Path().binding.as_Struct()->m_markings.can_unsize; + if( dst_is_unsizable || src_is_unsizable ) + { + DEBUG("Struct unsize? " << dst_ty << " <- " << src_ty); + const auto& str = *dst_ty.m_data.as_Path().binding.as_Struct(); + const auto& dst_gp = dst_ty.m_data.as_Path().path.m_data.as_Generic(); + const auto& src_gp = src_ty.m_data.as_Path().path.m_data.as_Generic(); + + if( dst_gp == src_gp ) + { + DEBUG("Can't Unsize, destination and source are identical"); + return false; + } + else if( dst_gp.m_path == src_gp.m_path ) + { + DEBUG("Checking for Unsize " << dst_gp << " <- " << src_gp); + // Structures are equal, add the requirement that the ?Sized parameter also impl Unsize + const auto& dst_inner = dst_gp.m_params.m_types.at(str.m_markings.unsized_param); + const auto& src_inner = src_gp.m_params.m_types.at(str.m_markings.unsized_param); + return this->can_unsize(sp, dst_inner, src_inner); + } + else + { + DEBUG("Can't Unsize, destination and source are different structs"); + return false; + } + } + } + + // (Trait) <- Foo + if( const auto* de = dst_ty.m_data.opt_TraitObject() ) + { + // TODO: Check if src_ty is !Sized + // - Only allowed if the source is a trait object with the same data trait and lesser bounds + + DEBUG("TraitObject unsize? " << dst_ty << " <- " << src_ty); + + // (Trait) <- (Trait+Foo) + if( const auto* se = src_ty.m_data.opt_TraitObject() ) + { + // 1. Data trait must be the same + if( de->m_trait != se->m_trait ) + { + return ::HIR::Compare::Unequal; + } + + // 2. Destination markers must be a strict subset + for(const auto& mt : de->m_markers) + { + bool found = false; + for(const auto& omt : se->m_markers) { + if( omt == mt ) { + found = true; + break; + } + } + if( !found ) { + // Return early. + return false; + } + } + + return true; + } + + bool good; + + ::HIR::TypeRef::Data::Data_TraitObject tmp_e; + tmp_e.m_trait.m_path = de->m_trait.m_path.m_path; + + // Check data trait first. + if( de->m_trait.m_path.m_path == ::HIR::SimplePath() ) { + ASSERT_BUG(sp, de->m_markers.size() > 0, "TraitObject with no traits - " << dst_ty); + good = true; + } + else { + good = false; + find_impl(sp, de->m_trait.m_path.m_path, de->m_trait.m_path.m_params, src_ty, + [&](const auto impl, auto fuzz) { + assert( !fuzz ); + good = true; + for(const auto& aty : de->m_trait.m_type_bounds) { + auto atyv = impl.get_type(aty.first.c_str()); + if( atyv == ::HIR::TypeRef() ) + { + // Get the trait from which this associated type comes. + // Insert a UfcsKnown path for that + auto p = ::HIR::Path( src_ty.clone(), de->m_trait.m_path.clone(), aty.first ); + // Run EAT + atyv = ::HIR::TypeRef::new_path( mv$(p), {} ); + } + this->expand_associated_types(sp, atyv); + if( aty.second != atyv ) { + good = false; + DEBUG("ATY " << aty.first << " mismatch - " << aty.second << " != " << atyv); + } + } + return true; + }); + } + + // Then markers + auto cb = [&](const auto impl, auto ){ + tmp_e.m_markers.back().m_params = impl.get_trait_params(); + return true; + }; + for(const auto& marker : de->m_markers) + { + if(!good) break; + tmp_e.m_markers.push_back( marker.m_path ); + good &= this->find_impl(sp, marker.m_path, marker.m_params, src_ty, cb); + } + + return good; + } + + // [T] <- [T; n] + if( const auto* de = dst_ty.m_data.opt_Slice() ) + { + if( const auto* se = src_ty.m_data.opt_Array() ) + { + DEBUG("Array unsize? " << *de->inner << " <- " << *se->inner); + return *se->inner == *de->inner; + } + } + + DEBUG("Can't unsize, no rules matched"); + return ::HIR::Compare::Unequal; + +} + bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeRef& ty) const { // If `T: Copy`, then it can't need drop glue diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 16302218..4c094218 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -170,6 +170,7 @@ public: ) const; /// bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; + bool iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function cb) const; // -------------- @@ -177,6 +178,7 @@ public: // ------------- bool type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const; bool type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const; + bool can_unsize(const Span& sp, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) const; /// Returns `true` if the passed type either implements Drop, or contains a type that implements Drop bool type_needs_drop_glue(const Span& sp, const ::HIR::TypeRef& ty) const; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 625731cc..69f787c0 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -814,6 +814,7 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl drop_scope_values(scope_def); // Emit ScopeEnd for all controlled values + #if 0 ::MIR::Statement::Data_ScopeEnd se; if(const auto* e = scope_def.data.opt_Variables() ) { se.vars = e->vars; @@ -827,6 +828,7 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl if( !se.vars.empty() || !se.tmps.empty() ) { this->push_stmt(sp, ::MIR::Statement( mv$(se) )); } + #endif } // 3. Pop scope (last because `drop_scope_values` uses the stack) -- cgit v1.2.3 From 828a19bd28eb39da6108545175bbb4427aaf2a4e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Jun 2017 09:45:02 +0800 Subject: HIR Typecheck - Remove assertion that static impls aren't fuzzy --- src/hir_typeck/static.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/hir_typeck') diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index b46567fd..ad0fc46b 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -1583,7 +1583,7 @@ bool StaticTraitResolve::can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty good = false; find_impl(sp, de->m_trait.m_path.m_path, de->m_trait.m_path.m_params, src_ty, [&](const auto impl, auto fuzz) { - assert( !fuzz ); + //ASSERT_BUG(sp, !fuzz, "Fuzzy match in can_unsize - " << dst_ty << " <- " << src_ty << " - " << impl); good = true; for(const auto& aty : de->m_trait.m_type_bounds) { auto atyv = impl.get_type(aty.first.c_str()); -- cgit v1.2.3