/* valadatatype.c generated by valac, the Vala compiler
 * generated from valadatatype.vala, do not modify */

/* valadatatype.vala
 *
 * Copyright (C) 2006-2010  Jürg Billeter
 * Copyright (C) 2006-2008  Raffaele Sandrini
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	Jürg Billeter <j@bitron.ch>
 *	Raffaele Sandrini <raffaele@sandrini.ch>
 */

#include "vala.h"
#include <glib.h>
#include <valagee.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>

#define _vala_iterable_unref0(var) ((var == NULL) ? NULL : (var = (vala_iterable_unref (var), NULL)))
#define _vala_code_node_unref0(var) ((var == NULL) ? NULL : (var = (vala_code_node_unref (var), NULL)))
#define _vala_scope_unref0(var) ((var == NULL) ? NULL : (var = (vala_scope_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _vala_code_context_unref0(var) ((var == NULL) ? NULL : (var = (vala_code_context_unref (var), NULL)))
#define _vala_iterator_unref0(var) ((var == NULL) ? NULL : (var = (vala_iterator_unref (var), NULL)))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))

struct _ValaDataTypePrivate {
	gboolean _value_owned;
	gboolean _nullable;
	ValaSymbol* _symbol;
	ValaSymbol* _context_symbol;
	gboolean _floating_reference;
	gboolean _is_dynamic;
	ValaList* type_argument_list;
};

static gint ValaDataType_private_offset;
static gpointer vala_data_type_parent_class = NULL;
static ValaList* vala_data_type__empty_type_list;
static ValaList* vala_data_type__empty_type_list = NULL;

static void vala_data_type_set_symbol (ValaDataType* self,
                                ValaSymbol* value);
static void vala_data_type_real_accept (ValaCodeNode* base,
                                 ValaCodeVisitor* visitor);
static void vala_data_type_real_accept_children (ValaCodeNode* base,
                                          ValaCodeVisitor* visitor);
static gchar* vala_data_type_real_to_string (ValaCodeNode* base);
static gchar* vala_data_type_real_to_qualified_string (ValaDataType* self,
                                                ValaScope* scope);
static ValaDataType* vala_data_type_real_copy (ValaDataType* self);
static gboolean vala_data_type_real_equals (ValaDataType* self,
                                     ValaDataType* type2);
static gboolean vala_data_type_real_stricter (ValaDataType* self,
                                       ValaDataType* type2);
static void vala_data_type_real_replace_type (ValaCodeNode* base,
                                       ValaDataType* old_type,
                                       ValaDataType* new_type);
static gboolean vala_data_type_real_compatible (ValaDataType* self,
                                         ValaDataType* target_type);
 G_GNUC_INTERNAL ValaDataType* vala_semantic_analyzer_get_instance_base_type_for_member (ValaDataType* derived_instance_type,
                                                                        ValaTypeSymbol* type_symbol,
                                                                        ValaCodeNode* node_reference);
static gboolean vala_data_type_real_is_invokable (ValaDataType* self);
static ValaDataType* vala_data_type_real_get_return_type (ValaDataType* self);
static ValaList* vala_data_type_real_get_parameters (ValaDataType* self);
static gboolean vala_data_type_real_is_reference_type_or_type_parameter (ValaDataType* self);
static gboolean vala_data_type_real_is_accessible (ValaDataType* self,
                                            ValaSymbol* sym);
static ValaSymbol* vala_data_type_real_get_member (ValaDataType* self,
                                            const gchar* member_name);
static ValaSymbol* vala_data_type_real_get_pointer_member (ValaDataType* self,
                                                    const gchar* member_name);
static gboolean vala_data_type_real_is_real_struct_type (ValaDataType* self);
static gboolean vala_data_type_real_is_disposable (ValaDataType* self);
static ValaDataType* vala_data_type_real_get_actual_type (ValaDataType* self,
                                                   ValaDataType* derived_instance_type,
                                                   ValaList* method_type_arguments,
                                                   ValaCodeNode* node_reference);
static ValaDataType* vala_data_type_real_infer_type_argument (ValaDataType* self,
                                                       ValaTypeParameter* type_param,
                                                       ValaDataType* value_type);
static gchar* vala_data_type_real_to_prototype_string (ValaDataType* self,
                                                const gchar* override_name);
static void vala_data_type_finalize (ValaCodeNode * obj);
static GType vala_data_type_get_type_once (void);

static inline gpointer
vala_data_type_get_instance_private (ValaDataType* self)
{
	return G_STRUCT_MEMBER_P (self, ValaDataType_private_offset);
}

gboolean
vala_data_type_get_value_owned (ValaDataType* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_value_owned;
	return result;
}

void
vala_data_type_set_value_owned (ValaDataType* self,
                                gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_value_owned = value;
}

gboolean
vala_data_type_get_nullable (ValaDataType* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_nullable;
	return result;
}

void
vala_data_type_set_nullable (ValaDataType* self,
                             gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_nullable = value;
}

ValaSymbol*
vala_data_type_get_symbol (ValaDataType* self)
{
	ValaSymbol* result;
	ValaSymbol* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_symbol;
	result = _tmp0_;
	return result;
}

static void
vala_data_type_set_symbol (ValaDataType* self,
                           ValaSymbol* value)
{
	g_return_if_fail (self != NULL);
	self->priv->_symbol = value;
}

ValaSymbol*
vala_data_type_get_context_symbol (ValaDataType* self)
{
	ValaSymbol* result;
	ValaSymbol* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_context_symbol;
	result = _tmp0_;
	return result;
}

void
vala_data_type_set_context_symbol (ValaDataType* self,
                                   ValaSymbol* value)
{
	g_return_if_fail (self != NULL);
	self->priv->_context_symbol = value;
}

ValaTypeSymbol*
vala_data_type_get_type_symbol (ValaDataType* self)
{
	ValaTypeSymbol* result;
	ValaSymbol* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_symbol;
	result = VALA_IS_TYPESYMBOL (_tmp0_) ? ((ValaTypeSymbol*) _tmp0_) : NULL;
	return result;
}

gboolean
vala_data_type_get_floating_reference (ValaDataType* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_floating_reference;
	return result;
}

void
vala_data_type_set_floating_reference (ValaDataType* self,
                                       gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_floating_reference = value;
}

gboolean
vala_data_type_get_is_dynamic (ValaDataType* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_is_dynamic;
	return result;
}

void
vala_data_type_set_is_dynamic (ValaDataType* self,
                               gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_is_dynamic = value;
}

ValaDataType*
vala_data_type_construct_with_symbol (GType object_type,
                                      ValaSymbol* symbol,
                                      ValaSourceReference* source_reference)
{
	ValaDataType* self = NULL;
	self = (ValaDataType*) vala_code_node_construct (object_type);
	vala_data_type_set_symbol (self, symbol);
	vala_code_node_set_source_reference ((ValaCodeNode*) self, source_reference);
	return self;
}

/**
 * Appends the specified type as generic type argument.
 *
 * @param arg a type reference
 */
void
vala_data_type_add_type_argument (ValaDataType* self,
                                  ValaDataType* arg)
{
	ValaList* _tmp0_;
	ValaList* _tmp3_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (arg != NULL);
	_tmp0_ = self->priv->type_argument_list;
	if (_tmp0_ == NULL) {
		GEqualFunc _tmp1_;
		ValaArrayList* _tmp2_;
		_tmp1_ = g_direct_equal;
		_tmp2_ = vala_array_list_new (VALA_TYPE_DATA_TYPE, (GBoxedCopyFunc) vala_code_node_ref, (GDestroyNotify) vala_code_node_unref, _tmp1_);
		_vala_iterable_unref0 (self->priv->type_argument_list);
		self->priv->type_argument_list = (ValaList*) _tmp2_;
	}
	_tmp3_ = self->priv->type_argument_list;
	vala_collection_add ((ValaCollection*) _tmp3_, arg);
	vala_code_node_set_parent_node ((ValaCodeNode*) arg, (ValaCodeNode*) self);
}

/**
 * Returns the list of generic type arguments.
 *
 * @return type argument list
 */
ValaList*
vala_data_type_get_type_arguments (ValaDataType* self)
{
	ValaList* _tmp0_;
	ValaList* _tmp2_;
	ValaList* _tmp5_;
	ValaList* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->type_argument_list;
	if (_tmp0_ != NULL) {
		ValaList* _tmp1_;
		_tmp1_ = self->priv->type_argument_list;
		result = _tmp1_;
		return result;
	}
	_tmp2_ = vala_data_type__empty_type_list;
	if (_tmp2_ == NULL) {
		GEqualFunc _tmp3_;
		ValaArrayList* _tmp4_;
		_tmp3_ = g_direct_equal;
		_tmp4_ = vala_array_list_new (VALA_TYPE_DATA_TYPE, (GBoxedCopyFunc) vala_code_node_ref, (GDestroyNotify) vala_code_node_unref, _tmp3_);
		_vala_iterable_unref0 (vala_data_type__empty_type_list);
		vala_data_type__empty_type_list = (ValaList*) _tmp4_;
	}
	_tmp5_ = vala_data_type__empty_type_list;
	result = _tmp5_;
	return result;
}

gboolean
vala_data_type_has_type_arguments (ValaDataType* self)
{
	ValaList* _tmp0_;
	ValaList* _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->type_argument_list;
	if (_tmp0_ == NULL) {
		result = FALSE;
		return result;
	}
	_tmp1_ = self->priv->type_argument_list;
	_tmp2_ = vala_collection_get_size ((ValaCollection*) _tmp1_);
	_tmp3_ = _tmp2_;
	result = _tmp3_ > 0;
	return result;
}

/**
 * Removes all generic type arguments.
 */
void
vala_data_type_remove_all_type_arguments (ValaDataType* self)
{
	g_return_if_fail (self != NULL);
	_vala_iterable_unref0 (self->priv->type_argument_list);
	self->priv->type_argument_list = NULL;
}

static void
vala_data_type_real_accept (ValaCodeNode* base,
                            ValaCodeVisitor* visitor)
{
	ValaDataType * self;
	self = (ValaDataType*) base;
	g_return_if_fail (visitor != NULL);
	vala_code_visitor_visit_data_type (visitor, self);
}

static void
vala_data_type_real_accept_children (ValaCodeNode* base,
                                     ValaCodeVisitor* visitor)
{
	ValaDataType * self;
	gboolean _tmp0_ = FALSE;
	ValaList* _tmp1_;
	self = (ValaDataType*) base;
	g_return_if_fail (visitor != NULL);
	_tmp1_ = self->priv->type_argument_list;
	if (_tmp1_ != NULL) {
		ValaList* _tmp2_;
		gint _tmp3_;
		gint _tmp4_;
		_tmp2_ = self->priv->type_argument_list;
		_tmp3_ = vala_collection_get_size ((ValaCollection*) _tmp2_);
		_tmp4_ = _tmp3_;
		_tmp0_ = _tmp4_ > 0;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		{
			ValaList* _type_arg_list = NULL;
			ValaList* _tmp5_;
			gint _type_arg_size = 0;
			ValaList* _tmp6_;
			gint _tmp7_;
			gint _tmp8_;
			gint _type_arg_index = 0;
			_tmp5_ = self->priv->type_argument_list;
			_type_arg_list = _tmp5_;
			_tmp6_ = _type_arg_list;
			_tmp7_ = vala_collection_get_size ((ValaCollection*) _tmp6_);
			_tmp8_ = _tmp7_;
			_type_arg_size = _tmp8_;
			_type_arg_index = -1;
			while (TRUE) {
				gint _tmp9_;
				gint _tmp10_;
				ValaDataType* type_arg = NULL;
				ValaList* _tmp11_;
				gpointer _tmp12_;
				ValaDataType* _tmp13_;
				_type_arg_index = _type_arg_index + 1;
				_tmp9_ = _type_arg_index;
				_tmp10_ = _type_arg_size;
				if (!(_tmp9_ < _tmp10_)) {
					break;
				}
				_tmp11_ = _type_arg_list;
				_tmp12_ = vala_list_get (_tmp11_, _type_arg_index);
				type_arg = (ValaDataType*) _tmp12_;
				_tmp13_ = type_arg;
				vala_code_node_accept ((ValaCodeNode*) _tmp13_, visitor);
				_vala_code_node_unref0 (type_arg);
			}
		}
	}
}

static gchar*
vala_data_type_real_to_string (ValaCodeNode* base)
{
	ValaDataType * self;
	gchar* _tmp0_;
	gchar* result;
	self = (ValaDataType*) base;
	_tmp0_ = vala_data_type_to_qualified_string (self, NULL);
	result = _tmp0_;
	return result;
}

static gpointer
_vala_code_node_ref0 (gpointer self)
{
	return self ? vala_code_node_ref (self) : NULL;
}

static gpointer
_vala_scope_ref0 (gpointer self)
{
	return self ? vala_scope_ref (self) : NULL;
}

static gpointer
_vala_iterable_ref0 (gpointer self)
{
	return self ? vala_iterable_ref (self) : NULL;
}

