static bool is_typeparam_base_sub_x(ast_t* sub, ast_t* super, errorframe_t* errors) { switch(ast_id(super)) { case TK_UNIONTYPE: return is_x_sub_union(sub, super, errors); case TK_ISECTTYPE: return is_x_sub_isect(sub, super, errors); case TK_TUPLETYPE: case TK_NOMINAL: return false; case TK_TYPEPARAMREF: return is_typeparam_sub_typeparam(sub, super, errors); case TK_ARROW: return is_typeparam_sub_arrow(sub, super, errors); default: {} } assert(0); return false; }
// The subtype is a typeparam, the supertype could be anything. static bool is_typeparam_subtype(ast_t* sub, ast_t* super) { switch(ast_id(super)) { case TK_TYPEPARAMREF: if(is_typeparam_sub_typeparam(sub, super)) return true; break; case TK_UNIONTYPE: if(is_subtype_union(sub, super)) return true; break; case TK_ISECTTYPE: if(is_subtype_isect(sub, super)) return true; break; case TK_ARROW: if(is_subtype_arrow(sub, super)) return true; break; default: {} } // We can be a subtype if our upper bounds, ie our constraint, is a subtype. ast_t* sub_def = (ast_t*)ast_data(sub); ast_t* constraint = ast_childidx(sub_def, 1); if(ast_id(constraint) == TK_TYPEPARAMREF) { ast_t* constraint_def = (ast_t*)ast_data(constraint); if(constraint_def == sub_def) return false; } // Constraint must be modified with sub ephemerality. AST_GET_CHILDREN(sub, name, cap, eph); ast_t* r_constraint = set_cap_and_ephemeral(constraint, TK_NONE, ast_id(eph)); bool ok = is_subtype(r_constraint, super); ast_free_unattached(r_constraint); return ok; }