diff options
author | John Hodge <tpg@mutabah.net> | 2015-08-31 14:06:26 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-08-31 14:06:26 +0800 |
commit | 68607811e4e8d6feba95f55c3e49da9923fc35fd (patch) | |
tree | 665891a1fac39c1d9a87617ad1af1ca27b139a60 /src/convert | |
parent | 261f2aea278e1185f69b06e65501c1ca718df47c (diff) | |
download | mrust-68607811e4e8d6feba95f55c3e49da9923fc35fd.tar.gz |
Convert path bindings to TAGGED_UNION, improve resolve logic (leading to error)
Diffstat (limited to 'src/convert')
-rw-r--r-- | src/convert/ast_iterate.cpp | 25 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 182 | ||||
-rw-r--r-- | src/convert/typecheck_bounds.cpp | 4 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 65 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 78 |
5 files changed, 232 insertions, 122 deletions
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 72cfd009..10eaf80b 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -178,25 +178,26 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) const auto& hint_binding = hint_path.binding(); const auto& pat_binding = pat_path.binding(); DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path()); - switch( hint_binding.type() ) - { - case AST::PathBinding::UNBOUND: + TU_MATCH_DEF( AST::PathBinding, (hint_binding), (info), + ( + throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path())) + ), + (Unbound, throw ::std::runtime_error("Unbound path in pattern"); - case AST::PathBinding::ENUM: { + ), + (Enum, // The pattern's path must refer to a variant of the hint path // - Actual type params are checked by the 'handle_pattern_enum' code - if( pat_binding.type() != AST::PathBinding::ENUM_VAR ) + if( !pat_binding.is_EnumVar() ) throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - if( pat_binding.bound_enumvar().enum_ != &hint_binding.bound_enum() ) + if( pat_binding.as_EnumVar().enum_ != info.enum_ ) throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - const auto& enm = *pat_binding.bound_enumvar().enum_; - auto idx = pat_binding.bound_enumvar().idx; + const auto& enm = *pat_binding.as_EnumVar().enum_; + auto idx = pat_binding.as_EnumVar().idx; auto& var = enm.variants().at(idx); handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns); - break; } - default: - throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path())); - } + ) + ) } break; } } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 901a3acb..821d4810 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -89,9 +89,11 @@ public: ::rust::option<const LocalItem&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
- bool find_local_item(AST::Path& path, bool allow_variables);
- bool find_mod_item(AST::Path& path);
- bool find_super_mod_item(AST::Path& path);
+ bool find_local_item(AST::Path& path, const ::std::string& name, bool allow_variables);
+ //bool find_local_item(AST::Path& path, bool allow_variables);
+ bool find_mod_item(AST::Path& path, const ::std::string& name);
+ bool find_self_mod_item(AST::Path& path, const ::std::string& name);
+ bool find_super_mod_item(AST::Path& path, const ::std::string& name);
bool find_type_param(const ::std::string& name);
// TODO: Handle a block and obtain the local module (if any)
@@ -319,11 +321,11 @@ void CPathResolver::end_scope() // > Search local use definitions (function-level)
// - TODO: Local use statements (scoped)
// > Search module-level definitions
-bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path)
+bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path, const ::std::string& name, bool is_leaf)
{
TRACE_FUNCTION_F("mod_path="<<mod_path);
// - Allow leaf nodes if path is a single node, don't skip private wildcard imports
- auto item = module.find_item(path[0].name(), (path.size() == 1), false);
+ auto item = module.find_item(name, is_leaf, false);
switch(item.type())
{
case AST::Module::ItemRef::ITEM_none:
@@ -358,6 +360,9 @@ bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, c return true;
}
}
+bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path) {
+ return lookup_path_in_module(crate, module, mod_path, path, path[0].name(), path.size() == 1);
+}
/// Perform path resolution within a generic definition block
void CPathResolver::handle_params(AST::TypeParams& params)
@@ -445,7 +450,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode INDENT();
// Already absolute, our job is done
// - However, if the path isn't bound, bind it
- if( !path.binding().is_bound() ) {
+ if( path.binding().is_Unbound() ) {
path.resolve(m_crate);
}
else {
@@ -460,11 +465,38 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // > Variable: (wait, how is this known already?)
// - 'self'
case AST::Path::Class::Local:
- //if(
- // 1. Check for local items
- // 2. Type parameters (ONLY when in expression mode)
- // 3. Module items
- //throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int");
+ if( !path.binding().is_Unbound() )
+ {
+ DEBUG("- Path " << path << " already bound");
+ }
+ else
+ {
+ const auto& info = path.m_class.as_Local();
+ // 1. Check for local items
+ if( this->find_local_item(path, info.name, (mode == CASTIterator::MODE_EXPR)) ) {
+ path.resolve(m_crate);
+ break ;
+ }
+ else {
+ // No match, fall through
+ }
+ // 2. Type parameters (ONLY when in type mode)
+ if( mode == CASTIterator::MODE_TYPE ) {
+ throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int type param");
+ }
+ // 3. Module items
+ if( this->find_mod_item(path, info.name) ) {
+ path.resolve(m_crate);
+ break;
+ }
+ else {
+ }
+
+ DEBUG("no matches found for path = " << path);
+ if( mode != MODE_BIND )
+ throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (Local)");
+ return ;
+ }
break;
case AST::Path::Class::Relative:
@@ -472,8 +504,8 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // > Return values: name or path
{
bool allow_variables = (mode == CASTIterator::MODE_EXPR && path.is_trivial());
- if( this->find_local_item(path, allow_variables) ) {
- //path.resolve(m_crate);
+ if( this->find_local_item(path, path[0].name(), allow_variables) ) {
+ path.resolve(m_crate);
break ;
}
else {
@@ -495,13 +527,14 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode auto newpath = AST::Path(AST::Path::TagUfcs(), TypeRef(TypeRef::TagArg(), path[0].name()), TypeRef());
newpath.add_tailing(path);
path = mv$(newpath);
+ handle_path_ufcs(path, mode);
}
else {
// Mark as local
- // - TODO: Also need to annotate
// - TODO: Not being trivial is an error, not a bug
assert( path.is_trivial() );
path = AST::Path(AST::Path::TagLocal(), path[0].name());
+ // - TODO: Need to bind this to the source parameter block
}
break;
}
@@ -509,7 +542,8 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // 3. current module
{
- if( this->find_mod_item(path) ) {
+ if( this->find_mod_item(path, path[0].name()) ) {
+ path.resolve(m_crate);
break;
}
else {
@@ -524,7 +558,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // Module relative
case AST::Path::Class::Self:{
- if( this->find_mod_item(path) ) {
+ if( this->find_self_mod_item(path, path[0].name()) ) {
break;
}
else {
@@ -535,7 +569,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode break; }
// Parent module relative
case AST::Path::Class::Super:{
- if( this->find_super_mod_item(path) ) {
+ if( this->find_super_mod_item(path, path[0].name()) ) {
break;
}
else {
@@ -547,25 +581,76 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode }
// TODO: Are there any reasons not to be bound at this point?
- //assert( path.binding().is_bound() );
+ //assert( !path.binding().is_Unbound() );
}
void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mode)
{
+ assert(path.m_class.is_UFCS());
auto& info = path.m_class.as_UFCS();
+ TRACE_FUNCTION_F("info={< " << *info.type << " as " << *info.trait << ">::" << info.nodes << "}");
+ const ::std::string& item_name = info.nodes[0].name();
// 1. Handle sub-types
handle_type(*info.type);
handle_type(*info.trait);
// 2. Handle wildcard traits (locate in inherent impl, or from an in-scope trait)
if( info.trait->is_wildcard() )
{
- DEBUG("Searching for impls when trait is _");
+ DEBUG("Searching for impls when trait is _ (trait = " << *info.trait << ")");
// Search applicable type parameters for known implementations
// 1. Inherent
AST::Impl* impl_ptr;
::std::vector<TypeRef> params;
- if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, ¶ms) )
+ if( info.type->is_type_param() && info.type->type_param() == "Self" )
+ {
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - Handle '<Self as _>::...'");
+ }
+ else if( info.type->is_type_param() )
+ {
+ DEBUG("Checking applicable generic bounds");
+ const auto& tp = *info.type->type_params_ptr();
+ assert(&tp != nullptr);
+ bool success = false;
+
+ // Enumerate bounds
+ for( const auto& bound : tp.bounds() )
+ {
+ DEBUG("bound = " << bound);
+ if( bound.is_trait() && bound.test() == *info.type )
+ {
+ const auto& t = *bound.bound().binding().as_Trait().trait_;
+ {
+ const auto& fcns = t.functions();
+ auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Item<AST::Function>& a) { return a.name == item_name; } );
+ if( it != fcns.end() ) {
+ // Found it.
+ if( info.nodes.size() != 1 )
+ throw ParseError::Generic("CPathResolver::handle_path_ufcs - Multiple arguments");
+ *info.trait = bound.bound();
+ success = true;
+ break;
+ }
+ }
+ {
+ const auto& types = t.types();
+ auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Item<AST::TypeAlias>& a) { return a.name == item_name; } );
+ if( it != types.end() ) {
+ // Found it.
+ *info.trait = bound.bound();
+ success = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if( !success )
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait for generic");
+ // - re-handle, to ensure that the bound is resolved
+ handle_type(*info.trait);
+ }
+ else if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, ¶ms) )
{
DEBUG("Found matching inherent impl");
// - Mark as being from the inherent, and move along
@@ -573,16 +658,18 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod *info.trait = TypeRef(TypeRef::TagInvalid());
}
else
- {
- // Iterate all traits in scope, and find one that is impled for this type
- throw ParseError::Todo("CPathResolver::handle_path - UFCS, find trait");
+ {
+ // Iterate all traits in scope, and find one that is implemented for this type
+ // - TODO: Iterate traits to find match for <Type as _>
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait");
}
}
// 3. Call resolve to attempt binding
path.resolve(m_crate);
}
-bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) {
+bool CPathResolver::find_local_item(AST::Path& path, const ::std::string& name, bool allow_variables)
+{
TRACE_FUNCTION_F("path="<<path<<", allow_variables="<<allow_variables);
// Search current scopes for a name
// - This should search both the expression stack
@@ -594,8 +681,9 @@ bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) { {
for( auto it2 = s.locals.rbegin(); it2 != s.locals.rend(); ++it2 )
{
- if( *it2 == path[0].name() ) {
- path = AST::Path(AST::Path::TagLocal(), path[0].name());
+ if( *it2 == name ) {
+ path = AST::Path(AST::Path::TagLocal(), name);
+ path.bind_variable(0);
return true;
}
}
@@ -603,19 +691,29 @@ bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) { if( s.module != nullptr )
{
DEBUG("- Looking in sub-module '" << s.module_path << "'");
- if( lookup_path_in_module(m_crate, *s.module, s.module_path, path) )
+ if( lookup_path_in_module(m_crate, *s.module, s.module_path, path, name, path.is_trivial()) )
return true;
}
}
return false;
}
-bool CPathResolver::find_mod_item(AST::Path& path) {
+bool CPathResolver::find_mod_item(AST::Path& path, const ::std::string& name) {
+ const AST::Module* mod = m_module;
+ do {
+ if( lookup_path_in_module(m_crate, *mod, m_module_path, path, name, path.size()==1) )
+ return true;
+ if( mod->name() == "" )
+ throw ParseError::Todo("Handle anon modules when resoling unqualified relative paths");
+ } while( mod->name() == "" );
+ return false;
+}
+bool CPathResolver::find_self_mod_item(AST::Path& path, const ::std::string& name) {
if( m_module->name() == "" )
throw ParseError::Todo("Correct handling of 'self' in anon modules");
- return lookup_path_in_module(m_crate, *m_module, m_module_path, path);
+ return lookup_path_in_module(m_crate, *m_module, m_module_path, path, name, path.size()==1);
}
-bool CPathResolver::find_super_mod_item(AST::Path& path) {
+bool CPathResolver::find_super_mod_item(AST::Path& path, const ::std::string& name) {
if( m_module->name() == "" )
throw ParseError::Todo("Correct handling of 'super' in anon modules");
@@ -628,7 +726,7 @@ bool CPathResolver::find_super_mod_item(AST::Path& path) { // 2. Resolve that path
super_path.resolve(m_crate);
// 3. Call lookup_path_in_module
- return lookup_path_in_module(m_crate, super_path.binding().bound_module(), super_path, path);
+ return lookup_path_in_module(m_crate, *super_path.binding().as_Module().module_, super_path, path, name, path.size()==1);
}
bool CPathResolver::find_type_param(const ::std::string& name) {
for( auto it = m_locals.end(); it -- != m_locals.begin(); )
@@ -810,24 +908,22 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod // If wildcard, make sure it's sane
if( imp.name == "" )
{
- switch(imp.data.binding().type())
- {
- case AST::PathBinding::UNBOUND:
- throw ParseError::BugCheck("path unbound after calling .resolve()");
- case AST::PathBinding::MODULE:
- break;
- case AST::PathBinding::ENUM:
- break;
-
- default:
+ TU_MATCH_DEF(AST::PathBinding, (imp.data.binding()), (info),
+ (
throw ParseError::Generic("Wildcard imports are only allowed on modules and enums");
- }
+ ),
+ (Unbound,
+ throw ParseError::BugCheck("path unbound after calling .resolve()");
+ ),
+ (Module, (void)0;),
+ (Enum, (void)0;)
+ )
}
}
for( auto& new_imp : new_imports )
{
- if( not new_imp.binding().is_bound() ) {
+ if( new_imp.binding().is_Unbound() ) {
new_imp.resolve(crate, false);
}
mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name());
diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp index 4112bf27..1216e959 100644 --- a/src/convert/typecheck_bounds.cpp +++ b/src/convert/typecheck_bounds.cpp @@ -25,9 +25,9 @@ void CGenericBoundChecker::handle_params(AST::TypeParams& params) if( bound.is_trait() ) { auto& trait = bound.bound(); - assert(trait.binding().is_bound()); + assert( !trait.binding().is_Unbound() ); DEBUG("trait = " << trait); - if( trait.binding().type() != AST::PathBinding::TRAIT ) + if( trait.binding().is_Trait() ) { //throw CompileError::BoundNotTrait( bound.lex_scope(), bound.param(), trait ); throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait : " << trait.binding())); diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 8a4bc84f..e2bd1857 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -300,14 +300,16 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) if( p.is_absolute() ) { // grab bound item - switch(p.binding().type()) - { - case AST::PathBinding::STATIC: - node.get_res_type() = p.binding().bound_static().type(); - break; - case AST::PathBinding::ENUM_VAR: { - const AST::Enum& enm = *p.binding().bound_enumvar().enum_; - auto idx = p.binding().bound_enumvar().idx; + TU_MATCH_DEF(AST::PathBinding, (p.binding()), (info), + ( + throw ::std::runtime_error( FMT("Unknown binding type on named value : "<<p) ); + ), + (Static, + node.get_res_type() = info.static_->type(); + ), + (EnumVar, + const AST::Enum& enm = *info.enum_; + auto idx = info.idx; // Enum variant: // - Check that this variant takes no arguments if( enm.variants()[idx].m_sub_types.size() > 0 ) @@ -322,10 +324,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) while(pn.args().size() < num_params) pn.args().push_back( TypeRef() ); node.get_res_type() = TypeRef(tp); - break; } - default: - throw ::std::runtime_error( FMT("Unknown binding type on named value : "<<p) ); - } + ) + ) } else { @@ -415,16 +415,16 @@ void CTC_NodeVisitor::visit(AST::ExprNode_Field& node) // TODO Move this logic to types.cpp? const AST::Path& p = tr->path(); - switch( p.binding().type() ) - { - case AST::PathBinding::STRUCT: { + TU_MATCH_DEF( AST::PathBinding, (p.binding()), (info), + ( + throw ::std::runtime_error("TODO: Get field from non-structure"); + ), + (Struct, const AST::PathNode& lastnode = p.nodes().back(); - AST::Struct& s = const_cast<AST::Struct&>( p.binding().bound_struct() ); + AST::Struct& s = const_cast<AST::Struct&>( *info.struct_ ); node.get_res_type().merge_with( s.get_field_type(node.m_name.c_str(), lastnode.args()) ); - break; } - default: - throw ::std::runtime_error("TODO: Get field from non-structure"); - } + ) + ) DEBUG("deref_count = " << deref_count); for( unsigned i = 0; i < deref_count; i ++ ) { @@ -575,9 +575,12 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) argtypes.push_back( arg->get_res_type() ); } - if(node.m_path.binding().type() == AST::PathBinding::FUNCTION) - { - const AST::Function& fcn = node.m_path.binding().bound_func(); + TU_MATCH_DEF( AST::PathBinding, (node.m_path.binding()), (info), + ( + throw ::std::runtime_error("CallPath on non-function"); + ), + (Function, + const AST::Function& fcn = *info.func_; if( fcn.params().ty_params().size() > 0 ) { @@ -586,11 +589,10 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) DEBUG("ExprNode_CallPath - rt = " << fcn.rettype()); node.get_res_type().merge_with( fcn.rettype() ); - } - else if(node.m_path.binding().type() == AST::PathBinding::ENUM_VAR) - { - const AST::Enum& enm = *node.m_path.binding().bound_enumvar().enum_; - const unsigned int idx = node.m_path.binding().bound_enumvar().idx; + ), + (EnumVar, + const AST::Enum& enm = *info.enum_; + const unsigned int idx = info.idx; auto& path_node_enum = node.m_path[node.m_path.size()-2]; m_tc.check_enum_variant(path_node_enum.args(), argtypes, enm.params(), enm.variants().at(idx)); @@ -601,11 +603,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) DEBUG("ExprNode_CallPath - enum t = " << ty); node.get_res_type().merge_with(ty); - } - else - { - throw ::std::runtime_error("CallPath on non-function"); - } + ) + ) } void Typecheck_Expr(AST::Crate& crate) diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index f3fe5047..e8cbbc05 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -235,43 +235,57 @@ void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode p { TRACE_FUNCTION_F("path = " << path); AST::PathNode& last_node = path[path.size()-1]; - const AST::TypeParams* params = nullptr; - switch(path.binding().type()) - { - case AST::PathBinding::UNBOUND: - throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) ); - case AST::PathBinding::MODULE: - DEBUG("WTF - Module path, isn't this invalid at this stage?"); - break; - case AST::PathBinding::TRAIT: - params = &path.binding().bound_trait().params(); - if(0) - case AST::PathBinding::STRUCT: - params = &path.binding().bound_struct().params(); - if(0) - case AST::PathBinding::ENUM: - params = &path.binding().bound_enum().params(); - - { + auto comm = [&](const AST::TypeParams& params) { auto lt = find_type_by_name("Self"); TypeRef self_type; // =TypeRef(TypeRef::TagPath(), path) if( lt ) self_type = lt->fixed_type; - check_generic_params(*params, last_node.args(), self_type, (m_within_expr > 0)); - } - break; - case AST::PathBinding::ALIAS: - params = &path.binding().bound_alias().params(); - if(0) - case AST::PathBinding::FUNCTION: - params = &path.binding().bound_func().params(); - - check_generic_params(*params, last_node.args(), TypeRef(TypeRef::TagInvalid()), (m_within_expr > 0)); - break; - default: - throw ::std::runtime_error("Unknown path type in CGenericParamChecker::handle_path"); - } + check_generic_params(params, last_node.args(), self_type, (m_within_expr > 0)); + }; + + TU_MATCH( AST::PathBinding, (path.binding()), (info), + (Unbound, + throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) ); + ), + (Module, + DEBUG("WTF - Module path, isn't this invalid at this stage?"); + ), + (Trait, + comm( info.trait_->params() ); + ), + (Struct, + comm( info.struct_->params() ); + ), + (Enum, + comm( info.enum_->params() ); + ), + (TypeAlias, + comm( info.alias_->params() ); + ), + (Function, + check_generic_params(info.func_->params(), last_node.args(), TypeRef(TypeRef::TagInvalid()), (m_within_expr > 0)); + ), + + (EnumVar, + throw ::std::runtime_error("TODO: handle_path EnumVar"); + ), + (Static, + throw ::std::runtime_error("TODO: handle_path Static"); + ), + (StructMethod, + throw ::std::runtime_error("TODO: handle_path StructMethod"); + ), + (TraitMethod, + throw ::std::runtime_error("TODO: handle_path TraitMethod"); + ), + (TypeParameter, + throw ::std::runtime_error("TODO: handle_path TypeParameter"); + ), + (Variable, + throw ::std::runtime_error("TODO: handle_path Variable"); + ) + ) } void CGenericParamChecker::handle_expr(AST::ExprNode& root) |