static gchar*
vala_data_type_real_to_qualified_string (ValaDataType* self,
                                         ValaScope* scope)
{
	gchar* s = NULL;
	ValaTypeSymbol* _tmp0_;
	ValaTypeSymbol* _tmp1_;
	ValaList* type_args = NULL;
	ValaList* _tmp44_;
	ValaList* _tmp45_;
	ValaList* _tmp46_;
	gint _tmp47_;
	gint _tmp48_;
	gboolean _tmp71_;
	gchar* result;
	_tmp0_ = vala_data_type_get_type_symbol (self);
	_tmp1_ = _tmp0_;
	if (_tmp1_ != NULL) {
		ValaSymbol* global_symbol = NULL;
		ValaTypeSymbol* _tmp2_;
		ValaTypeSymbol* _tmp3_;
		ValaSymbol* _tmp4_;
		ValaSymbol* sym = NULL;
		ValaScope* parent_scope = NULL;
		ValaScope* _tmp18_;
		gboolean _tmp31_ = FALSE;
		ValaSymbol* _tmp32_;
		_tmp2_ = vala_data_type_get_type_symbol (self);
		_tmp3_ = _tmp2_;
		_tmp4_ = _vala_code_node_ref0 ((ValaSymbol*) _tmp3_);
		global_symbol = _tmp4_;
		while (TRUE) {
			gboolean _tmp5_ = FALSE;
			ValaSymbol* _tmp6_;
			ValaSymbol* _tmp7_;
			ValaSymbol* _tmp8_;
			ValaSymbol* _tmp14_;
			ValaSymbol* _tmp15_;
			ValaSymbol* _tmp16_;
			ValaSymbol* _tmp17_;
			_tmp6_ = global_symbol;
			_tmp7_ = vala_symbol_get_parent_symbol (_tmp6_);
			_tmp8_ = _tmp7_;
			if (_tmp8_ != NULL) {
				ValaSymbol* _tmp9_;
				ValaSymbol* _tmp10_;
				ValaSymbol* _tmp11_;
				const gchar* _tmp12_;
				const gchar* _tmp13_;
				_tmp9_ = global_symbol;
				_tmp10_ = vala_symbol_get_parent_symbol (_tmp9_);
				_tmp11_ = _tmp10_;
				_tmp12_ = vala_symbol_get_name (_tmp11_);
				_tmp13_ = _tmp12_;
				_tmp5_ = _tmp13_ != NULL;
			} else {
				_tmp5_ = FALSE;
			}
			if (!_tmp5_) {
				break;
			}
			_tmp14_ = global_symbol;
			_tmp15_ = vala_symbol_get_parent_symbol (_tmp14_);
			_tmp16_ = _tmp15_;
			_tmp17_ = _vala_code_node_ref0 (_tmp16_);
			_vala_code_node_unref0 (global_symbol);
			global_symbol = _tmp17_;
		}
		sym = NULL;
		_tmp18_ = _vala_scope_ref0 (scope);
		parent_scope = _tmp18_;
		while (TRUE) {
			gboolean _tmp19_ = FALSE;
			ValaSymbol* _tmp20_;
			ValaScope* _tmp22_;
			ValaSymbol* _tmp23_;
			const gchar* _tmp24_;
			const gchar* _tmp25_;
			ValaSymbol* _tmp26_;
			ValaScope* _tmp27_;
			ValaScope* _tmp28_;
			ValaScope* _tmp29_;
			ValaScope* _tmp30_;
			_tmp20_ = sym;
			if (_tmp20_ == NULL) {
				ValaScope* _tmp21_;
				_tmp21_ = parent_scope;
				_tmp19_ = _tmp21_ != NULL;
			} else {
				_tmp19_ = FALSE;
			}
			if (!_tmp19_) {
				break;
			}
			_tmp22_ = parent_scope;
			_tmp23_ = global_symbol;
			_tmp24_ = vala_symbol_get_name (_tmp23_);
			_tmp25_ = _tmp24_;
			_tmp26_ = vala_scope_lookup (_tmp22_, _tmp25_);
			_vala_code_node_unref0 (sym);
			sym = _tmp26_;
			_tmp27_ = parent_scope;
			_tmp28_ = vala_scope_get_parent_scope (_tmp27_);
			_tmp29_ = _tmp28_;
			_tmp30_ = _vala_scope_ref0 (_tmp29_);
			_vala_scope_unref0 (parent_scope);
			parent_scope = _tmp30_;
		}
		_tmp32_ = sym;
		if (_tmp32_ != NULL) {
			ValaSymbol* _tmp33_;
			ValaSymbol* _tmp34_;
			_tmp33_ = global_symbol;
			_tmp34_ = sym;
			_tmp31_ = _tmp33_ != _tmp34_;
		} else {
			_tmp31_ = FALSE;
		}
		if (_tmp31_) {
			ValaTypeSymbol* _tmp35_;
			ValaTypeSymbol* _tmp36_;
			gchar* _tmp37_;
			gchar* _tmp38_;
			gchar* _tmp39_;
			_tmp35_ = vala_data_type_get_type_symbol (self);
			_tmp36_ = _tmp35_;
			_tmp37_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp36_);
			_tmp38_ = _tmp37_;
			_tmp39_ = g_strconcat ("global::", _tmp38_, NULL);
			_g_free0 (s);
			s = _tmp39_;
			_g_free0 (_tmp38_);
		} else {
			ValaTypeSymbol* _tmp40_;
			ValaTypeSymbol* _tmp41_;
			gchar* _tmp42_;
			_tmp40_ = vala_data_type_get_type_symbol (self);
			_tmp41_ = _tmp40_;
			_tmp42_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp41_);
			_g_free0 (s);
			s = _tmp42_;
		}
		_vala_scope_unref0 (parent_scope);
		_vala_code_node_unref0 (sym);
		_vala_code_node_unref0 (global_symbol);
	} else {
		gchar* _tmp43_;
		_tmp43_ = g_strdup ("null");
		_g_free0 (s);
		s = _tmp43_;
	}
	_tmp44_ = vala_data_type_get_type_arguments (self);
	_tmp45_ = _vala_iterable_ref0 (_tmp44_);
	type_args = _tmp45_;
	_tmp46_ = type_args;
	_tmp47_ = vala_collection_get_size ((ValaCollection*) _tmp46_);
	_tmp48_ = _tmp47_;
	if (_tmp48_ > 0) {
		const gchar* _tmp49_;
		gchar* _tmp50_;
		gboolean first = FALSE;
		const gchar* _tmp69_;
		gchar* _tmp70_;
		_tmp49_ = s;
		_tmp50_ = g_strconcat (_tmp49_, "<", NULL);
		_g_free0 (s);
		s = _tmp50_;
		first = TRUE;
		{
			ValaList* _type_arg_list = NULL;
			ValaList* _tmp51_;
			gint _type_arg_size = 0;
			ValaList* _tmp52_;
			gint _tmp53_;
			gint _tmp54_;
			gint _type_arg_index = 0;
			_tmp51_ = type_args;
			_type_arg_list = _tmp51_;
			_tmp52_ = _type_arg_list;
			_tmp53_ = vala_collection_get_size ((ValaCollection*) _tmp52_);
			_tmp54_ = _tmp53_;
			_type_arg_size = _tmp54_;
			_type_arg_index = -1;
			while (TRUE) {
				gint _tmp55_;
				gint _tmp56_;
				ValaDataType* type_arg = NULL;
				ValaList* _tmp57_;
				gpointer _tmp58_;
				ValaDataType* _tmp61_;
				const gchar* _tmp64_;
				ValaDataType* _tmp65_;
				gchar* _tmp66_;
				gchar* _tmp67_;
				gchar* _tmp68_;
				_type_arg_index = _type_arg_index + 1;
				_tmp55_ = _type_arg_index;
				_tmp56_ = _type_arg_size;
				if (!(_tmp55_ < _tmp56_)) {
					break;
				}
				_tmp57_ = _type_arg_list;
				_tmp58_ = vala_list_get (_tmp57_, _type_arg_index);
				type_arg = (ValaDataType*) _tmp58_;
				if (!first) {
					const gchar* _tmp59_;
					gchar* _tmp60_;
					_tmp59_ = s;
					_tmp60_ = g_strconcat (_tmp59_, ",", NULL);
					_g_free0 (s);
					s = _tmp60_;
				} else {
					first = FALSE;
				}
				_tmp61_ = type_arg;
				if (vala_data_type_is_weak (_tmp61_)) {
					const gchar* _tmp62_;
					gchar* _tmp63_;
					_tmp62_ = s;
					_tmp63_ = g_strconcat (_tmp62_, "weak ", NULL);
					_g_free0 (s);
					s = _tmp63_;
				}
				_tmp64_ = s;
				_tmp65_ = type_arg;
				_tmp66_ = vala_data_type_to_qualified_string (_tmp65_, scope);
				_tmp67_ = _tmp66_;
				_tmp68_ = g_strconcat (_tmp64_, _tmp67_, NULL);
				_g_free0 (s);
				s = _tmp68_;
				_g_free0 (_tmp67_);
				_vala_code_node_unref0 (type_arg);
			}
		}
		_tmp69_ = s;
		_tmp70_ = g_strconcat (_tmp69_, ">", NULL);
		_g_free0 (s);
		s = _tmp70_;
	}
	_tmp71_ = self->priv->_nullable;
	if (_tmp71_) {
		const gchar* _tmp72_;
		gchar* _tmp73_;
		_tmp72_ = s;
		_tmp73_ = g_strconcat (_tmp72_, "?", NULL);
		_g_free0 (s);
		s = _tmp73_;
	}
	result = s;
	_vala_iterable_unref0 (type_args);
	return result;
}

gchar*
vala_data_type_to_qualified_string (ValaDataType* self,
                                    ValaScope* scope)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->to_qualified_string) {
		return _klass_->to_qualified_string (self, scope);
	}
	return NULL;
}

/**
 * Creates a shallow copy of this type reference.
 *
 * @return copy of this type reference
 */
static ValaDataType*
vala_data_type_real_copy (ValaDataType* self)
{
	g_critical ("Type `%s' does not implement abstract method `vala_data_type_copy'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return NULL;
}

ValaDataType*
vala_data_type_copy (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->copy) {
		return _klass_->copy (self);
	}
	return NULL;
}

/**
 * Checks two type references for equality. May only be used with
 * resolved type references.
 *
 * @param type2 a type reference
 * @return      true if this type reference is equal to type2, false
 *              otherwise
 */
static gboolean
vala_data_type_real_equals (ValaDataType* self,
                            ValaDataType* type2)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	ValaTypeSymbol* _tmp2_;
	ValaTypeSymbol* _tmp3_;
	ValaTypeSymbol* _tmp4_;
	ValaTypeSymbol* _tmp5_;
	gboolean _tmp6_ = FALSE;
	gboolean _tmp12_;
	gboolean _tmp13_;
	ValaList* type_args = NULL;
	ValaList* _tmp14_;
	ValaList* _tmp15_;
	ValaList* type2_args = NULL;
	ValaList* _tmp16_;
	ValaList* _tmp17_;
	ValaList* _tmp18_;
	gint _tmp19_;
	gint _tmp20_;
	ValaList* _tmp21_;
	gint _tmp22_;
	gint _tmp23_;
	gboolean result;
	g_return_val_if_fail (type2 != NULL, FALSE);
	if (vala_data_type_is_disposable (type2) != vala_data_type_is_disposable (self)) {
		result = FALSE;
		return result;
	}
	_tmp0_ = type2->priv->_nullable;
	_tmp1_ = self->priv->_nullable;
	if (_tmp0_ != _tmp1_) {
		result = FALSE;
		return result;
	}
	_tmp2_ = vala_data_type_get_type_symbol (type2);
	_tmp3_ = _tmp2_;
	_tmp4_ = vala_data_type_get_type_symbol (self);
	_tmp5_ = _tmp4_;
	if (_tmp3_ != _tmp5_) {
		result = FALSE;
		return result;
	}
	if (VALA_IS_GENERIC_TYPE (type2)) {
		_tmp6_ = TRUE;
	} else {
		_tmp6_ = VALA_IS_GENERIC_TYPE (self);
	}
	if (_tmp6_) {
		gboolean _tmp7_ = FALSE;
		ValaTypeParameter* _tmp8_;
		ValaTypeParameter* _tmp9_;
		ValaTypeParameter* _tmp10_;
		ValaTypeParameter* _tmp11_;
		if (!VALA_IS_GENERIC_TYPE (type2)) {
			_tmp7_ = TRUE;
		} else {
			_tmp7_ = !VALA_IS_GENERIC_TYPE (self);
		}
		if (_tmp7_) {
			result = FALSE;
			return result;
		}
		_tmp8_ = vala_generic_type_get_type_parameter (G_TYPE_CHECK_INSTANCE_CAST (type2, VALA_TYPE_GENERIC_TYPE, ValaGenericType));
		_tmp9_ = _tmp8_;
		_tmp10_ = vala_generic_type_get_type_parameter (G_TYPE_CHECK_INSTANCE_CAST (self, VALA_TYPE_GENERIC_TYPE, ValaGenericType));
		_tmp11_ = _tmp10_;
		if (!vala_typeparameter_equals (_tmp9_, _tmp11_)) {
			result = FALSE;
			return result;
		}
	}
	_tmp12_ = type2->priv->_floating_reference;
	_tmp13_ = self->priv->_floating_reference;
	if (_tmp12_ != _tmp13_) {
		result = FALSE;
		return result;
	}
	_tmp14_ = vala_data_type_get_type_arguments (self);
	_tmp15_ = _vala_iterable_ref0 (_tmp14_);
	type_args = _tmp15_;
	_tmp16_ = vala_data_type_get_type_arguments (type2);
	_tmp17_ = _vala_iterable_ref0 (_tmp16_);
	type2_args = _tmp17_;
	_tmp18_ = type2_args;
	_tmp19_ = vala_collection_get_size ((ValaCollection*) _tmp18_);
	_tmp20_ = _tmp19_;
	_tmp21_ = type_args;
	_tmp22_ = vala_collection_get_size ((ValaCollection*) _tmp21_);
	_tmp23_ = _tmp22_;
	if (_tmp20_ != _tmp23_) {
		result = FALSE;
		_vala_iterable_unref0 (type2_args);
		_vala_iterable_unref0 (type_args);
		return result;
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp24_ = FALSE;
			_tmp24_ = TRUE;
			while (TRUE) {
				ValaList* _tmp26_;
				gint _tmp27_;
				gint _tmp28_;
				ValaList* _tmp29_;
				gpointer _tmp30_;
				ValaDataType* _tmp31_;
				ValaList* _tmp32_;
				gpointer _tmp33_;
				ValaDataType* _tmp34_;
				gboolean _tmp35_;
				if (!_tmp24_) {
					gint _tmp25_;
					_tmp25_ = i;
					i = _tmp25_ + 1;
				}
				_tmp24_ = FALSE;
				_tmp26_ = type_args;
				_tmp27_ = vala_collection_get_size ((ValaCollection*) _tmp26_);
				_tmp28_ = _tmp27_;
				if (!(i < _tmp28_)) {
					break;
				}
				_tmp29_ = type2_args;
				_tmp30_ = vala_list_get (_tmp29_, i);
				_tmp31_ = (ValaDataType*) _tmp30_;
				_tmp32_ = type_args;
				_tmp33_ = vala_list_get (_tmp32_, i);
				_tmp34_ = (ValaDataType*) _tmp33_;
				_tmp35_ = !vala_data_type_equals (_tmp31_, _tmp34_);
				_vala_code_node_unref0 (_tmp34_);
				_vala_code_node_unref0 (_tmp31_);
				if (_tmp35_) {
					result = FALSE;
					_vala_iterable_unref0 (type2_args);
					_vala_iterable_unref0 (type_args);
					return result;
				}
			}
		}
	}
	result = TRUE;
	_vala_iterable_unref0 (type2_args);
	_vala_iterable_unref0 (type_args);
	return result;
}

