summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/static.cpp145
-rw-r--r--src/hir_typeck/static.hpp3
-rw-r--r--src/trans/codegen_c.cpp8
3 files changed, 152 insertions, 4 deletions
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index 1bc6820c..f3b483c9 100644
--- a/src/hir_typeck/static.cpp
+++ b/src/hir_typeck/static.cpp
@@ -1378,6 +1378,151 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty)
throw "";
}
+bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeRef& ty) const
+{
+ // If `T: Copy`, then it can't need drop glue
+ if( type_is_copy(sp, ty) )
+ return false;
+
+ TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e),
+ (Generic,
+ return true;
+ ),
+ (Path,
+ if( e.binding.is_Opaque() )
+ return true;
+
+ auto pp = ::HIR::PathParams();
+ bool has_direct_drop = this->find_impl(sp, m_lang_Drop, &pp, ty, [&](auto , bool){ return true; }, true);
+ if( has_direct_drop )
+ return true;
+
+ ::HIR::TypeRef tmp_ty;
+ const auto& pe = e.path.m_data.as_Generic();
+ auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.m_params, nullptr, nullptr);
+ auto monomorph = [&](const auto& tpl)->const ::HIR::TypeRef& {
+ if( monomorphise_type_needed(tpl) ) {
+ tmp_ty = monomorphise_type_with(sp, tpl, monomorph_cb, false);
+ this->expand_associated_types(sp, tmp_ty);
+ return tmp_ty;
+ }
+ else {
+ return tpl;
+ }
+ };
+ TU_MATCHA( (e.binding), (pbe),
+ (Unbound,
+ BUG(sp, "Unbound path");
+ ),
+ (Opaque,
+ // Technically a bug, checked above
+ return true;
+ ),
+ (Struct,
+ TU_MATCHA( (pbe->m_data), (se),
+ (Unit,
+ ),
+ (Tuple,
+ for(const auto& e : se)
+ {
+ if( type_needs_drop_glue(sp, monomorph(e.ent)) )
+ return true;
+ }
+ ),
+ (Named,
+ for(const auto& e : se)
+ {
+ if( type_needs_drop_glue(sp, monomorph(e.second.ent)) )
+ return true;
+ }
+ )
+ )
+ return false;
+ ),
+ (Enum,
+ for(const auto& e : pbe->m_variants)
+ {
+ TU_MATCHA( (e.second), (ve),
+ (Unit,
+ ),
+ (Value,
+ ),
+ (Tuple,
+ for(const auto& e : ve)
+ {
+ if( type_needs_drop_glue(sp, monomorph(e.ent)) )
+ return true;
+ }
+ ),
+ (Struct,
+ for(const auto& e : ve)
+ {
+ if( type_needs_drop_glue(sp, monomorph(e.second.ent)) )
+ return true;
+ }
+ )
+ )
+ }
+ return false;
+ ),
+ (Union,
+ // Unions don't have drop glue unless they impl Drop
+ return false;
+ )
+ )
+ ),
+ (Diverge,
+ return false;
+ ),
+ (Closure,
+ // TODO: Destructure?
+ return true;
+ ),
+ (Infer,
+ BUG(sp, "type_needs_drop_glue on _");
+ return false;
+ ),
+ (Borrow,
+ // &-ptrs don't have drop glue
+ if( e.type != ::HIR::BorrowType::Owned )
+ return false;
+ return type_needs_drop_glue(sp, *e.inner);
+ ),
+ (Pointer,
+ return false;
+ ),
+ (Function,
+ return false;
+ ),
+ (Primitive,
+ return false;
+ ),
+ (Array,
+ return type_needs_drop_glue(sp, *e.inner);
+ ),
+ (Slice,
+ return type_needs_drop_glue(sp, *e.inner);
+ ),
+ (TraitObject,
+ return true;
+ ),
+ (ErasedType,
+ // Is this an error?
+ return true;
+ ),
+ (Tuple,
+ for(const auto& ty : e)
+ {
+ if( !type_needs_drop_glue(sp, ty) )
+ return true;
+ }
+ return false;
+ )
+ )
+ assert(!"Fell off the end of type_needs_drop_glue");
+ throw "";
+}
+
const ::HIR::TypeRef* StaticTraitResolve::is_type_owned_box(const ::HIR::TypeRef& ty) const
{
if( ! ty.m_data.is_Path() ) {
diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp
index cde9797c..16302218 100644
--- a/src/hir_typeck/static.hpp
+++ b/src/hir_typeck/static.hpp
@@ -178,6 +178,9 @@ 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;
+ /// 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;
+
const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const;
const ::HIR::TypeRef* is_type_phantom_data(const ::HIR::TypeRef& ty) const;
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index c3532073..5386de18 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -2116,15 +2116,15 @@ namespace {
else if( name == "needs_drop" ) {
// Returns `true` if the actual type given as `T` requires drop glue;
// returns `false` if the actual type provided for `T` implements `Copy`. (Either otherwise)
+ // NOTE: libarena assumes that this returns `true` iff T doesn't require drop glue.
const auto& ty = params.m_types.at(0);
emit_lvalue(e.ret_val);
m_of << " = ";
- if( m_resolve.type_is_copy(Span(), ty) ) {
- m_of << "false";
+ if( m_resolve.type_needs_drop_glue(mir_res.sp, ty) ) {
+ m_of << "true";
}
- // If T: !Copy, return true
else {
- m_of << "true";
+ m_of << "false";
}
}
else if( name == "uninit" ) {