@@ -2534,6 +2534,63 @@ static bool check_good_vars_or_uninterpreted(term_manager_t *mngr, uint32_t n, c
25342534 return true;
25352535}
25362536
2537+ static bool mcsat_assumption_type_supported (type_table_t * types , type_t tau ) {
2538+ type_kind_t kind = type_kind (types , tau );
2539+ uint32_t i ;
2540+
2541+ switch (kind ) {
2542+ case BOOL_TYPE :
2543+ case INT_TYPE :
2544+ case REAL_TYPE :
2545+ case SCALAR_TYPE :
2546+ case BITVECTOR_TYPE :
2547+ return true;
2548+
2549+ case TUPLE_TYPE : {
2550+ tuple_type_t * tuple = tuple_type_desc (types , tau );
2551+ for (i = 0 ; i < tuple -> nelem ; i ++ ) {
2552+ if (! mcsat_assumption_type_supported (types , tuple -> elem [i ])) {
2553+ return false;
2554+ }
2555+ }
2556+ return true;
2557+ }
2558+
2559+ default :
2560+ return false;
2561+ }
2562+ }
2563+
2564+ // Check that the type of every term in v is one that the MCSAT solver can
2565+ // decide on as an assumption value. Tuple types are supported if all their
2566+ // recursively flattened leaves are supported scalar decision types. Other
2567+ // type kinds (UNINTERPRETED_TYPE, FUNCTION_TYPE, FF_TYPE, etc.) reach the
2568+ // MCSAT solver but trigger an assertion failure inside
2569+ // mcsat_value_construct_from_value (or a NULL decide_assignment dispatch),
2570+ // so we reject them here with a clear error code (issue #615).
2571+ //
2572+ // All elements of v must already be good terms.
2573+ static bool check_mcsat_assumption_types (term_manager_t * mngr , uint32_t n , const term_t * v ) {
2574+ term_table_t * tbl ;
2575+ type_table_t * types ;
2576+ uint32_t i ;
2577+
2578+ tbl = term_manager_get_terms (mngr );
2579+ types = tbl -> types ;
2580+ for (i = 0 ; i < n ; i ++ ) {
2581+ type_t tau = term_type (tbl , v [i ]);
2582+ if (! mcsat_assumption_type_supported (types , tau )) {
2583+ error_report_t * error = get_yices_error ();
2584+ error -> code = MCSAT_ERROR_ASSUMPTION_TYPE_NOT_SUPPORTED ;
2585+ error -> term1 = v [i ];
2586+ error -> type1 = tau ;
2587+ return false;
2588+ }
2589+ }
2590+
2591+ return true;
2592+ }
2593+
25372594// Check whether arrays v and a define a valid substitution
25382595// both must be arrays of n elements
25392596static bool check_good_substitution (term_manager_t * mngr , uint32_t n , const term_t * v , const term_t * a ) {
@@ -9571,6 +9628,18 @@ static bool good_terms_for_check_with_model(uint32_t n, const term_t t[]) {
95719628 MT_PROTECT (bool , __yices_globals .lock , _o_good_terms_for_check_with_model (n , t ));
95729629}
95739630
9631+ /*
9632+ * Same as _o_good_terms_for_check_with_model, but additionally checks that
9633+ * the type of each assumption term is one MCSAT can decide on. This guards
9634+ * against the crash reported in issue #615. Tuple assumptions are allowed
9635+ * only if every recursively flattened leaf type is supported by an MCSAT
9636+ * decision plugin.
9637+ */
9638+ static bool _o_good_assumption_terms_for_mcsat (uint32_t n , const term_t t []) {
9639+ return _o_good_terms_for_check_with_model (n , t )
9640+ && check_mcsat_assumption_types (__yices_globals .manager , n , t );
9641+ }
9642+
95749643/*
95759644 * Check context with model
95769645 * - param = parameter for check sat (or NULL for default parameters)
@@ -9588,10 +9657,16 @@ static smt_status_t _o_yices_check_context_with_model(context_t *ctx, const para
95889657 return YICES_STATUS_ERROR ;
95899658 }
95909659
9591- if (! _o_good_terms_for_check_with_model (n , t )) {
9592- // this sets the error code already (to VARIABLE_REQUIRED)
9593- // but Dejan created another error code that means the same thing here.
9594- set_error_code (MCSAT_ERROR_ASSUMPTION_TERM_NOT_SUPPORTED );
9660+ if (! _o_good_assumption_terms_for_mcsat (n , t )) {
9661+ // Normalize the error code: VARIABLE_REQUIRED (set by the
9662+ // term-shape check) becomes MCSAT_ERROR_ASSUMPTION_TERM_NOT_SUPPORTED,
9663+ // matching the long-standing convention here. The new
9664+ // MCSAT_ERROR_ASSUMPTION_TYPE_NOT_SUPPORTED (set by the type-kind
9665+ // check) is left as-is so callers can distinguish "wrong shape" from
9666+ // "wrong type". term1/type1 fields are preserved.
9667+ if (yices_error_code () == VARIABLE_REQUIRED ) {
9668+ set_error_code (MCSAT_ERROR_ASSUMPTION_TERM_NOT_SUPPORTED );
9669+ }
95959670 return YICES_STATUS_ERROR ;
95969671 }
95979672
@@ -9669,10 +9744,11 @@ static smt_status_t _o_yices_check_context_with_model_and_hint(context_t *ctx, c
96699744 return YICES_STATUS_ERROR ;
96709745 }
96719746
9672- if (! _o_good_terms_for_check_with_model (n , t )) {
9673- // this sets the error code already (to VARIABLE_REQUIRED)
9674- // but Dejan created another error code that means the same thing here.
9675- set_error_code (MCSAT_ERROR_ASSUMPTION_TERM_NOT_SUPPORTED );
9747+ if (! _o_good_assumption_terms_for_mcsat (n , t )) {
9748+ // See note in _o_yices_check_context_with_model.
9749+ if (yices_error_code () == VARIABLE_REQUIRED ) {
9750+ set_error_code (MCSAT_ERROR_ASSUMPTION_TERM_NOT_SUPPORTED );
9751+ }
96769752 return YICES_STATUS_ERROR ;
96779753 }
96789754
@@ -9880,16 +9956,28 @@ EXPORTED smt_status_t yices_check_context_with_interpolation(interpolation_conte
98809956 ctx -> model = yices_get_model (ctx -> ctx_A , true);
98819957 }
98829958
9883- // Pop both contexts
9884- if (result != YICES_STATUS_ERROR ) {
9959+ // Pop both contexts. Preserve the original error report if the loop above
9960+ // failed (for example, via model-refutation assumption validation).
9961+ {
9962+ bool preserve_error = result == YICES_STATUS_ERROR ;
9963+ error_report_t saved_error ;
9964+ if (preserve_error ) {
9965+ saved_error = * get_yices_error ();
9966+ }
9967+
98859968 ret = yices_pop (ctx -> ctx_B );
9886- if (ret ) {
9969+ if (ret && ! preserve_error ) {
98879970 result = YICES_STATUS_ERROR ;
9888- } else {
9889- ret = yices_pop (ctx -> ctx_A );
9890- if (ret ) {
9891- result = YICES_STATUS_ERROR ;
9892- }
9971+ }
9972+ // Pop A even if popping B failed: both contexts were pushed above and
9973+ // must be balanced independently.
9974+ ret = yices_pop (ctx -> ctx_A );
9975+ if (ret && !preserve_error ) {
9976+ result = YICES_STATUS_ERROR ;
9977+ }
9978+
9979+ if (preserve_error ) {
9980+ * get_yices_error () = saved_error ;
98939981 }
98949982 }
98959983
0 commit comments