gboolean
vala_data_type_equals (ValaDataType* self,
                       ValaDataType* type2)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->equals) {
		return _klass_->equals (self, type2);
	}
	return FALSE;
}

/**
 * Checks whether this type reference is at least as strict as the
 * specified type reference type2.
 *
 * @param type2 a type reference
 * @return      true if this type reference is stricter or equal
 */
static gboolean
vala_data_type_real_stricter (ValaDataType* self,
                              ValaDataType* type2)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_;
	gboolean _tmp3_ = FALSE;
	ValaTypeSymbol* _tmp4_;
	ValaTypeSymbol* _tmp5_;
	ValaTypeSymbol* _tmp6_;
	ValaTypeSymbol* _tmp7_;
	gboolean _tmp8_;
	gboolean _tmp9_;
	gboolean result;
	g_return_val_if_fail (type2 != NULL, FALSE);
	if (vala_data_type_is_disposable (type2) != vala_data_type_is_disposable (self)) {
		result = FALSE;
		return result;
	}
	_tmp1_ = type2->priv->_nullable;
	if (!_tmp1_) {
		gboolean _tmp2_;
		_tmp2_ = self->priv->_nullable;
		_tmp0_ = _tmp2_;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	if (VALA_IS_GENERIC_TYPE (self)) {
		_tmp3_ = TRUE;
	} else {
		_tmp3_ = VALA_IS_GENERIC_TYPE (type2);
	}
	if (_tmp3_) {
		result = TRUE;
		return result;
	}
	_tmp4_ = vala_data_type_get_type_symbol (type2);
	_tmp5_ = _tmp4_;
	_tmp6_ = vala_data_type_get_type_symbol (self);
	_tmp7_ = _tmp6_;
	if (_tmp5_ != _tmp7_) {
		result = FALSE;
		return result;
	}
	_tmp8_ = type2->priv->_floating_reference;
	_tmp9_ = self->priv->_floating_reference;
	if (_tmp8_ != _tmp9_) {
		result = FALSE;
		return result;
	}
	result = TRUE;
	return result;
}

gboolean
vala_data_type_stricter (ValaDataType* self,
                         ValaDataType* type2)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->stricter) {
		return _klass_->stricter (self, type2);
	}
	return FALSE;
}

static void
vala_data_type_real_replace_type (ValaCodeNode* base,
                                  ValaDataType* old_type,
                                  ValaDataType* new_type)
{
	ValaDataType * self;
	ValaList* _tmp0_;
	self = (ValaDataType*) base;
	g_return_if_fail (old_type != NULL);
	g_return_if_fail (new_type != NULL);
	_tmp0_ = self->priv->type_argument_list;
	if (_tmp0_ != NULL) {
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp1_ = FALSE;
				_tmp1_ = TRUE;
				while (TRUE) {
					ValaList* _tmp3_;
					gint _tmp4_;
					gint _tmp5_;
					ValaList* _tmp6_;
					gpointer _tmp7_;
					ValaDataType* _tmp8_;
					gboolean _tmp9_;
					if (!_tmp1_) {
						gint _tmp2_;
						_tmp2_ = i;
						i = _tmp2_ + 1;
					}
					_tmp1_ = FALSE;
					_tmp3_ = self->priv->type_argument_list;
					_tmp4_ = vala_collection_get_size ((ValaCollection*) _tmp3_);
					_tmp5_ = _tmp4_;
					if (!(i < _tmp5_)) {
						break;
					}
					_tmp6_ = self->priv->type_argument_list;
					_tmp7_ = vala_list_get (_tmp6_, i);
					_tmp8_ = (ValaDataType*) _tmp7_;
					_tmp9_ = _tmp8_ == old_type;
					_vala_code_node_unref0 (_tmp8_);
					if (_tmp9_) {
						ValaList* _tmp10_;
						_tmp10_ = self->priv->type_argument_list;
						vala_list_set (_tmp10_, i, new_type);
						return;
					}
				}
			}
		}
	}
}

