Changeset ef1da0e2


Ignore:
Timestamp:
Sep 20, 2022, 6:34:55 PM (2 years ago)
Author:
Fangren Yu <f37yu@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
79ae13d, a065f1f
Parents:
8f1e035
Message:

try to make parameter qualifier conversion work for assertions

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/monitor.hfa

    r8f1e035 ref1da0e2  
    6060void ^?{}( monitor_dtor_guard_t & this );
    6161
     62/*
    6263static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
    6364void delete( T * th ) {
     
    6566        free( th );
    6667}
     68*/
    6769
    6870static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
  • src/AST/Print.cpp

    r8f1e035 ref1da0e2  
    9090
    9191                static constexpr auto Qualifiers = make_array<const char*>(
    92                         "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
     92                        "const", "restrict", "volatile", "mutex", "_Atomic"
    9393                );
    9494        };
     
    16241624constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
    16251625constexpr array<const char*, 6> Printer::Names::StorageClasses;
    1626 constexpr array<const char*, 6> Printer::Names::Qualifiers;
     1626constexpr array<const char*, 5> Printer::Names::Qualifiers;
    16271627}
  • src/AST/TypeEnvironment.hpp

    r8f1e035 ref1da0e2  
    5656struct AssertCompare {
    5757        bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const {
     58                auto kind1 = ast::SymbolTable::getSpecialFunctionKind(d1->var->name);
     59                auto kind2 = ast::SymbolTable::getSpecialFunctionKind(d2->var->name);
     60                // heuristics optimization: force special functions to go last
     61                if (kind1 > kind2) return true;
     62                else if (kind1 < kind2) return false;
     63
    5864                int cmp = d1->var->name.compare( d2->var->name );
    5965                return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
  • src/ResolvExpr/CommonType.cc

    r8f1e035 ref1da0e2  
    2828#include "Unify.h"                       // for unifyExact, WidenMode
    2929#include "typeops.h"                     // for isFtype
     30#include "Tuples/Tuples.h"
    3031
    3132// #define DEBUG
     
    675676                ast::TypeEnvironment & tenv;
    676677                const ast::OpenVarSet & open;
     678                ast::AssertionSet & need;
     679                ast::AssertionSet & have;
    677680        public:
    678681                static size_t traceId;
     
    681684                CommonType_new(
    682685                        const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
    683                         ast::TypeEnvironment & env, const ast::OpenVarSet & o )
    684                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {}
     686                        ast::TypeEnvironment & env, const ast::OpenVarSet & o,
     687                        ast::AssertionSet & need, ast::AssertionSet & have )
     688                : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {}
    685689
    686690                void previsit( const ast::Node * ) { visit_children = false; }
     
    753757                bool tryResolveWithTypedEnum( const ast::Type * type1 ) {
    754758                        if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {
    755                                 ast::AssertionSet have, need; // unused
    756759                                ast::OpenVarSet newOpen{ open };
    757760                                if (enumInst->base->base
     
    792795                                        reset_qualifiers( t2 );
    793796
    794                                         ast::AssertionSet have, need;
    795797                                        ast::OpenVarSet newOpen{ open };
    796798                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    803805                                                }
    804806                                        }
     807                                        else if ( isFtype (t1) && isFtype (t2) ) {
     808                                                auto f1 = t1.as<ast::FunctionType>();
     809                                                if (!f1) return;
     810                                                auto f2 = t2.strict_as<ast::FunctionType>();
     811
     812                                                assertf(f1->returns.size() <= 1, "Function return should not be a list");
     813                                                assertf(f2->returns.size() <= 1, "Function return should not be a list");
     814
     815                                                if (
     816                                                        ( f1->params.size() != f2->params.size() || f1->returns.size() != f2->returns.size() )
     817                                                        && ! f1->isTtype()
     818                                                        && ! f2->isTtype()
     819                                                ) return;
     820
     821                                                auto params1 = flattenList( f1->params, tenv );
     822                                                auto params2 = flattenList( f2->params, tenv );
     823
     824                                                auto crnt1 = params1.begin();
     825                                                auto crnt2 = params2.begin();
     826                                                auto end1 = params1.end();
     827                                                auto end2 = params2.end();
     828
     829                                                while (crnt1 != end1 && crnt2 != end2 ) {
     830                                                        const ast::Type * arg1 = *crnt1;
     831                                                        const ast::Type * arg2 = *crnt2;
     832
     833                                                        bool isTuple1 = Tuples::isTtype( t1 );
     834                                                        bool isTuple2 = Tuples::isTtype( t2 );
     835
     836                                                        // assumes here that ttype *must* be last parameter
     837                                                        if ( isTuple1 && ! isTuple2 ) {
     838                                                                // combine remainder of list2, then unify
     839                                                                if (unifyExact(
     840                                                                        arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
     841                                                                        noWiden(), symtab )) {
     842                                                                                break;
     843
     844                                                                }
     845                                                                else return;
     846                                                        } else if ( ! isTuple1 && isTuple2 ) {
     847                                                                // combine remainder of list1, then unify
     848                                                                if (unifyExact(
     849                                                                        tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open,
     850                                                                        noWiden(), symtab )) {
     851                                                                                break;
     852
     853                                                                }
     854                                                                else return;
     855                                                        }
     856
     857                                                        // allow qualifiers of pointer and reference base to become more specific
     858                                                        if (auto ref1 = dynamic_cast<const ast::ReferenceType *> (arg1)) {
     859                                                                if (auto ref2 = dynamic_cast<const ast::ReferenceType *> (arg2)) {
     860                                                                        ast::ptr<ast::Type> base1 = ref1->base;
     861                                                                        ast::ptr<ast::Type> base2 = ref2->base;
     862
     863                                                                        // xxx - assume LHS is always the target type
     864
     865                                                                        if ( ! ((widen.second && ref2->qualifiers.is_mutex)
     866                                                                        || (ref1->qualifiers.is_mutex == ref2->qualifiers.is_mutex ))) return;
     867
     868                                                                        if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) {
     869
     870                                                                                reset_qualifiers(base1);
     871                                                                                reset_qualifiers(base2);
     872
     873                                                                                if ( ! unifyExact(
     874                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
     875                                                                                ) return;
     876                                                                        }       
     877                                                                }
     878                                                                else return;
     879                                                        }
     880                                                        else if (auto ptr1 = dynamic_cast<const ast::PointerType *> (arg1)) {
     881                                                                if (auto ptr2 = dynamic_cast<const ast::PointerType *> (arg2)) {
     882                                                                        ast::ptr<ast::Type> base1 = ptr1->base;
     883                                                                        ast::ptr<ast::Type> base2 = ptr2->base;
     884
     885                                                                        // xxx - assume LHS is always the target type
     886                                                                        // a function accepting const can always be called by non-const arg
     887
     888                                                                        if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) {
     889
     890                                                                                reset_qualifiers(base1);
     891                                                                                reset_qualifiers(base2);
     892
     893                                                                                if ( ! unifyExact(
     894                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
     895                                                                                ) return;
     896                                                                        }       
     897                                                                }
     898                                                                else return;
     899
     900                                                        }
     901                                                        else if (! unifyExact(
     902                                                                arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return;
     903
     904                                                        ++crnt1; ++crnt2;
     905                                                }
     906                                                if ( crnt1 != end1 ) {
     907                                                        // try unifying empty tuple with ttype
     908                                                        const ast::Type * t1 = *crnt1;
     909                                                        if (! Tuples::isTtype( t1 ) ) return;
     910                                                        if (! unifyExact(
     911                                                                t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
     912                                                                noWiden(), symtab )) return;
     913                                                } else if ( crnt2 != end2 ) {
     914                                                        // try unifying empty tuple with ttype
     915                                                        const ast::Type * t2 = *crnt2;
     916                                                        if (! Tuples::isTtype( t2 ) ) return;
     917                                                        if (! unifyExact(
     918                                                                tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open,
     919                                                                noWiden(), symtab )) return;
     920                                                }
     921                                                if ((f1->returns.size() == 0 && f2->returns.size() == 0)
     922                                                  || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) {
     923                                                        result = pointer;
     924
     925                                                        for (auto & assn : f1->assertions) {
     926                                                                auto i = need.find(assn);
     927                                                                if (i != need.end()) i->second.isUsed = true;
     928                                                                auto j = have.find(assn);
     929                                                                if (j != have.end()) j->second.isUsed = true;
     930                                                        }
     931
     932                                                        for (auto & assn : f2->assertions) {
     933                                                                auto i = need.find(assn);
     934                                                                if (i != need.end()) i->second.isUsed = true;
     935                                                                auto j = have.find(assn);
     936                                                                if (j != have.end()) j->second.isUsed = true;
     937                                                        }
     938
     939                                                }
     940                                        } // if ftype
     941                                       
    805942                                }
    806943                        } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
     
    839976                                        reset_qualifiers( t2 );
    840977
    841                                         ast::AssertionSet have, need;
    842978                                        ast::OpenVarSet newOpen{ open };
    843979                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    857993                                // xxx - does unifying a ref with typed enumInst makes sense?
    858994                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    859                                         result = commonType( type2, ref, widen, symtab, tenv, open );
     995                                        result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
    860996                        }
    861997                }
     
    8771013                        // xxx - is this already handled by unify?
    8781014                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    879                                 result = commonType( type2, enumInst, widen, symtab, tenv, open );
     1015                                result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
    8801016                }
    8811017
     
    8951031                                        reset_qualifiers( t2 );
    8961032
    897                                         ast::AssertionSet have, need;
    8981033                                        ast::OpenVarSet newOpen{ open };
    8991034                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    9991134        ast::ptr< ast::Type > commonType(
    10001135                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    1001                         WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    1002                         const ast::OpenVarSet & open
     1136                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     1137                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
    10031138        ) {
    10041139                unsigned depth1 = type1->referenceDepth();
     
    10361171                }
    10371172                // otherwise both are reference types of the same depth and this is handled by the visitor
    1038                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
     1173                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have };
    10391174                type1->accept( visitor );
    10401175                ast::ptr< ast::Type > result = visitor.core.result;
     
    10471182                                        if ( type->base ) {
    10481183                                                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    1049                                                 ast::AssertionSet have, need;
    10501184                                                ast::OpenVarSet newOpen{ open };
    10511185
  • src/ResolvExpr/ConversionCost.cc

    r8f1e035 ref1da0e2  
    2222#include "ResolvExpr/Cost.h"             // for Cost
    2323#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     24#include "ResolvExpr/Unify.h"
    2425#include "SymTab/Indexer.h"              // for Indexer
    2526#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    2627#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
    2728#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
     29
    2830
    2931namespace ResolvExpr {
     
    655657                                cost = Cost::safe;
    656658                        }
    657                 } else {
     659                }
     660                /*
     661                else if ( const ast::FunctionType * dstFunc = dstAsPtr->base.as<ast::FunctionType>()) {
     662                        if (const ast::FunctionType * srcFunc = pointerType->base.as<ast::FunctionType>()) {
     663                                if (dstFunc->params.empty() && dstFunc->isVarArgs ) {
     664                                        cost = Cost::unsafe; // assign any function to variadic fptr
     665                                }
     666                        }
     667                        else {
     668                                ast::AssertionSet need, have; // unused
     669                                ast::OpenVarSet open;
     670                                env.extractOpenVars(open);
     671                                ast::TypeEnvironment tenv = env;
     672                                if ( unify(dstAsPtr->base, pointerType->base, tenv, need, have, open, symtab) ) {
     673                                        cost = Cost::safe;
     674                                }
     675                        }
     676                        // else infinity
     677                }
     678                */
     679                else {
    658680                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
    659681                        if ( 0 < assignResult && tq1 <= tq2 ) {
  • src/ResolvExpr/SatisfyAssertions.cpp

    r8f1e035 ref1da0e2  
    3636#include "AST/SymbolTable.hpp"
    3737#include "AST/TypeEnvironment.hpp"
     38#include "FindOpenVars.h"
    3839#include "Common/FilterCombos.h"
    3940#include "Common/Indenter.h"
     
    161162
    162163        /// Satisfy a single assertion
    163         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat ) {
     164        bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
    164165                // skip unused assertions
    165166                if ( ! assn.second.isUsed ) return true;
     
    180181                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    181182                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
     183                        else if (skipUnbound) return false;
    182184
    183185                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    205207
    206208                        // only keep candidates which unify
    207                         if ( unify( toType, adjType, newEnv, newNeed, have, newOpen, sat.symtab ) ) {
    208                                 // set up binding slot for recursive assertions
    209                                 ast::UniqueId crntResnSlot = 0;
    210                                 if ( ! newNeed.empty() ) {
    211                                         crntResnSlot = ++globalResnSlot;
    212                                         for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
    213                                 }
    214 
    215                                 matches.emplace_back(
    216                                         cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    217                                         std::move( newOpen ), crntResnSlot );
     209
     210                        ast::OpenVarSet closed;
     211                        findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     212                        findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
     213                        if ( allowConversion ) {
     214                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     215                                        // set up binding slot for recursive assertions
     216                                        ast::UniqueId crntResnSlot = 0;
     217                                        if ( ! newNeed.empty() ) {
     218                                                crntResnSlot = ++globalResnSlot;
     219                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     220                                        }
     221
     222                                        matches.emplace_back(
     223                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     224                                                std::move( newOpen ), crntResnSlot );
     225                                }
     226                        }
     227                        else {
     228                                if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     229                                        // set up binding slot for recursive assertions
     230                                        ast::UniqueId crntResnSlot = 0;
     231                                        if ( ! newNeed.empty() ) {
     232                                                crntResnSlot = ++globalResnSlot;
     233                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     234                                        }
     235
     236                                        matches.emplace_back(
     237                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     238                                                std::move( newOpen ), crntResnSlot );
     239                                }
    218240                        }
    219241                }
     
    413435                // for each current mutually-compatible set of assertions
    414436                for ( SatState & sat : sats ) {
     437                        bool allowConversion = false;
    415438                        // stop this branch if a better option is already found
    416439                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    418441
    419442                        // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen.
     443
    420444                        for (unsigned resetCount = 0; ; ++resetCount) {
    421445                                ast::AssertionList next;
     
    424448                                for ( auto & assn : sat.need ) {
    425449                                        // fail early if any assertion is not satisfiable
    426                                         if ( ! satisfyAssertion( assn, sat ) ) {
     450                                        if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) {
    427451                                                next.emplace_back(assn);
    428452                                                // goto nextSat;
     
    433457                                // fail if nothing resolves
    434458                                else if (next.size() == sat.need.size()) {
    435                                         Indenter tabs{ 3 };
    436                                         std::ostringstream ss;
    437                                         ss << tabs << "Unsatisfiable alternative:\n";
    438                                         print( ss, *sat.cand, ++tabs );
    439                                         ss << (tabs-1) << "Could not satisfy assertion:\n";
    440                                         ast::print( ss, next[0].first, tabs );
    441 
    442                                         errors.emplace_back( ss.str() );
    443                                         goto nextSat;
    444                                 }
     459                                        if (allowConversion) {
     460                                                Indenter tabs{ 3 };
     461                                                std::ostringstream ss;
     462                                                ss << tabs << "Unsatisfiable alternative:\n";
     463                                                print( ss, *sat.cand, ++tabs );
     464                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
     465                                                ast::print( ss, next[0].first, tabs );
     466
     467                                                errors.emplace_back( ss.str() );
     468                                                goto nextSat;
     469                                        }
     470
     471                                        else {
     472                                                allowConversion = true;
     473                                                continue;
     474                                        }
     475                                }
     476                                allowConversion = false;
    445477                                sat.need = std::move(next);
    446478                        }
  • src/ResolvExpr/Unify.cc

    r8f1e035 ref1da0e2  
    693693        }
    694694
     695        namespace {
     696                                /// Replaces ttype variables with their bound types.
     697                /// If this isn't done when satifying ttype assertions, then argument lists can have
     698                /// different size and structure when they should be compatible.
     699                struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
     700                        ast::TypeEnvironment & tenv;
     701
     702                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
     703
     704                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     705                                if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
     706                                        // expand ttype parameter into its actual type
     707                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     708                                                return clz->bound;
     709                                        }
     710                                }
     711                                return typeInst;
     712                        }
     713                };
     714        }
     715       
     716        std::vector< ast::ptr< ast::Type > > flattenList(
     717                const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     718        ) {
     719                std::vector< ast::ptr< ast::Type > > dst;
     720                dst.reserve( src.size() );
     721                for ( const auto & d : src ) {
     722                        ast::Pass<TtypeExpander_new> expander{ env };
     723                        // TtypeExpander pass is impure (may mutate nodes in place)
     724                        // need to make nodes shared to prevent accidental mutation
     725                        ast::ptr<ast::Type> dc = d->accept(expander);
     726                        auto types = flatten( dc );
     727                        for ( ast::ptr< ast::Type > & t : types ) {
     728                                // outermost const, volatile, _Atomic qualifiers in parameters should not play
     729                                // a role in the unification of function types, since they do not determine
     730                                // whether a function is callable.
     731                                // NOTE: **must** consider at least mutex qualifier, since functions can be
     732                                // overloaded on outermost mutex and a mutex function has different
     733                                // requirements than a non-mutex function
     734                                remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
     735                                dst.emplace_back( t );
     736                        }
     737                }
     738                return dst;
     739        }
     740
    695741        class Unify_new final : public ast::WithShortCircuiting {
    696742                const ast::Type * type2;
     
    764810
    765811        private:
    766                 /// Replaces ttype variables with their bound types.
    767                 /// If this isn't done when satifying ttype assertions, then argument lists can have
    768                 /// different size and structure when they should be compatible.
    769                 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
    770                         ast::TypeEnvironment & tenv;
    771 
    772                         TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
    773 
    774                         const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    775                                 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
    776                                         // expand ttype parameter into its actual type
    777                                         if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
    778                                                 return clz->bound;
    779                                         }
    780                                 }
    781                                 return typeInst;
    782                         }
    783                 };
    784 
    785                 /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::Type > > flattenList(
    787                         const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    788                 ) {
    789                         std::vector< ast::ptr< ast::Type > > dst;
    790                         dst.reserve( src.size() );
    791                         for ( const auto & d : src ) {
    792                                 ast::Pass<TtypeExpander_new> expander{ env };
    793                                 // TtypeExpander pass is impure (may mutate nodes in place)
    794                                 // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::Type> dc = d->accept(expander);
    796                                 auto types = flatten( dc );
    797                                 for ( ast::ptr< ast::Type > & t : types ) {
    798                                         // outermost const, volatile, _Atomic qualifiers in parameters should not play
    799                                         // a role in the unification of function types, since they do not determine
    800                                         // whether a function is callable.
    801                                         // NOTE: **must** consider at least mutex qualifier, since functions can be
    802                                         // overloaded on outermost mutex and a mutex function has different
    803                                         // requirements than a non-mutex function
    804                                         remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( t );
    806                                 }
    807                         }
    808                         return dst;
    809                 }
    810 
    811                 /// Creates a tuple type based on a list of DeclWithType
    812                 template< typename Iter >
    813                 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
    814                         std::vector< ast::ptr< ast::Type > > types;
    815                         while ( crnt != end ) {
    816                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817                                 // that this results in a flat tuple
    818                                 flatten( *crnt, types );
    819 
    820                                 ++crnt;
    821                         }
    822 
    823                         return new ast::TupleType{ std::move(types) };
    824                 }
    825812
    826813                template< typename Iter >
     
    10341021        private:
    10351022                /// Creates a tuple type based on a list of Type
    1036                 static const ast::Type * tupleFromTypes(
    1037                         const std::vector< ast::ptr< ast::Type > > & tys
    1038                 ) {
    1039                         std::vector< ast::ptr< ast::Type > > out;
    1040                         for ( const ast::Type * ty : tys ) {
    1041                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    1042                                 // that this results in a flat tuple
    1043                                 flatten( ty, out );
    1044                         }
    1045 
    1046                         return new ast::TupleType{ std::move(out) };
    1047                 }
     1023               
    10481024
    10491025                static bool unifyList(
     
    12171193                        }
    12181194
    1219                 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1195                } else if ( common = commonType( t1, t2, env, need, have, open, widen, symtab )) {
    12201196                        // no exact unification, but common type
    12211197                        auto c = shallowCopy(common.get());
  • src/ResolvExpr/typeops.h

    r8f1e035 ref1da0e2  
    138138        Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
    139139        ast::ptr< ast::Type > commonType(
    140                 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
    141                 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
     140                const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
     141                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     142                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
     143        );
     144        // in Unify.cc
     145        std::vector< ast::ptr< ast::Type > > flattenList(
     146                const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     147        );
    142148
    143149        // in PolyCost.cc
     
    181187
    182188        /// flatten tuple type into existing list of types
    183         static inline void flatten(
     189        inline void flatten(
    184190                const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
    185191        ) {
     
    194200
    195201        /// flatten tuple type into list of types
    196         static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
     202        inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
    197203                std::vector< ast::ptr< ast::Type > > out;
    198204                out.reserve( type->size() );
     
    200206                return out;
    201207        }
     208
     209        template< typename Iter >
     210        const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
     211                std::vector< ast::ptr< ast::Type > > types;
     212                while ( crnt != end ) {
     213                        // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     214                        // that this results in a flat tuple
     215                        flatten( *crnt, types );
     216
     217                        ++crnt;
     218                }
     219
     220
     221                return new ast::TupleType{ std::move(types) };
     222        }
     223
     224        inline const ast::Type * tupleFromTypes(
     225                const std::vector< ast::ptr< ast::Type > > & tys
     226        ) {
     227                return tupleFromTypes( tys.begin(), tys.end() );
     228        }
     229
     230       
    202231
    203232        // in TypeEnvironment.cc
  • tests/concurrent/.expect/ctor-check.txt

    r8f1e035 ref1da0e2  
    22?{}: function
    33... with parameters
    4   this: lvalue reference to instance of struct Empty with body
     4  this: mutex reference to instance of struct Empty with body
    55... returning nothing
    66 with body
Note: See TracChangeset for help on using the changeset viewer.