summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/path.cpp97
-rw-r--r--src/hir/path.hpp5
-rw-r--r--src/hir/type.cpp15
-rw-r--r--src/hir_expand/ufcs_everything.cpp44
-rw-r--r--src/hir_typeck/expr_check.cpp41
-rw-r--r--src/hir_typeck/expr_cs.cpp34
-rw-r--r--src/mir/from_hir.cpp94
7 files changed, 229 insertions, 101 deletions
diff --git a/src/hir/path.cpp b/src/hir/path.cpp
index 1552c8f3..0df8a6d2 100644
--- a/src/hir/path.cpp
+++ b/src/hir/path.cpp
@@ -224,6 +224,43 @@ bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
throw "";
}
+::HIR::Compare HIR::PathParams::compare_with_placeholders(const Span& sp, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder) const
+{
+ using ::HIR::Compare;
+
+ auto rv = Compare::Equal;
+ if( this->m_types.size() > 0 || x.m_types.size() > 0 ) {
+ if( this->m_types.size() != x.m_types.size() ) {
+ return Compare::Unequal;
+ }
+ for( unsigned int i = 0; i < x.m_types.size(); i ++ )
+ {
+ auto rv2 = this->m_types[i].compare_with_placeholders( sp, x.m_types[i], resolve_placeholder );
+ if( rv2 == Compare::Unequal )
+ return Compare::Unequal;
+ if( rv2 == Compare::Fuzzy )
+ rv = Compare::Fuzzy;
+ }
+ }
+ return rv;
+}
+::HIR::Compare HIR::GenericPath::compare_with_placeholders(const Span& sp, const ::HIR::GenericPath& x, ::HIR::t_cb_resolve_type resolve_placeholder) const
+{
+ using ::HIR::Compare;
+
+ if( this->m_path.m_crate_name != x.m_path.m_crate_name )
+ return Compare::Unequal;
+ if( this->m_path.m_components.size() != x.m_path.m_components.size() )
+ return Compare::Unequal;
+ for(unsigned int i = 0; i < this->m_path.m_components.size(); i ++ )
+ {
+ if( this->m_path.m_components[i] != x.m_path.m_components[i] )
+ return Compare::Unequal;
+ }
+
+ return this->m_params. compare_with_placeholders(sp, x.m_params, resolve_placeholder);
+}
+
namespace {
::HIR::Compare compare_with_placeholders(
const Span& sp,
@@ -231,23 +268,7 @@ namespace {
::HIR::t_cb_resolve_type resolve_placeholder
)
{
- using ::HIR::Compare;
-
- auto rv = Compare::Equal;
- if( l.m_types.size() > 0 || r.m_types.size() > 0 ) {
- if( l.m_types.size() != r.m_types.size() ) {
- return Compare::Unequal;
- }
- for( unsigned int i = 0; i < r.m_types.size(); i ++ )
- {
- auto rv2 = l.m_types[i].compare_with_placeholders( sp, r.m_types[i], resolve_placeholder );
- if( rv2 == Compare::Unequal )
- return Compare::Unequal;
- if( rv2 == Compare::Fuzzy )
- rv = Compare::Fuzzy;
- }
- }
- return rv;
+ return l.compare_with_placeholders(sp, r, resolve_placeholder);
}
::HIR::Compare compare_with_placeholders(
const Span& sp,
@@ -255,19 +276,7 @@ namespace {
::HIR::t_cb_resolve_type resolve_placeholder
)
{
- using ::HIR::Compare;
-
- if( l.m_path.m_crate_name != r.m_path.m_crate_name )
- return Compare::Unequal;
- if( l.m_path.m_components.size() != r.m_path.m_components.size() )
- return Compare::Unequal;
- for(unsigned int i = 0; i < l.m_path.m_components.size(); i ++ )
- {
- if( l.m_path.m_components[i] != r.m_path.m_components[i] )
- return Compare::Unequal;
- }
-
- return compare_with_placeholders(sp, l.m_params, r.m_params, resolve_placeholder);
+ return l.compare_with_placeholders(sp, r, resolve_placeholder);
}
}
@@ -279,6 +288,34 @@ namespace {
}\
} while(0)
+::HIR::Compare HIR::TraitPath::compare_with_placeholders(const Span& sp, const TraitPath& x, t_cb_resolve_type resolve_placeholder) const
+{
+ auto rv = m_path .compare_with_placeholders(sp, x.m_path, resolve_placeholder);
+ if( rv == Compare::Unequal )
+ return rv;
+
+ // TODO: HRLs
+
+ auto it_l = m_type_bounds.begin();
+ auto it_r = x.m_type_bounds.begin();
+ while( it_l != m_type_bounds.end() && it_r != x.m_type_bounds.end() )
+ {
+ if( it_l->first != it_r->first ) {
+ return Compare::Unequal;
+ }
+ CMP( rv, it_l->second .compare_with_placeholders( sp, it_r->second, resolve_placeholder ) );
+ ++ it_l;
+ ++ it_r;
+ }
+
+ if( it_l != m_type_bounds.end() || it_r != x.m_type_bounds.end() )
+ {
+ return Compare::Unequal;
+ }
+
+ return rv;
+}
+
::HIR::Compare HIR::Path::compare_with_placeholders(const Span& sp, const Path& x, t_cb_resolve_type resolve_placeholder) const
{
if( this->m_data.tag() != x.m_data.tag() )
diff --git a/src/hir/path.hpp b/src/hir/path.hpp
index a4ee9ca1..57a8330b 100644
--- a/src/hir/path.hpp
+++ b/src/hir/path.hpp
@@ -89,6 +89,8 @@ struct PathParams
PathParams(PathParams&&) = default;
PathParams& operator=(PathParams&&) = default;
+ Compare compare_with_placeholders(const Span& sp, const PathParams& x, t_cb_resolve_type resolve_placeholder) const;
+
bool operator==(const PathParams& x) const;
bool operator!=(const PathParams& x) const { return !(*this == x); }
bool operator<(const PathParams& x) const { return ord(x) == OrdLess; }
@@ -111,6 +113,7 @@ public:
GenericPath(::HIR::SimplePath sp, ::HIR::PathParams params);
GenericPath clone() const;
+ Compare compare_with_placeholders(const Span& sp, const GenericPath& x, t_cb_resolve_type resolve_placeholder) const;
bool operator==(const GenericPath& x) const;
bool operator!=(const GenericPath& x) const { return !(*this == x); }
@@ -136,6 +139,8 @@ public:
const ::HIR::Trait* m_trait_ptr;
TraitPath clone() const;
+ Compare compare_with_placeholders(const Span& sp, const TraitPath& x, t_cb_resolve_type resolve_placeholder) const;
+
bool operator==(const TraitPath& x) const;
bool operator!=(const TraitPath& x) const { return !(*this == x); }
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 7a833a32..e51929c9 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -816,7 +816,20 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return Compare::Equal;
),
(TraitObject,
- TODO(sp, "Compare " << *this << " and " << right);
+ if( le.m_markers.size() != re.m_markers.size() )
+ return Compare::Unequal;
+ auto rv = le.m_trait .compare_with_placeholders( sp, re.m_trait, resolve_placeholder );
+ if( rv == Compare::Unequal )
+ return rv;
+ for( unsigned int i = 0; i < le.m_markers.size(); i ++ )
+ {
+ auto rv2 = le.m_markers[i] .compare_with_placeholders( sp, re.m_markers[i], resolve_placeholder );
+ if( rv2 == Compare::Unequal )
+ return Compare::Unequal;
+ if( rv2 == Compare::Fuzzy )
+ rv = Compare::Fuzzy;
+ }
+ return rv;
),
(Array,
if( le.size_val != re.size_val )
diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp
index 550b9517..c7c19d8c 100644
--- a/src/hir_expand/ufcs_everything.cpp
+++ b/src/hir_expand/ufcs_everything.cpp
@@ -4,6 +4,7 @@
*
* hir_expand/ufcs_everything.cpp
* - Expand all function calls (_CallMethod, and _CallValue) and operator overloads to _CallPath
+ * - Also handles borrow-unsize-deref for _Unsize on arrays (see comment in _Unsize)
*/
#include <hir/visitor.hpp>
#include <hir/expr.hpp>
@@ -649,7 +650,7 @@ namespace {
langitem = method = "deref_mut";
break;
case ::HIR::ValueUsage::Move:
- TODO(sp, "Support moving out of indexed values");
+ TODO(sp, "Support moving out of borrows");
break;
}
// Needs replacement, continue
@@ -676,6 +677,47 @@ namespace {
// - Dereference the result (which is an &-ptr)
m_replacement = NEWNODE( mv$(node.m_res_type), Deref, sp, mv$(m_replacement) );
}
+
+
+
+ void visit(::HIR::ExprNode_Unsize& node) override
+ {
+ ::HIR::ExprVisitorDef::visit(node);
+
+ // HACK: The autoderef code has to run before usage information is avaliable, so emits "invalid" _Unsize nodes
+ // - Fix that.
+ if( node.m_value->m_res_type.m_data.is_Array() )
+ {
+ const Span& sp = node.span();
+
+ ::HIR::BorrowType bt = ::HIR::BorrowType::Shared;
+ switch( node.m_usage )
+ {
+ case ::HIR::ValueUsage::Unknown:
+ BUG(sp, "Unknown usage type of _Unsize value");
+ break;
+ case ::HIR::ValueUsage::Borrow:
+ bt = ::HIR::BorrowType::Shared;
+ break;
+ case ::HIR::ValueUsage::Mutate:
+ bt = ::HIR::BorrowType::Unique;
+ break;
+ case ::HIR::ValueUsage::Move:
+ TODO(sp, "Support moving in _Unsize");
+ break;
+ }
+
+ auto ty_src = ::HIR::TypeRef::new_borrow(bt, node.m_value->m_res_type.clone());
+ auto ty_dst = ::HIR::TypeRef::new_borrow(bt, node.m_res_type.clone());
+ auto ty_dst2 = ty_dst.clone();
+ // Borrow
+ node.m_value = NEWNODE( mv$(ty_src), Borrow, sp, bt, mv$(node.m_value) );
+ // Unsize borrow
+ m_replacement = NEWNODE( mv$(ty_dst), Unsize, sp, mv$(node.m_value), mv$(ty_dst2) );
+ // Deref
+ m_replacement = NEWNODE( mv$(node.m_res_type), Deref, sp, mv$(m_replacement) );
+ }
+ }
};
class OuterVisitor:
public ::HIR::Visitor
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index fa12d363..71f28e8f 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -285,18 +285,37 @@ namespace {
const auto& src_ty = node.m_value->m_res_type;
const auto& dst_ty = node.m_res_type;
- // Check unsizability (including trait impls)
- // NOTE: Unsize applies inside borrows
- TU_MATCH_DEF(::HIR::TypeRef::Data, (dst_ty.m_data), (e),
- (
- ERROR(sp, E0000, "Invalid unsizing operation to " << dst_ty << " from " << src_ty);
- ),
- (TraitObject,
- ),
- (Slice,
- // TODO: Does unsize ever apply to arrays? - Yes.
+
+ 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();
+ if( se.type != de.type ) {
+ ERROR(sp, E0000, "Invalid unsizing operation to " << dst_ty << " from " << src_ty << " - Borrow class mismatch");
+ }
+ const auto& src_ty = *se.inner;
+ const auto& dst_ty = *de.inner;
+ // Check unsizability (including trait impls)
+ // NOTE: Unsize applies inside borrows
+ TU_MATCH_DEF(::HIR::TypeRef::Data, (dst_ty.m_data), (e),
+ (
+ ERROR(sp, E0000, "Invalid unsizing operation to " << dst_ty << " from " << src_ty);
+ ),
+ (TraitObject,
+ ),
+ (Slice,
+ // TODO: Does unsize ever apply to arrays? - Yes.
+ )
)
- )
+ }
+ else if( src_ty.m_data.is_Borrow() || dst_ty.m_data.is_Borrow() )
+ {
+ ERROR(sp, E0000, "Invalid unsizing operation to " << dst_ty << " from " << src_ty);
+ }
+ else
+ {
+ TODO(sp, "Check for impl of Unsize<" << dst_ty << "> for " << src_ty);
+ }
node.m_value->visit( *this );
}
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index e8bf8842..4ffd4b2a 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -2902,6 +2902,7 @@ const ::HIR::TypeRef& Context::get_var(const Span& sp, unsigned int idx) const {
{
ASSERT_BUG(span, ty_dst.m_data.is_Slice(), "Array should only ever autoderef to Slice");
+ // HACK: Emit an invalid _Unsize op that is fixed once usage type is known.
auto ty_dst_c = ty_dst.clone();
val_node = NEWNODE( mv$(ty_dst), span, _Unsize, mv$(val_node), mv$(ty_dst_c) );
DEBUG("- Unsize " << &*val_node << " -> " << val_node->m_res_type);
@@ -3053,10 +3054,10 @@ namespace {
TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Array, src_array,
context.equate_types(sp, *dst_slice.inner, *src_array.inner);
- add_coerce_borrow(context, node_ptr, ty_dst, [&](auto& node_ptr) {
- auto span = node_ptr->span();
- node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
- });
+ auto ty_dst_b = ::HIR::TypeRef::new_borrow(bt, ty_dst.clone());
+ auto ty_dst_b2 = ty_dst_b.clone();
+ auto span = node_ptr->span();
+ node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
context.m_ivars.mark_change();
return true;
@@ -3161,10 +3162,11 @@ namespace {
}
// Add _Unsize operator
- add_coerce_borrow(context, node_ptr, ty_dst, [&](auto& node_ptr) {
- auto span = node_ptr->span();
- node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
- });
+ auto ty_dst_b = ::HIR::TypeRef::new_borrow(bt, ty_dst.clone());
+ auto ty_dst_b2 = ty_dst_b.clone();
+ auto span = node_ptr->span();
+ node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
+
return true;
)
)
@@ -3196,10 +3198,11 @@ namespace {
});
if( found ) {
DEBUG("- Unsize " << &*node_ptr << " -> " << ty_dst);
- add_coerce_borrow(context, node_ptr, ty_dst, [&](auto& node_ptr) {
- auto span = node_ptr->span();
- node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
- });
+ auto ty_dst_b = ::HIR::TypeRef::new_borrow(bt, ty_dst.clone());
+ auto ty_dst_b2 = ty_dst_b.clone();
+ auto span = node_ptr->span();
+ node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
+
return true;
}
}
@@ -3233,11 +3236,8 @@ namespace {
{
DEBUG("- CoerceUnsize " << &*node_ptr << " -> " << ty_dst);
- TODO(sp, "Add Coerce op applying to pointer type for " << ty_src << " -> " << ty_dst);
- //add_coerce_borrow(context, node_ptr, ty_dst, [&](auto& node_ptr) {
- // auto span = node_ptr->span();
- // node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
- // });
+ auto span = node_ptr->span();
+ node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
return true;
}
}
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index dc890495..4a540c14 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -876,49 +876,61 @@ namespace {
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
- TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_out.m_data), (e),
- (
- TODO(node.span(), "MIR _Unsize to " << ty_out);
- ),
- // TODO: Unsize custom types containing a ?Size generic - See the Unsize trait
- //(Path,
- // ),
- //(Generic,
- // ),
- (Slice,
- if( ty_in.m_data.is_Array() )
- {
- const auto& in_array = ty_in.m_data.as_Array();
- auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::Constant( static_cast<uint64_t>(in_array.size_val) ) );
- m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
- }
- else if( ty_in.m_data.is_Generic() )
- {
- // HACK: FixedSizeArray uses `A: Unsize<[T]>` which will lead to the above code not working (as the size isn't known).
- // - Maybe _Meta on the `&A` would work as a stopgap (since A: Sized, it won't collide with &[T] or similar)
- auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ptr_lval.clone() }) );
- m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
- }
- else
- {
- ASSERT_BUG(node.span(), ty_in.m_data.is_Array(), "Unsize to slice from non-array - " << ty_in);
- }
- ),
- (TraitObject,
- // TODO: Obtain the vtable if the destination is a trait object
- // vtable exists as an unnamable associated type
+
+ if( ty_out.m_data.is_Borrow() && ty_in.m_data.is_Borrow() )
+ {
+ const auto& oe = ty_out.m_data.as_Borrow();
+ const auto& ie = ty_in.m_data.as_Borrow();
+ const auto& ty_out = *oe.inner;
+ const auto& ty_in = *ie.inner;
+ TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_out.m_data), (e),
+ (
+ TODO(node.span(), "MIR _Unsize to " << ty_out);
+ ),
+ // TODO: Unsize custom types containing a ?Size generic - See the Unsize trait
+ //(Path,
+ // ),
+ //(Generic,
+ // ),
+ (Slice,
+ if( ty_in.m_data.is_Array() )
+ {
+ const auto& in_array = ty_in.m_data.as_Array();
+ auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::Constant( static_cast<uint64_t>(in_array.size_val) ) );
+ m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
+ }
+ else if( ty_in.m_data.is_Generic() )
+ {
+ // HACK: FixedSizeArray uses `A: Unsize<[T]>` which will lead to the above code not working (as the size isn't known).
+ // - Maybe _Meta on the `&A` would work as a stopgap (since A: Sized, it won't collide with &[T] or similar)
+ auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ptr_lval.clone() }) );
+ m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
+ }
+ else
+ {
+ ASSERT_BUG(node.span(), ty_in.m_data.is_Array(), "Unsize to slice from non-array - " << ty_in);
+ }
+ ),
+ (TraitObject,
+ // TODO: Obtain the vtable if the destination is a trait object
+ // vtable exists as an unnamable associated type
- ::HIR::Path vtable { ty_in.clone(), e.m_trait.m_path.clone(), "#vtable" };
- ::HIR::TypeRef vtable_type { {} };
- auto vtable_lval = m_builder.lvalue_or_temp(
- node.span(),
- ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, mv$(vtable_type)),
- ::MIR::RValue( ::MIR::Constant::make_ItemAddr(mv$(vtable)) )
- );
-
- m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(vtable_lval) }) );
+ ::HIR::Path vtable { ty_in.clone(), e.m_trait.m_path.clone(), "#vtable" };
+ ::HIR::TypeRef vtable_type { {} };
+ auto vtable_lval = m_builder.lvalue_or_temp(
+ node.span(),
+ ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, mv$(vtable_type)),
+ ::MIR::RValue( ::MIR::Constant::make_ItemAddr(mv$(vtable)) )
+ );
+
+ m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(vtable_lval) }) );
+ )
)
- )
+ }
+ else
+ {
+ TODO(node.span(), "Support emitting CoerceUnsized-based _Unsize ops in MIR - " << ty_in << " -> " << ty_out);
+ }
}
void visit(::HIR::ExprNode_Index& node) override
{