static gboolean
vala_data_type_real_compatible (ValaDataType* self,
                                ValaDataType* target_type)
{
	ValaCodeContext* context = NULL;
	ValaCodeContext* _tmp0_;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	ValaCodeContext* _tmp3_;
	gboolean _tmp4_;
	gboolean _tmp5_;
	gboolean _tmp8_ = FALSE;
	ValaCodeContext* _tmp9_;
	ValaProfile _tmp10_;
	ValaProfile _tmp11_;
	gboolean _tmp43_ = FALSE;
	gboolean _tmp44_ = FALSE;
	ValaTypeSymbol* _tmp45_;
	ValaTypeSymbol* _tmp46_;
	ValaList* type_args = NULL;
	ValaList* _tmp59_;
	ValaList* _tmp60_;
	ValaList* target_type_args = NULL;
	ValaList* _tmp61_;
	ValaList* _tmp62_;
	ValaList* _tmp63_;
	gint _tmp64_;
	gint _tmp65_;
	ValaList* _tmp66_;
	gint _tmp67_;
	gint _tmp68_;
	gboolean _tmp82_ = FALSE;
	gboolean _tmp83_ = FALSE;
	ValaTypeSymbol* _tmp84_;
	ValaTypeSymbol* _tmp85_;
	gboolean _tmp116_ = FALSE;
	ValaTypeSymbol* _tmp117_;
	ValaTypeSymbol* _tmp118_;
	gboolean result;
	g_return_val_if_fail (target_type != NULL, FALSE);
	_tmp0_ = vala_code_context_get ();
	context = _tmp0_;
	_tmp3_ = context;
	_tmp4_ = vala_code_context_get_experimental_non_null (_tmp3_);
	_tmp5_ = _tmp4_;
	if (_tmp5_) {
		gboolean _tmp6_;
		_tmp6_ = self->priv->_nullable;
		_tmp2_ = _tmp6_;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		gboolean _tmp7_;
		_tmp7_ = target_type->priv->_nullable;
		_tmp1_ = !_tmp7_;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		result = FALSE;
		_vala_code_context_unref0 (context);
		return result;
	}
	_tmp9_ = context;
	_tmp10_ = vala_code_context_get_profile (_tmp9_);
	_tmp11_ = _tmp10_;
	if (_tmp11_ == VALA_PROFILE_GOBJECT) {
		ValaTypeSymbol* _tmp12_;
		ValaTypeSymbol* _tmp13_;
		_tmp12_ = vala_data_type_get_type_symbol (target_type);
		_tmp13_ = _tmp12_;
		_tmp8_ = _tmp13_ != NULL;
	} else {
		_tmp8_ = FALSE;
	}
	if (_tmp8_) {
		ValaDataType* gvalue_type = NULL;
		ValaCodeContext* _tmp14_;
		ValaSemanticAnalyzer* _tmp15_;
		ValaSemanticAnalyzer* _tmp16_;
		ValaStructValueType* _tmp17_;
		gboolean _tmp18_ = FALSE;
		ValaDataType* _tmp19_;
		ValaDataType* gvariant_type = NULL;
		ValaCodeContext* _tmp25_;
		ValaSemanticAnalyzer* _tmp26_;
		ValaSemanticAnalyzer* _tmp27_;
		ValaObjectType* _tmp28_;
		gboolean _tmp29_ = FALSE;
		ValaDataType* _tmp30_;
		_tmp14_ = context;
		_tmp15_ = vala_code_context_get_analyzer (_tmp14_);
		_tmp16_ = _tmp15_;
		_tmp17_ = _tmp16_->gvalue_type;
		gvalue_type = (ValaDataType*) _tmp17_;
		_tmp19_ = gvalue_type;
		if (_tmp19_ != NULL) {
			ValaTypeSymbol* _tmp20_;
			ValaTypeSymbol* _tmp21_;
			ValaDataType* _tmp22_;
			ValaTypeSymbol* _tmp23_;
			ValaTypeSymbol* _tmp24_;
			_tmp20_ = vala_data_type_get_type_symbol (target_type);
			_tmp21_ = _tmp20_;
			_tmp22_ = gvalue_type;
			_tmp23_ = vala_data_type_get_type_symbol (_tmp22_);
			_tmp24_ = _tmp23_;
			_tmp18_ = vala_typesymbol_is_subtype_of (_tmp21_, _tmp24_);
		} else {
			_tmp18_ = FALSE;
		}
		if (_tmp18_) {
			result = TRUE;
			_vala_code_context_unref0 (context);
			return result;
		}
		_tmp25_ = context;
		_tmp26_ = vala_code_context_get_analyzer (_tmp25_);
		_tmp27_ = _tmp26_;
		_tmp28_ = _tmp27_->gvariant_type;
		gvariant_type = (ValaDataType*) _tmp28_;
		_tmp30_ = gvariant_type;
		if (_tmp30_ != NULL) {
			ValaTypeSymbol* _tmp31_;
			ValaTypeSymbol* _tmp32_;
			ValaDataType* _tmp33_;
			ValaTypeSymbol* _tmp34_;
			ValaTypeSymbol* _tmp35_;
			_tmp31_ = vala_data_type_get_type_symbol (target_type);
			_tmp32_ = _tmp31_;
			_tmp33_ = gvariant_type;
			_tmp34_ = vala_data_type_get_type_symbol (_tmp33_);
			_tmp35_ = _tmp34_;
			_tmp29_ = vala_typesymbol_is_subtype_of (_tmp32_, _tmp35_);
		} else {
			_tmp29_ = FALSE;
		}
		if (_tmp29_) {
			result = TRUE;
			_vala_code_context_unref0 (context);
			return result;
		}
	}
	if (VALA_IS_POINTER_TYPE (target_type)) {
		gboolean _tmp36_ = FALSE;
		if (VALA_IS_GENERIC_TYPE (self)) {
			_tmp36_ = TRUE;
		} else {
			gboolean _tmp37_ = FALSE;
			ValaTypeSymbol* _tmp38_;
			ValaTypeSymbol* _tmp39_;
			_tmp38_ = vala_data_type_get_type_symbol (self);
			_tmp39_ = _tmp38_;
			if (_tmp39_ != NULL) {
				gboolean _tmp40_ = FALSE;
				ValaTypeSymbol* _tmp41_;
				ValaTypeSymbol* _tmp42_;
				_tmp41_ = vala_data_type_get_type_symbol (self);
				_tmp42_ = _tmp41_;
				if (vala_typesymbol_is_reference_type (_tmp42_)) {
					_tmp40_ = TRUE;
				} else {
					_tmp40_ = VALA_IS_DELEGATE_TYPE (self);
				}
				_tmp37_ = _tmp40_;
			} else {
				_tmp37_ = FALSE;
			}
			_tmp36_ = _tmp37_;
		}
		if (_tmp36_) {
			result = TRUE;
			_vala_code_context_unref0 (context);
			return result;
		}
		result = FALSE;
		_vala_code_context_unref0 (context);
		return result;
	}
	if (VALA_IS_GENERIC_TYPE (target_type)) {
		result = TRUE;
		_vala_code_context_unref0 (context);
		return result;
	}
	if (VALA_IS_ARRAY_TYPE (self) != VALA_IS_ARRAY_TYPE (target_type)) {
		result = FALSE;
		_vala_code_context_unref0 (context);
		return result;
	}
	_tmp45_ = vala_data_type_get_type_symbol (self);
	_tmp46_ = _tmp45_;
	if (VALA_IS_ENUM (_tmp46_)) {
		ValaTypeSymbol* _tmp47_;
		ValaTypeSymbol* _tmp48_;
		_tmp47_ = vala_data_type_get_type_symbol (target_type);
		_tmp48_ = _tmp47_;
		_tmp44_ = VALA_IS_STRUCT (_tmp48_);
	} else {
		_tmp44_ = FALSE;
	}
	if (_tmp44_) {
		ValaTypeSymbol* _tmp49_;
		ValaTypeSymbol* _tmp50_;
		_tmp49_ = vala_data_type_get_type_symbol (target_type);
		_tmp50_ = _tmp49_;
		_tmp43_ = vala_struct_is_integer_type (G_TYPE_CHECK_INSTANCE_CAST (_tmp50_, VALA_TYPE_STRUCT, ValaStruct));
	} else {
		_tmp43_ = FALSE;
	}
	if (_tmp43_) {
		result = TRUE;
		_vala_code_context_unref0 (context);
		return result;
	} else {
		gboolean _tmp51_ = FALSE;
		gboolean _tmp52_ = FALSE;
		ValaTypeSymbol* _tmp53_;
		ValaTypeSymbol* _tmp54_;
		_tmp53_ = vala_data_type_get_type_symbol (target_type);
		_tmp54_ = _tmp53_;
		if (VALA_IS_ENUM (_tmp54_)) {
			ValaTypeSymbol* _tmp55_;
			ValaTypeSymbol* _tmp56_;
			_tmp55_ = vala_data_type_get_type_symbol (self);
			_tmp56_ = _tmp55_;
			_tmp52_ = VALA_IS_STRUCT (_tmp56_);
		} else {
			_tmp52_ = FALSE;
		}
		if (_tmp52_) {
			ValaTypeSymbol* _tmp57_;
			ValaTypeSymbol* _tmp58_;
			_tmp57_ = vala_data_type_get_type_symbol (self);
			_tmp58_ = _tmp57_;
			_tmp51_ = vala_struct_is_integer_type (G_TYPE_CHECK_INSTANCE_CAST (_tmp58_, VALA_TYPE_STRUCT, ValaStruct));
		} else {
			_tmp51_ = FALSE;
		}
		if (_tmp51_) {
			result = TRUE;
			_vala_code_context_unref0 (context);
			return result;
		}
	}
	_tmp59_ = vala_data_type_get_type_arguments (self);
	_tmp60_ = _vala_iterable_ref0 (_tmp59_);
	type_args = _tmp60_;
	_tmp61_ = vala_data_type_get_type_arguments (target_type);
	_tmp62_ = _vala_iterable_ref0 (_tmp61_);
	target_type_args = _tmp62_;
	_tmp63_ = type_args;
	_tmp64_ = vala_collection_get_size ((ValaCollection*) _tmp63_);
	_tmp65_ = _tmp64_;
	_tmp66_ = target_type_args;
	_tmp67_ = vala_collection_get_size ((ValaCollection*) _tmp66_);
	_tmp68_ = _tmp67_;
	if (_tmp65_ == _tmp68_) {
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp69_ = FALSE;
				_tmp69_ = TRUE;
				while (TRUE) {
					ValaList* _tmp71_;
					gint _tmp72_;
					gint _tmp73_;
					ValaDataType* type_arg = NULL;
					ValaList* _tmp74_;
					gpointer _tmp75_;
					ValaDataType* target_type_arg = NULL;
					ValaList* _tmp76_;
					gpointer _tmp77_;
					gboolean _tmp78_ = FALSE;
					ValaDataType* _tmp79_;
					if (!_tmp69_) {
						gint _tmp70_;
						_tmp70_ = i;
						i = _tmp70_ + 1;
					}
					_tmp69_ = FALSE;
					_tmp71_ = type_args;
					_tmp72_ = vala_collection_get_size ((ValaCollection*) _tmp71_);
					_tmp73_ = _tmp72_;
					if (!(i < _tmp73_)) {
						break;
					}
					_tmp74_ = type_args;
					_tmp75_ = vala_list_get (_tmp74_, i);
					type_arg = (ValaDataType*) _tmp75_;
					_tmp76_ = target_type_args;
					_tmp77_ = vala_list_get (_tmp76_, i);
					target_type_arg = (ValaDataType*) _tmp77_;
					_tmp79_ = type_arg;
					if (!vala_data_type_is_non_null_simple_type (_tmp79_)) {
						ValaDataType* _tmp80_;
						ValaDataType* _tmp81_;
						_tmp80_ = type_arg;
						_tmp81_ = target_type_arg;
						_tmp78_ = vala_data_type_is_weak (_tmp80_) != vala_data_type_is_weak (_tmp81_);
					} else {
						_tmp78_ = FALSE;
					}
					if (_tmp78_) {
						result = FALSE;
						_vala_code_node_unref0 (target_type_arg);
						_vala_code_node_unref0 (type_arg);
						_vala_iterable_unref0 (target_type_args);
						_vala_iterable_unref0 (type_args);
						_vala_code_context_unref0 (context);
						return result;
					}
					_vala_code_node_unref0 (target_type_arg);
					_vala_code_node_unref0 (type_arg);
				}
			}
		}
	}
	_tmp84_ = vala_data_type_get_type_symbol (self);
	_tmp85_ = _tmp84_;
	if (_tmp85_ != NULL) {
		ValaTypeSymbol* _tmp86_;
		ValaTypeSymbol* _tmp87_;
		_tmp86_ = vala_data_type_get_type_symbol (target_type);
		_tmp87_ = _tmp86_;
		_tmp83_ = _tmp87_ != NULL;
	} else {
		_tmp83_ = FALSE;
	}
	if (_tmp83_) {
		ValaTypeSymbol* _tmp88_;
		ValaTypeSymbol* _tmp89_;
		ValaTypeSymbol* _tmp90_;
		ValaTypeSymbol* _tmp91_;
		_tmp88_ = vala_data_type_get_type_symbol (self);
		_tmp89_ = _tmp88_;
		_tmp90_ = vala_data_type_get_type_symbol (target_type);
		_tmp91_ = _tmp90_;
		_tmp82_ = vala_typesymbol_is_subtype_of (_tmp89_, _tmp91_);
	} else {
		_tmp82_ = FALSE;
	}
	if (_tmp82_) {
		ValaDataType* base_type = NULL;
		ValaTypeSymbol* _tmp92_;
		ValaTypeSymbol* _tmp93_;
		ValaDataType* _tmp94_;
		ValaList* base_type_args = NULL;
		ValaDataType* _tmp95_;
		ValaList* _tmp96_;
		ValaList* _tmp97_;
		ValaList* _tmp98_;
		gint _tmp99_;
		gint _tmp100_;
		ValaList* _tmp101_;
		gint _tmp102_;
		gint _tmp103_;
		_tmp92_ = vala_data_type_get_type_symbol (target_type);
		_tmp93_ = _tmp92_;
		_tmp94_ = vala_semantic_analyzer_get_instance_base_type_for_member (self, _tmp93_, (ValaCodeNode*) self);
		base_type = _tmp94_;
		_tmp95_ = base_type;
		_tmp96_ = vala_data_type_get_type_arguments (_tmp95_);
		_tmp97_ = _vala_iterable_ref0 (_tmp96_);
		base_type_args = _tmp97_;
		_tmp98_ = base_type_args;
		_tmp99_ = vala_collection_get_size ((ValaCollection*) _tmp98_);
		_tmp100_ = _tmp99_;
		_tmp101_ = target_type_args;
		_tmp102_ = vala_collection_get_size ((ValaCollection*) _tmp101_);
		_tmp103_ = _tmp102_;
		if (_tmp100_ == _tmp103_) {
			{
				gint i = 0;
				i = 0;
				{
					gboolean _tmp104_ = FALSE;
					_tmp104_ = TRUE;
					while (TRUE) {
						ValaList* _tmp106_;
						gint _tmp107_;
						gint _tmp108_;
						ValaList* _tmp109_;
						gpointer _tmp110_;
						ValaDataType* _tmp111_;
						ValaList* _tmp112_;
						gpointer _tmp113_;
						ValaDataType* _tmp114_;
						gboolean _tmp115_;
						if (!_tmp104_) {
							gint _tmp105_;
							_tmp105_ = i;
							i = _tmp105_ + 1;
						}
						_tmp104_ = FALSE;
						_tmp106_ = base_type_args;
						_tmp107_ = vala_collection_get_size ((ValaCollection*) _tmp106_);
						_tmp108_ = _tmp107_;
						if (!(i < _tmp108_)) {
							break;
						}
						_tmp109_ = base_type_args;
						_tmp110_ = vala_list_get (_tmp109_, i);
						_tmp111_ = (ValaDataType*) _tmp110_;
						_tmp112_ = target_type_args;
						_tmp113_ = vala_list_get (_tmp112_, i);
						_tmp114_ = (ValaDataType*) _tmp113_;
						_tmp115_ = !vala_data_type_compatible (_tmp111_, _tmp114_);
						_vala_code_node_unref0 (_tmp114_);
						_vala_code_node_unref0 (_tmp111_);
						if (_tmp115_) {
							result = FALSE;
							_vala_iterable_unref0 (base_type_args);
							_vala_code_node_unref0 (base_type);
							_vala_iterable_unref0 (target_type_args);
							_vala_iterable_unref0 (type_args);
							_vala_code_context_unref0 (context);
							return result;
						}
					}
				}
			}
		}
		result = TRUE;
		_vala_iterable_unref0 (base_type_args);
		_vala_code_node_unref0 (base_type);
		_vala_iterable_unref0 (target_type_args);
		_vala_iterable_unref0 (type_args);
		_vala_code_context_unref0 (context);
		return result;
	}
	_tmp117_ = vala_data_type_get_type_symbol (self);
	_tmp118_ = _tmp117_;
	if (VALA_IS_STRUCT (_tmp118_)) {
		ValaTypeSymbol* _tmp119_;
		ValaTypeSymbol* _tmp120_;
		_tmp119_ = vala_data_type_get_type_symbol (target_type);
		_tmp120_ = _tmp119_;
		_tmp116_ = VALA_IS_STRUCT (_tmp120_);
	} else {
		_tmp116_ = FALSE;
	}
	if (_tmp116_) {
		ValaStruct* expr_struct = NULL;
		ValaTypeSymbol* _tmp121_;
		ValaTypeSymbol* _tmp122_;
		ValaStruct* expect_struct = NULL;
		ValaTypeSymbol* _tmp123_;
		ValaTypeSymbol* _tmp124_;
		gboolean _tmp125_ = FALSE;
		ValaStruct* _tmp126_;
		gboolean _tmp128_ = FALSE;
		gboolean _tmp129_ = FALSE;
		ValaStruct* _tmp130_;
		gboolean _tmp141_ = FALSE;
		ValaStruct* _tmp142_;
		ValaStruct* _tmp144_;
		ValaStruct* _tmp145_;
		_tmp121_ = vala_data_type_get_type_symbol (self);
		_tmp122_ = _tmp121_;
		expr_struct = G_TYPE_CHECK_INSTANCE_CAST (_tmp122_, VALA_TYPE_STRUCT, ValaStruct);
		_tmp123_ = vala_data_type_get_type_symbol (target_type);
		_tmp124_ = _tmp123_;
		expect_struct = G_TYPE_CHECK_INSTANCE_CAST (_tmp124_, VALA_TYPE_STRUCT, ValaStruct);
		_tmp126_ = expr_struct;
		if (vala_struct_is_integer_type (_tmp126_)) {
			ValaStruct* _tmp127_;
			_tmp127_ = expect_struct;
			_tmp125_ = vala_struct_is_floating_type (_tmp127_);
		} else {
			_tmp125_ = FALSE;
		}
		if (_tmp125_) {
			result = TRUE;
			_vala_iterable_unref0 (target_type_args);
			_vala_iterable_unref0 (type_args);
			_vala_code_context_unref0 (context);
			return result;
		}
		_tmp130_ = expr_struct;
		if (vala_struct_is_integer_type (_tmp130_)) {
			ValaStruct* _tmp131_;
			_tmp131_ = expect_struct;
			_tmp129_ = vala_struct_is_integer_type (_tmp131_);
		} else {
			_tmp129_ = FALSE;
		}
		if (_tmp129_) {
			_tmp128_ = TRUE;
		} else {
			gboolean _tmp132_ = FALSE;
			ValaStruct* _tmp133_;
			_tmp133_ = expr_struct;
			if (vala_struct_is_floating_type (_tmp133_)) {
				ValaStruct* _tmp134_;
				_tmp134_ = expect_struct;
				_tmp132_ = vala_struct_is_floating_type (_tmp134_);
			} else {
				_tmp132_ = FALSE;
			}
			_tmp128_ = _tmp132_;
		}
		if (_tmp128_) {
			ValaStruct* _tmp135_;
			gint _tmp136_;
			gint _tmp137_;
			ValaStruct* _tmp138_;
			gint _tmp139_;
			gint _tmp140_;
			_tmp135_ = expr_struct;
			_tmp136_ = vala_struct_get_rank (_tmp135_);
			_tmp137_ = _tmp136_;
			_tmp138_ = expect_struct;
			_tmp139_ = vala_struct_get_rank (_tmp138_);
			_tmp140_ = _tmp139_;
			if (_tmp137_ <= _tmp140_) {
				result = TRUE;
				_vala_iterable_unref0 (target_type_args);
				_vala_iterable_unref0 (type_args);
				_vala_code_context_unref0 (context);
				return result;
			}
		}
		_tmp142_ = expr_struct;
		if (vala_struct_is_boolean_type (_tmp142_)) {
			ValaStruct* _tmp143_;
			_tmp143_ = expect_struct;
			_tmp141_ = vala_struct_is_boolean_type (_tmp143_);
		} else {
			_tmp141_ = FALSE;
		}
		if (_tmp141_) {
			result = TRUE;
			_vala_iterable_unref0 (target_type_args);
			_vala_iterable_unref0 (type_args);
			_vala_code_context_unref0 (context);
			return result;
		}
		_tmp144_ = expect_struct;
		_tmp145_ = expr_struct;
		if (vala_typesymbol_is_subtype_of ((ValaTypeSymbol*) _tmp144_, (ValaTypeSymbol*) _tmp145_)) {
			result = TRUE;
			_vala_iterable_unref0 (target_type_args);
			_vala_iterable_unref0 (type_args);
			_vala_code_context_unref0 (context);
			return result;
		}
	}
	result = FALSE;
	_vala_iterable_unref0 (target_type_args);
	_vala_iterable_unref0 (type_args);
	_vala_code_context_unref0 (context);
	return result;
}

