Merge branch 'LemonBoy-use-struct-pt2'

This commit is contained in:
Andrew Kelley 2019-05-29 16:32:16 -04:00
commit 7017388e9e
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 48 additions and 31 deletions

View File

@ -3453,11 +3453,12 @@ TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {
}
static bool is_container(ZigType *type_entry) {
bool is_container(ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdStruct:
return !type_entry->data.structure.is_slice;
case ZigTypeIdEnum:
case ZigTypeIdUnion:
return true;
@ -3498,9 +3499,9 @@ bool is_array_ref(ZigType *type_entry) {
return array->id == ZigTypeIdArray;
}
bool is_container_ref(ZigType *type_entry) {
return is_ref(type_entry) ?
is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
bool is_container_ref(ZigType *parent_ty) {
ZigType *ty = is_ref(parent_ty) ? parent_ty->data.pointer.child_type : parent_ty;
return is_slice(ty) || is_container(ty);
}
ZigType *container_ref_type(ZigType *type_entry) {
@ -3765,49 +3766,59 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
analyze_fn_ir(g, fn_table_entry, return_type_node);
}
static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
static void add_symbols_from_container(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
if (src_use_node->data.use.resolution == TldResolutionUnresolved) {
preview_use_decl(g, src_use_node, decls_scope);
}
ConstExprValue *use_target_value = src_use_node->data.use.using_namespace_value;
if (type_is_invalid(use_target_value->type)) {
ConstExprValue *use_expr = src_use_node->data.use.using_namespace_value;
if (type_is_invalid(use_expr->type)) {
decls_scope->any_imports_failed = true;
return;
}
dst_use_node->data.use.resolution = TldResolutionOk;
assert(use_target_value->special != ConstValSpecialRuntime);
assert(use_expr->special != ConstValSpecialRuntime);
ZigType *target_import = use_target_value->data.x_type;
assert(target_import);
// The source struct for the imported symbols
ZigType *src_ty = use_expr->data.x_type;
assert(src_ty);
if (target_import->id != ZigTypeIdStruct) {
if (!is_container(src_ty)) {
add_node_error(g, dst_use_node,
buf_sprintf("expected struct, found '%s'", buf_ptr(&target_import->name)));
buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&src_ty->name)));
decls_scope->any_imports_failed = true;
return;
}
if (get_container_scope(target_import)->any_imports_failed) {
// The source scope for the imported symbols
ScopeDecls *src_scope = get_container_scope(src_ty);
// The top-level container where the symbols are defined, it's used in the
// loop below in order to exclude the ones coming from an import statement
ZigType *src_import = get_scope_import(&src_scope->base);
assert(src_import != nullptr);
if (src_scope->any_imports_failed) {
decls_scope->any_imports_failed = true;
}
auto it = get_container_scope(target_import)->decl_table.entry_iterator();
auto it = src_scope->decl_table.entry_iterator();
for (;;) {
auto *entry = it.next();
if (!entry)
break;
Buf *target_tld_name = entry->key;
Tld *target_tld = entry->value;
if (target_tld->import != target_import ||
target_tld->visib_mod == VisibModPrivate)
{
if (target_tld->visib_mod == VisibModPrivate) {
continue;
}
Buf *target_tld_name = entry->key;
if (target_tld->import != src_import) {
continue;
}
auto existing_entry = decls_scope->decl_table.put_unique(target_tld_name, target_tld);
if (existing_entry) {
@ -3822,10 +3833,10 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
}
}
for (size_t i = 0; i < get_container_scope(target_import)->use_decls.length; i += 1) {
AstNode *use_decl_node = get_container_scope(target_import)->use_decls.at(i);
for (size_t i = 0; i < src_scope->use_decls.length; i += 1) {
AstNode *use_decl_node = src_scope->use_decls.at(i);
if (use_decl_node->data.use.visib_mod != VisibModPrivate)
add_symbols_from_import(g, use_decl_node, dst_use_node, decls_scope);
add_symbols_from_container(g, use_decl_node, dst_use_node, decls_scope);
}
}
@ -3837,7 +3848,7 @@ void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
{
return;
}
add_symbols_from_import(g, node, node, decls_scope);
add_symbols_from_container(g, node, node, decls_scope);
}
void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {

View File

@ -250,5 +250,6 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c);
void src_assert(bool ok, AstNode *source_node);
bool is_container(ZigType *type_entry);
#endif

View File

@ -10266,12 +10266,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
return result;
}
static bool is_container(ZigType *type) {
return type->id == ZigTypeIdStruct ||
type->id == ZigTypeIdEnum ||
type->id == ZigTypeIdUnion;
}
static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
assert(old_bb);
@ -16179,7 +16173,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(container_type)) {
return ira->codegen->invalid_instruction;
} else if (is_container_ref(container_type)) {
} else if (is_slice(container_type) || is_container_ref(container_type)) {
assert(container_ptr->value.type->id == ZigTypeIdPointer);
if (container_type->id == ZigTypeIdPointer) {
ZigType *bare_type = container_ref_type(container_type);
@ -16249,7 +16243,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(child_type)) {
return ira->codegen->invalid_instruction;
} else if (is_container(child_type) && !is_slice(child_type)) {
} else if (is_container(child_type)) {
if (child_type->id == ZigTypeIdEnum) {
if ((err = ensure_complete_type(ira->codegen, child_type)))
return ira->codegen->invalid_instruction;

View File

@ -163,7 +163,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"usingnamespace with wrong type",
\\use void;
,
"tmp.zig:1:1: error: expected struct, found 'void'",
"tmp.zig:1:1: error: expected struct, enum, or union; found 'void'",
);
cases.add(

View File

@ -549,3 +549,14 @@ test "packed struct with fp fields" {
expectEqual(f32(11.0), s.data[1]);
expectEqual(f32(20.0), s.data[2]);
}
test "use within struct scope" {
const S = struct {
use struct {
pub fn inner() i32 {
return 42;
}
};
};
expectEqual(i32(42), S.inner());
}