diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-04 23:57:02 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-04 23:57:02 +0800 |
commit | 3ff4cf2903a461fbbd37c37496e062b5645416ff (patch) | |
tree | 6fa29dfdfc775c3b4842c0cdb89951cf0f434d5e | |
parent | d4cfe751fd6b5a4a205dc88ed50d9ba03fb48f74 (diff) | |
download | mrust-3ff4cf2903a461fbbd37c37496e062b5645416ff.tar.gz |
HIR Typechck CS - Cleanup and work on correcting inferrence errors
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 176 |
1 files changed, 104 insertions, 72 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index cdcdb199..6da7578e 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2648,6 +2648,7 @@ void Context::add_revisit(::HIR::ExprNode& node) { } void Context::possible_equate_type_to(unsigned int ivar_index, const ::HIR::TypeRef& t) { + // TODO: If the other side is an ivar, add to the other list too possible_equate_type(ivar_index, t, true); } void Context::possible_equate_type_from(unsigned int ivar_index, const ::HIR::TypeRef& t) { @@ -2791,14 +2792,15 @@ namespace { if( ty_src.m_data.is_Infer() && ty_dst.m_data.is_Infer() ) { const auto& r_e = ty_src.m_data.as_Infer(); const auto& l_e = ty_dst.m_data.as_Infer(); - if( r_e.ty_class != ::HIR::InferClass::None ) { - context.equate_types(sp, ty_dst, ty_src); - return true; - } - if( l_e.ty_class != ::HIR::InferClass::None ) { - context.equate_types(sp, ty_dst, ty_src); - return true; - } + // TODO: Commented out - &-ptrs can infer to trait objects, and &-ptrs can infer from deref coercion + //if( r_e.ty_class != ::HIR::InferClass::None ) { + // context.equate_types(sp, ty_dst, ty_src); + // return true; + //} + //if( l_e.ty_class != ::HIR::InferClass::None ) { + // context.equate_types(sp, ty_dst, ty_src); + // return true; + //} context.possible_equate_type_to(r_e.index, ty_dst); context.possible_equate_type_from(l_e.index, ty_src); DEBUG("- Infer, add possibility"); @@ -2808,21 +2810,21 @@ namespace { // If the source is '_', we can't know yet TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Infer, r_e, // - 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; - } + //if( r_e.ty_class != ::HIR::InferClass::None ) { + // context.equate_types(sp, ty_dst, ty_src); + // return true; + //} context.possible_equate_type_to(r_e.index, ty_dst); DEBUG("- Infer, add possibility"); return false; ) TU_IFLET(::HIR::TypeRef::Data, ty_dst.m_data, Infer, l_e, - if( l_e.ty_class == ::HIR::InferClass::None ) { + //if( l_e.ty_class == ::HIR::InferClass::None ) { context.possible_equate_type_from(l_e.index, ty_src); DEBUG("- Infer, add possibility"); return false; - } + //} // - Otherwise, it could be a deref to the same ivar? (TODO) ) @@ -2995,59 +2997,70 @@ namespace { bool check_coerce(Context& context, const Context::Coercion& v) { ::HIR::ExprNodeP& node_ptr = *v.right_node_ptr; const auto& sp = node_ptr->span(); - const auto& ty = context.m_ivars.get_type(v.left_ty); - const auto& ty_r = context.m_ivars.get_type(node_ptr->m_res_type); - TRACE_FUNCTION_F(v << " - " << ty << " := " << ty_r); + const auto& ty_dst = context.m_ivars.get_type(v.left_ty); + const auto& ty_src = context.m_ivars.get_type(node_ptr->m_res_type); + TRACE_FUNCTION_F(v << " - " << ty_dst << " := " << ty_src); - if( context.m_ivars.types_equal(ty, ty_r) ) { + if( context.m_ivars.types_equal(ty_dst, ty_src) ) { return true; } // TODO: CoerceUnsized trait // 1. Check that the source type can coerce - TU_MATCH( ::HIR::TypeRef::Data, (ty_r.m_data), (e), + TU_MATCH( ::HIR::TypeRef::Data, (ty_src.m_data), (e), (Infer, + // If this ivar is of a primitive, equate (as primitives never coerce) if( e.ty_class != ::HIR::InferClass::None ) { - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; } + else { + TU_IFLET(::HIR::TypeRef::Data, ty_dst.m_data, Infer, e2, + context.possible_equate_type_to(e.index, ty_dst); + context.possible_equate_type_from(e2.index, ty_src); + ) + else { + context.possible_equate_type_to(e.index, ty_dst); + return false; + } + } ), (Diverge, return true; ), (Primitive, - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Path, if( ! e.binding.is_Unbound() ) { - // TODO: Apply the CoerceUnsized trait here - context.equate_types(sp, ty, node_ptr->m_res_type); + // TODO: Use the CoerceUnsized trait here + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; } ), (Generic, - //TODO(Span(), "check_coerce - Coercion from " << ty_r); - context.equate_types(sp, ty, node_ptr->m_res_type); + // TODO: CoerceUnsized bound? + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (TraitObject, - // TODO: Can bare trait objects coerce? - context.equate_types(sp, ty, node_ptr->m_res_type); + // Raw trait objects shouldn't even be encountered here?... + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Array, - // TODO: Can raw arrays coerce to anything? - context.equate_types(sp, ty, node_ptr->m_res_type); + // Raw [T; n] doesn't coerce, only borrows do + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Slice, - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Tuple, - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Borrow, @@ -3057,36 +3070,37 @@ namespace { // Pointers coerce to similar pointers of higher restriction if( e.type == ::HIR::BorrowType::Shared ) { // *const is the bottom of the tree, it doesn't coerce to anything - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; } ), (Function, // NOTE: Functions don't coerce (TODO: They could lose the origin marker?) - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Closure, // TODO: Can closures coerce to anything? // - (eventually maybe fn() if they don't capture, but that's not rustc yet) - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; - //TODO(sp, "check_coerce - Coercion from " << ty_r << " to " << ty); ) ) // 2. Check target type is a valid coercion // - Otherwise - Force equality - TU_MATCH( ::HIR::TypeRef::Data, (ty.m_data), (l_e), + TU_MATCH( ::HIR::TypeRef::Data, (ty_dst.m_data), (l_e), (Infer, + // If this ivar is of a primitive, equate (as primitives never coerce) + // TODO: Update for InferClass::Diverge ? if( l_e.ty_class != ::HIR::InferClass::None ) { - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; } // Can't do anything yet? // - Later code can handle "only path" coercions - context.possible_equate_type_from(l_e.index, ty_r); + context.possible_equate_type_from(l_e.index, ty_src); DEBUG("- Infer, add possibility"); return false; ), @@ -3094,40 +3108,40 @@ namespace { return true; ), (Primitive, - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (Path, if( ! l_e.binding.is_Unbound() ) { // TODO: CoerceUnsized - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; } ), (Generic, //TODO(Span(), "check_coerce - Coercion to " << ty); - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ), (TraitObject, // TODO: Can bare trait objects coerce? - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; ), (Array, - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; ), (Slice, - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; ), (Tuple, - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; ), (Borrow, - TU_IFLET(::HIR::TypeRef::Data, ty_r.m_data, Borrow, r_e, + TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Borrow, r_e, // If using `&mut T` where `&const T` is expected - insert a reborrow (&*) if( l_e.type == ::HIR::BorrowType::Shared && r_e.type == ::HIR::BorrowType::Unique ) { context.equate_types(sp, *l_e.inner, *r_e.inner); @@ -3141,7 +3155,7 @@ namespace { context.m_ivars.get_type(node_ptr->m_res_type); // &*<inner> node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_UniOp(mv$(span), ::HIR::ExprNode_UniOp::Op::Ref, mv$(node_ptr))); - node_ptr->m_res_type = ty.clone(); + node_ptr->m_res_type = ty_dst.clone(); context.m_ivars.get_type(node_ptr->m_res_type); context.m_ivars.mark_change(); @@ -3151,21 +3165,21 @@ namespace { if( l_e.type != r_e.type ) { // TODO: This could be allowed if left == Shared && right == Unique (reborrowing) - ERROR(sp, E0000, "Type mismatch between " << ty << " and " << ty_r << " - Borrow classes differ"); + ERROR(sp, E0000, "Type mismatch between " << ty_dst << " and " << ty_src << " - Borrow classes differ"); } // - Check for coercions return check_coerce_borrow(context, *l_e.inner, *r_e.inner, node_ptr); ) - else TU_IFLET(::HIR::TypeRef::Data, ty_r.m_data, Infer, r_e, + else TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Infer, r_e, // Leave for now if( r_e.ty_class != ::HIR::InferClass::None ) { // ERROR: Must be compatible - context.equate_types(sp, ty, ty_r); - BUG(sp, "Type error expected " << ty << " == " << ty_r); + context.equate_types(sp, ty_dst, ty_src); + BUG(sp, "Type error expected " << ty_dst << " == " << ty_src); } - context.possible_equate_type_to(r_e.index, ty); + context.possible_equate_type_to(r_e.index, ty_dst); DEBUG("- Infer, add possibility"); return false; ) @@ -3174,68 +3188,68 @@ namespace { else { // Error: Must be compatible, hand over to the equate code. // - If this returns early, it's because of a UFCS destructure - context.equate_types(sp, ty, ty_r); - //BUG(sp, "Type error expected " << ty << " == " << ty_r); + context.equate_types(sp, ty_dst, ty_src); + //BUG(sp, "Type error expected " << ty << " == " << ty_src); } ), (Pointer, // Pointers coerce from borrows and similar pointers - TU_IFLET(::HIR::TypeRef::Data, ty_r.m_data, Borrow, r_e, + TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Borrow, r_e, context.equate_types(sp, *l_e.inner, *r_e.inner); return true; ) - else TU_IFLET(::HIR::TypeRef::Data, ty_r.m_data, Pointer, r_e, + else TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Pointer, r_e, // If using `*mut T` where `*const T` is expected - add cast if( l_e.type == ::HIR::BorrowType::Shared && r_e.type == ::HIR::BorrowType::Unique ) { context.equate_types(sp, *l_e.inner, *r_e.inner); // Add cast down auto span = node_ptr->span(); - node_ptr->m_res_type = ty_r.clone(); - node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty.clone() )); - node_ptr->m_res_type = ty.clone(); + node_ptr->m_res_type = ty_src.clone(); + node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst.clone() )); + node_ptr->m_res_type = ty_dst.clone(); context.m_ivars.mark_change(); return true; } if( l_e.type != r_e.type ) { - ERROR(sp, E0000, "Type mismatch between " << ty << " and " << ty_r << " - Pointer mutability differs"); + ERROR(sp, E0000, "Type mismatch between " << ty_dst << " and " << ty_src << " - Pointer mutability differs"); } context.equate_types(sp, *l_e.inner, *r_e.inner); return true; ) - else TU_IFLET(::HIR::TypeRef::Data, ty_r.m_data, Infer, r_e, + else TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Infer, r_e, if( r_e.ty_class != ::HIR::InferClass::None ) { // ERROR: Must be compatible - context.equate_types(sp, ty, ty_r); - BUG(sp, "Type error expected " << ty << " == " << ty_r); + context.equate_types(sp, ty_dst, ty_src); + BUG(sp, "Type error expected " << ty_dst << " == " << ty_src); } // Can't do much for now - context.possible_equate_type_to(r_e.index, ty); + context.possible_equate_type_to(r_e.index, ty_dst); DEBUG("- Infer, add possibility"); return false; ) else { // Error: Must be compatible, hand over to the equate code. // - If this returns early, it's because of a UFCS destructure - context.equate_types(sp, ty, ty_r); - //BUG(sp, "Type error expected " << ty << " == " << ty_r); + context.equate_types(sp, ty_dst, ty_src); + //BUG(sp, "Type error expected " << ty << " == " << ty_src); } ), (Function, // TODO: Could capture-less closures coerce to fn() types? - context.equate_types(sp, ty, ty_r); + context.equate_types(sp, ty_dst, ty_src); return true; ), (Closure, - context.equate_types(sp, ty, node_ptr->m_res_type); + context.equate_types(sp, ty_dst, node_ptr->m_res_type); return true; ) ) //TODO(sp, "Typecheck_Code_CS - Coercion " << context.m_ivars.fmt_type(ty) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type)); - DEBUG("TODO - Coercion " << context.m_ivars.fmt_type(ty) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type)); + DEBUG("TODO - Coercion " << context.m_ivars.fmt_type(ty_dst) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type)); return false; } @@ -3299,25 +3313,43 @@ namespace { } // HACK: If the LHS is an opqaue UfcsKnown for the same trait and item, equate the inner types + #if 0 TU_IFLET(::HIR::TypeRef::Data, v.left_ty.m_data, Path, e, if( e.binding.is_Opaque() ) { TU_IFLET(::HIR::Path::Data, e.path.m_data, UfcsKnown, pe, if( pe.trait.m_path == v.trait && pe.item == v.name ) { + #if 0 context.equate_types(sp, *pe.type, v.impl_ty); - return true; + #else + TU_IFLET(::HIR::TypeRef::Data, context.get_type(*pe.type).m_data, Infer, e2, + //context.possible_equate_type_from(e2.index, v.impl_ty); + //context.possible_equate_type_to(e2.index, v.impl_ty); + return false; + ) + else TU_IFLET(::HIR::TypeRef::Data, context.get_type(v.impl_ty).m_data, Infer, e2, + //context.possible_equate_type_from(e2.index, *pe.type); + //context.possible_equate_type_to(e2.index, *pe.type); + return false; + ) + else { + context.equate_types(sp, *pe.type, v.impl_ty); + return true; + } + #endif } ) } ) + #endif // Locate applicable trait impl unsigned int count = 0; DEBUG("Searching for impl " << v.trait << v.params << " for " << context.m_ivars.fmt_type(v.impl_ty)); bool found = context.m_resolve.find_trait_impls(sp, v.trait, v.params, v.impl_ty, [&](auto impl, auto cmp) { - DEBUG("[check_associated] Found " << impl); + DEBUG("[check_associated] Found cmp=" << cmp << " " << impl); if( v.name != "" ) { auto out_ty_o = impl.get_type(v.name.c_str()); if( out_ty_o == ::HIR::TypeRef() ) @@ -3409,7 +3441,7 @@ namespace { const auto& ty_l = context.m_ivars.get_type(ty_l_ivar); if( !ty_l.m_data.is_Infer() ) { - DEBUG("- IVar " << ty_l << " had possibilities, but was known"); + DEBUG("- IVar " << i << " had possibilities, but was known to be " << ty_l); ivar_ent = Context::IVarPossible(); return ; } |