gboolean
vala_data_type_compatible (ValaDataType* self,
                           ValaDataType* target_type)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->compatible) {
		return _klass_->compatible (self, target_type);
	}
	return FALSE;
}

/**
 * Returns whether instances of this type are invokable.
 *
 * @return true if invokable, false otherwise
 */
static gboolean
vala_data_type_real_is_invokable (ValaDataType* self)
{
	gboolean result;
	result = FALSE;
	return result;
}

gboolean
vala_data_type_is_invokable (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->is_invokable) {
		return _klass_->is_invokable (self);
	}
	return FALSE;
}

/**
 * Returns the return type of this invokable.
 *
 * @return return type
 */
static ValaDataType*
vala_data_type_real_get_return_type (ValaDataType* self)
{
	ValaDataType* result;
	result = NULL;
	return result;
}

ValaDataType*
vala_data_type_get_return_type (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->get_return_type) {
		return _klass_->get_return_type (self);
	}
	return NULL;
}

/**
 * Returns the list of invocation parameters.
 *
 * @return parameter list
 */
static ValaList*
vala_data_type_real_get_parameters (ValaDataType* self)
{
	ValaList* result;
	result = NULL;
	return result;
}

ValaList*
vala_data_type_get_parameters (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->get_parameters) {
		return _klass_->get_parameters (self);
	}
	return NULL;
}

static gboolean
vala_data_type_real_is_reference_type_or_type_parameter (ValaDataType* self)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	ValaTypeSymbol* _tmp2_;
	ValaTypeSymbol* _tmp3_;
	gboolean result;
	_tmp2_ = vala_data_type_get_type_symbol (self);
	_tmp3_ = _tmp2_;
	if (_tmp3_ != NULL) {
		ValaTypeSymbol* _tmp4_;
		ValaTypeSymbol* _tmp5_;
		_tmp4_ = vala_data_type_get_type_symbol (self);
		_tmp5_ = _tmp4_;
		_tmp1_ = vala_typesymbol_is_reference_type (_tmp5_);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = VALA_IS_GENERIC_TYPE (self);
	}
	result = _tmp0_;
	return result;
}

gboolean
vala_data_type_is_reference_type_or_type_parameter (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->is_reference_type_or_type_parameter) {
		return _klass_->is_reference_type_or_type_parameter (self);
	}
	return FALSE;
}

static gboolean
vala_data_type_real_is_accessible (ValaDataType* self,
                                   ValaSymbol* sym)
{
	ValaTypeSymbol* _tmp9_;
	ValaTypeSymbol* _tmp10_;
	gboolean result;
	g_return_val_if_fail (sym != NULL, FALSE);
	{
		ValaList* _type_arg_list = NULL;
		ValaList* _tmp0_;
		gint _type_arg_size = 0;
		ValaList* _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _type_arg_index = 0;
		_tmp0_ = vala_data_type_get_type_arguments (self);
		_type_arg_list = _tmp0_;
		_tmp1_ = _type_arg_list;
		_tmp2_ = vala_collection_get_size ((ValaCollection*) _tmp1_);
		_tmp3_ = _tmp2_;
		_type_arg_size = _tmp3_;
		_type_arg_index = -1;
		while (TRUE) {
			gint _tmp4_;
			gint _tmp5_;
			ValaDataType* type_arg = NULL;
			ValaList* _tmp6_;
			gpointer _tmp7_;
			ValaDataType* _tmp8_;
			_type_arg_index = _type_arg_index + 1;
			_tmp4_ = _type_arg_index;
			_tmp5_ = _type_arg_size;
			if (!(_tmp4_ < _tmp5_)) {
				break;
			}
			_tmp6_ = _type_arg_list;
			_tmp7_ = vala_list_get (_tmp6_, _type_arg_index);
			type_arg = (ValaDataType*) _tmp7_;
			_tmp8_ = type_arg;
			if (!vala_data_type_is_accessible (_tmp8_, sym)) {
				result = FALSE;
				_vala_code_node_unref0 (type_arg);
				return result;
			}
			_vala_code_node_unref0 (type_arg);
		}
	}
	_tmp9_ = vala_data_type_get_type_symbol (self);
	_tmp10_ = _tmp9_;
	if (_tmp10_ != NULL) {
		ValaTypeSymbol* _tmp11_;
		ValaTypeSymbol* _tmp12_;
		_tmp11_ = vala_data_type_get_type_symbol (self);
		_tmp12_ = _tmp11_;
		result = vala_symbol_is_accessible ((ValaSymbol*) _tmp12_, sym);
		return result;
	}
	result = TRUE;
	return result;
}

gboolean
vala_data_type_is_accessible (ValaDataType* self,
                              ValaSymbol* sym)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->is_accessible) {
		return _klass_->is_accessible (self, sym);
	}
	return FALSE;
}

static ValaSymbol*
vala_data_type_real_get_member (ValaDataType* self,
                                const gchar* member_name)
{
	ValaSymbol* member = NULL;
	ValaSymbol* _tmp0_;
	gboolean _tmp3_ = FALSE;
	ValaSymbol* _tmp4_;
	ValaSymbol* result;
	g_return_val_if_fail (member_name != NULL, NULL);
	member = NULL;
	_tmp0_ = self->priv->_context_symbol;
	if (_tmp0_ != NULL) {
		ValaSymbol* _tmp1_;
		ValaSymbol* _tmp2_;
		_tmp1_ = self->priv->_context_symbol;
		_tmp2_ = vala_semantic_analyzer_symbol_lookup_inherited (_tmp1_, member_name);
		_vala_code_node_unref0 (member);
		member = _tmp2_;
	}
	_tmp4_ = member;
	if (_tmp4_ == NULL) {
		ValaTypeSymbol* _tmp5_;
		ValaTypeSymbol* _tmp6_;
		_tmp5_ = vala_data_type_get_type_symbol (self);
		_tmp6_ = _tmp5_;
		_tmp3_ = _tmp6_ != NULL;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		ValaTypeSymbol* _tmp7_;
		ValaTypeSymbol* _tmp8_;
		ValaSymbol* _tmp9_;
		_tmp7_ = vala_data_type_get_type_symbol (self);
		_tmp8_ = _tmp7_;
		_tmp9_ = vala_semantic_analyzer_symbol_lookup_inherited ((ValaSymbol*) _tmp8_, member_name);
		_vala_code_node_unref0 (member);
		member = _tmp9_;
	}
	result = member;
	return result;
}

ValaSymbol*
vala_data_type_get_member (ValaDataType* self,
                           const gchar* member_name)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->get_member) {
		return _klass_->get_member (self, member_name);
	}
	return NULL;
}

static ValaSymbol*
vala_data_type_real_get_pointer_member (ValaDataType* self,
                                        const gchar* member_name)
{
	ValaSymbol* result;
	g_return_val_if_fail (member_name != NULL, NULL);
	result = NULL;
	return result;
}

ValaSymbol*
vala_data_type_get_pointer_member (ValaDataType* self,
                                   const gchar* member_name)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->get_pointer_member) {
		return _klass_->get_pointer_member (self, member_name);
	}
	return NULL;
}

/**
 * Checks whether this data type references a real struct. A real struct
 * is a struct which is not a simple (fundamental) type.
 */
static gboolean
vala_data_type_real_is_real_struct_type (ValaDataType* self)
{
	ValaStruct* s = NULL;
	ValaTypeSymbol* _tmp0_;
	ValaTypeSymbol* _tmp1_;
	gboolean _tmp2_ = FALSE;
	ValaStruct* _tmp3_;
	gboolean result;
	_tmp0_ = vala_data_type_get_type_symbol (self);
	_tmp1_ = _tmp0_;
	s = VALA_IS_STRUCT (_tmp1_) ? ((ValaStruct*) _tmp1_) : NULL;
	_tmp3_ = s;
	if (_tmp3_ != NULL) {
		ValaStruct* _tmp4_;
		_tmp4_ = s;
		_tmp2_ = !vala_struct_is_simple_type (_tmp4_);
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		result = TRUE;
		return result;
	}
	result = FALSE;
	return result;
}

gboolean
vala_data_type_is_real_struct_type (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->is_real_struct_type) {
		return _klass_->is_real_struct_type (self);
	}
	return FALSE;
}

gboolean
vala_data_type_is_real_non_null_struct_type (ValaDataType* self)
{
	gboolean _tmp0_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (vala_data_type_is_real_struct_type (self)) {
		gboolean _tmp1_;
		_tmp1_ = self->priv->_nullable;
		_tmp0_ = !_tmp1_;
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

gboolean
vala_data_type_is_non_null_simple_type (ValaDataType* self)
{
	ValaStruct* s = NULL;
	ValaTypeSymbol* _tmp0_;
	ValaTypeSymbol* _tmp1_;
	gboolean _tmp2_ = FALSE;
	ValaStruct* _tmp3_;
	ValaTypeSymbol* _tmp6_;
	ValaTypeSymbol* _tmp7_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = vala_data_type_get_type_symbol (self);
	_tmp1_ = _tmp0_;
	s = VALA_IS_STRUCT (_tmp1_) ? ((ValaStruct*) _tmp1_) : NULL;
	_tmp3_ = s;
	if (_tmp3_ != NULL) {
		ValaStruct* _tmp4_;
		_tmp4_ = s;
		_tmp2_ = vala_struct_is_simple_type (_tmp4_);
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		gboolean _tmp5_;
		_tmp5_ = self->priv->_nullable;
		result = !_tmp5_;
		return result;
	}
	_tmp6_ = vala_data_type_get_type_symbol (self);
	_tmp7_ = _tmp6_;
	if (VALA_IS_ENUM (_tmp7_)) {
		gboolean _tmp8_;
		_tmp8_ = self->priv->_nullable;
		result = !_tmp8_;
		return result;
	}
	result = FALSE;
	return result;
}

/**
 * Returns whether the value needs to be disposed, i.e. whether
 * allocated memory or other resources need to be released when
 * the value is no longer needed.
 */
static gboolean
vala_data_type_real_is_disposable (ValaDataType* self)
{
	gboolean _tmp0_;
	gboolean result;
	_tmp0_ = self->priv->_value_owned;
	if (!_tmp0_) {
		result = FALSE;
		return result;
	}
	if (vala_data_type_is_reference_type_or_type_parameter (self)) {
		result = TRUE;
		return result;
	}
	result = FALSE;
	return result;
}

gboolean
vala_data_type_is_disposable (ValaDataType* self)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->is_disposable) {
		return _klass_->is_disposable (self);
	}
	return FALSE;
}

static ValaDataType*
vala_data_type_real_get_actual_type (ValaDataType* self,
                                     ValaDataType* derived_instance_type,
                                     ValaList* method_type_arguments,
                                     ValaCodeNode* node_reference)
{
	ValaDataType* _result_ = NULL;
	ValaDataType* _tmp0_;
	gboolean _tmp1_ = FALSE;
	ValaDataType* _tmp2_;
	ValaList* _tmp3_;
	ValaDataType* result;
	_tmp0_ = vala_data_type_copy (self);
	_result_ = _tmp0_;
	if (derived_instance_type == NULL) {
		_tmp1_ = method_type_arguments == NULL;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		result = _result_;
		return result;
	}
	_tmp2_ = _result_;
	_tmp3_ = _tmp2_->priv->type_argument_list;
	if (_tmp3_ != NULL) {
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp4_ = FALSE;
				_tmp4_ = TRUE;
				while (TRUE) {
					ValaDataType* _tmp6_;
					ValaList* _tmp7_;
					gint _tmp8_;
					gint _tmp9_;
					ValaDataType* _tmp10_;
					ValaList* _tmp11_;
					ValaDataType* _tmp12_;
					ValaList* _tmp13_;
					gpointer _tmp14_;
					ValaDataType* _tmp15_;
					ValaDataType* _tmp16_;
					ValaDataType* _tmp17_;
					if (!_tmp4_) {
						gint _tmp5_;
						_tmp5_ = i;
						i = _tmp5_ + 1;
					}
					_tmp4_ = FALSE;
					_tmp6_ = _result_;
					_tmp7_ = _tmp6_->priv->type_argument_list;
					_tmp8_ = vala_collection_get_size ((ValaCollection*) _tmp7_);
					_tmp9_ = _tmp8_;
					if (!(i < _tmp9_)) {
						break;
					}
					_tmp10_ = _result_;
					_tmp11_ = _tmp10_->priv->type_argument_list;
					_tmp12_ = _result_;
					_tmp13_ = _tmp12_->priv->type_argument_list;
					_tmp14_ = vala_list_get (_tmp13_, i);
					_tmp15_ = (ValaDataType*) _tmp14_;
					_tmp16_ = vala_data_type_get_actual_type (_tmp15_, derived_instance_type, method_type_arguments, node_reference);
					_tmp17_ = _tmp16_;
					vala_list_set (_tmp11_, i, _tmp17_);
					_vala_code_node_unref0 (_tmp17_);
					_vala_code_node_unref0 (_tmp15_);
				}
			}
		}
	}
	result = _result_;
	return result;
}

ValaDataType*
vala_data_type_get_actual_type (ValaDataType* self,
                                ValaDataType* derived_instance_type,
                                ValaList* method_type_arguments,
                                ValaCodeNode* node_reference)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->get_actual_type) {
		return _klass_->get_actual_type (self, derived_instance_type, method_type_arguments, node_reference);
	}
	return NULL;
}

