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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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());
Note: See TracChangeset for help on using the changeset viewer.