JL_DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b) { int msp = jl_type_morespecific(a,b); int btv = jl_has_typevars(b); if (btv) { if (jl_type_match_morespecific(a,b) == (jl_value_t*)jl_false) { if (jl_has_typevars(a)) return 0; return msp; } if (jl_has_typevars(a)) { type_match_invariance_mask = 0; //int result = jl_type_match_morespecific(b,a) == (jl_value_t*)jl_false); // this rule seems to work better: int result = jl_type_match(b,a) == (jl_value_t*)jl_false; type_match_invariance_mask = 1; if (result) return 1; } int nmsp = jl_type_morespecific(b,a); if (nmsp == msp) return 0; } if (jl_has_typevars((jl_value_t*)a)) { int nmsp = jl_type_morespecific(b,a); if (nmsp && msp) return 1; if (!btv && jl_types_equal(a,b)) return 1; if (jl_type_match_morespecific(b,a) != (jl_value_t*)jl_false) return 0; } return msp; }
int sigs_eq(jl_value_t *a, jl_value_t *b, int useenv) { if (jl_has_typevars(a) || jl_has_typevars(b)) { return jl_types_equal_generic(a,b,useenv); } return jl_subtype(a, b, 0) && jl_subtype(b, a, 0); }
int jl_args_morespecific(jl_value_t *a, jl_value_t *b) { int msp = jl_type_morespecific(a,b,0); if (jl_has_typevars(b)) { if (jl_type_match_morespecific(a,b) == (jl_value_t*)jl_false) { if (jl_has_typevars(a)) { return 0; } return msp; } if (jl_has_typevars(a)) { if (jl_type_match_morespecific(b,a) == (jl_value_t*)jl_false) { return 1; } } int nmsp = jl_type_morespecific(b,a,0); if (nmsp == msp) return 0; } if (jl_has_typevars((jl_value_t*)a)) { int nmsp = jl_type_morespecific(b,a,0); if (nmsp && msp) return 1; if (jl_type_match_morespecific(b,a) != (jl_value_t*)jl_false) { return 0; } } return msp; }
static int sigs_eq(jl_value_t *a, jl_value_t *b) { if (jl_has_typevars(a) || jl_has_typevars(b)) { return jl_types_equal_generic(a,b); } return jl_types_equal(a, b); }
int sigs_eq(jl_value_t *a, jl_value_t *b, int useenv) { // useenv == 0 : subtyping + ensure typevars correspond // useenv == 1 : subtyping + ensure typevars correspond + fail if bound != bound in some typevar match // useenv == 2 : ignore typevars (because UnionAll getting lost in intersection can cause jl_types_equal to fail in the wrong direction for some purposes) if (useenv != 2 && (jl_has_typevars(a) || jl_has_typevars(b))) { return jl_types_equal_generic(a, b, useenv); } return jl_subtype(a, b, 0) && jl_subtype(b, a, 0); }
int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, struct typemap_intersection_env *closure) { if (jl_typeof(map.unknown) == (jl_value_t*)jl_typemap_level_type) { jl_typemap_level_t *cache = map.node; jl_value_t *ty = NULL; size_t l = jl_datatype_nfields(closure->type); if (closure->va && l <= offs + 1) { ty = closure->va; } else if (l > offs) { ty = jl_tparam(closure->type, offs); } if (ty) { if (cache->targ != (void*)jl_nothing) { jl_value_t *typetype = jl_is_type_type(ty) ? jl_tparam0(ty) : NULL; if (typetype && !jl_has_typevars(typetype)) { if (is_cache_leaf(typetype)) { // direct lookup of leaf types union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, typetype, 1, offs); if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; } } } else { // else an array scan is required to check subtypes // first, fast-path: optimized pre-intersection test to see if `ty` could intersect with any Type if (typetype || jl_type_intersection((jl_value_t*)jl_type_type, ty) != jl_bottom_type) if (!jl_typemap_intersection_array_visitor(cache->targ, ty, 1, offs, closure)) return 0; } } if (cache->arg1 != (void*)jl_nothing) { if (is_cache_leaf(ty)) { // direct lookup of leaf types union jl_typemap_t ml = mtcache_hash_lookup(cache->arg1, ty, 0, offs); if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; } } else { // else an array scan is required to check subtypes if (!jl_typemap_intersection_array_visitor(cache->arg1, ty, 0, offs, closure)) return 0; } } } if (!jl_typemap_intersection_node_visitor(map.node->linear, closure)) return 0; if (ty) return jl_typemap_intersection_visitor(map.node->any, offs+1, closure); return 1; } else { return jl_typemap_intersection_node_visitor(map.leaf, closure); } }
static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value_t *ty, int8_t tparam, int8_t offs, jl_value_t *parent) { if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; if (!uid || is_kind(ty) || jl_has_typevars(ty)) // be careful not to put non-leaf types or DataType/TypeConstructor in the cache here, // since they should have a lower priority and need to go into the sorted list return NULL; if (pa->values == (void*)jl_nothing) { pa->indexes = jl_alloc_int_1d(0, INIT_CACHE_SIZE); jl_gc_wb(parent, pa->indexes); pa->values = jl_alloc_vec_any(0); jl_gc_wb(parent, pa->values); } while (1) { size_t slot = uid & (pa->indexes->nrows - 1); size_t idx = jl_intref(pa->indexes, slot); if (idx == 0) { jl_array_ptr_1d_push(pa->values, jl_nothing); idx = jl_array_len(pa->values); if (idx > jl_max_int(pa->indexes)) mtcache_rehash(pa, jl_array_len(pa->indexes), parent, tparam, offs); jl_intset(pa->indexes, slot, idx); return &((union jl_typemap_t*)jl_array_data(pa->values))[idx - 1]; } union jl_typemap_t *pml = &((union jl_typemap_t*)jl_array_data(pa->values))[idx - 1]; if (pml->unknown == jl_nothing) return pml; jl_value_t *t; if (jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_level_type) { t = pml->node->key; } else { assert(jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_entry_type); t = jl_field_type(pml->leaf->sig, offs); if (tparam) t = jl_tparam0(t); } if (t == ty) return pml; mtcache_rehash(pa, jl_array_len(pa->indexes) * 2, parent, tparam, offs); } } return NULL; }
static union jl_typemap_t *mtcache_hash_bp(jl_array_t **pa, jl_value_t *ty, int8_t tparam, int8_t offs, jl_value_t *parent) { if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; if (!uid || is_kind(ty) || jl_has_typevars(ty)) // be careful not to put non-leaf types or DataType/TypeConstructor in the cache here, // since they should have a lower priority and need to go into the sorted list return NULL; if (*pa == (void*)jl_nothing) { *pa = jl_alloc_vec_any(INIT_CACHE_SIZE); jl_gc_wb(parent, *pa); } while (1) { union jl_typemap_t *pml = &((union jl_typemap_t*)jl_array_data(*pa))[uid & ((*pa)->nrows-1)]; union jl_typemap_t ml = *pml; if (ml.unknown == NULL || ml.unknown == jl_nothing) { pml->unknown = jl_nothing; return pml; } jl_value_t *t; if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { t = ml.node->key; } else { t = jl_field_type(ml.leaf->sig, offs); if (tparam) t = jl_tparam0(t); } if (t == ty) return pml; mtcache_rehash(pa, parent, tparam, offs); } } return NULL; }