gboolean
vala_data_type_is_generic (ValaDataType* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (VALA_IS_GENERIC_TYPE (self)) {
		result = TRUE;
		return result;
	}
	if (!vala_data_type_has_type_arguments (self)) {
		result = FALSE;
		return result;
	}
	{
		ValaList* _type_arg_list = NULL;
		ValaList* _tmp0_;
		gint _type_arg_size = 0;
		ValaList* _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _type_arg_index = 0;
		_tmp0_ = self->priv->type_argument_list;
		_type_arg_list = _tmp0_;
		_tmp1_ = _type_arg_list;
		_tmp2_ = vala_collection_get_size ((ValaCollection*) _tmp1_);
		_tmp3_ = _tmp2_;
		_type_arg_size = _tmp3_;
		_type_arg_index = -1;
		while (TRUE) {
			gint _tmp4_;
			gint _tmp5_;
			ValaDataType* type_arg = NULL;
			ValaList* _tmp6_;
			gpointer _tmp7_;
			ValaDataType* _tmp8_;
			_type_arg_index = _type_arg_index + 1;
			_tmp4_ = _type_arg_index;
			_tmp5_ = _type_arg_size;
			if (!(_tmp4_ < _tmp5_)) {
				break;
			}
			_tmp6_ = _type_arg_list;
			_tmp7_ = vala_list_get (_tmp6_, _type_arg_index);
			type_arg = (ValaDataType*) _tmp7_;
			_tmp8_ = type_arg;
			if (vala_data_type_is_generic (_tmp8_)) {
				result = TRUE;
				_vala_code_node_unref0 (type_arg);
				return result;
			}
			_vala_code_node_unref0 (type_arg);
		}
	}
	result = FALSE;
	return result;
}

void
vala_data_type_replace_type_parameter (ValaDataType* self,
                                       ValaTypeParameter* old_type_param,
                                       ValaTypeParameter* new_type_param)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (old_type_param != NULL);
	g_return_if_fail (new_type_param != NULL);
	if (VALA_IS_GENERIC_TYPE (self)) {
		ValaSymbol* _tmp0_;
		_tmp0_ = self->priv->_symbol;
		if (_tmp0_ == G_TYPE_CHECK_INSTANCE_CAST (old_type_param, VALA_TYPE_SYMBOL, ValaSymbol)) {
			vala_data_type_set_symbol (self, (ValaSymbol*) new_type_param);
		}
		return;
	}
	if (!vala_data_type_has_type_arguments (self)) {
		return;
	}
	{
		ValaList* _type_arg_list = NULL;
		ValaList* _tmp1_;
		gint _type_arg_size = 0;
		ValaList* _tmp2_;
		gint _tmp3_;
		gint _tmp4_;
		gint _type_arg_index = 0;
		_tmp1_ = self->priv->type_argument_list;
		_type_arg_list = _tmp1_;
		_tmp2_ = _type_arg_list;
		_tmp3_ = vala_collection_get_size ((ValaCollection*) _tmp2_);
		_tmp4_ = _tmp3_;
		_type_arg_size = _tmp4_;
		_type_arg_index = -1;
		while (TRUE) {
			gint _tmp5_;
			gint _tmp6_;
			ValaDataType* type_arg = NULL;
			ValaList* _tmp7_;
			gpointer _tmp8_;
			ValaDataType* _tmp9_;
			_type_arg_index = _type_arg_index + 1;
			_tmp5_ = _type_arg_index;
			_tmp6_ = _type_arg_size;
			if (!(_tmp5_ < _tmp6_)) {
				break;
			}
			_tmp7_ = _type_arg_list;
			_tmp8_ = vala_list_get (_tmp7_, _type_arg_index);
			type_arg = (ValaDataType*) _tmp8_;
			_tmp9_ = type_arg;
			vala_data_type_replace_type_parameter (_tmp9_, old_type_param, new_type_param);
			_vala_code_node_unref0 (type_arg);
		}
	}
}

/**
 * Search for the type parameter in this formal type and match it in
 * value_type.
 */
static ValaDataType*
vala_data_type_real_infer_type_argument (ValaDataType* self,
                                         ValaTypeParameter* type_param,
                                         ValaDataType* value_type)
{
	ValaIterator* value_type_arg_it = NULL;
	ValaList* _tmp0_;
	ValaIterator* _tmp1_;
	ValaDataType* result;
	g_return_val_if_fail (type_param != NULL, NULL);
	g_return_val_if_fail (value_type != NULL, NULL);
	_tmp0_ = vala_data_type_get_type_arguments (value_type);
	_tmp1_ = vala_iterable_iterator ((ValaIterable*) _tmp0_);
	value_type_arg_it = _tmp1_;
	{
		ValaList* _formal_type_arg_list = NULL;
		ValaList* _tmp2_;
		gint _formal_type_arg_size = 0;
		ValaList* _tmp3_;
		gint _tmp4_;
		gint _tmp5_;
		gint _formal_type_arg_index = 0;
		_tmp2_ = vala_data_type_get_type_arguments (self);
		_formal_type_arg_list = _tmp2_;
		_tmp3_ = _formal_type_arg_list;
		_tmp4_ = vala_collection_get_size ((ValaCollection*) _tmp3_);
		_tmp5_ = _tmp4_;
		_formal_type_arg_size = _tmp5_;
		_formal_type_arg_index = -1;
		while (TRUE) {
			gint _tmp6_;
			gint _tmp7_;
			ValaDataType* formal_type_arg = NULL;
			ValaList* _tmp8_;
			gpointer _tmp9_;
			ValaIterator* _tmp10_;
			_formal_type_arg_index = _formal_type_arg_index + 1;
			_tmp6_ = _formal_type_arg_index;
			_tmp7_ = _formal_type_arg_size;
			if (!(_tmp6_ < _tmp7_)) {
				break;
			}
			_tmp8_ = _formal_type_arg_list;
			_tmp9_ = vala_list_get (_tmp8_, _formal_type_arg_index);
			formal_type_arg = (ValaDataType*) _tmp9_;
			_tmp10_ = value_type_arg_it;
			if (vala_iterator_next (_tmp10_)) {
				ValaDataType* inferred_type = NULL;
				ValaDataType* _tmp11_;
				ValaIterator* _tmp12_;
				gpointer _tmp13_;
				ValaDataType* _tmp14_;
				ValaDataType* _tmp15_;
				ValaDataType* _tmp16_;
				ValaDataType* _tmp17_;
				_tmp11_ = formal_type_arg;
				_tmp12_ = value_type_arg_it;
				_tmp13_ = vala_iterator_get (_tmp12_);
				_tmp14_ = (ValaDataType*) _tmp13_;
				_tmp15_ = vala_data_type_infer_type_argument (_tmp11_, type_param, _tmp14_);
				_tmp16_ = _tmp15_;
				_vala_code_node_unref0 (_tmp14_);
				inferred_type = _tmp16_;
				_tmp17_ = inferred_type;
				if (_tmp17_ != NULL) {
					result = inferred_type;
					_vala_code_node_unref0 (formal_type_arg);
					_vala_iterator_unref0 (value_type_arg_it);
					return result;
				}
				_vala_code_node_unref0 (inferred_type);
			}
			_vala_code_node_unref0 (formal_type_arg);
		}
	}
	result = NULL;
	_vala_iterator_unref0 (value_type_arg_it);
	return result;
}

ValaDataType*
vala_data_type_infer_type_argument (ValaDataType* self,
                                    ValaTypeParameter* type_param,
                                    ValaDataType* value_type)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->infer_type_argument) {
		return _klass_->infer_type_argument (self, type_param, value_type);
	}
	return NULL;
}

/**
 * Returns a stringified representation used for detailed error output
 *
 * @param override_name used as name if given
 * @return stringified representation
 */
static gchar*
vala_data_type_real_to_prototype_string (ValaDataType* self,
                                         const gchar* override_name)
{
	const gchar* _tmp0_ = NULL;
	gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* result;
	if (vala_data_type_is_weak (self)) {
		_tmp0_ = "unowned ";
	} else {
		_tmp0_ = "";
	}
	_tmp1_ = vala_data_type_to_qualified_string (self, NULL);
	_tmp2_ = _tmp1_;
	_tmp3_ = g_strdup_printf ("%s%s", _tmp0_, _tmp2_);
	_tmp4_ = _tmp3_;
	_g_free0 (_tmp2_);
	result = _tmp4_;
	return result;
}

gchar*
vala_data_type_to_prototype_string (ValaDataType* self,
                                    const gchar* override_name)
{
	ValaDataTypeClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = VALA_DATA_TYPE_GET_CLASS (self);
	if (_klass_->to_prototype_string) {
		return _klass_->to_prototype_string (self, override_name);
	}
	return NULL;
}

gboolean
vala_data_type_is_weak (ValaDataType* self)
{
	gboolean _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->_value_owned;
	if (_tmp0_) {
		result = FALSE;
		return result;
	} else {
		gboolean _tmp1_ = FALSE;
		if (VALA_IS_VOID_TYPE (self)) {
			_tmp1_ = TRUE;
		} else {
			_tmp1_ = VALA_IS_POINTER_TYPE (self);
		}
		if (_tmp1_) {
			result = FALSE;
			return result;
		} else {
			if (VALA_IS_VALUE_TYPE (self)) {
				gboolean _tmp2_;
				_tmp2_ = self->priv->_nullable;
				if (_tmp2_) {
					result = TRUE;
					return result;
				}
				result = FALSE;
				return result;
			}
		}
	}
	result = TRUE;
	return result;
}

static gboolean
string_contains (const gchar* self,
                 const gchar* needle)
{
	gchar* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (needle != NULL, FALSE);
	_tmp0_ = strstr ((gchar*) self, (gchar*) needle);
	result = _tmp0_ != NULL;
	return result;
}

static gchar*
string_replace (const gchar* self,
                const gchar* old,
                const gchar* replacement)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	GError* _inner_error0_ = NULL;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (old != NULL, NULL);
	g_return_val_if_fail (replacement != NULL, NULL);
	if ((*((gchar*) self)) == '\0') {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = (*((gchar*) old)) == '\0';
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = g_strcmp0 (old, replacement) == 0;
	}
	if (_tmp0_) {
		gchar* _tmp2_;
		_tmp2_ = g_strdup (self);
		result = _tmp2_;
		return result;
	}
	{
		GRegex* regex = NULL;
		gchar* _tmp3_;
		gchar* _tmp4_;
		GRegex* _tmp5_;
		GRegex* _tmp6_;
		gchar* _tmp7_ = NULL;
		GRegex* _tmp8_;
		gchar* _tmp9_;
		gchar* _tmp10_;
		_tmp3_ = g_regex_escape_string (old, -1);
		_tmp4_ = _tmp3_;
		_tmp5_ = g_regex_new (_tmp4_, 0, 0, &_inner_error0_);
		_tmp6_ = _tmp5_;
		_g_free0 (_tmp4_);
		regex = _tmp6_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == G_REGEX_ERROR) {
				goto __catch0_g_regex_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
		_tmp8_ = regex;
		_tmp9_ = g_regex_replace_literal (_tmp8_, self, (gssize) -1, 0, replacement, 0, &_inner_error0_);
		_tmp7_ = _tmp9_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			_g_regex_unref0 (regex);
			if (_inner_error0_->domain == G_REGEX_ERROR) {
				goto __catch0_g_regex_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
		_tmp10_ = _tmp7_;
		_tmp7_ = NULL;
		result = _tmp10_;
		_g_free0 (_tmp7_);
		_g_regex_unref0 (regex);
		return result;
	}
	goto __finally0;
	__catch0_g_regex_error:
	{
		g_clear_error (&_inner_error0_);
		g_assert_not_reached ();
	}
	__finally0:
	g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
	g_clear_error (&_inner_error0_);
	return NULL;
}

