Ignore:
Timestamp:
Aug 14, 2020, 11:40:04 AM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5715d43, fa5e0112
Parents:
309d814 (diff), badd22f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 14:55:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     65        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7777        PRINT(
    7878                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     112                Cost convCost = computeConversionCost(
     113                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113114                outCost += convCost;
    114115
    115                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 
    116                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 
     116                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     117                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117118                // infer parameters and this does not currently work for the reason stated below
    118119                Cost tmpCost = convCost;
     
    123124                        return new ast::CastExpr{ arg, newType };
    124125
    125                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not 
    126                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 
     126                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     127                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127128                        // once this is fixed it should be possible to resolve the cast.
    128                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 
    129                         // but it shouldn't be because this makes the conversion from DT* to DT* since 
     129                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     130                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130131                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131132
    132133                        // CandidateFinder finder{ symtab, env };
    133134                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     135                        // assertf( finder.candidates.size() > 0,
    135136                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     137                        // assertf( finder.candidates.size() == 1,
    137138                        //      "Somehow got multiple alternatives for known cast expression." );
    138139                        // return finder.candidates.front()->expr;
     
    143144
    144145        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     146        Cost computeApplicationConversionCost(
     147                CandidateRef cand, const ast::SymbolTable & symtab
    147148        ) {
    148149                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167168                                if ( function->isVarArgs ) {
    168169                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     170                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170171                                                << convCost << std::endl; ; )
    171172                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     173                                        cand->expr = ast::mutate_field_index(
     174                                                appExpr, &ast::ApplicationExpr::args, i,
    174175                                                referenceToRvalueConversion( args[i], convCost ) );
    175176                                        continue;
     
    180181                                // Default arguments should be free - don't include conversion cost.
    181182                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     183                                cand->expr = ast::mutate_field_index(
    183184                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184185                                ++param;
     
    188189                        // mark conversion cost and also specialization cost of param type
    189190                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     191                        cand->expr = ast::mutate_field_index(
     192                                appExpr, &ast::ApplicationExpr::args, i,
     193                                computeExpressionConversionCost(
    193194                                        args[i], paramType, symtab, cand->env, convCost ) );
    194195                        convCost.decSpec( specCost( paramType ) );
     
    198199                if ( param != params.end() ) return Cost::infinity;
    199200
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     201                // specialization cost of return types can't be accounted for directly, it disables
    201202                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202203                //
     
    215216        }
    216217
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     218        void makeUnifiableVars(
     219                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                ast::AssertionSet & need
    220221        ) {
    221222                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254255
    255256                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     257                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257258                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     259
     260                ArgPack(
     261                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261262                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     263                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263264                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     265
    265266                ArgPack(
    266                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 
    267                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 
    268                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 
     267                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     268                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270271                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271272                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     274
    274275                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    277                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 
    278                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     279                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     281
    281282                /// true if this pack is in the middle of an exploded argument
    282283                bool hasExpl() const { return nextExpl > 0; }
     
    286287                        return args[ nextArg-1 ][ explAlt ];
    287288                }
    288                
     289
    289290                /// Ends a tuple expression, consolidating the appropriate args
    290291                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307308
    308309        /// Instantiates an argument to match a parameter, returns false if no matching results left
    309         bool instantiateArgument( 
    310                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 
    311                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 
    312                 unsigned nTuples = 0 
     310        bool instantiateArgument(
     311                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     312                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     313                unsigned nTuples = 0
    313314        ) {
    314315                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318319                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319320                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     321                                if ( ! instantiateArgument(
    321322                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322323                                nTuples = 0;
     
    329330                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330331                        // paramType is a ttype, consumes all remaining arguments
    331                        
     332
    332333                        // completed tuples; will be spliced to end of results to finish
    333334                        std::vector< ArgPack > finalResults{};
     
    342343                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343344                                        unsigned nextArg = results[i].nextArg;
    344                                        
     345
    345346                                        // use next element of exploded tuple if present
    346347                                        if ( results[i].hasExpl() ) {
     
    352353                                                results.emplace_back(
    353354                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     355                                                        copy( results[i].need ), copy( results[i].have ),
    355356                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356357                                                        results[i].explAlt );
     
    370371                                                        // push empty tuple expression
    371372                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     373                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375374                                                        argType = newResult.expr->result;
    376375                                                } else {
     
    400399
    401400                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     401                                                if (
     402                                                        unify(
    404403                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     404                                                                newResult.open, symtab )
    406405                                                ) {
    407406                                                        finalResults.emplace_back( move( newResult ) );
     
    424423                                                if ( expl.exprs.empty() ) {
    425424                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     425                                                                results[i], move( env ), copy( results[i].need ),
    427426                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     427
    429428                                                        continue;
    430429                                                }
     
    432431                                                // add new result
    433432                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     433                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437436                                        }
     
    479478
    480479                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     480                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483482                                }
     
    495494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496495                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498497                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499498                                        }
     
    517516                                if ( expl.exprs.empty() ) {
    518517                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     518                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520519                                                nextArg + 1, expl.cost );
    521                                        
     520
    522521                                        continue;
    523522                                }
     
    539538                                        // add new result
    540539                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     540                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543542                                }
     
    548547                genStart = genEnd;
    549548
    550                 return genEnd != results.size();
     549                return genEnd != results.size();  // were any new results added?
    551550        }
    552551
    553552        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     553        const ast::Expr * restructureCast(
    555554                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556555        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     556                if (
     557                        arg->result->size() > 1
     558                        && ! toType->isVoid()
     559                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561560                ) {
    562                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    563                         // member of the tuple to its corresponding target type, producing the tuple of those 
    564                         // cast expressions. If there are more components of the tuple than components in the 
    565                         // target type, then excess components do not come out in the result expression (but 
     561                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     562                        // member of the tuple to its corresponding target type, producing the tuple of those
     563                        // cast expressions. If there are more components of the tuple than components in the
     564                        // target type, then excess components do not come out in the result expression (but
    566565                        // UniqueExpr ensures that the side effects will still be produced)
    567566                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     567                                // expressions which may contain side effects require a single unique instance of
    569568                                // the expression
    570569                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574573                                // cast each component
    575574                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     575                                components.emplace_back(
    577576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578577                        }
     
    594593
    595594        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     595        class Finder final : public ast::WithShortCircuiting {
     596                const ast::SymbolTable & symtab;
     597        public:
     598                static size_t traceId;
    597599                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599600                CandidateList & candidates;
    600601                const ast::TypeEnvironment & tenv;
    601602                ast::ptr< ast::Type > & targetType;
    602603
     604                enum Errors {
     605                        NotFound,
     606                        NoMatch,
     607                        ArgsToFew,
     608                        ArgsToMany,
     609                        RetsToFew,
     610                        RetsToMany,
     611                        NoReason
     612                };
     613
     614                struct {
     615                        Errors code = NotFound;
     616                } reason;
     617
    603618                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     619                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605620                  targetType( f.targetType ) {}
    606                
     621
    607622                void previsit( const ast::Node * ) { visit_children = false; }
    608623
     
    611626                void addCandidate( Args &&... args ) {
    612627                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     628                        reason.code = NoReason;
    613629                }
    614630
     
    639655
    640656                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     657                void validateFunctionCandidate(
     658                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     659                        CandidateList & out
    644660                ) {
    645                         ast::ApplicationExpr * appExpr = 
     661                        ast::ApplicationExpr * appExpr =
    646662                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647663                        // sum cost and accumulate arguments
     
    657673                        appExpr->args = move( vargs );
    658674                        // build and validate new candidate
    659                         auto newCand = 
     675                        auto newCand =
    660676                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661677                        PRINT(
     
    669685                /// Builds a list of candidates for a function, storing them in out
    670686                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     687                        const CandidateRef & func, const ast::FunctionType * funcType,
    672688                        const ExplodedArgs_new & args, CandidateList & out
    673689                ) {
     
    676692                        ast::TypeEnvironment funcEnv{ func->env };
    677693                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    678                         // add all type variables as open variables now so that those not used in the parameter
    679                         // list are still considered open
     694                        // add all type variables as open variables now so that those not used in the
     695                        // parameter list are still considered open
    680696                        funcEnv.add( funcType->forall );
    681697
     
    683699                                // attempt to narrow based on expected target type
    684700                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     701                                if ( ! unify(
     702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687703                                ) {
    688704                                        // unification failed, do not pursue this candidate
     
    698714                        for ( const ast::DeclWithType * param : funcType->params ) {
    699715                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     716                                // Try adding the arguments corresponding to the current parameter to the existing
    701717                                // matches
    702                                 if ( ! instantiateArgument( 
     718                                if ( ! instantiateArgument(
    703719                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704720                        }
     
    750766                                                        if ( expl.exprs.empty() ) {
    751767                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     768                                                                        results[i], move( env ), copy( results[i].need ),
     769                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754770                                                                        expl.cost );
    755771
     
    760776                                                        results.emplace_back(
    761777                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     778                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763779                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764780                                                }
     
    780796                /// Adds implicit struct-conversions to the alternative list
    781797                void addAnonConversions( const CandidateRef & cand ) {
    782                         // adds anonymous member interpretations whenever an aggregate value type is seen. 
    783                         // it's okay for the aggregate expression to have reference type -- cast it to the 
     798                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     799                        // it's okay for the aggregate expression to have reference type -- cast it to the
    784800                        // base type to treat the aggregate as the referenced value
    785801                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786802                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787803                        cand->env.apply( aggrType );
    788                        
     804
    789805                        if ( aggrType.as< ast::ReferenceType >() ) {
    790806                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799815
    800816                /// Adds aggregate member interpretations
    801                 void addAggMembers( 
    802                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 
    803                         const Candidate & cand, const Cost & addedCost, const std::string & name 
     817                void addAggMembers(
     818                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     819                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804820                ) {
    805821                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806822                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     823                                CandidateRef newCand = std::make_shared<Candidate>(
    808824                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     825                                // add anonymous member interpretations whenever an aggregate value type is seen
    810826                                // as a member expression
    811827                                addAnonConversions( newCand );
     
    815831
    816832                /// Adds tuple member interpretations
    817                 void addTupleMembers( 
    818                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 
    819                         const Cost & addedCost, const ast::Expr * member 
     833                void addTupleMembers(
     834                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     835                        const Cost & addedCost, const ast::Expr * member
    820836                ) {
    821837                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    822                                 // get the value of the constant expression as an int, must be between 0 and the 
     838                                // get the value of the constant expression as an int, must be between 0 and the
    823839                                // length of the tuple to have meaning
    824840                                long long val = constantExpr->intValue();
    825841                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826842                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     843                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828844                                                addedCost );
    829845                                }
     
    837853                        if ( funcFinder.candidates.empty() ) return;
    838854
    839                         std::vector< CandidateFinder > argCandidates =
     855                        reason.code = NoMatch;
     856
     857                        std::vector< CandidateFinder > argCandidates =
    840858                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     859
    842860                        // take care of possible tuple assignments
    843861                        // if not tuple assignment, handled as normal function call
     
    877895                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878896                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     897                                                        newFunc->expr =
    880898                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881899                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882900                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     901                                        } else if (
     902                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885903                                        ) {
    886904                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887905                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888906                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     907                                                                newFunc->expr =
    890908                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891909                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901919                                std::vector< ExplodedArg > funcE;
    902920                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     921                                for ( const CandidateRef & func : funcFinder ) {
    904922                                        funcE.emplace_back( *func, symtab );
    905923                                }
     
    913931                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914932                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     933                                                                newOp->expr =
    916934                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917935                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922940                        }
    923941
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     942                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925943                        // candidates
    926944                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934952                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935953                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     954
    937955                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938956                                        std::cerr << "parameters are:" << std::endl;
     
    957975                        promoteCvtCost( winners );
    958976
    959                         // function may return a struct/union value, in which case we need to add candidates 
    960                         // for implicit conversions to each of the anonymous members, which must happen after 
     977                        // function may return a struct/union value, in which case we need to add candidates
     978                        // for implicit conversions to each of the anonymous members, which must happen after
    961979                        // `findMinCost`, since anon conversions are never the cheapest
    962980                        for ( const CandidateRef & c : winners ) {
     
    966984
    967985                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     986                                // If resolution is unsuccessful with a target type, try again without, since it
    969987                                // will sometimes succeed when it wouldn't with a target type binding.
    970988                                // For example:
     
    9831001                /// true if expression is an lvalue
    9841002                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     1003                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    9861004                }
    9871005
     
    9891007                        CandidateFinder finder{ symtab, tenv };
    9901008                        finder.find( addressExpr->arg );
     1009
     1010                        if( finder.candidates.empty() ) return;
     1011
     1012                        reason.code = NoMatch;
     1013
    9911014                        for ( CandidateRef & r : finder.candidates ) {
    9921015                                if ( ! isLvalue( r->expr ) ) continue;
     
    10091032                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10101033
     1034                        if( !finder.candidates.empty() ) reason.code = NoMatch;
     1035
    10111036                        CandidateList matches;
    10121037                        for ( CandidateRef & cand : finder.candidates ) {
     
    10161041                                cand->env.extractOpenVars( open );
    10171042
    1018                                 // It is possible that a cast can throw away some values in a multiply-valued 
    1019                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 
    1020                                 // subexpression results that are cast directly. The candidate is invalid if it 
     1043                                // It is possible that a cast can throw away some values in a multiply-valued
     1044                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1045                                // subexpression results that are cast directly. The candidate is invalid if it
    10211046                                // has fewer results than there are types to cast to.
    10221047                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251050                                // unification run for side-effects
    10261051                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1052                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1053                                                symtab, cand->env );
    10281054                                PRINT(
    10291055                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371063                                        // count one safe conversion for each value that is thrown away
    10381064                                        thisCost.incSafe( discardedValues );
    1039                                         CandidateRef newCand = std::make_shared<Candidate>( 
    1040                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ), 
    1041                                                 copy( cand->env ), move( open ), move( need ), cand->cost, 
     1065                                        CandidateRef newCand = std::make_shared<Candidate>(
     1066                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1067                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421068                                                cand->cost + thisCost );
    10431069                                        inferParameters( newCand, matches );
     
    10571083                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581084                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1085                                addCandidate(
     1086                                        *r,
    10611087                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621088                        }
     
    10671093                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681094                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1095                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701096                                // base type to treat the aggregate as the referenced value
    10711097                                Cost addedCost = Cost::zero;
     
    10741100                                // find member of the given type
    10751101                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1102                                        addAggMembers(
    10771103                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781104                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1105                                        addAggMembers(
    10801106                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811107                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10921118                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    10931119                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1120                        if( declList.empty() ) return;
     1121
     1122                        reason.code = NoMatch;
     1123
    10941124                        for ( auto & data : declList ) {
    10951125                                Cost cost = Cost::zero;
     
    10971127
    10981128                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1129                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001130                                        cost );
    11011131                                PRINT(
     
    11071137                                        std::cerr << std::endl;
    11081138                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1139                                newCand->expr = ast::mutate_field(
     1140                                        newCand->expr.get(), &ast::Expr::result,
    11111141                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1142                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131143                                // as a name expression
    11141144                                addAnonConversions( newCand );
     
    11201150                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211151                        // creation
    1122                         addCandidate( 
     1152                        addCandidate(
    11231153                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241154                }
     
    11301160                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311161                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1162                                addCandidate(
     1163                                        new ast::SizeofExpr{
     1164                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351165                                        tenv );
    11361166                        } else {
     
    11411171                                CandidateList winners = findMinCost( finder.candidates );
    11421172                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1173                                        SemanticError(
    11441174                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451175                                }
     
    11541184                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551185                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1186                                addCandidate(
     1187                                        new ast::AlignofExpr{
     1188                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591189                                        tenv );
    11601190                        } else {
     
    11651195                                CandidateList winners = findMinCost( finder.candidates );
    11661196                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1197                                        SemanticError(
    11681198                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691199                                }
     
    11721202                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731203                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1204                                addCandidate(
    11751205                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761206                        }
     
    11851215                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861216                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1217                                addCandidate(
    11881218                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891219                        }
     
    12061236                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12071237                        if ( finder2.candidates.empty() ) return;
     1238
     1239                        reason.code = NoMatch;
    12081240
    12091241                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12181250
    12191251                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1252                                                new ast::LogicalExpr{
    12211253                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221254                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12401272                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12411273                        if ( finder3.candidates.empty() ) return;
     1274
     1275                        reason.code = NoMatch;
    12421276
    12431277                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12561290                                                ast::AssertionSet have;
    12571291
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1292                                                // unify true and false results, then infer parameters to produce new
    12591293                                                // candidates
    12601294                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1295                                                if (
     1296                                                        unify(
     1297                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1298                                                                common )
    12651299                                                ) {
    12661300                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1301                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681302                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691303                                                        newExpr->result = common ? common : r2->expr->result;
    12701304                                                        // convert both options to result type
    12711305                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1306                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731307                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741308                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871321                        ast::TypeEnvironment env{ tenv };
    12881322                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1323
    12901324                        CandidateFinder finder2{ symtab, env };
    12911325                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13171351                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13181352                        if ( finder2.candidates.empty() ) return;
     1353
     1354                        reason.code = NoMatch;
    13191355
    13201356                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13301366
    13311367                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1368                                        if (
     1369                                                unify(
     1370                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1371                                                        common )
    13361372                                        ) {
    13371373                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1374                                                ast::RangeExpr * newExpr =
    13391375                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401376                                                newExpr->result = common ? common : r1->expr->result;
    13411377                                                // add candidate
    13421378                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1379                                                        newExpr, move( env ), move( open ), move( need ),
    13441380                                                        r1->cost + r2->cost );
    13451381                                                inferParameters( newCand, candidates );
     
    13501386
    13511387                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1388                        std::vector< CandidateFinder > subCandidates =
    13531389                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541390                        std::vector< CandidateList > possibilities;
     
    13701406
    13711407                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1408                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731409                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741410                        }
     
    14121448                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131449                                toType = adjustExprType( toType, tenv, symtab );
    1414                                 // The call to find must occur inside this loop, otherwise polymorphic return 
    1415                                 // types are not bound to the initialization type, since return type variables are 
    1416                                 // only open for the duration of resolving the UntypedExpr. 
     1450                                // The call to find must occur inside this loop, otherwise polymorphic return
     1451                                // types are not bound to the initialization type, since return type variables are
     1452                                // only open for the duration of resolving the UntypedExpr.
    14171453                                CandidateFinder finder{ symtab, tenv, toType };
    14181454                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14191455                                for ( CandidateRef & cand : finder.candidates ) {
     1456                                        if(reason.code == NotFound) reason.code = NoMatch;
     1457
    14201458                                        ast::TypeEnvironment env{ cand->env };
    14211459                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14261464                                        )
    14271465
    1428                                         // It is possible that a cast can throw away some values in a multiply-valued 
    1429                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 
    1430                                         // the subexpression results that are cast directly. The candidate is invalid 
     1466                                        // It is possible that a cast can throw away some values in a multiply-valued
     1467                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1468                                        // the subexpression results that are cast directly. The candidate is invalid
    14311469                                        // if it has fewer results than there are types to cast to.
    14321470                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351473                                        // unification run for side-effects
    14361474                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1475                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1476                                                        symtab, env );
     1477
    14391478                                        if ( thisCost != Cost::infinity ) {
    14401479                                                // count one safe conversion for each value that is thrown away
    14411480                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1481                                                CandidateRef newCand = std::make_shared<Candidate>(
     1482                                                        new ast::InitExpr{
     1483                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1484                                                                initAlt.designation },
    14461485                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471486                                                inferParameters( newCand, matches );
     
    14691508        };
    14701509
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     1510        // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
     1511        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721512        /// return type. Skips ambiguous candidates.
    14731513        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861526                        {
    14871527                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1528                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881529                                candidate->env.apply( newType );
    14891530                                mangleName = Mangle::mangle( newType );
     
    14941535                                if ( candidate->cost < found->second.candidate->cost ) {
    14951536                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1537                                                std::cerr << "cost " << candidate->cost << " beats "
    14971538                                                        << found->second.candidate->cost << std::endl;
    14981539                                        )
     
    15001541                                        found->second = PruneStruct{ candidate };
    15011542                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1502                                         // if one of the candidates contains a deleted identifier, can pick the other, 
    1503                                         // since deleted expressions should not be ambiguous if there is another option 
     1543                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1544                                        // since deleted expressions should not be ambiguous if there is another option
    15041545                                        // that is at least as good
    15051546                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151556                                } else {
    15161557                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1558                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181559                                                        << found->second.candidate->cost << std::endl;
    15191560                                        )
     
    15301571
    15311572                        CandidateRef cand = target.second.candidate;
    1532                        
     1573
    15331574                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341575                        cand->env.applyFree( newResult );
    15351576                        cand->expr = ast::mutate_field(
    15361577                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1578
    15381579                        out.emplace_back( cand );
    15391580                }
     
    15491590
    15501591        if ( mode.failFast && candidates.empty() ) {
    1551                 SemanticError( expr, "No reasonable alternatives for expression " );
     1592                switch(finder.core.reason.code) {
     1593                case Finder::NotFound:
     1594                        { SemanticError( expr, "No alternatives for expression " ); break; }
     1595                case Finder::NoMatch:
     1596                        { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
     1597                case Finder::ArgsToFew:
     1598                case Finder::ArgsToMany:
     1599                case Finder::RetsToFew:
     1600                case Finder::RetsToMany:
     1601                case Finder::NoReason:
     1602                default:
     1603                        { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
     1604                }
    15521605        }
    15531606
     
    15581611                std::vector< std::string > errors;
    15591612                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1613                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611614                }
    15621615
     
    15831636
    15841637                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1638
    15861639                if ( mode.failFast && pruned.empty() ) {
    15871640                        std::ostringstream stream;
     
    16021655                )
    16031656                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1657                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051658                                << std::endl;
    16061659                )
    16071660        }
    16081661
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1662        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101663        // adjusted
    16111664        if ( mode.adjust ) {
    16121665                for ( CandidateRef & r : candidates ) {
    1613                         r->expr = ast::mutate_field( 
    1614                                 r->expr.get(), &ast::Expr::result, 
    1615                                 adjustExprType( r->expr->result, r->env, symtab ) );
     1666                        r->expr = ast::mutate_field(
     1667                                r->expr.get(), &ast::Expr::result,
     1668                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161669                }
    16171670        }
     
    16251678}
    16261679
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1680std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1681        const std::vector< ast::ptr< ast::Expr > > & xs
    16291682) {
    16301683        std::vector< CandidateFinder > out;
    16311684
    16321685        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1686                out.emplace_back( localSyms, env );
    16341687                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1688
    16361689                PRINT(
    16371690                        std::cerr << "findSubExprs" << std::endl;
Note: See TracChangeset for help on using the changeset viewer.