refine distinct construction semantics
This commit is contained in:
@@ -935,6 +935,14 @@ valid_layout_type :: proc(checker: ^Checker, value: types.Type) -> bool {
|
||||
return types.is_runtime_value(value, &checker.module.types)
|
||||
}
|
||||
|
||||
is_integer_bound_type :: proc(checker: ^Checker, value: types.Type) -> bool {
|
||||
representation := value
|
||||
if backing, ok := types.distinct_scalar_backing(value, &checker.module.types); ok {
|
||||
representation = backing
|
||||
}
|
||||
return types.is_concrete_integer(representation)
|
||||
}
|
||||
|
||||
type_builtin_value :: proc(checker: ^Checker, kind: Type_Builtin, value: types.Type) -> i128 {
|
||||
#partial switch kind {
|
||||
case .Size_Of:
|
||||
@@ -984,11 +992,7 @@ build_type_builtin :: proc(
|
||||
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "layout target must be a sized runtime value type, got %s", type_label(checker, target))
|
||||
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
|
||||
}
|
||||
bound_representation := target
|
||||
if backing, ok := types.distinct_scalar_backing(target, &checker.module.types); ok {
|
||||
bound_representation = backing
|
||||
}
|
||||
if (kind == .Min_Value || kind == .Max_Value) && !types.is_concrete_integer(bound_representation) {
|
||||
if (kind == .Min_Value || kind == .Max_Value) && !is_integer_bound_type(checker, target) {
|
||||
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "integer bound target must be a concrete integer type, got %s", type_label(checker, target))
|
||||
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
|
||||
}
|
||||
@@ -5423,7 +5427,7 @@ infer_expr :: proc(
|
||||
last = types.USIZE
|
||||
} else if len(expr.args) == 1 {
|
||||
target, ok := resolve_type_argument(checker, expr.args[0], pkg, file)
|
||||
last = target if ok && types.is_concrete_integer(target) else types.INVALID
|
||||
last = target if ok && is_integer_bound_type(checker, target) else types.INVALID
|
||||
} else {
|
||||
last = types.INVALID
|
||||
}
|
||||
@@ -6821,7 +6825,7 @@ infer_all :: proc(checker: ^Checker) {
|
||||
checker.global_types[index] = types.USIZE
|
||||
} else if len(expr.args) == 1 {
|
||||
target, ok := resolve_type_argument(checker, expr.args[0], global.pkg, global.file)
|
||||
if ok && types.is_concrete_integer(target) {
|
||||
if ok && is_integer_bound_type(checker, target) {
|
||||
checker.global_types[index] = target
|
||||
}
|
||||
}
|
||||
@@ -10313,14 +10317,21 @@ build_expr :: proc(
|
||||
if frame.stage == 8 {
|
||||
distinct_item, ok := types.node(&checker.module.types, frame.target_type)
|
||||
actual := checker.module.exprs[last].type
|
||||
if ok && distinct_item.kind == .Distinct &&
|
||||
!types.can_retype_distinct(actual, frame.target_type, &checker.module.types) {
|
||||
backing := types.resolve_alias(distinct_item.child, &checker.module.types)
|
||||
if types.is_concrete_scalar(backing) && !types.is_bool(backing) {
|
||||
last = build_scalar_cast(checker, last, backing, expr.span)
|
||||
actual = checker.module.exprs[last].type
|
||||
}
|
||||
}
|
||||
if !ok || distinct_item.kind != .Distinct ||
|
||||
!types.can_retype_distinct(actual, frame.target_type, &checker.module.types) {
|
||||
id := source.addf(
|
||||
checker.diagnostics,
|
||||
expr.span,
|
||||
"distinct type '%s' requires an exact %s value, got %s",
|
||||
"cannot construct distinct type '%s' from %s",
|
||||
symbol_text(checker, expr.name),
|
||||
types.name(distinct_item.child),
|
||||
types.name(actual),
|
||||
)
|
||||
last = invalid_hir_expr(checker, expr.span, id, frame.target_type)
|
||||
|
||||
Reference in New Issue
Block a user