gchar*
vala_data_type_get_type_signature (ValaDataType* self,
                                   ValaSymbol* symbol)
{
	ValaArrayType* array_type = NULL;
	ValaArrayType* _tmp2_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (symbol != NULL) {
		gchar* sig = NULL;
		gchar* _tmp0_;
		const gchar* _tmp1_;
		_tmp0_ = vala_code_node_get_attribute_string ((ValaCodeNode*) symbol, "DBus", "signature", NULL);
		sig = _tmp0_;
		_tmp1_ = sig;
		if (_tmp1_ != NULL) {
			result = sig;
			return result;
		}
		_g_free0 (sig);
	}
	array_type = VALA_IS_ARRAY_TYPE (self) ? ((ValaArrayType*) self) : NULL;
	_tmp2_ = array_type;
	if (_tmp2_ != NULL) {
		gchar* element_type_signature = NULL;
		ValaArrayType* _tmp3_;
		ValaDataType* _tmp4_;
		ValaDataType* _tmp5_;
		gchar* _tmp6_;
		const gchar* _tmp7_;
		ValaArrayType* _tmp8_;
		gint _tmp9_;
		gint _tmp10_;
		gchar* _tmp11_;
		gchar* _tmp12_;
		const gchar* _tmp13_;
		gchar* _tmp14_;
		gchar* _tmp15_;
		_tmp3_ = array_type;
		_tmp4_ = vala_array_type_get_element_type (_tmp3_);
		_tmp5_ = _tmp4_;
		_tmp6_ = vala_data_type_get_type_signature (_tmp5_, NULL);
		element_type_signature = _tmp6_;
		_tmp7_ = element_type_signature;
		if (_tmp7_ == NULL) {
			result = NULL;
			_g_free0 (element_type_signature);
			return result;
		}
		_tmp8_ = array_type;
		_tmp9_ = vala_array_type_get_rank (_tmp8_);
		_tmp10_ = _tmp9_;
		_tmp11_ = g_strnfill ((gsize) _tmp10_, 'a');
		_tmp12_ = _tmp11_;
		_tmp13_ = element_type_signature;
		_tmp14_ = g_strconcat (_tmp12_, _tmp13_, NULL);
		_tmp15_ = _tmp14_;
		_g_free0 (_tmp12_);
		result = _tmp15_;
		_g_free0 (element_type_signature);
		return result;
	} else {
		gboolean _tmp16_ = FALSE;
		ValaTypeSymbol* _tmp17_;
		ValaTypeSymbol* _tmp18_;
		_tmp17_ = vala_data_type_get_type_symbol (self);
		_tmp18_ = _tmp17_;
		if (VALA_IS_ENUM (_tmp18_)) {
			ValaTypeSymbol* _tmp19_;
			ValaTypeSymbol* _tmp20_;
			_tmp19_ = vala_data_type_get_type_symbol (self);
			_tmp20_ = _tmp19_;
			_tmp16_ = vala_code_node_get_attribute_bool ((ValaCodeNode*) _tmp20_, "DBus", "use_string_marshalling", FALSE);
		} else {
			_tmp16_ = FALSE;
		}
		if (_tmp16_) {
			gchar* _tmp21_;
			_tmp21_ = g_strdup ("s");
			result = _tmp21_;
			return result;
		} else {
			ValaTypeSymbol* _tmp22_;
			ValaTypeSymbol* _tmp23_;
			_tmp22_ = vala_data_type_get_type_symbol (self);
			_tmp23_ = _tmp22_;
			if (_tmp23_ != NULL) {
				gchar* sig = NULL;
				ValaTypeSymbol* _tmp24_;
				ValaTypeSymbol* _tmp25_;
				gchar* _tmp26_;
				ValaStruct* st = NULL;
				ValaTypeSymbol* _tmp27_;
				ValaTypeSymbol* _tmp28_;
				ValaEnum* en = NULL;
				ValaTypeSymbol* _tmp29_;
				ValaTypeSymbol* _tmp30_;
				gboolean _tmp31_ = FALSE;
				const gchar* _tmp32_;
				ValaList* type_args = NULL;
				ValaList* _tmp68_;
				ValaList* _tmp69_;
				gboolean _tmp70_ = FALSE;
				gboolean _tmp71_ = FALSE;
				const gchar* _tmp72_;
				gboolean _tmp95_ = FALSE;
				const gchar* _tmp96_;
				_tmp24_ = vala_data_type_get_type_symbol (self);
				_tmp25_ = _tmp24_;
				_tmp26_ = vala_code_node_get_attribute_string ((ValaCodeNode*) _tmp25_, "CCode", "type_signature", NULL);
				sig = _tmp26_;
				_tmp27_ = vala_data_type_get_type_symbol (self);
				_tmp28_ = _tmp27_;
				st = VALA_IS_STRUCT (_tmp28_) ? ((ValaStruct*) _tmp28_) : NULL;
				_tmp29_ = vala_data_type_get_type_symbol (self);
				_tmp30_ = _tmp29_;
				en = VALA_IS_ENUM (_tmp30_) ? ((ValaEnum*) _tmp30_) : NULL;
				_tmp32_ = sig;
				if (_tmp32_ == NULL) {
					ValaStruct* _tmp33_;
					_tmp33_ = st;
					_tmp31_ = _tmp33_ != NULL;
				} else {
					_tmp31_ = FALSE;
				}
				if (_tmp31_) {
					GString* str = NULL;
					GString* _tmp34_;
					GString* _tmp35_;
					GString* _tmp56_;
					GString* _tmp57_;
					const gchar* _tmp58_;
					gchar* _tmp59_;
					_tmp34_ = g_string_new ("");
					str = _tmp34_;
					_tmp35_ = str;
					g_string_append_c (_tmp35_, '(');
					{
						ValaList* _f_list = NULL;
						ValaStruct* _tmp36_;
						ValaList* _tmp37_;
						gint _f_size = 0;
						ValaList* _tmp38_;
						gint _tmp39_;
						gint _tmp40_;
						gint _f_index = 0;
						_tmp36_ = st;
						_tmp37_ = vala_struct_get_fields (_tmp36_);
						_f_list = _tmp37_;
						_tmp38_ = _f_list;
						_tmp39_ = vala_collection_get_size ((ValaCollection*) _tmp38_);
						_tmp40_ = _tmp39_;
						_f_size = _tmp40_;
						_f_index = -1;
						while (TRUE) {
							gint _tmp41_;
							gint _tmp42_;
							ValaField* f = NULL;
							ValaList* _tmp43_;
							gpointer _tmp44_;
							ValaField* _tmp45_;
							ValaMemberBinding _tmp46_;
							ValaMemberBinding _tmp47_;
							_f_index = _f_index + 1;
							_tmp41_ = _f_index;
							_tmp42_ = _f_size;
							if (!(_tmp41_ < _tmp42_)) {
								break;
							}
							_tmp43_ = _f_list;
							_tmp44_ = vala_list_get (_tmp43_, _f_index);
							f = (ValaField*) _tmp44_;
							_tmp45_ = f;
							_tmp46_ = vala_field_get_binding (_tmp45_);
							_tmp47_ = _tmp46_;
							if (_tmp47_ == VALA_MEMBER_BINDING_INSTANCE) {
								gchar* s = NULL;
								ValaField* _tmp48_;
								ValaDataType* _tmp49_;
								ValaDataType* _tmp50_;
								ValaField* _tmp51_;
								gchar* _tmp52_;
								const gchar* _tmp53_;
								_tmp48_ = f;
								_tmp49_ = vala_variable_get_variable_type ((ValaVariable*) _tmp48_);
								_tmp50_ = _tmp49_;
								_tmp51_ = f;
								_tmp52_ = vala_data_type_get_type_signature (_tmp50_, (ValaSymbol*) _tmp51_);
								s = _tmp52_;
								_tmp53_ = s;
								if (_tmp53_ != NULL) {
									GString* _tmp54_;
									const gchar* _tmp55_;
									_tmp54_ = str;
									_tmp55_ = s;
									g_string_append (_tmp54_, _tmp55_);
								} else {
									result = NULL;
									_g_free0 (s);
									_vala_code_node_unref0 (f);
									_g_string_free0 (str);
									_g_free0 (sig);
									return result;
								}
								_g_free0 (s);
							}
							_vala_code_node_unref0 (f);
						}
					}
					_tmp56_ = str;
					g_string_append_c (_tmp56_, ')');
					_tmp57_ = str;
					_tmp58_ = _tmp57_->str;
					_tmp59_ = g_strdup (_tmp58_);
					_g_free0 (sig);
					sig = _tmp59_;
					_g_string_free0 (str);
				} else {
					gboolean _tmp60_ = FALSE;
					const gchar* _tmp61_;
					_tmp61_ = sig;
					if (_tmp61_ == NULL) {
						ValaEnum* _tmp62_;
						_tmp62_ = en;
						_tmp60_ = _tmp62_ != NULL;
					} else {
						_tmp60_ = FALSE;
					}
					if (_tmp60_) {
						ValaEnum* _tmp63_;
						gboolean _tmp64_;
						gboolean _tmp65_;
						_tmp63_ = en;
						_tmp64_ = vala_enum_get_is_flags (_tmp63_);
						_tmp65_ = _tmp64_;
						if (_tmp65_) {
							gchar* _tmp66_;
							_tmp66_ = g_strdup ("u");
							result = _tmp66_;
							_g_free0 (sig);
							return result;
						} else {
							gchar* _tmp67_;
							_tmp67_ = g_strdup ("i");
							result = _tmp67_;
							_g_free0 (sig);
							return result;
						}
					}
				}
				_tmp68_ = vala_data_type_get_type_arguments (self);
				_tmp69_ = _vala_iterable_ref0 (_tmp68_);
				type_args = _tmp69_;
				_tmp72_ = sig;
				if (_tmp72_ != NULL) {
					const gchar* _tmp73_;
					_tmp73_ = sig;
					_tmp71_ = string_contains (_tmp73_, "%s");
				} else {
					_tmp71_ = FALSE;
				}
				if (_tmp71_) {
					ValaList* _tmp74_;
					gint _tmp75_;
					gint _tmp76_;
					_tmp74_ = type_args;
					_tmp75_ = vala_collection_get_size ((ValaCollection*) _tmp74_);
					_tmp76_ = _tmp75_;
					_tmp70_ = _tmp76_ > 0;
				} else {
					_tmp70_ = FALSE;
				}
				if (_tmp70_) {
					gchar* element_sig = NULL;
					gchar* _tmp77_;
					const gchar* _tmp92_;
					const gchar* _tmp93_;
					gchar* _tmp94_;
					_tmp77_ = g_strdup ("");
					element_sig = _tmp77_;
					{
						ValaList* _type_arg_list = NULL;
						ValaList* _tmp78_;
						gint _type_arg_size = 0;
						ValaList* _tmp79_;
						gint _tmp80_;
						gint _tmp81_;
						gint _type_arg_index = 0;
						_tmp78_ = type_args;
						_type_arg_list = _tmp78_;
						_tmp79_ = _type_arg_list;
						_tmp80_ = vala_collection_get_size ((ValaCollection*) _tmp79_);
						_tmp81_ = _tmp80_;
						_type_arg_size = _tmp81_;
						_type_arg_index = -1;
						while (TRUE) {
							gint _tmp82_;
							gint _tmp83_;
							ValaDataType* type_arg = NULL;
							ValaList* _tmp84_;
							gpointer _tmp85_;
							gchar* s = NULL;
							ValaDataType* _tmp86_;
							gchar* _tmp87_;
							const gchar* _tmp88_;
							_type_arg_index = _type_arg_index + 1;
							_tmp82_ = _type_arg_index;
							_tmp83_ = _type_arg_size;
							if (!(_tmp82_ < _tmp83_)) {
								break;
							}
							_tmp84_ = _type_arg_list;
							_tmp85_ = vala_list_get (_tmp84_, _type_arg_index);
							type_arg = (ValaDataType*) _tmp85_;
							_tmp86_ = type_arg;
							_tmp87_ = vala_data_type_get_type_signature (_tmp86_, NULL);
							s = _tmp87_;
							_tmp88_ = s;
							if (_tmp88_ != NULL) {
								const gchar* _tmp89_;
								const gchar* _tmp90_;
								gchar* _tmp91_;
								_tmp89_ = element_sig;
								_tmp90_ = s;
								_tmp91_ = g_strconcat (_tmp89_, _tmp90_, NULL);
								_g_free0 (element_sig);
								element_sig = _tmp91_;
							}
							_g_free0 (s);
							_vala_code_node_unref0 (type_arg);
						}
					}
					_tmp92_ = sig;
					_tmp93_ = element_sig;
					_tmp94_ = string_replace (_tmp92_, "%s", _tmp93_);
					_g_free0 (sig);
					sig = _tmp94_;
					_g_free0 (element_sig);
				}
				_tmp96_ = sig;
				if (_tmp96_ == NULL) {
					gboolean _tmp97_ = FALSE;
					gboolean _tmp98_ = FALSE;
					ValaTypeSymbol* _tmp99_;
					ValaTypeSymbol* _tmp100_;
					gchar* _tmp101_;
					gchar* _tmp102_;
					gboolean _tmp103_;
					_tmp99_ = vala_data_type_get_type_symbol (self);
					_tmp100_ = _tmp99_;
					_tmp101_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp100_);
					_tmp102_ = _tmp101_;
					_tmp103_ = g_strcmp0 (_tmp102_, "GLib.UnixInputStream") == 0;
					_g_free0 (_tmp102_);
					if (_tmp103_) {
						_tmp98_ = TRUE;
					} else {
						ValaTypeSymbol* _tmp104_;
						ValaTypeSymbol* _tmp105_;
						gchar* _tmp106_;
						gchar* _tmp107_;
						_tmp104_ = vala_data_type_get_type_symbol (self);
						_tmp105_ = _tmp104_;
						_tmp106_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp105_);
						_tmp107_ = _tmp106_;
						_tmp98_ = g_strcmp0 (_tmp107_, "GLib.UnixOutputStream") == 0;
						_g_free0 (_tmp107_);
					}
					if (_tmp98_) {
						_tmp97_ = TRUE;
					} else {
						ValaTypeSymbol* _tmp108_;
						ValaTypeSymbol* _tmp109_;
						gchar* _tmp110_;
						gchar* _tmp111_;
						_tmp108_ = vala_data_type_get_type_symbol (self);
						_tmp109_ = _tmp108_;
						_tmp110_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp109_);
						_tmp111_ = _tmp110_;
						_tmp97_ = g_strcmp0 (_tmp111_, "GLib.Socket") == 0;
						_g_free0 (_tmp111_);
					}
					_tmp95_ = _tmp97_;
				} else {
					_tmp95_ = FALSE;
				}
				if (_tmp95_) {
					gchar* _tmp112_;
					_tmp112_ = g_strdup ("h");
					result = _tmp112_;
					_vala_iterable_unref0 (type_args);
					_g_free0 (sig);
					return result;
				}
				result = sig;
				_vala_iterable_unref0 (type_args);
				return result;
			} else {
				result = NULL;
				return result;
			}
		}
	}
}

/**
 * Returns whether the given amount of type-argument matches the symbol's count of type-parameters
 *
 * @param context a CodeContext
 * @param allow_none whether no type-argments are allowed
 * @return true if successful
 */
