summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp3
-rw-r--r--src/ast/ast.hpp6
-rw-r--r--src/ast/dump.cpp26
-rw-r--r--src/expand/derive.cpp65
-rw-r--r--src/expand/lang_item.cpp2
-rw-r--r--src/expand/mod.cpp2
-rw-r--r--src/hir/from_ast.cpp30
-rw-r--r--src/hir/from_ast_expr.cpp2
-rw-r--r--src/hir/hir.cpp154
-rw-r--r--src/hir/pattern.cpp8
-rw-r--r--src/hir_conv/bind.cpp35
-rw-r--r--src/hir_expand/closures.cpp1
-rw-r--r--src/hir_typeck/expr_check.cpp72
-rw-r--r--src/hir_typeck/expr_cs.cpp146
-rw-r--r--src/hir_typeck/helpers.cpp112
-rw-r--r--src/hir_typeck/helpers.hpp2
-rw-r--r--src/hir_typeck/static.cpp237
-rw-r--r--src/hir_typeck/static.hpp2
-rw-r--r--src/main.cpp1
-rw-r--r--src/mir/from_hir.cpp29
-rw-r--r--src/mir/helpers.cpp70
-rw-r--r--src/mir/mir_builder.cpp92
-rw-r--r--src/mir/optimise.cpp187
-rw-r--r--src/parse/expr.cpp15
-rw-r--r--src/parse/lex.cpp2
-rw-r--r--src/parse/root.cpp8
-rw-r--r--src/resolve/absolute.cpp4
-rw-r--r--src/resolve/index.cpp14
-rw-r--r--src/trans/codegen.cpp20
-rw-r--r--src/trans/codegen.hpp4
-rw-r--r--src/trans/codegen_c.cpp47
-rw-r--r--src/trans/mangling.cpp2
32 files changed, 1085 insertions, 315 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 39250a41..df5f4d5a 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -175,6 +175,9 @@ Enum Enum::clone() const
Struct Struct::clone() const
{
TU_MATCHA( (m_data), (e),
+ (Unit,
+ return Struct(m_params.clone());
+ ),
(Tuple,
decltype(e.ents) new_fields;
for(const auto& f : e.ents)
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index b63cb2e6..c067001a 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -319,6 +319,7 @@ public:
TAGGED_UNION_EX(StructData, (), Struct,
(
+ (Unit, struct {}),
(Tuple, struct {
::std::vector<TupleItem> ents;
}),
@@ -339,6 +340,11 @@ public:
StructData m_data;
Struct() {}
+ Struct(GenericParams params):
+ m_params( mv$(params) ),
+ m_data( StructData::make_Unit({}) )
+ {
+ }
Struct( GenericParams params, ::std::vector<StructItem> fields ):
m_params( move(params) ),
m_data( StructData::make_Struct({mv$(fields)}) )
diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp
index a6c298b0..0d77054c 100644
--- a/src/ast/dump.cpp
+++ b/src/ast/dump.cpp
@@ -991,22 +991,18 @@ void RustPrinter::handle_struct(const AST::Struct& s)
print_params(s.params());
TU_MATCH(AST::StructData, (s.m_data), (e),
+ (Unit,
+ m_os << " /* unit-like */\n";
+ print_bounds(s.params());
+ m_os << indent() << ";\n";
+ ),
(Tuple,
- if( e.ents.size() == 0 )
- {
- m_os << " /* unit-like */\n";
- print_bounds(s.params());
- m_os << indent() << ";\n";
- }
- else
- {
- m_os << "(";
- for( const auto& i : e.ents )
- m_os << i.m_type << ", ";
- m_os << ")\n";
- print_bounds(s.params());
- m_os << indent() << ";\n";
- }
+ m_os << "(";
+ for( const auto& i : e.ents )
+ m_os << i.m_type << ", ";
+ m_os << ")\n";
+ print_bounds(s.params());
+ m_os << indent() << ";\n";
),
(Struct,
m_os << "\n";
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index c363b689..f09e9298 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -102,6 +102,8 @@ struct Deriver
{
::std::vector<TypeRef> ret;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -299,6 +301,13 @@ public:
// Generate code for Debug
AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ node = NEWNODE(NamedValue, AST::Path("f"));
+ node = NEWNODE(CallMethod,
+ mv$(node), AST::PathNode("write_str",{}),
+ vec$( NEWNODE(String, name) )
+ );
+ ),
(Struct,
node = NEWNODE(NamedValue, AST::Path("f"));
node = NEWNODE(CallMethod,
@@ -480,6 +489,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -685,6 +696,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -896,6 +909,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -1049,6 +1064,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -1265,6 +1282,9 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ nodes.push_back( NEWNODE(NamedValue, AST::Path(ty_path)) );
+ ),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP> > vals;
for( const auto& fld : e.ents )
@@ -1274,19 +1294,12 @@ public:
nodes.push_back( NEWNODE(StructLiteral, ty_path, nullptr, mv$(vals)) );
),
(Tuple,
- if( e.ents.size() == 0 )
- {
- nodes.push_back( NEWNODE(NamedValue, AST::Path(ty_path)) );
- }
- else
+ ::std::vector<AST::ExprNodeP> vals;
+ for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
- ::std::vector<AST::ExprNodeP> vals;
- for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
- {
- vals.push_back( this->clone_val_ref(core_name, this->field(FMT(idx))) );
- }
- nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
+ vals.push_back( this->clone_val_ref(core_name, this->field(FMT(idx))) );
}
+ nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
)
)
@@ -1428,6 +1441,9 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ nodes.push_back( NEWNODE(NamedValue, AST::Path(ty_path)) );
+ ),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP> > vals;
for( const auto& fld : e.ents )
@@ -1437,19 +1453,12 @@ public:
nodes.push_back( NEWNODE(StructLiteral, ty_path, nullptr, mv$(vals)) );
),
(Tuple,
- if( e.ents.size() == 0 )
- {
- nodes.push_back( NEWNODE(NamedValue, AST::Path(ty_path)) );
- }
- else
+ ::std::vector<AST::ExprNodeP> vals;
+ for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
- ::std::vector<AST::ExprNodeP> vals;
- for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
- {
- vals.push_back( this->default_call(core_name) );
- }
- nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
+ vals.push_back( this->default_call(core_name) );
}
+ nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
)
)
@@ -1522,6 +1531,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
for( const auto& fld : e.ents )
{
@@ -1680,6 +1691,8 @@ public:
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
unsigned int idx = 0;
for( const auto& fld : e.ents )
@@ -1707,6 +1720,9 @@ public:
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ node = get_val_ok(core_name);
+ ),
(Struct,
node = NEWNODE(CallPath,
this->get_trait_path_Encoder() + "emit_struct",
@@ -1917,6 +1933,8 @@ public:
AST::ExprNodeP node_v;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ ),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP > > vals;
unsigned int idx = 0;
@@ -1949,6 +1967,9 @@ public:
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Unit,
+ node = NEWNODE(NamedValue, mv$(base_path));
+ ),
(Struct,
assert( !args[2] );
args[2] = NEWNODE(Integer, e.ents.size(), CORETYPE_UINT);
diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp
index 988dc0e0..5c92cd76 100644
--- a/src/expand/lang_item.cpp
+++ b/src/expand/lang_item.cpp
@@ -70,6 +70,7 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }
+ else if( name == "freeze" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "iterator" ) { /* mrustc just desugars? */ }
@@ -91,6 +92,7 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
}
else if( name == "str_eq" ) { }
+ else if( name == "drop_in_place" ) { }
// - builtin `box` support
else if( name == "exchange_malloc" ) { }
else if( name == "exchange_free" ) { }
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index 81a3c5b6..01786284 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -906,6 +906,8 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
(Struct,
TU_MATCH(AST::StructData, (e.m_data), (sd),
+ (Unit,
+ ),
(Struct,
for(auto it = sd.ents.begin(); it != sd.ents.end(); ) {
auto& si = *it;
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 255546e7..c0a3151e 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -819,18 +819,16 @@ namespace {
::HIR::Struct::Data data;
TU_MATCH(::AST::StructData, (ent.m_data), (e),
+ (Unit,
+ data = ::HIR::Struct::Data::make_Unit({});
+ ),
(Tuple,
- if( e.ents.size() == 0 ) {
- data = ::HIR::Struct::Data::make_Unit({});
- }
- else {
- ::HIR::Struct::Data::Data_Tuple fields;
+ ::HIR::Struct::Data::Data_Tuple fields;
- for(const auto& field : e.ents)
- fields.push_back( { field.m_is_public, LowerHIR_Type(field.m_type) } );
+ for(const auto& field : e.ents)
+ fields.push_back( { field.m_is_public, LowerHIR_Type(field.m_type) } );
- data = ::HIR::Struct::Data::make_Tuple( mv$(fields) );
- }
+ data = ::HIR::Struct::Data::make_Tuple( mv$(fields) );
),
(Struct,
::HIR::Struct::Data::Data_Named fields;
@@ -1218,12 +1216,14 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
),
(Struct,
/// Add value reference
- TU_IFLET( ::AST::StructData, e.m_data, Tuple, e2,
- if( e2.ents.size() == 0 )
- _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstant({item_path.get_simple_path()}) );
- else
- _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstructor({item_path.get_simple_path()}) );
- )
+ if( e.m_data.is_Unit() ) {
+ _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstant({item_path.get_simple_path()}) );
+ }
+ else if( e.m_data.is_Tuple() ) {
+ _add_mod_val_item( mod, item.name, item.is_pub, ::HIR::ValueItem::make_StructConstructor({item_path.get_simple_path()}) );
+ }
+ else {
+ }
_add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Struct(item_path, e) );
),
(Enum,
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index cd2b27fa..9085bd3b 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -627,7 +627,7 @@ struct LowerHIR_ExprNode_Visitor:
if( e.struct_->m_data.is_Struct() ) {
ERROR(v.span(), E0000, "Named value referring to a struct that isn't tuple-like or unit-like - " << v.m_path);
}
- is_tuple_constructor = e.struct_->m_data.as_Tuple().ents.size() > 0;
+ is_tuple_constructor = e.struct_->m_data.is_Tuple();
}
else
{
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index d50c3e49..66070dc7 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -339,6 +339,11 @@ bool ::HIR::MarkerImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_res
}
namespace {
+
+ struct TypeOrdSpecific_MixedOrdering
+ {
+ };
+
::Ordering typelist_ord_specific(const Span& sp, const ::std::vector<::HIR::TypeRef>& left, const ::std::vector<::HIR::TypeRef>& right);
::Ordering type_ord_specific(const Span& sp, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right)
@@ -397,7 +402,22 @@ namespace {
TODO(sp, "Path - " << le.path << " and " << right);
),
(TraitObject,
- TODO(sp, "TraitObject - " << left);
+ ASSERT_BUG(sp, right.m_data.is_TraitObject(), "Mismatched types - "<< left << " vs " << right);
+ const auto& re = right.m_data.as_TraitObject();
+ ASSERT_BUG(sp, le.m_trait.m_path.m_path == re.m_trait.m_path.m_path, "Mismatched types - "<< left << " vs " << right);
+ ASSERT_BUG(sp, le.m_markers.size() == re.m_markers.size(), "Mismatched types - "<< left << " vs " << right);
+
+ auto ord = typelist_ord_specific(sp, le.m_trait.m_path.m_params.m_types, re.m_trait.m_path.m_params.m_types);
+ if( ord != ::OrdEqual )
+ return ord;
+ for(size_t i = 0; i < le.m_markers.size(); i ++)
+ {
+ ASSERT_BUG(sp, le.m_markers[i].m_path == re.m_markers[i].m_path, "Mismatched types - " << left << " vs " << right);
+ ord = typelist_ord_specific(sp, le.m_markers[i].m_params.m_types, re.m_markers[i].m_params.m_types);
+ if(ord != ::OrdEqual)
+ return ord;
+ }
+ return ::OrdEqual;
),
(ErasedType,
TODO(sp, "ErasedType - " << left);
@@ -464,11 +484,15 @@ namespace {
::Ordering typelist_ord_specific(const Span& sp, const ::std::vector<::HIR::TypeRef>& le, const ::std::vector<::HIR::TypeRef>& re)
{
auto rv = ::OrdEqual;
+ assert(le.size() == re.size());
for(unsigned int i = 0; i < le.size(); i ++) {
auto a = type_ord_specific(sp, le[i], re[i]);
if( a != ::OrdEqual ) {
if( rv != ::OrdEqual && a != rv )
- BUG(sp, "Inconsistent ordering between type lists");
+ {
+ DEBUG("Inconsistent ordering between type lists - i=" << i << " [" << le << "] vs [" << re << "]");
+ throw TypeOrdSpecific_MixedOrdering {};
+ }
rv = a;
}
}
@@ -525,20 +549,35 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const
{
static const Span _sp;
const Span& sp = _sp;
+ TRACE_FUNCTION;
+ //DEBUG("this = " << *this);
+ //DEBUG("other = " << other);
// >> https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md#defining-the-precedence-rules
// 1. If this->m_type is less specific than other.m_type: return false
- if( type_ord_specific(sp, this->m_type, other.m_type) == ::OrdLess ) {
- return false;
+ try
+ {
+ auto ord = type_ord_specific(sp, this->m_type, other.m_type);
+ if( ord != ::OrdEqual ) {
+ DEBUG("- Type " << (ord == ::OrdLess ? "less" : "more") << " specific - " << this->m_type << " AND " << other.m_type);
+ return ord == ::OrdLess;
+ }
+ // 2. If any in te.impl->m_params is less specific than oe.impl->m_params: return false
+ ord = typelist_ord_specific(sp, this->m_trait_args.m_types, other.m_trait_args.m_types);
+ if( ord != ::OrdEqual ) {
+ DEBUG("- Trait arguments " << (ord == ::OrdLess ? "less" : "more") << " specific");
+ return ord == ::OrdLess;
+ }
}
- // 2. If any in te.impl->m_params is less specific than oe.impl->m_params: return false
- if( typelist_ord_specific(sp, this->m_trait_args.m_types, other.m_trait_args.m_types) == ::OrdLess ) {
- return false;
+ catch(const TypeOrdSpecific_MixedOrdering& e)
+ {
+ BUG(sp, "Mixed ordering in more_specific_than");
}
- if( other.m_params.m_bounds.size() == 0 ) {
- return m_params.m_bounds.size() > 0;
- }
+ //if( other.m_params.m_bounds.size() == 0 ) {
+ // DEBUG("- Params (none in other, some in this)");
+ // return m_params.m_bounds.size() > 0;
+ //}
// 3. Compare bound set, if there is a rule in oe that is missing from te; return false
// TODO: Cache these lists (calculate after outer typecheck?)
auto bounds_t = flatten_bounds(m_params.m_bounds);
@@ -549,7 +588,10 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const
// If there are less bounds in this impl, it can't be more specific.
if( bounds_t.size() < bounds_o.size() )
+ {
+ DEBUG("Bound count");
return false;
+ }
auto it_t = bounds_t.begin();
auto it_o = bounds_o.begin();
@@ -627,6 +669,7 @@ bool ::HIR::TraitImpl::overlaps_with(const ::HIR::TraitImpl& other) const
static bool types_overlap(const ::HIR::TypeRef& a, const ::HIR::TypeRef& b)
{
static Span sp;
+ //DEBUG("(" << a << "," << b << ")");
if( a.m_data.is_Generic() || b.m_data.is_Generic() )
return true;
// TODO: Unbound/Opaque paths?
@@ -665,9 +708,21 @@ bool ::HIR::TraitImpl::overlaps_with(const ::HIR::TraitImpl& other) const
TODO(sp, "Path - " << ae.path << " and " << be.path);
),
(TraitObject,
- if( ae.m_trait.m_path != be.m_trait.m_path )
+ if( ae.m_trait.m_path.m_path != be.m_trait.m_path.m_path )
+ return false;
+ if( !H::types_overlap(ae.m_trait.m_path.m_params, be.m_trait.m_path.m_params) )
return false;
- TODO(sp, "TraitObject - " << a << " and " << b);
+ // Marker traits only overlap if the lists are the same (with overlap)
+ if( ae.m_markers.size() != be.m_markers.size() )
+ return false;
+ for(size_t i = 0; i < ae.m_markers.size(); i++)
+ {
+ if( ae.m_markers[i].m_path != be.m_markers[i].m_path )
+ return false;
+ if( !H::types_overlap(ae.m_markers[i].m_params, be.m_markers[i].m_params) )
+ return false;
+ }
+ return true;
),
(ErasedType,
TODO(sp, "ErasedType - " << a);
@@ -717,16 +772,89 @@ bool ::HIR::TraitImpl::overlaps_with(const ::HIR::TraitImpl& other) const
}
};
+ // Quick Check: If the types are equal, they do overlap
+ if(this->m_type == other.m_type && this->m_trait_args == other.m_trait_args)
+ {
+ return true;
+ }
+
// 1. Are the impl types of the same form (or is one generic)
if( ! H::types_overlap(this->m_type, other.m_type) )
return false;
if( ! H::types_overlap(this->m_trait_args, other.m_trait_args) )
return false;
- return this->m_type == other.m_type && this->m_trait_args == other.m_trait_args;
+ DEBUG("TODO: Handle potential overlap (when not exactly equal)");
+ //return this->m_type == other.m_type && this->m_trait_args == other.m_trait_args;
+ Span sp;
+
+ // TODO: Use `type_ord_specific` but treat any case of mixed ordering as this returning `false`
+ try
+ {
+ type_ord_specific(sp, this->m_type, other.m_type);
+ typelist_ord_specific(sp, this->m_trait_args.m_types, other.m_trait_args.m_types);
+ }
+ catch(const TypeOrdSpecific_MixedOrdering& /*e*/)
+ {
+ return false;
+ }
// TODO: Detect `impl<T> Foo<T> for Bar<T>` vs `impl<T> Foo<&T> for Bar<T>`
// > Create values for impl params from the type, then check if the trait params are compatible
+ // > Requires two lists, and telling which one to use by the end
+ auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; };
+ ::std::vector<const ::HIR::TypeRef*> impl_tys;
+ auto cb_match = [&](unsigned int idx, const ::HIR::TypeRef& x)->::HIR::Compare {
+ assert(idx < impl_tys.size());
+ if( impl_tys.at(idx) )
+ {
+ DEBUG("Compare " << x << " and " << *impl_tys.at(idx));
+ return (x == *impl_tys.at(idx) ? ::HIR::Compare::Equal : ::HIR::Compare::Unequal);
+ }
+ else
+ {
+ impl_tys.at(idx) = &x;
+ return ::HIR::Compare::Equal;
+ }
+ };
+ impl_tys.resize( this->m_params.m_types.size() );
+ if( ! this->m_type.match_test_generics(sp, other.m_type, cb_ident, cb_match) )
+ {
+ DEBUG("- Type mismatch, try other ordering");
+ impl_tys.clear(); impl_tys.resize( other.m_params.m_types.size() );
+ if( !other.m_type.match_test_generics(sp, this->m_type, cb_ident, cb_match) )
+ {
+ DEBUG("- Type mismatch in both orderings");
+ return false;
+ }
+ if( other.m_trait_args.match_test_generics_fuzz(sp, this->m_trait_args, cb_ident, cb_match) != ::HIR::Compare::Equal )
+ {
+ DEBUG("- Params mismatch");
+ return false;
+ }
+ // Matched with second ording
+ }
+ else if( this->m_trait_args.match_test_generics_fuzz(sp, other.m_trait_args, cb_ident, cb_match) != ::HIR::Compare::Equal )
+ {
+ DEBUG("- Param mismatch, try other ordering");
+ impl_tys.clear(); impl_tys.resize( other.m_params.m_types.size() );
+ if( !other.m_type.match_test_generics(sp, this->m_type, cb_ident, cb_match) )
+ {
+ DEBUG("- Type mismatch in alt ordering");
+ return false;
+ }
+ if( other.m_trait_args.match_test_generics_fuzz(sp, this->m_trait_args, cb_ident, cb_match) != ::HIR::Compare::Equal )
+ {
+ DEBUG("- Params mismatch in alt ordering");
+ return false;
+ }
+ // Matched with second ordering
+ }
+ else
+ {
+ // Matched with first ordering
+ }
+
return true;
}
diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp
index f51d7990..da6446d7 100644
--- a/src/hir/pattern.cpp
+++ b/src/hir/pattern.cpp
@@ -126,16 +126,16 @@ namespace HIR {
os << "]";
),
(SplitSlice,
- os << "[";
+ os << "[ ";
for(const auto& s : e.leading)
os << s << ", ";
if( e.extra_bind.is_valid() ) {
os << e.extra_bind;
}
- os << ".. ";
+ os << "..";
for(const auto& s : e.trailing)
- os << s << ", ";
- os << "]";
+ os << ", " << s;
+ os << " ]";
)
)
return os;
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp
index 20e8f7ca..cf443eb6 100644
--- a/src/hir_conv/bind.cpp
+++ b/src/hir_conv/bind.cpp
@@ -247,35 +247,42 @@ namespace {
),
(Struct,
const auto& str = get_struct_ptr(sp, m_crate, e.path);
- TU_IFLET(::HIR::Struct::Data, str.m_data, Named, _,
- e.binding = &str;
- )
+ if(str.m_data.is_Named() ) {
+ }
+ else if( str.m_data.is_Unit() && e.sub_patterns.size() == 0 ) {
+ }
+ 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_expand/closures.cpp b/src/hir_expand/closures.cpp
index 82681a47..b58f2398 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 1b4317a6..fe67865f 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 );
}
@@ -473,6 +488,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();
)
)
@@ -704,6 +727,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),
@@ -713,7 +739,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;
@@ -728,6 +757,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());
}
@@ -992,10 +1022,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, &params, 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, &params, 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 <ity as trait>::name
+ }
+ else if( res != atyv )
+ {
+ ERROR(sp, E0000, "Associated type on " << trait << params << " for " << ity << " doesn't match - " << res << " != " << atyv);
+ }
+ }
return true;
});
@@ -1003,7 +1052,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/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 2388d078..eb922414 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 );
}
@@ -1155,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;
),
@@ -1162,6 +1170,18 @@ namespace {
TODO(node.span(), "StructLiteral of a union - " << ty);
),
(Struct,
+ 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");
+
+ if( node.m_base_value ) {
+ auto _ = this->push_inner_coerce_scoped(false);
+ node.m_base_value->visit( *this );
+ }
+ 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;
)
@@ -1208,7 +1228,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
@@ -3390,7 +3410,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
@@ -3730,10 +3751,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;
@@ -3806,6 +3831,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;
@@ -4123,22 +4151,35 @@ 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;
}
// 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,
@@ -4155,8 +4196,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;
)
@@ -4702,12 +4751,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;
)
@@ -4908,8 +4960,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") )
{
@@ -4974,7 +5046,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
@@ -4993,9 +5065,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);
@@ -5006,27 +5079,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) )
{
+ 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) )
{
- // Ignore
+ DEBUG("[check_associated] - More specific than existing - " << 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
@@ -5602,6 +5681,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 ) {
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index a1c64bec..a3fe9b1c 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -469,6 +469,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);
),
@@ -1079,25 +1081,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 ) {
@@ -2155,7 +2145,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 )
@@ -2163,6 +2153,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) ) {
@@ -2814,6 +2805,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;
}
@@ -2897,6 +2905,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);
@@ -3284,6 +3352,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 ) {
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<void(::HIR::TypeRef new_dst)> new_type_callback) const {
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index 8baa2557..d8b692c9 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 ---
@@ -1204,6 +1206,43 @@ bool StaticTraitResolve::iterate_bounds( ::std::function<bool(const ::HIR::Gener
}
return false;
}
+
+
+bool StaticTraitResolve::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function<bool(const ::HIR::TraitPath&)> 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 `<Self as Trait>::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;
+}
+
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
@@ -1435,6 +1474,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<Struct<..., U, ...>>
+ 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_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());
+ 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<bool(const ::HIR::TraitPath&)> 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/main.cpp b/src/main.cpp
index 8616ff2f..ec4e9f38 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -483,6 +483,7 @@ int main(int argc, char *argv[])
// - MIR Exportable (public generic, #[inline], or used by a either of those)
// - Require codegen (public or used by an exported function)
TransOptions trans_opt;
+ trans_opt.opt_level = params.opt_level;
for(const char* libdir : params.lib_search_dirs ) {
trans_opt.library_search_dirs.push_back( libdir );
}
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index ceda0a87..d9796aed 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -1723,6 +1723,16 @@ namespace {
}));
}
+ // rustc has drop_in_place as a lang item, mrustc uses an intrinsic
+ if( gpath.m_path == m_builder.crate().get_lang_item_path_opt("drop_in_place") )
+ {
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ next_block, panic_block,
+ res.clone(), ::MIR::CallTarget::make_Intrinsic({ "drop_in_place", gpath.m_params.clone() }),
+ mv$(values)
+ }));
+ }
+
if( fcn.m_return.m_data.is_Diverge() )
{
unconditional_diverge = true;
@@ -1814,19 +1824,22 @@ namespace {
::std::stringstream(node.m_field) >> idx;
m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) );
}
- else if( val_ty.m_data.as_Path().binding.is_Struct() ) {
- const auto& str = *node.m_value->m_res_type.m_data.as_Path().binding.as_Struct();
+ else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) {
+ const auto& str = **bep;
const auto& fields = str.m_data.as_Named();
idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin();
m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) );
}
- else {
- const auto& unm = *node.m_value->m_res_type.m_data.as_Path().binding.as_Union();
+ else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Union() ) {
+ const auto& unm = **bep;
const auto& fields = unm.m_variants;
idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin();
m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) );
}
+ else {
+ BUG(node.span(), "Field access on non-union/struct - " << val_ty);
+ }
}
void visit(::HIR::ExprNode_Literal& node) override
{
@@ -2075,6 +2088,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();
)
)
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp
index 9242ccb7..c38e73e9 100644
--- a/src/mir/helpers.cpp
+++ b/src/mir/helpers.cpp
@@ -106,31 +106,53 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c
return te[e.field_index];
),
(Path,
- MIR_ASSERT(*this, te.binding.is_Struct(), "Field on non-Struct - " << ty);
- const auto& str = *te.binding.as_Struct();
- auto monomorph = [&](const auto& ty)->const auto& {
- if( monomorphise_type_needed(ty) ) {
- tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty);
- m_resolve.expand_associated_types(sp, tmp);
- return tmp;
- }
- else {
- return ty;
- }
- };
- TU_MATCHA( (str.m_data), (se),
- (Unit,
- MIR_BUG(*this, "Field on unit-like struct - " << ty);
- ),
- (Tuple,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path);
- return monomorph(se[e.field_index].ent);
- ),
- (Named,
- MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path);
- return monomorph(se[e.field_index].second.ent);
+ if( const auto* tep = te.binding.opt_Struct() )
+ {
+ const auto& str = **tep;
+ auto monomorph = [&](const auto& ty)->const auto& {
+ if( monomorphise_type_needed(ty) ) {
+ tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty);
+ m_resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return ty;
+ }
+ };
+ TU_MATCHA( (str.m_data), (se),
+ (Unit,
+ MIR_BUG(*this, "Field on unit-like struct - " << ty);
+ ),
+ (Tuple,
+ MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path);
+ return monomorph(se[e.field_index].ent);
+ ),
+ (Named,
+ MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path);
+ return monomorph(se[e.field_index].second.ent);
+ )
)
- )
+ }
+ else if( const auto* tep = te.binding.opt_Union() )
+ {
+ const auto& unm = **tep;
+ auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& {
+ if( monomorphise_type_needed(t) ) {
+ tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t);
+ m_resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return t;
+ }
+ };
+ MIR_ASSERT(*this, e.field_index < unm.m_variants.size(), "Field index out of range for union");
+ return maybe_monomorph(unm.m_variants.at(e.field_index).second.ent);
+ }
+ else
+ {
+ MIR_BUG(*this, "Field access on invalid type - " << ty);
+ }
)
)
),
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index 8cb8c088..478146e8 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)
@@ -1638,39 +1640,59 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::
cb( *te.inner );
),
(Path,
- ASSERT_BUG(sp, te.binding.is_Struct(), "Field on non-Struct - " << ty);
- const auto& str = *te.binding.as_Struct();
- TU_MATCHA( (str.m_data), (se),
- (Unit,
- BUG(sp, "Field on unit-like struct - " << ty);
- ),
- (Tuple,
- ASSERT_BUG(sp, e.field_index < se.size(),
- "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size());
- const auto& fld = se[e.field_index];
- if( monomorphise_type_needed(fld.ent) ) {
- auto sty = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- m_resolve.expand_associated_types(sp, sty);
- cb(sty);
- }
- else {
- cb(fld.ent);
- }
- ),
- (Named,
- ASSERT_BUG(sp, e.field_index < se.size(),
- "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size());
- const auto& fld = se[e.field_index].second;
- if( monomorphise_type_needed(fld.ent) ) {
- auto sty = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent);
- m_resolve.expand_associated_types(sp, sty);
- cb(sty);
- }
- else {
- cb(fld.ent);
- }
+ ::HIR::TypeRef tmp;
+ if( const auto* tep = te.binding.opt_Struct() )
+ {
+ const auto& str = **tep;
+ auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& {
+ if( monomorphise_type_needed(t) ) {
+ tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, t);
+ m_resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return t;
+ }
+ };
+ TU_MATCHA( (str.m_data), (se),
+ (Unit,
+ BUG(sp, "Field on unit-like struct - " << ty);
+ ),
+ (Tuple,
+ ASSERT_BUG(sp, e.field_index < se.size(),
+ "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size());
+ const auto& fld = se[e.field_index];
+ cb( maybe_monomorph(fld.ent) );
+ ),
+ (Named,
+ ASSERT_BUG(sp, e.field_index < se.size(),
+ "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size());
+ const auto& fld = se[e.field_index].second;
+ cb( maybe_monomorph(fld.ent) );
+ )
)
- )
+ }
+ else if( const auto* tep = te.binding.opt_Union() )
+ {
+ BUG(sp, "Field access on a union isn't valid, use Downcast instead - " << ty);
+ const auto& unm = **tep;
+ auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& {
+ if( monomorphise_type_needed(t) ) {
+ tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t);
+ m_resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return t;
+ }
+ };
+ ASSERT_BUG(sp, e.field_index < unm.m_variants.size(), "Field index out of range for union");
+ cb( maybe_monomorph(unm.m_variants.at(e.field_index).second.ent) );
+ }
+ else
+ {
+ BUG(sp, "Field acess on unexpected type - " << ty);
+ }
),
(Tuple,
ASSERT_BUG(sp, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size());
@@ -2196,8 +2218,10 @@ void MirBuilder::drop_value_from_state(const Span& sp, const VarState& vs, ::MIR
),
(Partial,
bool is_enum = false;
+ bool is_union = false;
with_val_type(sp, lv, [&](const auto& ty){
is_enum = ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum();
+ is_union = ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Union();
});
if(is_enum)
{
@@ -2207,6 +2231,10 @@ void MirBuilder::drop_value_from_state(const Span& sp, const VarState& vs, ::MIR
// drop_value_from_state(sp, vse.inner_states[i], ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast<unsigned int>(i) }));
//}
}
+ else if( is_union )
+ {
+ // NOTE: Unions don't drop inner items.
+ }
else
{
for(size_t i = 0; i < vse.inner_states.size(); i ++)
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index 3b5fa036..8e350c45 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -390,6 +390,58 @@ namespace {
)
return nullptr;
}
+
+
+ void visit_blocks_mut(::MIR::TypeResolve& state, ::MIR::Function& fcn, ::std::function<void(::MIR::BasicBlockId, ::MIR::BasicBlock&)> cb)
+ {
+ ::std::vector<bool> visited( fcn.blocks.size() );
+ ::std::vector< ::MIR::BasicBlockId> to_visit;
+ to_visit.push_back( 0 );
+ while( to_visit.size() > 0 )
+ {
+ auto bb = to_visit.back(); to_visit.pop_back();
+ if( visited[bb] ) continue;
+ visited[bb] = true;
+ auto& block = fcn.blocks[bb];
+
+ cb(bb, block);
+
+ TU_MATCHA( (block.terminator), (e),
+ (Incomplete,
+ ),
+ (Return,
+ ),
+ (Diverge,
+ ),
+ (Goto,
+ if( !visited[e] )
+ to_visit.push_back(e);
+ ),
+ (Panic,
+ ),
+ (If,
+ if( !visited[e.bb0] )
+ to_visit.push_back(e.bb0);
+ if( !visited[e.bb1] )
+ to_visit.push_back(e.bb1);
+ ),
+ (Switch,
+ for(auto& target : e.targets)
+ if( !visited[target] )
+ to_visit.push_back(target);
+ ),
+ (Call,
+ if( !visited[e.ret_block] )
+ to_visit.push_back(e.ret_block);
+ if( !visited[e.panic_block] )
+ to_visit.push_back(e.panic_block);
+ )
+ )
+ }
+ }
+ void visit_blocks(::MIR::TypeResolve& state, const ::MIR::Function& fcn, ::std::function<void(::MIR::BasicBlockId, const ::MIR::BasicBlock&)> cb) {
+ visit_blocks_mut(state, const_cast<::MIR::Function&>(fcn), [cb](auto id, auto& blk){ cb(id, blk); });
+ }
}
bool MIR_Optimise_BlockSimplify(::MIR::TypeResolve& state, ::MIR::Function& fcn);
@@ -398,6 +450,7 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F
bool MIR_Optimise_UnifyTemporaries(::MIR::TypeResolve& state, ::MIR::Function& fcn);
bool MIR_Optimise_UnifyBlocks(::MIR::TypeResolve& state, ::MIR::Function& fcn);
bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn);
+bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn);
bool MIR_Optimise_GarbageCollect_Partial(::MIR::TypeResolve& state, ::MIR::Function& fcn);
bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn);
@@ -445,6 +498,9 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
// >> Combine Duplicate Blocks
change_happened |= MIR_Optimise_UnifyBlocks(state, fcn);
+ // >> Remove assignments of unsed drop flags
+ change_happened |= MIR_Optimise_DeadDropFlags(state, fcn);
+
if( change_happened )
{
#if DUMP_AFTER_PASS
@@ -2231,6 +2287,45 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F
return replacement_happend;
}
+// ----------------------------------------
+// Clear all drop flags that are never read
+// ----------------------------------------
+bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn)
+{
+ ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() );
+ visit_blocks(state, fcn, [&read_drop_flags](auto , const ::MIR::BasicBlock& block) {
+ for(const auto& stmt : block.statements)
+ {
+ if( const auto* e = stmt.opt_SetDropFlag() )
+ {
+ if(e->other != ~0u) {
+ read_drop_flags[e->other] = true;
+ }
+ }
+ else if( const auto* e = stmt.opt_Drop() )
+ {
+ if(e->flag_idx != ~0u) {
+ read_drop_flags[e->flag_idx] = true;
+ }
+ }
+ }
+ });
+ bool removed_statement = false;
+ visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) {
+ for(auto it = block.statements.begin(); it != block.statements.end(); )
+ {
+ if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) {
+ removed_statement = true;
+ it = block.statements.erase(it);
+ }
+ else {
+ ++ it;
+ }
+ }
+ });
+ return removed_statement;
+}
+
// --------------------------------------------------------------------
// Clear all unused blocks
@@ -2238,47 +2333,10 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F
bool MIR_Optimise_GarbageCollect_Partial(::MIR::TypeResolve& state, ::MIR::Function& fcn)
{
::std::vector<bool> visited( fcn.blocks.size() );
- ::std::vector< ::MIR::BasicBlockId> to_visit;
- to_visit.push_back( 0 );
- while( to_visit.size() > 0 )
- {
- auto bb = to_visit.back(); to_visit.pop_back();
- if( visited[bb] ) continue;
- visited[bb] = true;
- const auto& block = fcn.blocks[bb];
-
- TU_MATCHA( (block.terminator), (e),
- (Incomplete,
- ),
- (Return,
- ),
- (Diverge,
- ),
- (Goto,
- if( !visited[e] )
- to_visit.push_back(e);
- ),
- (Panic,
- ),
- (If,
- if( !visited[e.bb0] )
- to_visit.push_back(e.bb0);
- if( !visited[e.bb1] )
- to_visit.push_back(e.bb1);
- ),
- (Switch,
- for(auto& target : e.targets)
- if( !visited[target] )
- to_visit.push_back(target);
- ),
- (Call,
- if( !visited[e.ret_block] )
- to_visit.push_back(e.ret_block);
- if( !visited[e.panic_block] )
- to_visit.push_back(e.panic_block);
- )
- )
- }
+ visit_blocks(state, fcn, [&visited](auto bb, const auto& _blokc) {
+ assert( !visited[bb] );
+ visited[bb] = true;
+ });
bool rv = false;
for(unsigned int i = 0; i < visited.size(); i ++)
{
@@ -2301,13 +2359,9 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn
::std::vector<bool> used_vars( fcn.named_variables.size() );
::std::vector<bool> used_dfs( fcn.drop_flags.size() );
::std::vector<bool> visited( fcn.blocks.size() );
- ::std::vector< ::MIR::BasicBlockId> to_visit;
- to_visit.push_back( 0 );
- while( to_visit.size() > 0 )
- {
- auto bb = to_visit.back(); to_visit.pop_back();
+
+ visit_blocks(state, fcn, [&](auto bb, const auto& block) {
visited[bb] = true;
- const auto& block = fcn.blocks[bb];
auto assigned_lval = [&](const ::MIR::LValue& lv) {
if(const auto* le = lv.opt_Temporary() )
@@ -2339,40 +2393,11 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn
}
}
- TU_MATCHA( (block.terminator), (e),
- (Incomplete,
- ),
- (Return,
- ),
- (Diverge,
- ),
- (Goto,
- if( !visited[e] )
- to_visit.push_back(e);
- ),
- (Panic,
- ),
- (If,
- if( !visited[e.bb0] )
- to_visit.push_back(e.bb0);
- if( !visited[e.bb1] )
- to_visit.push_back(e.bb1);
- ),
- (Switch,
- for(auto& target : e.targets)
- if( !visited[target] )
- to_visit.push_back(target);
- ),
- (Call,
- if( !visited[e.ret_block] )
- to_visit.push_back(e.ret_block);
- if( !visited[e.panic_block] )
- to_visit.push_back(e.panic_block);
-
- assigned_lval(e.ret_val);
- )
- )
- }
+ if( const auto* te = block.terminator.opt_Call() )
+ {
+ assigned_lval(te->ret_val);
+ }
+ });
::std::vector<unsigned int> block_rewrite_table;
for(unsigned int i = 0, j = 0; i < fcn.blocks.size(); i ++)
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index bc17ea9e..28729b93 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -999,9 +999,18 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
while( GET_TOK(tok, lex) == TOK_IDENT )
{
auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- ExprNodeP val = Parse_Stmt(lex);
- items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+
+ if( lex.lookahead(0) != TOK_COLON )
+ {
+ ExprNodeP val = NEWNODE( AST::ExprNode_NamedValue, ::AST::Path(name) );
+ items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+ }
+ else
+ {
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ ExprNodeP val = Parse_Stmt(lex);
+ items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+ }
if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
break;
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index a92753d8..0587e443 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -466,11 +466,13 @@ Token Lexer::getTokenInt()
else if(suffix == "i16") num_type = CORETYPE_I16;
else if(suffix == "i32") num_type = CORETYPE_I32;
else if(suffix == "i64") num_type = CORETYPE_I64;
+ else if(suffix == "i128") num_type = CORETYPE_I128;
else if(suffix == "isize") num_type = CORETYPE_INT;
else if(suffix == "u8") num_type = CORETYPE_U8;
else if(suffix == "u16") num_type = CORETYPE_U16;
else if(suffix == "u32") num_type = CORETYPE_U32;
else if(suffix == "u64") num_type = CORETYPE_U64;
+ else if(suffix == "u128") num_type = CORETYPE_U128;
else if(suffix == "usize") num_type = CORETYPE_UINT;
else if(suffix == "f32") num_type = CORETYPE_F32;
else if(suffix == "f64") num_type = CORETYPE_F64;
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 3bdd34b1..5f8ed0a3 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -563,7 +563,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
else if(tok.type() == TOK_SEMICOLON)
{
// Unit-like struct
- return AST::Struct(mv$(params), ::std::vector<AST::TupleItem>());
+ return AST::Struct(mv$(params));
}
else if(tok.type() == TOK_BRACE_OPEN)
{
@@ -594,7 +594,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
}
//if( items.size() == 0 )
// WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong");
- return AST::Struct(::std::move(params), ::std::move(items));
+ return AST::Struct(mv$(params), mv$(items));
}
else
{
@@ -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<TypeRef> 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()) );
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index db85ed3f..26a45a1e 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -1020,7 +1020,7 @@ namespace {
}
break;
}
- ERROR(sp, E0000, "Couldn't find path component '" << path_abs.nodes.back().name() << "' of " << path);
+ ERROR(sp, E0000, "Couldn't find " << Context::lookup_mode_msg(mode) << " '" << path_abs.nodes.back().name() << "' of " << path);
}
}
@@ -1946,6 +1946,8 @@ void Resolve_Absolute_Struct(Context& item_context, ::AST::Struct& e)
Resolve_Absolute_Generic(item_context, e.params());
TU_MATCH(::AST::StructData, (e.m_data), (s),
+ (Unit,
+ ),
(Tuple,
for(auto& field : s.ents) {
Resolve_Absolute_Type(item_context, field.m_type);
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index 7b988bc0..f57fc3e6 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -149,7 +149,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
(Struct,
p.bind( ::AST::PathBinding::make_Struct({&e}) );
// - If the struct is a tuple-like struct (or unit-like), it presents in the value namespace
- if( e.m_data.is_Tuple() ) {
+ if( ! e.m_data.is_Struct() ) {
_add_item_value(i.data.span, mod, i.name, i.is_pub, p);
}
_add_item_type(i.data.span, mod, i.name, i.is_pub, mv$(p));
@@ -209,15 +209,9 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
_add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
// - If the struct is a tuple-like struct, it presents in the value namespace
assert(e.struct_ || e.hir);
- if( e.struct_ ) {
- if( e.struct_->m_data.is_Tuple() ) {
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
- }
- }
- else {
- if( ! e.hir->m_data.is_Named() ) {
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
- }
+ if( !(e.struct_ ? e.struct_->m_data.is_Struct() : e.hir->m_data.is_Named()) )
+ {
+ _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
}
),
(Static , _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide); ),
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp
index 7989981b..a571b5e4 100644
--- a/src/trans/codegen.cpp
+++ b/src/trans/codegen.cpp
@@ -87,16 +87,18 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const
{
DEBUG("FUNCTION " << ent.first);
assert( ent.second->ptr );
- if( ent.second->ptr->m_code.m_mir ) {
- codegen->emit_function_proto(ent.first, *ent.second->ptr, ent.second->pp);
+ const auto& fcn = *ent.second->ptr;
+ bool is_extern = ! static_cast<bool>(fcn.m_code);
+ if( fcn.m_code.m_mir ) {
+ codegen->emit_function_proto(ent.first, fcn, ent.second->pp, is_extern);
}
else {
// TODO: Why would an intrinsic be in the queue?
// - If it's exported it does.
- if( ent.second->ptr->m_abi == "rust-intrinsic" ) {
+ if( fcn.m_abi == "rust-intrinsic" ) {
}
else {
- codegen->emit_function_ext(ent.first, *ent.second->ptr, ent.second->pp);
+ codegen->emit_function_ext(ent.first, fcn, ent.second->pp);
}
}
}
@@ -148,7 +150,8 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const
const auto& pp = ent.second->pp;
TRACE_FUNCTION_F(path);
DEBUG("FUNCTION CODE " << path);
- // TODO: If this is a provided trait method, it needs to be monomorphised too.
+ bool is_extern = ! static_cast<bool>(fcn.m_code);
+ // If this is a provided trait method, it needs to be monomorphised too.
bool is_method = ( fcn.m_args.size() > 0 && visit_ty_with(fcn.m_args[0].second, [&](const auto& x){return x == ::HIR::TypeRef("Self",0xFFFF);}) );
if( pp.has_types() || is_method )
{
@@ -164,11 +167,14 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const
MIR_Cleanup(resolve, ip, *mir, args, ret_type);
MIR_Optimise(resolve, ip, *mir, args, ret_type);
MIR_Validate(resolve, ip, *mir, args, ret_type);
- codegen->emit_function_code(path, fcn, ent.second->pp, mir);
+ // TODO: Flag that this should be a weak (or weak-er) symbol?
+ // - If it's from an external crate, it should be weak
+ codegen->emit_function_code(path, fcn, ent.second->pp, is_extern, mir);
}
// TODO: Detect if the function was a #[inline] function from another crate, and don't emit if that is the case?
+ // - Emiting is nice, but it should be emitted as a weak symbol
else {
- codegen->emit_function_code(path, fcn, pp, fcn.m_code.m_mir);
+ codegen->emit_function_code(path, fcn, pp, is_extern, fcn.m_code.m_mir);
}
}
}
diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp
index b317e632..65135d18 100644
--- a/src/trans/codegen.hpp
+++ b/src/trans/codegen.hpp
@@ -50,8 +50,8 @@ public:
virtual void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {}
virtual void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) {}
- virtual void emit_function_proto(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) {}
- virtual void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, const ::MIR::FunctionPointer& code) {}
+ virtual void emit_function_proto(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def) {}
+ virtual void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def, const ::MIR::FunctionPointer& code) {}
};
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 2d7a521d..946c7fac 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -119,13 +119,13 @@ namespace {
auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start");
if( c_start_path == ::HIR::SimplePath() )
{
- m_of << "\t" << Trans_Mangle( ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "start")) ) << "("
+ m_of << "\treturn " << Trans_Mangle( ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "start")) ) << "("
<< "(uint8_t*)" << Trans_Mangle( ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "mrustc-main")) ) << ", argc, (uint8_t**)argv"
<< ");\n";
}
else
{
- m_of << "\t" << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(argc, argv);\n";
+ m_of << "\treturn " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(argc, argv);\n";
}
m_of << "}\n";
}
@@ -195,7 +195,8 @@ namespace {
// TODO: use a formatter specific to shell escaping
cmd_ss << "\"" << FmtEscaped(arg) << "\" ";
}
- DEBUG("- " << cmd_ss.str());
+ //DEBUG("- " << cmd_ss.str());
+ ::std::cout << "Running comamnd - " << cmd_ss.str() << ::std::endl;
if( system(cmd_ss.str().c_str()) )
{
abort();
@@ -425,6 +426,8 @@ namespace {
::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> > args;
if( item.m_markings.has_drop_impl ) {
+ if( p.m_path.m_crate_name != m_crate.m_crate_name )
+ m_of << "static ";
m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ");\n";
}
else if( m_resolve.is_type_owned_box(struct_ty) )
@@ -1062,7 +1065,15 @@ namespace {
}
),
(Float,
- m_of << e;
+ if( ::std::isnan(e) ) {
+ m_of << "NAN";
+ }
+ else if( ::std::isinf(e) ) {
+ m_of << "INFINITY";
+ }
+ else {
+ m_of << e;
+ }
),
(BorrowOf,
TU_MATCHA( (e.m_data), (pe),
@@ -1246,7 +1257,7 @@ namespace {
m_mir_res = nullptr;
}
- void emit_function_proto(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) override
+ void emit_function_proto(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def) override
{
::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "/*proto*/ fn " << p;), ::HIR::TypeRef(), {}, *(::MIR::Function*)nullptr };
m_mir_res = &top_mir_res;
@@ -1256,12 +1267,16 @@ namespace {
{
m_of << "#define " << Trans_Mangle(p) << " " << item.m_linkage.name << "\n";
}
+ if( is_extern_def )
+ {
+ m_of << "static ";
+ }
emit_function_header(p, item, params);
m_of << ";\n";
m_mir_res = nullptr;
}
- void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, const ::MIR::FunctionPointer& code) override
+ void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def, const ::MIR::FunctionPointer& code) override
{
TRACE_FUNCTION_F(p);
@@ -1276,6 +1291,9 @@ namespace {
m_mir_res = &mir_res;
m_of << "// " << p << "\n";
+ if( is_extern_def ) {
+ m_of << "static ";
+ }
emit_function_header(p, item, params);
m_of << "\n";
m_of << "{\n";
@@ -2186,18 +2204,23 @@ namespace {
switch( ty.m_data.as_Primitive() )
{
case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::I8:
emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0));
break;
case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::I16:
emit_lvalue(e.ret_val); m_of << " = __builtin_bswap16("; emit_param(e.args.at(0)); m_of << ")";
break;
case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::I32:
emit_lvalue(e.ret_val); m_of << " = __builtin_bswap32("; emit_param(e.args.at(0)); m_of << ")";
break;
case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::I64:
emit_lvalue(e.ret_val); m_of << " = __builtin_bswap64("; emit_param(e.args.at(0)); m_of << ")";
break;
case ::HIR::CoreType::U128:
+ case ::HIR::CoreType::I128:
emit_lvalue(e.ret_val); m_of << " = __builtin_bswap128("; emit_param(e.args.at(0)); m_of << ")";
break;
default:
@@ -2273,6 +2296,12 @@ namespace {
else if( name == "unchecked_rem" ) {
emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " % "; emit_param(e.args.at(1));
}
+ else if( name == "unchecked_shl" ) {
+ emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " << "; emit_param(e.args.at(1));
+ }
+ else if( name == "unchecked_shr" ) {
+ emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " >> "; emit_param(e.args.at(1));
+ }
// Bit Twiddling
// - CounT Leading Zeroes
// - CounT Trailing Zeroes
@@ -2463,6 +2492,9 @@ namespace {
auto ordering = H::get_atomic_ordering(mir_res, name, 7+6);
m_of << "atomic_thread_fence(" << ordering << ")";
}
+ else if( name == "atomic_singlethreadfence" || name.compare(0, 7+18, "atomic_singlethreadfence_") == 0 ) {
+ // TODO: Does this matter?
+ }
else {
MIR_BUG(mir_res, "Unknown intrinsic '" << name << "'");
}
@@ -2718,7 +2750,8 @@ namespace {
emit_literal(ty, lit, {});
),
(Float,
- emit_dst(); m_of << " = " << e;
+ emit_dst(); m_of << " = ";
+ emit_literal(ty, lit, {});
),
(BorrowOf,
if( ty.m_data.is_Function() )
diff --git a/src/trans/mangling.cpp b/src/trans/mangling.cpp
index 4ea56581..0f3acfd9 100644
--- a/src/trans/mangling.cpp
+++ b/src/trans/mangling.cpp
@@ -148,7 +148,7 @@ namespace {
),
(Tuple,
return FMT_CB(ss,
- ss << "$T";
+ ss << "$T" << te.size();
for(const auto& t : te)
ss << "_" << Trans_Mangle(t);
);