diff options
-rw-r--r-- | src/hir_typeck/static.cpp | 145 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 3 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 8 |
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" ) { |