gboolean
vala_data_type_check_type_arguments (ValaDataType* self,
                                     ValaCodeContext* context,
                                     gboolean allow_none)
{
	gint n_type_args = 0;
	ValaList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gint expected_n_type_args = 0;
	ValaTypeSymbol* _tmp3_;
	ValaTypeSymbol* _tmp4_;
	gboolean _tmp30_ = FALSE;
	gboolean _tmp31_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (context != NULL, FALSE);
	_tmp0_ = vala_data_type_get_type_arguments (self);
	_tmp1_ = vala_collection_get_size ((ValaCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	n_type_args = _tmp2_;
	expected_n_type_args = 0;
	_tmp3_ = vala_data_type_get_type_symbol (self);
	_tmp4_ = _tmp3_;
	if (VALA_IS_OBJECT_TYPE_SYMBOL (_tmp4_)) {
		ValaTypeSymbol* _tmp5_;
		ValaTypeSymbol* _tmp6_;
		ValaList* _tmp7_;
		gint _tmp8_;
		gint _tmp9_;
		_tmp5_ = vala_data_type_get_type_symbol (self);
		_tmp6_ = _tmp5_;
		_tmp7_ = vala_object_type_symbol_get_type_parameters (G_TYPE_CHECK_INSTANCE_CAST (_tmp6_, VALA_TYPE_OBJECT_TYPE_SYMBOL, ValaObjectTypeSymbol));
		_tmp8_ = vala_collection_get_size ((ValaCollection*) _tmp7_);
		_tmp9_ = _tmp8_;
		expected_n_type_args = _tmp9_;
	} else {
		ValaTypeSymbol* _tmp10_;
		ValaTypeSymbol* _tmp11_;
		_tmp10_ = vala_data_type_get_type_symbol (self);
		_tmp11_ = _tmp10_;
		if (VALA_IS_STRUCT (_tmp11_)) {
			ValaTypeSymbol* _tmp12_;
			ValaTypeSymbol* _tmp13_;
			ValaList* _tmp14_;
			gint _tmp15_;
			gint _tmp16_;
			_tmp12_ = vala_data_type_get_type_symbol (self);
			_tmp13_ = _tmp12_;
			_tmp14_ = vala_struct_get_type_parameters (G_TYPE_CHECK_INSTANCE_CAST (_tmp13_, VALA_TYPE_STRUCT, ValaStruct));
			_tmp15_ = vala_collection_get_size ((ValaCollection*) _tmp14_);
			_tmp16_ = _tmp15_;
			expected_n_type_args = _tmp16_;
		} else {
			ValaTypeSymbol* _tmp17_;
			ValaTypeSymbol* _tmp18_;
			_tmp17_ = vala_data_type_get_type_symbol (self);
			_tmp18_ = _tmp17_;
			if (VALA_IS_DELEGATE (_tmp18_)) {
				ValaTypeSymbol* _tmp19_;
				ValaTypeSymbol* _tmp20_;
				ValaList* _tmp21_;
				gint _tmp22_;
				gint _tmp23_;
				_tmp19_ = vala_data_type_get_type_symbol (self);
				_tmp20_ = _tmp19_;
				_tmp21_ = vala_delegate_get_type_parameters (G_TYPE_CHECK_INSTANCE_CAST (_tmp20_, VALA_TYPE_DELEGATE, ValaDelegate));
				_tmp22_ = vala_collection_get_size ((ValaCollection*) _tmp21_);
				_tmp23_ = _tmp22_;
				expected_n_type_args = _tmp23_;
			} else {
				if (n_type_args > 0) {
					ValaSourceReference* _tmp24_;
					ValaSourceReference* _tmp25_;
					ValaTypeSymbol* _tmp26_;
					ValaTypeSymbol* _tmp27_;
					gchar* _tmp28_;
					gchar* _tmp29_;
					_tmp24_ = vala_code_node_get_source_reference ((ValaCodeNode*) self);
					_tmp25_ = _tmp24_;
					_tmp26_ = vala_data_type_get_type_symbol (self);
					_tmp27_ = _tmp26_;
					_tmp28_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp27_);
					_tmp29_ = _tmp28_;
					vala_report_error (_tmp25_, "`%s' does not support type arguments", _tmp29_);
					_g_free0 (_tmp29_);
					vala_code_node_set_error ((ValaCodeNode*) self, TRUE);
					result = FALSE;
					return result;
				} else {
					result = TRUE;
					return result;
				}
			}
		}
	}
	if (!allow_none) {
		_tmp31_ = TRUE;
	} else {
		_tmp31_ = n_type_args > 0;
	}
	if (_tmp31_) {
		_tmp30_ = n_type_args < expected_n_type_args;
	} else {
		_tmp30_ = FALSE;
	}
	if (_tmp30_) {
		ValaSourceReference* _tmp32_;
		ValaSourceReference* _tmp33_;
		ValaTypeSymbol* _tmp34_;
		ValaTypeSymbol* _tmp35_;
		gchar* _tmp36_;
		gchar* _tmp37_;
		vala_code_node_set_error ((ValaCodeNode*) self, TRUE);
		_tmp32_ = vala_code_node_get_source_reference ((ValaCodeNode*) self);
		_tmp33_ = _tmp32_;
		_tmp34_ = vala_data_type_get_type_symbol (self);
		_tmp35_ = _tmp34_;
		_tmp36_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp35_);
		_tmp37_ = _tmp36_;
		vala_report_error (_tmp33_, "too few type arguments for `%s'", _tmp37_);
		_g_free0 (_tmp37_);
		result = FALSE;
		return result;
	} else {
		gboolean _tmp38_ = FALSE;
		gboolean _tmp39_ = FALSE;
		if (!allow_none) {
			_tmp39_ = TRUE;
		} else {
			_tmp39_ = n_type_args > 0;
		}
		if (_tmp39_) {
			_tmp38_ = n_type_args > expected_n_type_args;
		} else {
			_tmp38_ = FALSE;
		}
		if (_tmp38_) {
			ValaSourceReference* _tmp40_;
			ValaSourceReference* _tmp41_;
			ValaTypeSymbol* _tmp42_;
			ValaTypeSymbol* _tmp43_;
			gchar* _tmp44_;
			gchar* _tmp45_;
			vala_code_node_set_error ((ValaCodeNode*) self, TRUE);
			_tmp40_ = vala_code_node_get_source_reference ((ValaCodeNode*) self);
			_tmp41_ = _tmp40_;
			_tmp42_ = vala_data_type_get_type_symbol (self);
			_tmp43_ = _tmp42_;
			_tmp44_ = vala_symbol_get_full_name ((ValaSymbol*) _tmp43_);
			_tmp45_ = _tmp44_;
			vala_report_error (_tmp41_, "too many type arguments for `%s'", _tmp45_);
			_g_free0 (_tmp45_);
			result = FALSE;
			return result;
		}
	}
	{
		ValaList* _type_list = NULL;
		ValaList* _tmp46_;
		gint _type_size = 0;
		ValaList* _tmp47_;
		gint _tmp48_;
		gint _tmp49_;
		gint _type_index = 0;
		_tmp46_ = vala_data_type_get_type_arguments (self);
		_type_list = _tmp46_;
		_tmp47_ = _type_list;
		_tmp48_ = vala_collection_get_size ((ValaCollection*) _tmp47_);
		_tmp49_ = _tmp48_;
		_type_size = _tmp49_;
		_type_index = -1;
		while (TRUE) {
			gint _tmp50_;
			gint _tmp51_;
			ValaDataType* type = NULL;
			ValaList* _tmp52_;
			gpointer _tmp53_;
			ValaDataType* _tmp54_;
			_type_index = _type_index + 1;
			_tmp50_ = _type_index;
			_tmp51_ = _type_size;
			if (!(_tmp50_ < _tmp51_)) {
				break;
			}
			_tmp52_ = _type_list;
			_tmp53_ = vala_list_get (_tmp52_, _type_index);
			type = (ValaDataType*) _tmp53_;
			_tmp54_ = type;
			if (!vala_code_node_check ((ValaCodeNode*) _tmp54_, context)) {
				result = FALSE;
				_vala_code_node_unref0 (type);
				return result;
			}
			_vala_code_node_unref0 (type);
		}
	}
	result = TRUE;
	return result;
}

ValaDataType*
vala_data_type_construct (GType object_type)
{
	ValaDataType* self = NULL;
	self = (ValaDataType*) vala_code_node_construct (object_type);
	return self;
}

static void
vala_data_type_class_init (ValaDataTypeClass * klass,
                           gpointer klass_data)
{
	vala_data_type_parent_class = g_type_class_peek_parent (klass);
	((ValaCodeNodeClass *) klass)->finalize = vala_data_type_finalize;
	g_type_class_adjust_private_offset (klass, &ValaDataType_private_offset);
	((ValaCodeNodeClass *) klass)->accept = (void (*) (ValaCodeNode*, ValaCodeVisitor*)) vala_data_type_real_accept;
	((ValaCodeNodeClass *) klass)->accept_children = (void (*) (ValaCodeNode*, ValaCodeVisitor*)) vala_data_type_real_accept_children;
	((ValaCodeNodeClass *) klass)->to_string = (gchar* (*) (ValaCodeNode*)) vala_data_type_real_to_string;
	((ValaDataTypeClass *) klass)->to_qualified_string = (gchar* (*) (ValaDataType*, ValaScope*)) vala_data_type_real_to_qualified_string;
	((ValaDataTypeClass *) klass)->copy = (ValaDataType* (*) (ValaDataType*)) vala_data_type_real_copy;
	((ValaDataTypeClass *) klass)->equals = (gboolean (*) (ValaDataType*, ValaDataType*)) vala_data_type_real_equals;
	((ValaDataTypeClass *) klass)->stricter = (gboolean (*) (ValaDataType*, ValaDataType*)) vala_data_type_real_stricter;
	((ValaCodeNodeClass *) klass)->replace_type = (void (*) (ValaCodeNode*, ValaDataType*, ValaDataType*)) vala_data_type_real_replace_type;
	((ValaDataTypeClass *) klass)->compatible = (gboolean (*) (ValaDataType*, ValaDataType*)) vala_data_type_real_compatible;
	((ValaDataTypeClass *) klass)->is_invokable = (gboolean (*) (ValaDataType*)) vala_data_type_real_is_invokable;
	((ValaDataTypeClass *) klass)->get_return_type = (ValaDataType* (*) (ValaDataType*)) vala_data_type_real_get_return_type;
	((ValaDataTypeClass *) klass)->get_parameters = (ValaList* (*) (ValaDataType*)) vala_data_type_real_get_parameters;
	((ValaDataTypeClass *) klass)->is_reference_type_or_type_parameter = (gboolean (*) (ValaDataType*)) vala_data_type_real_is_reference_type_or_type_parameter;
	((ValaDataTypeClass *) klass)->is_accessible = (gboolean (*) (ValaDataType*, ValaSymbol*)) vala_data_type_real_is_accessible;
	((ValaDataTypeClass *) klass)->get_member = (ValaSymbol* (*) (ValaDataType*, const gchar*)) vala_data_type_real_get_member;
	((ValaDataTypeClass *) klass)->get_pointer_member = (ValaSymbol* (*) (ValaDataType*, const gchar*)) vala_data_type_real_get_pointer_member;
	((ValaDataTypeClass *) klass)->is_real_struct_type = (gboolean (*) (ValaDataType*)) vala_data_type_real_is_real_struct_type;
	((ValaDataTypeClass *) klass)->is_disposable = (gboolean (*) (ValaDataType*)) vala_data_type_real_is_disposable;
	((ValaDataTypeClass *) klass)->get_actual_type = (ValaDataType* (*) (ValaDataType*, ValaDataType*, ValaList*, ValaCodeNode*)) vala_data_type_real_get_actual_type;
	((ValaDataTypeClass *) klass)->infer_type_argument = (ValaDataType* (*) (ValaDataType*, ValaTypeParameter*, ValaDataType*)) vala_data_type_real_infer_type_argument;
	((ValaDataTypeClass *) klass)->to_prototype_string = (gchar* (*) (ValaDataType*, const gchar*)) vala_data_type_real_to_prototype_string;
}

static void
vala_data_type_instance_init (ValaDataType * self,
                              gpointer klass)
{
	self->priv = vala_data_type_get_instance_private (self);
}

static void
vala_data_type_finalize (ValaCodeNode * obj)
{
	ValaDataType * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, VALA_TYPE_DATA_TYPE, ValaDataType);
	_vala_iterable_unref0 (self->priv->type_argument_list);
	VALA_CODE_NODE_CLASS (vala_data_type_parent_class)->finalize (obj);
}

/**
 * A reference to a data type. This is used to specify static types of
 * expressions.
 */
static GType
vala_data_type_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (ValaDataTypeClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) vala_data_type_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ValaDataType), 0, (GInstanceInitFunc) vala_data_type_instance_init, NULL };
	GType vala_data_type_type_id;
	vala_data_type_type_id = g_type_register_static (VALA_TYPE_CODE_NODE, "ValaDataType", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
	ValaDataType_private_offset = g_type_add_instance_private (vala_data_type_type_id, sizeof (ValaDataTypePrivate));
	return vala_data_type_type_id;
}

GType
vala_data_type_get_type (void)
{
	static volatile gsize vala_data_type_type_id__once = 0;
	if (g_once_init_enter (&vala_data_type_type_id__once)) {
		GType vala_data_type_type_id;
		vala_data_type_type_id = vala_data_type_get_type_once ();
		g_once_init_leave (&vala_data_type_type_id__once, vala_data_type_type_id);
	}
	return vala_data_type_type_id__once;
}

