// The subtype is a pointer, the supertype could be anything. static bool is_pointer_subtype(ast_t* sub, ast_t* super) { switch(ast_id(super)) { case TK_NOMINAL: { // Must be a Pointer, and the type argument must be the same. return is_pointer(super) && is_eq_typeargs(sub, super) && is_sub_cap_and_ephemeral(sub, super); } case TK_TYPEPARAMREF: { // We must be a subtype of the constraint. ast_t* def = (ast_t*)ast_data(super); ast_t* constraint = ast_childidx(def, 1); return is_pointer_subtype(sub, constraint); } case TK_ARROW: { // We must be a subtype of the lower bounds. ast_t* lower = viewpoint_lower(super); bool ok = is_pointer_subtype(sub, lower); ast_free_unattached(lower); return ok; } default: {} } return false; }
// Both sub and super are nominal types. static bool is_nominal_sub_nominal(ast_t* sub, ast_t* super) { if(!is_sub_cap_and_ephemeral(sub, super)) return false; ast_t* sub_def = (ast_t*)ast_data(sub); ast_t* super_def = (ast_t*)ast_data(super); // If we are the same nominal type, our typeargs must be the same. if(sub_def == super_def) return is_eq_typeargs(sub, super); switch(ast_id(super_def)) { case TK_PRIMITIVE: case TK_CLASS: case TK_ACTOR: // If we aren't the same type, we can't be a subtype of a concrete type. return false; case TK_INTERFACE: // Check for an explicit provide or a structural subtype. return is_nominal_sub_trait(sub, super) || is_nominal_sub_interface(sub, super); case TK_TRAIT: // Check for a nominal subtype. return is_nominal_sub_trait(sub, super); default: {} } return false; }
static bool is_trait_sub_trait(ast_t* sub, ast_t* super, errorframe_t* errors) { // R = R' or implements(R, R') // k <: k' // --- // R k <: R' k' ast_t* sub_def = (ast_t*)ast_data(sub); ast_t* super_def = (ast_t*)ast_data(super); bool ret = true; if(sub_def == super_def) { if(!is_eq_typeargs(sub, super, errors)) ret = false; } else if(!nominal_provides_trait(sub, super, errors)) { ret = false; } if(!is_sub_cap_and_eph(sub, super, errors)) ret = false; return ret; }
static bool is_nominal_sub_entity(ast_t* sub, ast_t* super, errorframe_t* errors) { // N = C // k <: k' // --- // N k <: C k' ast_t* sub_def = (ast_t*)ast_data(sub); ast_t* super_def = (ast_t*)ast_data(super); bool ret = true; if(sub_def != super_def) { if(errors != NULL) { ast_error_frame(errors, sub, "%s is not a subtype of %s", ast_print_type(sub), ast_print_type(super)); } return false; } if(!is_eq_typeargs(sub, super, errors)) ret = false; if(!is_sub_cap_and_eph(sub, super, errors)) ret = false; return ret; }
static bool exact_nominal(ast_t* a, ast_t* b) { AST_GET_CHILDREN(a, a_pkg, a_id, a_typeargs, a_cap, a_eph); AST_GET_CHILDREN(b, b_pkg, b_id, b_typeargs, b_cap, b_eph); ast_t* a_def = (ast_t*)ast_data(a); ast_t* b_def = (ast_t*)ast_data(b); return (a_def == b_def) && (ast_id(a_cap) == ast_id(b_cap)) && (ast_id(a_eph) == ast_id(b_eph)) && is_eq_typeargs(a, b, false); }
static bool is_nominal_eq_nominal(ast_t* sub, ast_t* super) { ast_t* sub_cap = fetch_cap(sub); ast_t* sub_eph = ast_sibling(sub_cap); ast_t* super_cap = fetch_cap(super); ast_t* super_eph = ast_sibling(super_cap); token_id t_sub_cap = ast_id(sub_cap); token_id t_sub_eph = ast_id(sub_eph); token_id t_super_cap = ast_id(super_cap); token_id t_super_eph = ast_id(super_eph); if((t_sub_cap != t_super_cap) || (t_sub_eph != t_super_eph)) return false; ast_t* sub_def = (ast_t*)ast_data(sub); ast_t* super_def = (ast_t*)ast_data(super); // If we are the same nominal type, our typeargs must be the same. if(sub_def == super_def) return is_eq_typeargs(sub, super); return false; }