gccrs: Add name resolution pass to the Rust front-end

The name resolution is split into two phases, one toplevel pass which scans
the whole "Crate" which iterates all items and nested items in modules to
generate a context class full of CanonicalPath items. It also generates
a hierarchy of parent->child and child->parent relationships using the AST
NodeId for PathResolution in the second phase.

The second phase drills into each item like functions and creates a stack
of canonical paths for variables etc so that we can store information in
a side table of usage variable 'a' resolves to NodeId '123' which refers
to the NodeId of the "let a;" statement.

	gcc/rust/
	* resolve/rust-ast-resolve-base.cc: New.
	* resolve/rust-ast-resolve-base.h: New.
	* resolve/rust-ast-resolve-expr.cc: New.
	* resolve/rust-ast-resolve-expr.h: New.
	* resolve/rust-ast-resolve-implitem.h: New.
	* resolve/rust-ast-resolve-item.cc: New.
	* resolve/rust-ast-resolve-item.h: New.
	* resolve/rust-ast-resolve-path.cc: New.
	* resolve/rust-ast-resolve-path.h: New.
	* resolve/rust-ast-resolve-pattern.cc: New.
	* resolve/rust-ast-resolve-pattern.h: New.
	* resolve/rust-ast-resolve-stmt.cc: New.
	* resolve/rust-ast-resolve-stmt.h: New.
	* resolve/rust-ast-resolve-struct-expr-field.cc: New.
	* resolve/rust-ast-resolve-struct-expr-field.h: New.
	* resolve/rust-ast-resolve-toplevel.h: New.
	* resolve/rust-ast-resolve-type.cc: New.
	* resolve/rust-ast-resolve-type.h: New.
	* resolve/rust-ast-resolve.cc: New.
	* resolve/rust-ast-resolve.h: New.
	* resolve/rust-ast-verify-assignee.h: New.
	* resolve/rust-name-resolver.cc: New.
	* resolve/rust-name-resolver.h: New.
This commit is contained in:
Philip Herron
2022-08-23 16:19:04 +01:00
committed by Arthur Cohen
parent 1841081a8a
commit 85a8fe00f8
23 changed files with 6772 additions and 0 deletions

View File

@@ -0,0 +1,658 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-base.h"
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-path.h"
#include "rust-item.h"
namespace Rust {
namespace Resolver {
bool
ResolverBase::resolve_visibility (const AST::Visibility &vis)
{
if (vis.has_path ())
{
auto path = vis.get_path ();
ResolvePath::go (&path);
// Do we need to lookup something here?
// Is it just about resolving the names correctly so we can look them up
// later?
}
return true;
}
// Default visitors implementations
void
ResolverBase::visit (AST::Token &)
{}
void
ResolverBase::visit (AST::DelimTokenTree &)
{}
void
ResolverBase::visit (AST::AttrInputMetaItemContainer &)
{}
void
ResolverBase::visit (AST::IdentifierExpr &)
{}
void
ResolverBase::visit (AST::Lifetime &)
{}
void
ResolverBase::visit (AST::LifetimeParam &)
{}
void
ResolverBase::visit (AST::ConstGenericParam &)
{}
void
ResolverBase::visit (AST::PathInExpression &)
{}
void
ResolverBase::visit (AST::TypePathSegment &)
{}
void
ResolverBase::visit (AST::TypePathSegmentGeneric &)
{}
void
ResolverBase::visit (AST::TypePathSegmentFunction &)
{}
void
ResolverBase::visit (AST::TypePath &)
{}
void
ResolverBase::visit (AST::QualifiedPathInExpression &)
{}
void
ResolverBase::visit (AST::QualifiedPathInType &)
{}
void
ResolverBase::visit (AST::LiteralExpr &)
{}
void
ResolverBase::visit (AST::AttrInputLiteral &)
{}
void
ResolverBase::visit (AST::MetaItemLitExpr &)
{}
void
ResolverBase::visit (AST::MetaItemPathLit &)
{}
void
ResolverBase::visit (AST::BorrowExpr &)
{}
void
ResolverBase::visit (AST::DereferenceExpr &)
{}
void
ResolverBase::visit (AST::ErrorPropagationExpr &)
{}
void
ResolverBase::visit (AST::NegationExpr &)
{}
void
ResolverBase::visit (AST::ArithmeticOrLogicalExpr &)
{}
void
ResolverBase::visit (AST::ComparisonExpr &)
{}
void
ResolverBase::visit (AST::LazyBooleanExpr &)
{}
void
ResolverBase::visit (AST::TypeCastExpr &)
{}
void
ResolverBase::visit (AST::AssignmentExpr &)
{}
void
ResolverBase::visit (AST::CompoundAssignmentExpr &)
{}
void
ResolverBase::visit (AST::GroupedExpr &)
{}
void
ResolverBase::visit (AST::ArrayElemsValues &)
{}
void
ResolverBase::visit (AST::ArrayElemsCopied &)
{}
void
ResolverBase::visit (AST::ArrayExpr &)
{}
void
ResolverBase::visit (AST::ArrayIndexExpr &)
{}
void
ResolverBase::visit (AST::TupleExpr &)
{}
void
ResolverBase::visit (AST::TupleIndexExpr &)
{}
void
ResolverBase::visit (AST::StructExprStruct &)
{}
void
ResolverBase::visit (AST::StructExprFieldIdentifier &)
{}
void
ResolverBase::visit (AST::StructExprFieldIdentifierValue &)
{}
void
ResolverBase::visit (AST::StructExprFieldIndexValue &)
{}
void
ResolverBase::visit (AST::StructExprStructFields &)
{}
void
ResolverBase::visit (AST::StructExprStructBase &)
{}
void
ResolverBase::visit (AST::CallExpr &)
{}
void
ResolverBase::visit (AST::MethodCallExpr &)
{}
void
ResolverBase::visit (AST::FieldAccessExpr &)
{}
void
ResolverBase::visit (AST::ClosureExprInner &)
{}
void
ResolverBase::visit (AST::BlockExpr &)
{}
void
ResolverBase::visit (AST::ClosureExprInnerTyped &)
{}
void
ResolverBase::visit (AST::ContinueExpr &)
{}
void
ResolverBase::visit (AST::BreakExpr &)
{}
void
ResolverBase::visit (AST::RangeFromToExpr &)
{}
void
ResolverBase::visit (AST::RangeFromExpr &)
{}
void
ResolverBase::visit (AST::RangeToExpr &)
{}
void
ResolverBase::visit (AST::RangeFullExpr &)
{}
void
ResolverBase::visit (AST::RangeFromToInclExpr &)
{}
void
ResolverBase::visit (AST::RangeToInclExpr &)
{}
void
ResolverBase::visit (AST::ReturnExpr &)
{}
void
ResolverBase::visit (AST::UnsafeBlockExpr &)
{}
void
ResolverBase::visit (AST::LoopExpr &)
{}
void
ResolverBase::visit (AST::WhileLoopExpr &)
{}
void
ResolverBase::visit (AST::WhileLetLoopExpr &)
{}
void
ResolverBase::visit (AST::ForLoopExpr &)
{}
void
ResolverBase::visit (AST::IfExpr &)
{}
void
ResolverBase::visit (AST::IfExprConseqElse &)
{}
void
ResolverBase::visit (AST::IfExprConseqIf &)
{}
void
ResolverBase::visit (AST::IfExprConseqIfLet &)
{}
void
ResolverBase::visit (AST::IfLetExpr &)
{}
void
ResolverBase::visit (AST::IfLetExprConseqElse &)
{}
void
ResolverBase::visit (AST::IfLetExprConseqIf &)
{}
void
ResolverBase::visit (AST::IfLetExprConseqIfLet &)
{}
void
ResolverBase::visit (AST::MatchExpr &)
{}
void
ResolverBase::visit (AST::AwaitExpr &)
{}
void
ResolverBase::visit (AST::AsyncBlockExpr &)
{}
void
ResolverBase::visit (AST::TypeParam &)
{}
void
ResolverBase::visit (AST::LifetimeWhereClauseItem &)
{}
void
ResolverBase::visit (AST::TypeBoundWhereClauseItem &)
{}
void
ResolverBase::visit (AST::Method &)
{}
void
ResolverBase::visit (AST::Module &)
{}
void
ResolverBase::visit (AST::ExternCrate &)
{}
void
ResolverBase::visit (AST::UseTreeGlob &)
{}
void
ResolverBase::visit (AST::UseTreeList &)
{}
void
ResolverBase::visit (AST::UseTreeRebind &)
{}
void
ResolverBase::visit (AST::UseDeclaration &)
{}
void
ResolverBase::visit (AST::Function &)
{}
void
ResolverBase::visit (AST::TypeAlias &)
{}
void
ResolverBase::visit (AST::StructStruct &)
{}
void
ResolverBase::visit (AST::TupleStruct &)
{}
void
ResolverBase::visit (AST::EnumItem &)
{}
void
ResolverBase::visit (AST::EnumItemTuple &)
{}
void
ResolverBase::visit (AST::EnumItemStruct &)
{}
void
ResolverBase::visit (AST::EnumItemDiscriminant &)
{}
void
ResolverBase::visit (AST::Enum &)
{}
void
ResolverBase::visit (AST::Union &)
{}
void
ResolverBase::visit (AST::ConstantItem &)
{}
void
ResolverBase::visit (AST::StaticItem &)
{}
void
ResolverBase::visit (AST::TraitItemFunc &)
{}
void
ResolverBase::visit (AST::TraitItemMethod &)
{}
void
ResolverBase::visit (AST::TraitItemConst &)
{}
void
ResolverBase::visit (AST::TraitItemType &)
{}
void
ResolverBase::visit (AST::Trait &)
{}
void
ResolverBase::visit (AST::InherentImpl &)
{}
void
ResolverBase::visit (AST::TraitImpl &)
{}
void
ResolverBase::visit (AST::ExternalStaticItem &)
{}
void
ResolverBase::visit (AST::ExternalFunctionItem &)
{}
void
ResolverBase::visit (AST::ExternBlock &)
{}
void
ResolverBase::visit (AST::MacroMatchFragment &)
{}
void
ResolverBase::visit (AST::MacroMatchRepetition &)
{}
void
ResolverBase::visit (AST::MacroMatcher &)
{}
void
ResolverBase::visit (AST::MacroRulesDefinition &)
{}
void
ResolverBase::visit (AST::MacroInvocation &)
{}
void
ResolverBase::visit (AST::MetaItemPath &)
{}
void
ResolverBase::visit (AST::MetaItemSeq &)
{}
void
ResolverBase::visit (AST::MetaWord &)
{}
void
ResolverBase::visit (AST::MetaNameValueStr &)
{}
void
ResolverBase::visit (AST::MetaListPaths &)
{}
void
ResolverBase::visit (AST::MetaListNameValueStr &)
{}
void
ResolverBase::visit (AST::LiteralPattern &)
{}
void
ResolverBase::visit (AST::IdentifierPattern &)
{}
void
ResolverBase::visit (AST::WildcardPattern &)
{}
void
ResolverBase::visit (AST::RangePatternBoundLiteral &)
{}
void
ResolverBase::visit (AST::RangePatternBoundPath &)
{}
void
ResolverBase::visit (AST::RangePatternBoundQualPath &)
{}
void
ResolverBase::visit (AST::RangePattern &)
{}
void
ResolverBase::visit (AST::ReferencePattern &)
{}
void
ResolverBase::visit (AST::StructPatternFieldTuplePat &)
{}
void
ResolverBase::visit (AST::StructPatternFieldIdentPat &)
{}
void
ResolverBase::visit (AST::StructPatternFieldIdent &)
{}
void
ResolverBase::visit (AST::StructPattern &)
{}
void
ResolverBase::visit (AST::TupleStructItemsNoRange &)
{}
void
ResolverBase::visit (AST::TupleStructItemsRange &)
{}
void
ResolverBase::visit (AST::TupleStructPattern &)
{}
void
ResolverBase::visit (AST::TuplePatternItemsMultiple &)
{}
void
ResolverBase::visit (AST::TuplePatternItemsRanged &)
{}
void
ResolverBase::visit (AST::TuplePattern &)
{}
void
ResolverBase::visit (AST::GroupedPattern &)
{}
void
ResolverBase::visit (AST::SlicePattern &)
{}
void
ResolverBase::visit (AST::EmptyStmt &)
{}
void
ResolverBase::visit (AST::LetStmt &)
{}
void
ResolverBase::visit (AST::ExprStmtWithoutBlock &)
{}
void
ResolverBase::visit (AST::ExprStmtWithBlock &)
{}
void
ResolverBase::visit (AST::TraitBound &)
{}
void
ResolverBase::visit (AST::ImplTraitType &)
{}
void
ResolverBase::visit (AST::TraitObjectType &)
{}
void
ResolverBase::visit (AST::ParenthesisedType &)
{}
void
ResolverBase::visit (AST::ImplTraitTypeOneBound &)
{}
void
ResolverBase::visit (AST::TraitObjectTypeOneBound &)
{}
void
ResolverBase::visit (AST::TupleType &)
{}
void
ResolverBase::visit (AST::NeverType &)
{}
void
ResolverBase::visit (AST::RawPointerType &)
{}
void
ResolverBase::visit (AST::ReferenceType &)
{}
void
ResolverBase::visit (AST::ArrayType &)
{}
void
ResolverBase::visit (AST::SliceType &)
{}
void
ResolverBase::visit (AST::InferredType &)
{}
void
ResolverBase::visit (AST::BareFunctionType &)
{}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,221 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_BASE_H
#define RUST_AST_RESOLVE_BASE_H
#include "rust-ast-visitor.h"
#include "rust-name-resolver.h"
#include "rust-diagnostics.h"
#include "rust-location.h"
namespace Rust {
namespace Resolver {
class ResolverBase : public AST::ASTVisitor
{
public:
virtual ~ResolverBase () {}
void visit (AST::Token &);
void visit (AST::DelimTokenTree &);
void visit (AST::AttrInputMetaItemContainer &);
void visit (AST::IdentifierExpr &);
void visit (AST::Lifetime &);
void visit (AST::LifetimeParam &);
void visit (AST::ConstGenericParam &);
void visit (AST::PathInExpression &);
void visit (AST::TypePathSegment &);
void visit (AST::TypePathSegmentGeneric &);
void visit (AST::TypePathSegmentFunction &);
void visit (AST::TypePath &);
void visit (AST::QualifiedPathInExpression &);
void visit (AST::QualifiedPathInType &);
void visit (AST::LiteralExpr &);
void visit (AST::AttrInputLiteral &);
void visit (AST::MetaItemLitExpr &);
void visit (AST::MetaItemPathLit &);
void visit (AST::BorrowExpr &);
void visit (AST::DereferenceExpr &);
void visit (AST::ErrorPropagationExpr &);
void visit (AST::NegationExpr &);
void visit (AST::ArithmeticOrLogicalExpr &);
void visit (AST::ComparisonExpr &);
void visit (AST::LazyBooleanExpr &);
void visit (AST::TypeCastExpr &);
void visit (AST::AssignmentExpr &);
void visit (AST::CompoundAssignmentExpr &);
void visit (AST::GroupedExpr &);
void visit (AST::ArrayElemsValues &);
void visit (AST::ArrayElemsCopied &);
void visit (AST::ArrayExpr &);
void visit (AST::ArrayIndexExpr &);
void visit (AST::TupleExpr &);
void visit (AST::TupleIndexExpr &);
void visit (AST::StructExprStruct &);
void visit (AST::StructExprFieldIdentifier &);
void visit (AST::StructExprFieldIdentifierValue &);
void visit (AST::StructExprFieldIndexValue &);
void visit (AST::StructExprStructFields &);
void visit (AST::StructExprStructBase &);
void visit (AST::CallExpr &);
void visit (AST::MethodCallExpr &);
void visit (AST::FieldAccessExpr &);
void visit (AST::ClosureExprInner &);
void visit (AST::BlockExpr &);
void visit (AST::ClosureExprInnerTyped &);
void visit (AST::ContinueExpr &);
void visit (AST::BreakExpr &);
void visit (AST::RangeFromToExpr &);
void visit (AST::RangeFromExpr &);
void visit (AST::RangeToExpr &);
void visit (AST::RangeFullExpr &);
void visit (AST::RangeFromToInclExpr &);
void visit (AST::RangeToInclExpr &);
void visit (AST::ReturnExpr &);
void visit (AST::UnsafeBlockExpr &);
void visit (AST::LoopExpr &);
void visit (AST::WhileLoopExpr &);
void visit (AST::WhileLetLoopExpr &);
void visit (AST::ForLoopExpr &);
void visit (AST::IfExpr &);
void visit (AST::IfExprConseqElse &);
void visit (AST::IfExprConseqIf &);
void visit (AST::IfExprConseqIfLet &);
void visit (AST::IfLetExpr &);
void visit (AST::IfLetExprConseqElse &);
void visit (AST::IfLetExprConseqIf &);
void visit (AST::IfLetExprConseqIfLet &);
void visit (AST::MatchExpr &);
void visit (AST::AwaitExpr &);
void visit (AST::AsyncBlockExpr &);
void visit (AST::TypeParam &);
void visit (AST::LifetimeWhereClauseItem &);
void visit (AST::TypeBoundWhereClauseItem &);
void visit (AST::Method &);
void visit (AST::Module &);
void visit (AST::ExternCrate &);
void visit (AST::UseTreeGlob &);
void visit (AST::UseTreeList &);
void visit (AST::UseTreeRebind &);
void visit (AST::UseDeclaration &);
void visit (AST::Function &);
void visit (AST::TypeAlias &);
void visit (AST::StructStruct &);
void visit (AST::TupleStruct &);
void visit (AST::EnumItem &);
void visit (AST::EnumItemTuple &);
void visit (AST::EnumItemStruct &);
void visit (AST::EnumItemDiscriminant &);
void visit (AST::Enum &);
void visit (AST::Union &);
void visit (AST::ConstantItem &);
void visit (AST::StaticItem &);
void visit (AST::TraitItemFunc &);
void visit (AST::TraitItemMethod &);
void visit (AST::TraitItemConst &);
void visit (AST::TraitItemType &);
void visit (AST::Trait &);
void visit (AST::InherentImpl &);
void visit (AST::TraitImpl &);
void visit (AST::ExternalStaticItem &);
void visit (AST::ExternalFunctionItem &);
void visit (AST::ExternBlock &);
void visit (AST::MacroMatchFragment &);
void visit (AST::MacroMatchRepetition &);
void visit (AST::MacroMatcher &);
void visit (AST::MacroRulesDefinition &);
void visit (AST::MacroInvocation &);
void visit (AST::MetaItemPath &);
void visit (AST::MetaItemSeq &);
void visit (AST::MetaWord &);
void visit (AST::MetaNameValueStr &);
void visit (AST::MetaListPaths &);
void visit (AST::MetaListNameValueStr &);
void visit (AST::LiteralPattern &);
void visit (AST::IdentifierPattern &);
void visit (AST::WildcardPattern &);
void visit (AST::RangePatternBoundLiteral &);
void visit (AST::RangePatternBoundPath &);
void visit (AST::RangePatternBoundQualPath &);
void visit (AST::RangePattern &);
void visit (AST::ReferencePattern &);
void visit (AST::StructPatternFieldTuplePat &);
void visit (AST::StructPatternFieldIdentPat &);
void visit (AST::StructPatternFieldIdent &);
void visit (AST::StructPattern &);
void visit (AST::TupleStructItemsNoRange &);
void visit (AST::TupleStructItemsRange &);
void visit (AST::TupleStructPattern &);
void visit (AST::TuplePatternItemsMultiple &);
void visit (AST::TuplePatternItemsRanged &);
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
void visit (AST::SlicePattern &);
void visit (AST::EmptyStmt &);
void visit (AST::LetStmt &);
void visit (AST::ExprStmtWithoutBlock &);
void visit (AST::ExprStmtWithBlock &);
void visit (AST::TraitBound &);
void visit (AST::ImplTraitType &);
void visit (AST::TraitObjectType &);
void visit (AST::ParenthesisedType &);
void visit (AST::ImplTraitTypeOneBound &);
void visit (AST::TraitObjectTypeOneBound &);
void visit (AST::TupleType &);
void visit (AST::NeverType &);
void visit (AST::RawPointerType &);
void visit (AST::ReferenceType &);
void visit (AST::ArrayType &);
void visit (AST::SliceType &);
void visit (AST::InferredType &);
void visit (AST::BareFunctionType &);
protected:
ResolverBase ()
: resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()),
resolved_node (UNKNOWN_NODEID)
{}
/**
* Resolve a visibility's path through the name resolver
*/
bool resolve_visibility (const AST::Visibility &vis);
Resolver *resolver;
Analysis::Mappings *mappings;
NodeId resolved_node;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_BASE_H

View File

@@ -0,0 +1,574 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-stmt.h"
#include "rust-ast-resolve-struct-expr-field.h"
#include "rust-ast-verify-assignee.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-pattern.h"
#include "rust-ast-resolve-path.h"
namespace Rust {
namespace Resolver {
void
ResolveExpr::go (AST::Expr *expr, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
ResolveExpr resolver (prefix, canonical_prefix);
expr->accept_vis (resolver);
}
void
ResolveExpr::visit (AST::TupleIndexExpr &expr)
{
ResolveExpr::go (expr.get_tuple_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::TupleExpr &expr)
{
if (expr.is_unit ())
return;
for (auto &elem : expr.get_tuple_elems ())
ResolveExpr::go (elem.get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::PathInExpression &expr)
{
ResolvePath::go (&expr);
}
void
ResolveExpr::visit (AST::QualifiedPathInExpression &expr)
{
ResolvePath::go (&expr);
}
void
ResolveExpr::visit (AST::ReturnExpr &expr)
{
if (expr.has_returned_expr ())
ResolveExpr::go (expr.get_returned_expr ().get (), prefix,
canonical_prefix);
}
void
ResolveExpr::visit (AST::CallExpr &expr)
{
ResolveExpr::go (expr.get_function_expr ().get (), prefix, canonical_prefix);
for (auto &param : expr.get_params ())
ResolveExpr::go (param.get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::MethodCallExpr &expr)
{
ResolveExpr::go (expr.get_receiver_expr ().get (), prefix, canonical_prefix);
if (expr.get_method_name ().has_generic_args ())
{
AST::GenericArgs &args = expr.get_method_name ().get_generic_args ();
ResolveGenericArgs::go (args, prefix, canonical_prefix);
}
auto const &in_params = expr.get_params ();
for (auto &param : in_params)
ResolveExpr::go (param.get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::AssignmentExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_right_expr ().get (), prefix, canonical_prefix);
// need to verify the assignee
VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ());
}
void
ResolveExpr::visit (AST::IdentifierExpr &expr)
{
if (resolver->get_name_scope ().lookup (
CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
&resolved_node))
{
resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
}
else if (resolver->get_type_scope ().lookup (
CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
&resolved_node))
{
resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
}
else
{
rust_error_at (expr.get_locus (), "failed to find name: %s",
expr.as_string ().c_str ());
}
}
void
ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_right_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::CompoundAssignmentExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_right_expr ().get (), prefix, canonical_prefix);
// need to verify the assignee
VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ());
}
void
ResolveExpr::visit (AST::ComparisonExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_right_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::LazyBooleanExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_right_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::NegationExpr &expr)
{
ResolveExpr::go (expr.get_negated_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::TypeCastExpr &expr)
{
ResolveType::go (expr.get_type_to_cast_to ().get ());
ResolveExpr::go (expr.get_casted_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::IfExpr &expr)
{
ResolveExpr::go (expr.get_condition_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::IfExprConseqElse &expr)
{
ResolveExpr::go (expr.get_condition_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_else_block ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::IfExprConseqIf &expr)
{
ResolveExpr::go (expr.get_condition_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_conseq_if_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::IfLetExpr &expr)
{
ResolveExpr::go (expr.get_value_expr ().get (), prefix, canonical_prefix);
NodeId scope_node_id = expr.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
for (auto &pattern : expr.get_patterns ())
{
PatternDeclaration::go (pattern.get ());
}
ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix);
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}
void
ResolveExpr::visit (AST::BlockExpr &expr)
{
NodeId scope_node_id = expr.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
for (auto &s : expr.get_statements ())
{
if (s->is_item ())
ResolveStmt::go (s.get (), prefix, canonical_prefix,
CanonicalPath::create_empty ());
}
for (auto &s : expr.get_statements ())
{
if (!s->is_item ())
ResolveStmt::go (s.get (), prefix, canonical_prefix,
CanonicalPath::create_empty ());
}
if (expr.has_tail_expr ())
ResolveExpr::go (expr.get_tail_expr ().get (), prefix, canonical_prefix);
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}
void
ResolveExpr::visit (AST::UnsafeBlockExpr &expr)
{
expr.get_block_expr ()->accept_vis (*this);
}
void
ResolveExpr::visit (AST::ArrayElemsValues &elems)
{
for (auto &elem : elems.get_values ())
ResolveExpr::go (elem.get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::ArrayExpr &expr)
{
expr.get_array_elems ()->accept_vis (*this);
}
void
ResolveExpr::visit (AST::ArrayIndexExpr &expr)
{
ResolveExpr::go (expr.get_array_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_index_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::ArrayElemsCopied &expr)
{
ResolveExpr::go (expr.get_num_copies ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_elem_to_copy ().get (), prefix, canonical_prefix);
}
// this this an empty struct constructor like 'S {}'
void
ResolveExpr::visit (AST::StructExprStruct &struct_expr)
{
ResolveExpr::go (&struct_expr.get_struct_name (), prefix, canonical_prefix);
}
// this this a struct constructor with fields
void
ResolveExpr::visit (AST::StructExprStructFields &struct_expr)
{
ResolveExpr::go (&struct_expr.get_struct_name (), prefix, canonical_prefix);
if (struct_expr.has_struct_base ())
{
AST::StructBase &base = struct_expr.get_struct_base ();
ResolveExpr::go (base.get_base_struct ().get (), prefix,
canonical_prefix);
}
auto const &struct_fields = struct_expr.get_fields ();
for (auto &struct_field : struct_fields)
{
ResolveStructExprField::go (struct_field.get (), prefix,
canonical_prefix);
}
}
void
ResolveExpr::visit (AST::GroupedExpr &expr)
{
ResolveExpr::go (expr.get_expr_in_parens ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::FieldAccessExpr &expr)
{
ResolveExpr::go (expr.get_receiver_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::LoopExpr &expr)
{
if (expr.has_loop_label ())
{
auto label = expr.get_loop_label ();
if (label.get_lifetime ().get_lifetime_type ()
!= AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
"Labels must be a named lifetime value");
return;
}
auto label_name = label.get_lifetime ().get_lifetime_name ();
auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
resolver->get_label_scope ().insert (
CanonicalPath::new_seg (expr.get_node_id (), label_name),
label_lifetime_node_id, label.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
rust_error_at (label.get_locus (), "label redefined multiple times");
rust_error_at (locus, "was defined here");
});
}
ResolveExpr::go (expr.get_loop_block ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::BreakExpr &expr)
{
if (expr.has_label ())
{
auto label = expr.get_label ();
if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
"Labels must be a named lifetime value");
return;
}
NodeId resolved_node = UNKNOWN_NODEID;
if (!resolver->get_label_scope ().lookup (
CanonicalPath::new_seg (label.get_node_id (),
label.get_lifetime_name ()),
&resolved_node))
{
rust_error_at (expr.get_label ().get_locus (),
"failed to resolve label");
return;
}
resolver->insert_resolved_label (label.get_node_id (), resolved_node);
}
if (expr.has_break_expr ())
ResolveExpr::go (expr.get_break_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::WhileLoopExpr &expr)
{
if (expr.has_loop_label ())
{
auto label = expr.get_loop_label ();
if (label.get_lifetime ().get_lifetime_type ()
!= AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
"Labels must be a named lifetime value");
return;
}
auto label_name = label.get_lifetime ().get_lifetime_name ();
auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
resolver->get_label_scope ().insert (
CanonicalPath::new_seg (label.get_node_id (), label_name),
label_lifetime_node_id, label.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
rust_error_at (label.get_locus (), "label redefined multiple times");
rust_error_at (locus, "was defined here");
});
}
ResolveExpr::go (expr.get_predicate_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_loop_block ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::ForLoopExpr &expr)
{
if (expr.has_loop_label ())
{
auto label = expr.get_loop_label ();
if (label.get_lifetime ().get_lifetime_type ()
!= AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
"Labels must be a named lifetime value");
return;
}
auto label_name = label.get_lifetime ().get_lifetime_name ();
auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
resolver->get_label_scope ().insert (
CanonicalPath::new_seg (label.get_node_id (), label_name),
label_lifetime_node_id, label.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
rust_error_at (label.get_locus (), "label redefined multiple times");
rust_error_at (locus, "was defined here");
});
}
// this needs a new rib to contain the pattern
NodeId scope_node_id = expr.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
// resolve the expression
PatternDeclaration::go (expr.get_pattern ().get ());
ResolveExpr::go (expr.get_iterator_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_loop_block ().get (), prefix, canonical_prefix);
// done
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}
void
ResolveExpr::visit (AST::ContinueExpr &expr)
{
if (expr.has_label ())
{
auto label = expr.get_label ();
if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
"Labels must be a named lifetime value");
return;
}
NodeId resolved_node = UNKNOWN_NODEID;
if (!resolver->get_label_scope ().lookup (
CanonicalPath::new_seg (label.get_node_id (),
label.get_lifetime_name ()),
&resolved_node))
{
rust_error_at (expr.get_label ().get_locus (),
"failed to resolve label");
return;
}
resolver->insert_resolved_label (label.get_node_id (), resolved_node);
}
}
void
ResolveExpr::visit (AST::BorrowExpr &expr)
{
ResolveExpr::go (expr.get_borrowed_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::DereferenceExpr &expr)
{
ResolveExpr::go (expr.get_dereferenced_expr ().get (), prefix,
canonical_prefix);
}
void
ResolveExpr::visit (AST::MatchExpr &expr)
{
ResolveExpr::go (expr.get_scrutinee_expr ().get (), prefix, canonical_prefix);
for (auto &match_case : expr.get_match_cases ())
{
// each arm is in its own scope
NodeId scope_node_id = match_case.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
// resolve
AST::MatchArm &arm = match_case.get_arm ();
if (arm.has_match_arm_guard ())
ResolveExpr::go (arm.get_guard_expr ().get (), prefix,
canonical_prefix);
// insert any possible new patterns
for (auto &pattern : arm.get_patterns ())
{
PatternDeclaration::go (pattern.get ());
}
// resolve the body
ResolveExpr::go (match_case.get_expr ().get (), prefix, canonical_prefix);
// done
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}
}
void
ResolveExpr::visit (AST::RangeFromToExpr &expr)
{
ResolveExpr::go (expr.get_from_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_to_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::RangeFromExpr &expr)
{
ResolveExpr::go (expr.get_from_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::RangeToExpr &expr)
{
ResolveExpr::go (expr.get_to_expr ().get (), prefix, canonical_prefix);
}
void
ResolveExpr::visit (AST::RangeFullExpr &expr)
{
// nothing to do
}
void
ResolveExpr::visit (AST::RangeFromToInclExpr &expr)
{
ResolveExpr::go (expr.get_from_expr ().get (), prefix, canonical_prefix);
ResolveExpr::go (expr.get_to_expr ().get (), prefix, canonical_prefix);
}
ResolveExpr::ResolveExpr (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,133 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_EXPR_H
#define RUST_AST_RESOLVE_EXPR_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
class ResolveExpr : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Expr *expr, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::TupleIndexExpr &expr) override;
void visit (AST::TupleExpr &expr) override;
void visit (AST::PathInExpression &expr) override;
void visit (AST::QualifiedPathInExpression &expr) override;
void visit (AST::ReturnExpr &expr) override;
void visit (AST::CallExpr &expr) override;
void visit (AST::MethodCallExpr &expr) override;
void visit (AST::AssignmentExpr &expr) override;
void visit (AST::IdentifierExpr &expr) override;
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
void visit (AST::CompoundAssignmentExpr &expr) override;
void visit (AST::ComparisonExpr &expr) override;
void visit (AST::LazyBooleanExpr &expr) override;
void visit (AST::NegationExpr &expr) override;
void visit (AST::TypeCastExpr &expr) override;
void visit (AST::IfExpr &expr) override;
void visit (AST::IfExprConseqElse &expr) override;
void visit (AST::IfExprConseqIf &expr) override;
void visit (AST::IfLetExpr &expr) override;
void visit (AST::BlockExpr &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
void visit (AST::ArrayElemsValues &elems) override;
void visit (AST::ArrayExpr &expr) override;
void visit (AST::ArrayIndexExpr &expr) override;
void visit (AST::ArrayElemsCopied &elems) override;
// this this an empty struct constructor like 'S {}'
void visit (AST::StructExprStruct &struct_expr) override;
// this this a struct constructor with fields
void visit (AST::StructExprStructFields &struct_expr) override;
void visit (AST::GroupedExpr &expr) override;
void visit (AST::FieldAccessExpr &expr) override;
void visit (AST::LoopExpr &expr) override;
void visit (AST::BreakExpr &expr) override;
void visit (AST::WhileLoopExpr &expr) override;
void visit (AST::ForLoopExpr &expr) override;
void visit (AST::ContinueExpr &expr) override;
void visit (AST::BorrowExpr &expr) override;
void visit (AST::DereferenceExpr &expr) override;
void visit (AST::MatchExpr &expr) override;
void visit (AST::RangeFromToExpr &expr) override;
void visit (AST::RangeFromExpr &expr) override;
void visit (AST::RangeToExpr &expr) override;
void visit (AST::RangeFullExpr &expr) override;
void visit (AST::RangeFromToInclExpr &expr) override;
private:
ResolveExpr (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_EXPR_H

View File

@@ -0,0 +1,275 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_IMPLITEM_H
#define RUST_AST_RESOLVE_IMPLITEM_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
class ResolveToplevelImplItem : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::InherentImplItem *item, const CanonicalPath &prefix)
{
if (item->is_marked_for_strip ())
return;
ResolveToplevelImplItem resolver (prefix);
item->accept_vis (resolver);
}
static void go (AST::TraitImplItem *item, const CanonicalPath &prefix)
{
if (item->is_marked_for_strip ())
return;
ResolveToplevelImplItem resolver (prefix);
item->accept_vis (resolver);
}
void visit (AST::TypeAlias &type) override
{
auto decl
= CanonicalPath::new_seg (type.get_node_id (), type.get_new_type_name ());
auto path = prefix.append (decl);
resolver->get_type_scope ().insert (
path, type.get_node_id (), type.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (type.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
void visit (AST::ConstantItem &constant) override
{
auto decl = CanonicalPath::new_seg (constant.get_node_id (),
constant.get_identifier ());
auto path = prefix.append (decl);
resolver->get_name_scope ().insert (
path, constant.get_node_id (), constant.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (constant.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
void visit (AST::Function &function) override
{
auto decl = CanonicalPath::new_seg (function.get_node_id (),
function.get_function_name ());
auto path = prefix.append (decl);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
void visit (AST::Method &method) override
{
auto decl = CanonicalPath::new_seg (method.get_node_id (),
method.get_method_name ());
auto path = prefix.append (decl);
resolver->get_name_scope ().insert (
path, method.get_node_id (), method.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (method.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
private:
ResolveToplevelImplItem (const CanonicalPath &prefix)
: ResolverBase (), prefix (prefix)
{
rust_assert (!prefix.is_empty ());
}
const CanonicalPath &prefix;
};
class ResolveTopLevelTraitItems : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::TraitItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
ResolveTopLevelTraitItems resolver (prefix, canonical_prefix);
item->accept_vis (resolver);
};
void visit (AST::TraitItemFunc &function) override
{
auto decl = CanonicalPath::new_seg (
function.get_node_id (),
function.get_trait_function_decl ().get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (function.get_node_id (), cpath);
}
void visit (AST::TraitItemMethod &method) override
{
auto decl = CanonicalPath::new_seg (
method.get_node_id (), method.get_trait_method_decl ().get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, method.get_node_id (), method.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (method.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (method.get_node_id (), cpath);
}
void visit (AST::TraitItemConst &constant) override
{
auto decl = CanonicalPath::new_seg (constant.get_node_id (),
constant.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, constant.get_node_id (), constant.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (constant.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (constant.get_node_id (), cpath);
}
void visit (AST::TraitItemType &type) override
{
auto decl
= CanonicalPath::new_seg (type.get_node_id (), type.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, type.get_node_id (), type.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (type.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (type.get_node_id (), cpath);
}
private:
ResolveTopLevelTraitItems (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
class ResolveToplevelExternItem : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::ExternalItem *item, const CanonicalPath &prefix)
{
ResolveToplevelExternItem resolver (prefix);
item->accept_vis (resolver);
};
void visit (AST::ExternalFunctionItem &function) override
{
auto decl = CanonicalPath::new_seg (function.get_node_id (),
function.get_identifier ());
auto path = prefix.append (decl);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
}
void visit (AST::ExternalStaticItem &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
resolver->get_name_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
}
private:
ResolveToplevelExternItem (const CanonicalPath &prefix)
: ResolverBase (), prefix (prefix)
{}
const CanonicalPath &prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_IMPLITEM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,149 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_ITEM_H
#define RUST_AST_RESOLVE_ITEM_H
#include "rust-ast-full-decls.h"
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
#include "rust-ast-resolve-toplevel.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-pattern.h"
#include "rust-ast-resolve-stmt.h"
#include "config.h"
namespace Rust {
namespace Resolver {
class ResolveTraitItems : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::TraitItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::TraitItemType &type) override;
void visit (AST::TraitItemFunc &func) override;
void visit (AST::TraitItemMethod &func) override;
void visit (AST::TraitItemConst &constant) override;
private:
ResolveTraitItems (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
class ResolveItem : public ResolverBase
{
public:
using Rust::Resolver::ResolverBase::visit;
static void go (AST::Item *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::TypeAlias &alias) override;
void visit (AST::Module &module) override;
void visit (AST::TupleStruct &struct_decl) override;
void visit (AST::Enum &enum_decl) override;
/* EnumItem doesn't need to be handled, no fields. */
void visit (AST::EnumItem &item) override;
void visit (AST::EnumItemTuple &item) override;
void visit (AST::EnumItemStruct &item) override;
void visit (AST::EnumItemDiscriminant &item) override;
void visit (AST::StructStruct &struct_decl) override;
void visit (AST::Union &union_decl) override;
void visit (AST::StaticItem &var) override;
void visit (AST::ConstantItem &constant) override;
void visit (AST::Function &function) override;
void visit (AST::InherentImpl &impl_block) override;
void visit (AST::Method &method) override;
void visit (AST::TraitImpl &impl_block) override;
void visit (AST::Trait &trait) override;
void visit (AST::ExternBlock &extern_block) override;
void visit (AST::UseDeclaration &) override;
protected:
void resolve_impl_item (AST::TraitImplItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void resolve_impl_item (AST::InherentImplItem *item,
const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void resolve_extern_item (AST::ExternalItem *item);
ResolveItem (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
class ResolveImplItems : public ResolveItem
{
using Rust::Resolver::ResolveItem::visit;
public:
static void go (AST::InherentImplItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
static void go (AST::TraitImplItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::TypeAlias &alias) override;
private:
ResolveImplItems (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
};
class ResolveExternItem : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::ExternalItem *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::ExternalFunctionItem &function) override;
void visit (AST::ExternalStaticItem &item) override;
private:
ResolveExternItem (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#if CHECKING_P
namespace selftest {
extern void
rust_simple_path_resolve_test (void);
} // namespace selftest
#endif // CHECKING_P
#endif // RUST_AST_RESOLVE_ITEM_H

View File

@@ -0,0 +1,384 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-path.h"
#include "rust-ast-resolve-type.h"
#include "rust-path.h"
namespace Rust {
namespace Resolver {
ResolvePath::ResolvePath () : ResolverBase () {}
void
ResolvePath::go (AST::PathInExpression *expr)
{
ResolvePath resolver;
resolver.resolve_path (expr);
}
void
ResolvePath::go (AST::QualifiedPathInExpression *expr)
{
ResolvePath resolver;
resolver.resolve_path (expr);
}
void
ResolvePath::go (AST::SimplePath *expr)
{
ResolvePath resolver;
resolver.resolve_path (expr);
}
void
ResolvePath::resolve_path (AST::PathInExpression *expr)
{
NodeId resolved_node_id = UNKNOWN_NODEID;
NodeId module_scope_id = resolver->peek_current_module_scope ();
NodeId previous_resolved_node_id = module_scope_id;
for (size_t i = 0; i < expr->get_segments ().size (); i++)
{
auto &segment = expr->get_segments ().at (i);
const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
bool is_first_segment = i == 0;
resolved_node_id = UNKNOWN_NODEID;
bool in_middle_of_path = i > 0;
if (in_middle_of_path && segment.is_lower_self_seg ())
{
// error[E0433]: failed to resolve: `self` in paths can only be used
// in start position
rust_error_at (segment.get_locus (),
"failed to resolve: %<%s%> in paths can only be used "
"in start position",
segment.as_string ().c_str ());
return;
}
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
if (segment.is_crate_path_seg ())
{
// what is the current crate scope node id?
module_scope_id = crate_scope_id;
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
}
else if (segment.is_super_path_seg ())
{
if (module_scope_id == crate_scope_id)
{
rust_error_at (segment.get_locus (),
"cannot use %<super%> at the crate scope");
return;
}
module_scope_id = resolver->peek_parent_module_scope ();
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
}
// resolve any generic args
if (segment.has_generic_args ())
ResolveGenericArgs::go (segment.get_generic_args ());
// logic is awkward here there are a few cases
//
// T::Default
// mod::foo::impl_item
// super::super::module::item
// self
// self::foo
// self::foo::baz
//
// T::Default we can only resolve the T and cant do anything about Default
// its dependant on associated types
//
// mod::foo::impl_item
// we can resolve mod::foo but nothing about impl_item but we need to
// _always resolve generic arguments
//
// self is a simple single lookup
//
// we have module_scope_id for the next module_scope to lookup
// resolved_node_id is the thing we have resolve this segment to
//
// new algo?
// we can only use module resolution when the previous segment is either
// unknown or equal to this module_scope_id
//
// can only use old resolution when previous segment is unkown
if (is_first_segment)
{
// name scope first
NodeId resolved_node = UNKNOWN_NODEID;
const CanonicalPath path
= CanonicalPath::new_seg (segment.get_node_id (),
ident_seg.as_string ());
if (resolver->get_name_scope ().lookup (path, &resolved_node))
{
resolver->insert_resolved_name (segment.get_node_id (),
resolved_node);
resolved_node_id = resolved_node;
}
// check the type scope
else if (resolver->get_type_scope ().lookup (path, &resolved_node))
{
resolver->insert_resolved_type (segment.get_node_id (),
resolved_node);
resolved_node_id = resolved_node;
}
else if (segment.is_lower_self_seg ())
{
module_scope_id = crate_scope_id;
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
}
else
{
// no error handling here since we might be able to resolve via
// the module hierarchy and handle errors at the end
}
}
if (resolved_node_id == UNKNOWN_NODEID
&& previous_resolved_node_id == module_scope_id)
{
Optional<CanonicalPath &> resolved_child
= mappings->lookup_module_child (module_scope_id,
ident_seg.as_string ());
if (resolved_child.is_some ())
{
NodeId resolved_node = resolved_child->get_node_id ();
if (resolver->get_name_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_name (segment.get_node_id (),
resolved_node);
}
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_type (segment.get_node_id (),
resolved_node);
}
else
{
rust_error_at (segment.get_locus (),
"Cannot find path %<%s%> in this scope",
segment.as_string ().c_str ());
return;
}
}
}
bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
if (did_resolve_segment)
{
if (mappings->node_is_module (resolved_node_id)
|| mappings->node_is_crate (resolved_node_id))
{
module_scope_id = resolved_node_id;
}
previous_resolved_node_id = resolved_node_id;
}
else if (is_first_segment)
{
rust_error_at (segment.get_locus (),
"Cannot find path %<%s%> in this scope",
segment.as_string ().c_str ());
return;
}
}
resolved_node = resolved_node_id;
if (resolved_node_id != UNKNOWN_NODEID)
{
// name scope first
if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
{
resolver->insert_resolved_name (expr->get_node_id (),
resolved_node_id);
}
// check the type scope
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node_id))
{
resolver->insert_resolved_type (expr->get_node_id (),
resolved_node_id);
}
else
{
gcc_unreachable ();
}
}
}
void
ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr)
{
AST::QualifiedPathType &root_segment = expr->get_qualified_path_type ();
ResolveType::go (root_segment.get_type ().get ());
if (root_segment.has_as_clause ())
ResolveType::go (&root_segment.get_as_type_path ());
for (auto &segment : expr->get_segments ())
{
// we cant actually do anything with the segment itself since this is all
// the job of the type system to figure it out but we can resolve any
// generic arguments used
if (segment.has_generic_args ())
ResolveGenericArgs::go (segment.get_generic_args ());
}
}
void
ResolvePath::resolve_path (AST::SimplePath *expr)
{
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
NodeId module_scope_id = resolver->peek_current_module_scope ();
NodeId resolved_node_id = UNKNOWN_NODEID;
for (size_t i = 0; i < expr->get_segments ().size (); i++)
{
auto &segment = expr->get_segments ().at (i);
bool is_first_segment = i == 0;
resolved_node_id = UNKNOWN_NODEID;
if (segment.is_crate_path_seg ())
{
// what is the current crate scope node id?
module_scope_id = crate_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
}
else if (segment.is_super_path_seg ())
{
if (module_scope_id == crate_scope_id)
{
rust_error_at (segment.get_locus (),
"cannot use %<super%> at the crate scope");
return;
}
module_scope_id = resolver->peek_parent_module_scope ();
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
}
Optional<CanonicalPath &> resolved_child
= mappings->lookup_module_child (module_scope_id,
segment.get_segment_name ());
if (resolved_child.is_some ())
{
NodeId resolved_node = resolved_child->get_node_id ();
if (resolver->get_name_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_name (segment.get_node_id (),
resolved_node);
}
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_type (segment.get_node_id (),
resolved_node);
}
else
{
rust_error_at (segment.get_locus (),
"Cannot find path %<%s%> in this scope",
segment.as_string ().c_str ());
return;
}
}
if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
{
// name scope first
NodeId resolved_node = UNKNOWN_NODEID;
const CanonicalPath path
= CanonicalPath::new_seg (segment.get_node_id (),
segment.get_segment_name ());
if (resolver->get_name_scope ().lookup (path, &resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_name (segment.get_node_id (),
resolved_node);
}
// check the type scope
else if (resolver->get_type_scope ().lookup (path, &resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_type (segment.get_node_id (),
resolved_node);
}
}
if (resolved_node_id == UNKNOWN_NODEID)
{
rust_error_at (segment.get_locus (),
"cannot find simple path segment %<%s%> in this scope",
segment.as_string ().c_str ());
return;
}
if (mappings->node_is_module (resolved_node_id))
{
module_scope_id = resolved_node_id;
}
}
resolved_node = resolved_node_id;
if (resolved_node_id != UNKNOWN_NODEID)
{
// name scope first
if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
{
resolver->insert_resolved_name (expr->get_node_id (),
resolved_node_id);
}
// check the type scope
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node_id))
{
resolver->insert_resolved_type (expr->get_node_id (),
resolved_node_id);
}
else
{
gcc_unreachable ();
}
}
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,52 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_PATH_H
#define RUST_AST_RESOLVE_PATH_H
#include "rust-ast-resolve-base.h"
namespace Rust {
namespace Resolver {
class ResolvePath : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::PathInExpression *expr);
static void go (AST::QualifiedPathInExpression *expr);
static void go (AST::SimplePath *expr);
private:
ResolvePath ();
void resolve_path (AST::PathInExpression *expr);
void resolve_path (AST::QualifiedPathInExpression *expr);
void resolve_path (AST::SimplePath *expr);
void
resolve_simple_path_segments (CanonicalPath prefix, size_t offs,
const std::vector<AST::SimplePathSegment> &segs,
NodeId expr_node_id, Location expr_locus);
};
} // namespace Resolver
} // namespace Rust
#endif // !RUST_AST_RESOLVE_PATH_H

View File

@@ -0,0 +1,163 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-pattern.h"
#include "rust-ast-resolve-path.h"
#include "rust-ast-resolve-expr.h"
namespace Rust {
namespace Resolver {
void
PatternDeclaration::visit (AST::PathInExpression &pattern)
{
ResolvePath::go (&pattern);
}
void
PatternDeclaration::visit (AST::TupleStructPattern &pattern)
{
ResolvePath::go (&pattern.get_path ());
std::unique_ptr<AST::TupleStructItems> &items = pattern.get_items ();
switch (items->get_item_type ())
{
case AST::TupleStructItems::RANGE: {
// TODO
gcc_unreachable ();
}
break;
case AST::TupleStructItems::NO_RANGE: {
AST::TupleStructItemsNoRange &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (*items.get ());
for (auto &inner_pattern : items_no_range.get_patterns ())
{
PatternDeclaration::go (inner_pattern.get ());
}
}
break;
}
}
void
PatternDeclaration::visit (AST::StructPattern &pattern)
{
ResolvePath::go (&pattern.get_path ());
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
{
switch (field->get_item_type ())
{
case AST::StructPatternField::ItemType::TUPLE_PAT: {
// TODO
gcc_unreachable ();
}
break;
case AST::StructPatternField::ItemType::IDENT_PAT: {
// TODO
gcc_unreachable ();
}
break;
case AST::StructPatternField::ItemType::IDENT: {
AST::StructPatternFieldIdent &ident
= static_cast<AST::StructPatternFieldIdent &> (*field.get ());
resolver->get_name_scope ().insert (
CanonicalPath::new_seg (ident.get_node_id (),
ident.get_identifier ()),
ident.get_node_id (), ident.get_locus ());
}
break;
}
}
// TODO
rust_assert (!struct_pattern_elems.has_etc ());
}
void
PatternDeclaration::visit (AST::TuplePattern &pattern)
{
std::unique_ptr<AST::TuplePatternItems> &items = pattern.get_items ();
switch (items->get_pattern_type ())
{
case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
AST::TuplePatternItemsMultiple &ref
= *static_cast<AST::TuplePatternItemsMultiple *> (
pattern.get_items ().get ());
for (auto &p : ref.get_patterns ())
p->accept_vis (*this);
}
break;
case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
AST::TuplePatternItemsRanged &ref
= *static_cast<AST::TuplePatternItemsRanged *> (
pattern.get_items ().get ());
for (auto &p : ref.get_lower_patterns ())
p->accept_vis (*this);
for (auto &p : ref.get_upper_patterns ())
p->accept_vis (*this);
}
break;
}
}
static void
resolve_range_pattern_bound (AST::RangePatternBound *bound)
{
switch (bound->get_bound_type ())
{
case AST::RangePatternBound::RangePatternBoundType::LITERAL:
// Nothing to resolve for a literal.
break;
case AST::RangePatternBound::RangePatternBoundType::PATH: {
AST::RangePatternBoundPath &ref
= *static_cast<AST::RangePatternBoundPath *> (bound);
ResolvePath::go (&ref.get_path ());
}
break;
case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
AST::RangePatternBoundQualPath &ref
= *static_cast<AST::RangePatternBoundQualPath *> (bound);
ResolvePath::go (&ref.get_qualified_path ());
}
break;
}
}
void
PatternDeclaration::visit (AST::RangePattern &pattern)
{
resolve_range_pattern_bound (pattern.get_upper_bound ().get ());
resolve_range_pattern_bound (pattern.get_lower_bound ().get ());
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,98 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_PATTERN_H
#define RUST_AST_RESOLVE_PATTERN_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
class ResolvePattern : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Pattern *pattern)
{
ResolvePattern resolver;
pattern->accept_vis (resolver);
}
void visit (AST::IdentifierPattern &pattern) override
{
if (resolver->get_name_scope ().lookup (
CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()),
&resolved_node))
{
resolver->insert_resolved_name (pattern.get_node_id (), resolved_node);
}
}
private:
ResolvePattern () : ResolverBase () {}
};
class PatternDeclaration : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Pattern *pattern)
{
PatternDeclaration resolver;
pattern->accept_vis (resolver);
};
void visit (AST::IdentifierPattern &pattern) override
{
// if we have a duplicate id this then allows for shadowing correctly
// as new refs to this decl will match back here so it is ok to overwrite
resolver->get_name_scope ().insert (
CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()),
pattern.get_node_id (), pattern.get_locus ());
}
void visit (AST::WildcardPattern &pattern) override
{
resolver->get_name_scope ().insert (
CanonicalPath::new_seg (pattern.get_node_id (), "_"),
pattern.get_node_id (), pattern.get_locus ());
}
// cases in a match expression
void visit (AST::PathInExpression &pattern) override;
void visit (AST::StructPattern &pattern) override;
void visit (AST::TupleStructPattern &pattern) override;
void visit (AST::TuplePattern &pattern) override;
void visit (AST::RangePattern &pattern) override;
private:
PatternDeclaration () : ResolverBase () {}
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_PATTERN_H

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-item.h"
#include "rust-ast-resolve-stmt.h"
namespace Rust {
namespace Resolver {
void
ResolveStmt::visit (AST::ExternBlock &extern_block)
{
resolve_visibility (extern_block.get_visibility ());
for (auto &item : extern_block.get_extern_items ())
{
ResolveToplevelExternItem::go (item.get (),
CanonicalPath::create_empty ());
ResolveExternItem::go (item.get (), prefix, canonical_prefix);
}
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,378 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_STMT_H
#define RUST_AST_RESOLVE_STMT_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-pattern.h"
#include "rust-ast-resolve-expr.h"
namespace Rust {
namespace Resolver {
class ResolveStmt : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Stmt *stmt, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix,
const CanonicalPath &enum_prefix)
{
if (stmt->is_marked_for_strip ())
return;
ResolveStmt resolver (prefix, canonical_prefix, enum_prefix);
stmt->accept_vis (resolver);
}
void visit (AST::ExprStmtWithBlock &stmt) override
{
ResolveExpr::go (stmt.get_expr ().get (), prefix, canonical_prefix);
}
void visit (AST::ExprStmtWithoutBlock &stmt) override
{
ResolveExpr::go (stmt.get_expr ().get (), prefix, canonical_prefix);
}
void visit (AST::ConstantItem &constant) override
{
auto decl = CanonicalPath::new_seg (constant.get_node_id (),
constant.get_identifier ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (constant.get_node_id (), cpath);
resolver->get_name_scope ().insert (
path, constant.get_node_id (), constant.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (constant.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
ResolveType::go (constant.get_type ().get ());
ResolveExpr::go (constant.get_expr ().get (), prefix, canonical_prefix);
}
void visit (AST::LetStmt &stmt) override
{
if (stmt.has_init_expr ())
{
ResolveExpr::go (stmt.get_init_expr ().get (), prefix,
canonical_prefix);
}
PatternDeclaration::go (stmt.get_pattern ().get ());
if (stmt.has_type ())
ResolveType::go (stmt.get_type ().get ());
}
void visit (AST::TupleStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId scope_node_id = struct_decl.get_node_id ();
resolver->get_type_scope ().push (scope_node_id);
if (struct_decl.has_generics ())
{
for (auto &generic : struct_decl.get_generic_params ())
ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
}
for (AST::TupleField &field : struct_decl.get_fields ())
ResolveType::go (field.get_field_type ().get ());
resolver->get_type_scope ().pop ();
}
void visit (AST::Enum &enum_decl) override
{
auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
enum_decl.get_identifier ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (enum_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId scope_node_id = enum_decl.get_node_id ();
resolver->get_type_scope ().push (scope_node_id);
if (enum_decl.has_generics ())
{
for (auto &generic : enum_decl.get_generic_params ())
ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
}
for (auto &variant : enum_decl.get_variants ())
ResolveStmt::go (variant.get (), path, canonical_prefix, path);
resolver->get_type_scope ().pop ();
}
void visit (AST::EnumItem &item) override
{
auto decl = enum_prefix.append (
CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (item.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
// Done, no fields.
}
void visit (AST::EnumItemTuple &item) override
{
auto decl = enum_prefix.append (
CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (item.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &field : item.get_tuple_fields ())
{
if (field.get_field_type ()->is_marked_for_strip ())
continue;
ResolveType::go (field.get_field_type ().get ());
}
}
void visit (AST::EnumItemStruct &item) override
{
auto decl = enum_prefix.append (
CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (item.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &field : item.get_struct_fields ())
{
if (field.get_field_type ()->is_marked_for_strip ())
continue;
ResolveType::go (field.get_field_type ().get ());
}
}
void visit (AST::EnumItemDiscriminant &item) override
{
auto decl = enum_prefix.append (
CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (item.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
// Done, no fields.
}
void visit (AST::StructStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId scope_node_id = struct_decl.get_node_id ();
resolver->get_type_scope ().push (scope_node_id);
if (struct_decl.has_generics ())
{
for (auto &generic : struct_decl.get_generic_params ())
ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
}
for (AST::StructField &field : struct_decl.get_fields ())
{
if (field.get_field_type ()->is_marked_for_strip ())
continue;
ResolveType::go (field.get_field_type ().get ());
}
resolver->get_type_scope ().pop ();
}
void visit (AST::Union &union_decl) override
{
auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
union_decl.get_identifier ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
resolver->get_type_scope ().insert (
path, union_decl.get_node_id (), union_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (union_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId scope_node_id = union_decl.get_node_id ();
resolver->get_type_scope ().push (scope_node_id);
if (union_decl.has_generics ())
for (auto &generic : union_decl.get_generic_params ())
ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
for (AST::StructField &field : union_decl.get_variants ())
{
if (field.get_field_type ()->is_marked_for_strip ())
continue;
ResolveType::go (field.get_field_type ().get ());
}
resolver->get_type_scope ().pop ();
}
void visit (AST::Function &function) override
{
auto decl = CanonicalPath::new_seg (function.get_node_id (),
function.get_function_name ());
auto path = decl; // this ensures we have the correct relative resolution
auto cpath = canonical_prefix.append (decl);
mappings->insert_canonical_path (function.get_node_id (), cpath);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId scope_node_id = function.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
if (function.has_generics ())
for (auto &generic : function.get_generic_params ())
ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
if (function.has_return_type ())
ResolveType::go (function.get_return_type ().get ());
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto &param : function.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
PatternDeclaration::go (param.get_pattern ().get ());
}
// resolve the function body
ResolveExpr::go (function.get_definition ().get (), path, cpath);
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}
void visit (AST::ExternBlock &extern_block) override;
private:
ResolveStmt (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix,
const CanonicalPath &enum_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
enum_prefix (enum_prefix)
{}
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
/* item declaration statements are not given a canonical path, but enum items
* (variants) do inherit the enum path/identifier name. */
const CanonicalPath &enum_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_STMT_H

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-struct-expr-field.h"
#include "rust-ast-resolve-expr.h"
namespace Rust {
namespace Resolver {
void
ResolveStructExprField::go (AST::StructExprField *field,
const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
ResolveStructExprField resolver (prefix, canonical_prefix);
field->accept_vis (resolver);
}
ResolveStructExprField::ResolveStructExprField (
const CanonicalPath &prefix, const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
void
ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
{
ResolveExpr::go (field.get_value ().get (), prefix, canonical_prefix);
}
void
ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field)
{
ResolveExpr::go (field.get_value ().get (), prefix, canonical_prefix);
}
void
ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field)
{
AST::IdentifierExpr expr (field.get_field_name (), {}, field.get_locus ());
expr.set_node_id (field.get_node_id ());
ResolveExpr::go (&expr, prefix, canonical_prefix);
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,55 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
// this resolves values being assigned not that the field actually exists yet.
class ResolveStructExprField : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::StructExprField *field, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
void visit (AST::StructExprFieldIdentifierValue &field) override;
void visit (AST::StructExprFieldIndexValue &field) override;
void visit (AST::StructExprFieldIdentifier &field) override;
private:
ResolveStructExprField (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD

View File

@@ -0,0 +1,460 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_TOPLEVEL_H
#define RUST_AST_RESOLVE_TOPLEVEL_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-implitem.h"
#include "rust-ast-full.h"
#include "rust-name-resolver.h"
#include "rust-session-manager.h"
namespace Rust {
namespace Resolver {
class ResolveTopLevel : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Item *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
if (item->is_marked_for_strip ())
return;
ResolveTopLevel resolver (prefix, canonical_prefix);
item->accept_vis (resolver);
NodeId current_module = resolver.resolver->peek_current_module_scope ();
resolver.mappings->insert_child_item_to_parent_module_mapping (
item->get_node_id (), current_module);
}
void visit (AST::Module &module) override
{
auto mod
= CanonicalPath::new_seg (module.get_node_id (), module.get_name ());
auto path = prefix.append (mod);
auto cpath = canonical_prefix.append (mod);
resolver->get_name_scope ().insert (
path, module.get_node_id (), module.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (module.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, mod);
mappings->insert_module_child (current_module, module.get_node_id ());
resolver->push_new_module_scope (module.get_node_id ());
for (auto &item : module.get_items ())
ResolveTopLevel::go (item.get (), path, cpath);
resolver->pop_module_scope ();
mappings->insert_canonical_path (module.get_node_id (), cpath);
}
void visit (AST::TypeAlias &alias) override
{
auto talias = CanonicalPath::new_seg (alias.get_node_id (),
alias.get_new_type_name ());
auto path = prefix.append (talias);
auto cpath = canonical_prefix.append (talias);
resolver->get_type_scope ().insert (
path, alias.get_node_id (), alias.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (alias.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, talias);
mappings->insert_canonical_path (alias.get_node_id (), cpath);
}
void visit (AST::TupleStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
}
void visit (AST::Enum &enum_decl) override
{
auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
enum_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (enum_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &variant : enum_decl.get_variants ())
ResolveTopLevel::go (variant.get (), path, cpath);
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
}
void visit (AST::EnumItem &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemTuple &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemStruct &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemDiscriminant &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::StructStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
}
void visit (AST::Union &union_decl) override
{
auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
union_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, union_decl.get_node_id (), union_decl.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (union_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
}
void visit (AST::StaticItem &var) override
{
auto decl
= CanonicalPath::new_seg (var.get_node_id (), var.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, var.get_node_id (), var.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (var.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (var.get_node_id (), cpath);
}
void visit (AST::ConstantItem &constant) override
{
auto decl = CanonicalPath::new_seg (constant.get_node_id (),
constant.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, constant.get_node_id (), constant.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (constant.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (constant.get_node_id (), cpath);
}
void visit (AST::Function &function) override
{
auto decl = CanonicalPath::new_seg (function.get_node_id (),
function.get_function_name ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (function.get_node_id (), cpath);
}
void visit (AST::InherentImpl &impl_block) override
{
std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
CanonicalPath impl_type
= CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
raw_impl_type_path);
CanonicalPath impl_prefix = prefix.append (impl_type);
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
void visit (AST::TraitImpl &impl_block) override
{
std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
CanonicalPath impl_type_seg
= CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
raw_impl_type_path);
std::string raw_trait_type_path = impl_block.get_trait_path ().as_string ();
CanonicalPath trait_type_seg
= CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (),
raw_trait_type_path);
CanonicalPath projection
= CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
trait_type_seg,
impl_type_seg);
CanonicalPath impl_prefix = prefix.append (projection);
resolver->get_name_scope ().insert (
impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (impl_block.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
void visit (AST::Trait &trait) override
{
auto decl
= CanonicalPath::new_seg (trait.get_node_id (), trait.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, trait.get_node_id (), trait.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (trait.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &item : trait.get_trait_items ())
ResolveTopLevelTraitItems::go (item.get (), path, cpath);
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (trait.get_node_id (), cpath);
}
void visit (AST::ExternBlock &extern_block) override
{
for (auto &item : extern_block.get_extern_items ())
{
ResolveToplevelExternItem::go (item.get (), prefix);
}
}
void visit (AST::ExternCrate &extern_crate) override
{
if (extern_crate.is_marked_for_strip ())
return;
NodeId resolved_crate = UNKNOWN_NODEID;
if (extern_crate.references_self ())
{
CrateNum crate_num = mappings->get_current_crate ();
bool ok = mappings->crate_num_to_nodeid (crate_num, resolved_crate);
rust_assert (ok);
}
else
{
CrateNum found_crate_num = UNKNOWN_CREATENUM;
bool found
= mappings->lookup_crate_name (extern_crate.get_referenced_crate (),
found_crate_num);
if (!found)
{
rust_error_at (extern_crate.get_locus (), "unknown crate %<%s%>",
extern_crate.get_referenced_crate ().c_str ());
return;
}
bool ok
= mappings->crate_num_to_nodeid (found_crate_num, resolved_crate);
if (!ok)
{
rust_internal_error_at (extern_crate.get_locus (),
"failed to resolve crate to nodeid");
return;
}
}
if (resolved_crate == UNKNOWN_NODEID)
{
rust_error_at (extern_crate.get_locus (), "failed to resolve crate");
return;
}
// mark the node as resolved
resolver->insert_resolved_name (extern_crate.get_node_id (),
resolved_crate);
CanonicalPath decl
= extern_crate.has_as_clause ()
? CanonicalPath::new_seg (extern_crate.get_node_id (),
extern_crate.get_as_clause ())
: CanonicalPath::new_seg (extern_crate.get_node_id (),
extern_crate.get_referenced_crate ());
resolver->get_type_scope ().insert (
decl, resolved_crate, extern_crate.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (extern_crate.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
private:
ResolveTopLevel (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_TOPLEVEL_H

View File

@@ -0,0 +1,582 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-expr.h"
namespace Rust {
namespace Resolver {
// rust-ast-resolve-type.h
void
ResolveType::visit (AST::ArrayType &type)
{
type.get_elem_type ()->accept_vis (*this);
ResolveExpr::go (type.get_size_expr ().get (), CanonicalPath::create_empty (),
CanonicalPath::create_empty ());
}
void
ResolveType::visit (AST::TraitObjectTypeOneBound &type)
{
ResolveTypeBound::go (&type.get_trait_bound ());
}
void
ResolveType::visit (AST::TraitObjectType &type)
{
for (auto &bound : type.get_type_param_bounds ())
{
/* NodeId bound_resolved_id = */
ResolveTypeBound::go (bound.get ());
}
}
void
ResolveType::visit (AST::ReferenceType &type)
{
resolved_node = ResolveType::go (type.get_type_referenced ().get ());
}
void
ResolveType::visit (AST::RawPointerType &type)
{
resolved_node = ResolveType::go (type.get_type_pointed_to ().get ());
}
void
ResolveType::visit (AST::InferredType &type)
{
// FIXME
}
void
ResolveType::visit (AST::NeverType &type)
{
// FIXME
}
void
ResolveType::visit (AST::SliceType &type)
{
resolved_node = ResolveType::go (type.get_elem_type ().get ());
}
// resolve relative type-paths
bool
ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
{
auto resolver = Resolver::get ();
auto mappings = Analysis::Mappings::get ();
NodeId module_scope_id = resolver->peek_current_module_scope ();
NodeId previous_resolved_node_id = module_scope_id;
for (size_t i = 0; i < path.get_segments ().size (); i++)
{
auto &segment = path.get_segments ().at (i);
const AST::PathIdentSegment &ident_seg = segment->get_ident_segment ();
bool is_first_segment = i == 0;
resolved_node_id = UNKNOWN_NODEID;
bool in_middle_of_path = i > 0;
if (in_middle_of_path && segment->is_lower_self_seg ())
{
// error[E0433]: failed to resolve: `self` in paths can only be used
// in start position
rust_error_at (segment->get_locus (),
"failed to resolve: %<%s%> in paths can only be used "
"in start position",
segment->as_string ().c_str ());
return false;
}
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
if (segment->is_crate_path_seg ())
{
// what is the current crate scope node id?
module_scope_id = crate_scope_id;
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment->get_node_id (),
module_scope_id);
continue;
}
else if (segment->is_super_path_seg ())
{
if (module_scope_id == crate_scope_id)
{
rust_error_at (segment->get_locus (),
"cannot use super at the crate scope");
return false;
}
module_scope_id = resolver->peek_parent_module_scope ();
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment->get_node_id (),
module_scope_id);
continue;
}
switch (segment->get_type ())
{
case AST::TypePathSegment::SegmentType::GENERIC: {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
if (s->has_generic_args ())
ResolveGenericArgs::go (s->get_generic_args ());
}
break;
case AST::TypePathSegment::SegmentType::REG:
// nothing to do
break;
case AST::TypePathSegment::SegmentType::FUNCTION:
gcc_unreachable ();
break;
}
if (is_first_segment)
{
// name scope first
NodeId resolved_node = UNKNOWN_NODEID;
const CanonicalPath path
= CanonicalPath::new_seg (segment->get_node_id (),
ident_seg.as_string ());
if (resolver->get_type_scope ().lookup (path, &resolved_node))
{
resolver->insert_resolved_type (segment->get_node_id (),
resolved_node);
resolved_node_id = resolved_node;
}
else if (resolver->get_name_scope ().lookup (path, &resolved_node))
{
resolver->insert_resolved_name (segment->get_node_id (),
resolved_node);
resolved_node_id = resolved_node;
}
else if (segment->is_lower_self_seg ())
{
// what is the current crate scope node id?
module_scope_id = crate_scope_id;
previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment->get_node_id (),
module_scope_id);
continue;
}
}
if (resolved_node_id == UNKNOWN_NODEID
&& previous_resolved_node_id == module_scope_id)
{
Optional<CanonicalPath &> resolved_child
= mappings->lookup_module_child (module_scope_id,
ident_seg.as_string ());
if (resolved_child.is_some ())
{
NodeId resolved_node = resolved_child->get_node_id ();
if (resolver->get_name_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_name (segment->get_node_id (),
resolved_node);
}
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node))
{
resolved_node_id = resolved_node;
resolver->insert_resolved_type (segment->get_node_id (),
resolved_node);
}
else
{
rust_error_at (segment->get_locus (),
"Cannot find path %<%s%> in this scope",
segment->as_string ().c_str ());
return false;
}
}
}
bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
if (did_resolve_segment)
{
if (mappings->node_is_module (resolved_node_id)
|| mappings->node_is_crate (resolved_node_id))
{
module_scope_id = resolved_node_id;
}
previous_resolved_node_id = resolved_node_id;
}
else if (is_first_segment)
{
rust_error_at (segment->get_locus (),
"failed to resolve TypePath: %s in this scope",
segment->as_string ().c_str ());
return false;
}
}
if (resolved_node_id != UNKNOWN_NODEID)
{
// name scope first
if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
{
resolver->insert_resolved_name (path.get_node_id (),
resolved_node_id);
}
// check the type scope
else if (resolver->get_type_scope ().decl_was_declared_here (
resolved_node_id))
{
resolver->insert_resolved_type (path.get_node_id (),
resolved_node_id);
}
else
{
gcc_unreachable ();
}
}
return true;
}
// qualified type paths
ResolveRelativeQualTypePath::ResolveRelativeQualTypePath ()
: failure_flag (false)
{}
bool
ResolveRelativeQualTypePath::go (AST::QualifiedPathInType &path)
{
ResolveRelativeQualTypePath o;
// resolve the type and trait path
auto &qualified_path = path.get_qualified_path_type ();
if (!o.resolve_qual_seg (qualified_path))
return false;
// qualified types are similar to other paths in that we cannot guarantee
// that we can resolve the path at name resolution. We must look up
// associated types and type information to figure this out properly
std::unique_ptr<AST::TypePathSegment> &associated
= path.get_associated_segment ();
associated->accept_vis (o);
if (o.failure_flag)
return false;
for (auto &seg : path.get_segments ())
{
seg->accept_vis (o);
if (o.failure_flag)
return false;
}
return true;
}
bool
ResolveRelativeQualTypePath::resolve_qual_seg (AST::QualifiedPathType &seg)
{
if (seg.is_error ())
{
rust_error_at (seg.get_locus (), "segment has error: %s",
seg.as_string ().c_str ());
return false;
}
auto type = seg.get_type ().get ();
NodeId type_resolved_node = ResolveType::go (type);
if (type_resolved_node == UNKNOWN_NODEID)
return false;
if (!seg.has_as_clause ())
return true;
NodeId trait_resolved_node = ResolveType::go (&seg.get_as_type_path ());
if (trait_resolved_node == UNKNOWN_NODEID)
return false;
return true;
}
void
ResolveRelativeQualTypePath::visit (AST::TypePathSegmentGeneric &seg)
{
if (seg.is_error ())
{
failure_flag = true;
rust_error_at (seg.get_locus (), "segment has error: %s",
seg.as_string ().c_str ());
return;
}
ResolveGenericArgs::go (seg.get_generic_args ());
}
void
ResolveRelativeQualTypePath::visit (AST::TypePathSegment &seg)
{
if (seg.is_error ())
{
failure_flag = true;
rust_error_at (seg.get_locus (), "segment has error: %s",
seg.as_string ().c_str ());
return;
}
}
// resolve to canonical path
bool
ResolveTypeToCanonicalPath::go (AST::Type *type, CanonicalPath &result)
{
ResolveTypeToCanonicalPath resolver;
type->accept_vis (resolver);
result = resolver.result;
return !resolver.result.is_empty ();
}
void
ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
{
NodeId resolved_node = UNKNOWN_NODEID;
if (!resolver->lookup_resolved_name (path.get_node_id (), &resolved_node))
{
resolver->lookup_resolved_type (path.get_node_id (), &resolved_node);
}
if (resolved_node == UNKNOWN_NODEID)
return;
const CanonicalPath *type_path = nullptr;
if (mappings->lookup_canonical_path (resolved_node, &type_path))
{
auto &final_seg = path.get_segments ().back ();
switch (final_seg->get_type ())
{
case AST::TypePathSegment::SegmentType::GENERIC: {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
std::vector<CanonicalPath> args;
if (s->has_generic_args ())
{
ResolveGenericArgs::go (s->get_generic_args ());
for (auto &generic : s->get_generic_args ().get_generic_args ())
{
// FIXME: What do we want to do here in case there is a
// constant or an ambiguous const generic?
// TODO: At that point, will all generics have been
// disambiguated? Can we thus canonical resolve types and
// const and `gcc_unreachable` on ambiguous types?
// This is probably fine as we just want to canonicalize
// types, right?
if (generic.get_kind () == AST::GenericArg::Kind::Type)
{
CanonicalPath arg = CanonicalPath::create_empty ();
bool ok = ResolveTypeToCanonicalPath::go (
generic.get_type ().get (), arg);
if (ok)
args.push_back (std::move (arg));
}
}
}
result = *type_path;
if (!args.empty ())
{
// append this onto the path
std::string buf;
for (size_t i = 0; i < args.size (); i++)
{
bool has_next = (i + 1) < args.size ();
const auto &arg = args.at (i);
buf += arg.get ();
if (has_next)
buf += ", ";
}
std::string arg_seg = "<" + buf + ">";
CanonicalPath argument_seg
= CanonicalPath::new_seg (s->get_node_id (), arg_seg);
result = result.append (argument_seg);
}
}
break;
default:
result = *type_path;
break;
}
}
}
void
ResolveTypeToCanonicalPath::visit (AST::ReferenceType &type)
{
CanonicalPath path = CanonicalPath::create_empty ();
bool ok
= ResolveTypeToCanonicalPath::go (type.get_type_referenced ().get (), path);
if (ok)
{
std::string ref_type_str = type.is_mut () ? "mut" : "";
std::string ref_path = "&" + ref_type_str + " " + path.get ();
result = CanonicalPath::new_seg (type.get_node_id (), ref_path);
}
}
void
ResolveTypeToCanonicalPath::visit (AST::RawPointerType &type)
{
CanonicalPath path = CanonicalPath::create_empty ();
bool ok
= ResolveTypeToCanonicalPath::go (type.get_type_pointed_to ().get (), path);
if (ok)
{
std::string ptr_type_str
= type.get_pointer_type () == AST::RawPointerType::CONST ? "const"
: "mut";
std::string ptr_path = "*" + ptr_type_str + " " + path.get ();
result = CanonicalPath::new_seg (type.get_node_id (), ptr_path);
}
}
void
ResolveTypeToCanonicalPath::visit (AST::SliceType &type)
{
CanonicalPath path = CanonicalPath::create_empty ();
bool ok = ResolveTypeToCanonicalPath::go (type.get_elem_type ().get (), path);
if (ok)
{
std::string slice_path = "[" + path.get () + "]";
result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
}
}
void
ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type)
{
CanonicalPath path = CanonicalPath::create_empty ();
bool ok
= ResolveTypeToCanonicalPath::go (&type.get_trait_bound ().get_type_path (),
path);
if (ok)
{
std::string slice_path = "<dyn " + path.get () + ">";
result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
}
}
void
ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
{
// FIXME is this actually allowed? dyn A+B
gcc_unreachable ();
}
ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath ()
: ResolverBase (), result (CanonicalPath::create_empty ())
{}
bool
ResolveGenericArgs::is_const_value_name (const CanonicalPath &path)
{
NodeId resolved;
auto found = resolver->get_name_scope ().lookup (path, &resolved);
return found;
}
bool
ResolveGenericArgs::is_type_name (const CanonicalPath &path)
{
NodeId resolved;
auto found = resolver->get_type_scope ().lookup (path, &resolved);
return found;
}
void
ResolveGenericArgs::disambiguate (AST::GenericArg &arg)
{
auto path = canonical_prefix.append (
CanonicalPath::new_seg (UNKNOWN_NODEID, arg.get_path ()));
auto is_type = is_type_name (path);
auto is_value = is_const_value_name (path);
// In case we cannot find anything, we resolve the ambiguity to a type.
// This causes the typechecker to error out properly and when necessary.
// But types also take priority over const values in the case of
// ambiguities, hence the weird control flow
if (is_type || (!is_type && !is_value))
arg = arg.disambiguate_to_type ();
else if (is_value)
arg = arg.disambiguate_to_const ();
}
void
ResolveGenericArgs::resolve_disambiguated_generic (AST::GenericArg &arg)
{
switch (arg.get_kind ())
{
case AST::GenericArg::Kind::Const:
ResolveExpr::go (arg.get_expression ().get (), prefix, canonical_prefix);
break;
case AST::GenericArg::Kind::Type:
ResolveType::go (arg.get_type ().get ());
break;
default:
gcc_unreachable ();
}
}
void
ResolveGenericArgs::go (AST::GenericArgs &generic_args)
{
auto empty = CanonicalPath::create_empty ();
go (generic_args, empty, empty);
}
void
ResolveGenericArgs::go (AST::GenericArgs &generic_args,
const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
auto resolver = ResolveGenericArgs (prefix, canonical_prefix);
for (auto &arg : generic_args.get_generic_args ())
{
if (arg.get_kind () == AST::GenericArg::Kind::Either)
resolver.disambiguate (arg);
resolver.resolve_disambiguated_generic (arg);
}
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,290 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_TYPE_H
#define RUST_AST_RESOLVE_TYPE_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-resolve-expr.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
class ResolveRelativeTypePath
{
public:
static bool go (AST::TypePath &path, NodeId &resolved_node_id);
};
class ResolveRelativeQualTypePath : public ResolverBase
{
using ResolverBase::visit;
public:
static bool go (AST::QualifiedPathInType &path);
void visit (AST::TypePathSegmentGeneric &seg) override;
void visit (AST::TypePathSegment &seg) override;
protected:
bool resolve_qual_seg (AST::QualifiedPathType &seg);
private:
ResolveRelativeQualTypePath ();
bool failure_flag;
};
class ResolveType : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static NodeId go (AST::Type *type)
{
ResolveType resolver;
type->accept_vis (resolver);
return resolver.resolved_node;
}
void visit (AST::BareFunctionType &fntype) override
{
for (auto &param : fntype.get_function_params ())
ResolveType::go (param.get_type ().get ());
if (fntype.has_return_type ())
ResolveType::go (fntype.get_return_type ().get ());
}
void visit (AST::TupleType &tuple) override
{
if (tuple.is_unit_type ())
{
resolved_node = resolver->get_unit_type_node_id ();
return;
}
for (auto &elem : tuple.get_elems ())
ResolveType::go (elem.get ());
}
void visit (AST::TypePath &path) override
{
ResolveRelativeTypePath::go (path, resolved_node);
}
void visit (AST::QualifiedPathInType &path) override
{
ResolveRelativeQualTypePath::go (path);
}
void visit (AST::ArrayType &type) override;
void visit (AST::ReferenceType &type) override;
void visit (AST::InferredType &type) override;
void visit (AST::NeverType &type) override;
void visit (AST::RawPointerType &type) override;
void visit (AST::TraitObjectTypeOneBound &type) override;
void visit (AST::TraitObjectType &type) override;
void visit (AST::SliceType &type) override;
private:
ResolveType () : ResolverBase () {}
};
class ResolveTypeBound : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static NodeId go (AST::TypeParamBound *type)
{
ResolveTypeBound resolver;
type->accept_vis (resolver);
return resolver.resolved_node;
};
void visit (AST::TraitBound &bound) override
{
resolved_node = ResolveType::go (&bound.get_type_path ());
}
private:
ResolveTypeBound () : ResolverBase () {}
};
class ResolveGenericParam : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static NodeId go (AST::GenericParam *param, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
ResolveGenericParam resolver (prefix, canonical_prefix);
param->accept_vis (resolver);
return resolver.resolved_node;
}
void visit (AST::ConstGenericParam &param) override
{
ResolveType::go (param.get_type ().get ());
if (param.has_default_value ())
ResolveExpr::go (param.get_default_value ().get_expression ().get (),
prefix, canonical_prefix);
ok = true;
}
void visit (AST::TypeParam &param) override
{
// if it has a type lets resolve it
if (param.has_type ())
ResolveType::go (param.get_type ().get ());
if (param.has_type_param_bounds ())
{
for (auto &bound : param.get_type_param_bounds ())
{
ResolveTypeBound::go (bound.get ());
}
}
auto seg = CanonicalPath::new_seg (param.get_node_id (),
param.get_type_representation ());
resolver->get_type_scope ().insert (
seg, param.get_node_id (), param.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
rust_error_at (param.get_locus (),
"generic param redefined multiple times");
rust_error_at (locus, "was defined here");
});
mappings->insert_canonical_path (param.get_node_id (), seg);
}
private:
ResolveGenericParam (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), ok (false), prefix (prefix),
canonical_prefix (canonical_prefix)
{}
bool ok;
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
class ResolveWhereClause : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void Resolve (AST::WhereClause &where_clause)
{
ResolveWhereClause r;
for (auto &clause : where_clause.get_items ())
clause->accept_vis (r);
}
void visit (AST::TypeBoundWhereClauseItem &item) override
{
ResolveType::go (item.get_type ().get ());
if (item.has_type_param_bounds ())
{
for (auto &bound : item.get_type_param_bounds ())
{
ResolveTypeBound::go (bound.get ());
}
}
}
private:
ResolveWhereClause () : ResolverBase () {}
};
class ResolveTypeToCanonicalPath : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static bool go (AST::Type *type, CanonicalPath &result);
void visit (AST::TypePath &path) override;
void visit (AST::ReferenceType &type) override;
void visit (AST::RawPointerType &type) override;
void visit (AST::SliceType &type) override;
void visit (AST::TraitObjectTypeOneBound &type) override;
void visit (AST::TraitObjectType &type) override;
private:
ResolveTypeToCanonicalPath ();
CanonicalPath result;
};
class ResolveGenericArgs : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::GenericArgs &generic_args);
static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix);
private:
ResolveGenericArgs (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
bool is_type_name (const CanonicalPath &path);
bool is_const_value_name (const CanonicalPath &path);
/**
* Resolve a disambiguated generic arg
*/
void disambiguate (AST::GenericArg &arg);
/**
* Resolve a disambiguated generic arg
*/
void resolve_disambiguated_generic (AST::GenericArg &arg);
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_TYPE_H

View File

@@ -0,0 +1,115 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-ast-resolve.h"
#include "rust-ast-full.h"
#include "rust-tyty.h"
#include "rust-ast-resolve-toplevel.h"
#include "rust-ast-resolve-item.h"
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-struct-expr-field.h"
extern bool
saw_errors (void);
namespace Rust {
namespace Resolver {
// NameResolution
NameResolution *
NameResolution::get ()
{
static NameResolution *instance;
if (instance == nullptr)
instance = new NameResolution ();
return instance;
}
NameResolution::NameResolution ()
: resolver (Resolver::get ()), mappings (Analysis::Mappings::get ())
{
// these are global
resolver->get_type_scope ().push (mappings->get_next_node_id ());
resolver->insert_builtin_types (resolver->get_type_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
}
void
NameResolution::Resolve (AST::Crate &crate)
{
auto resolver = get ();
resolver->go (crate);
}
void
NameResolution::go (AST::Crate &crate)
{
// lookup current crate name
CrateNum cnum = mappings->get_current_crate ();
std::string crate_name;
bool ok = mappings->get_crate_name (cnum, crate_name);
rust_assert (ok);
// setup the ribs
NodeId scope_node_id = crate.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
// get the root segment
CanonicalPath crate_prefix
= CanonicalPath::new_seg (scope_node_id, crate_name);
crate_prefix.set_crate_num (cnum);
// setup a dummy crate node
resolver->get_name_scope ().insert (
CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"),
crate.get_node_id (), Location ());
// setup the root scope
resolver->push_new_module_scope (scope_node_id);
// first gather the top-level namespace names then we drill down so this
// allows for resolving forward declarations since an impl block might have
// a Self type Foo which is defined after the impl block for example.
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
ResolveTopLevel::go (it->get (), CanonicalPath::create_empty (),
crate_prefix);
// FIXME remove this
if (saw_errors ())
{
resolver->pop_module_scope ();
return;
}
// next we can drill down into the items and their scopes
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
ResolveItem::go (it->get (), CanonicalPath::create_empty (), crate_prefix);
// done
resolver->pop_module_scope ();
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_H
#define RUST_AST_RESOLVE_H
#include "rust-name-resolver.h"
#include "rust-ast-full.h"
#include "rust-hir-map.h"
namespace Rust {
namespace Resolver {
class NameResolution
{
public:
static void Resolve (AST::Crate &crate);
static NameResolution *get ();
~NameResolution () {}
private:
void go (AST::Crate &crate);
NameResolution ();
Resolver *resolver;
Analysis::Mappings *mappings;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_H

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_VERIFY_ASSIGNEE
#define RUST_AST_VERIFY_ASSIGNEE
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
class VerifyAsignee : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static bool go (AST::Expr *assignee, NodeId parent)
{
VerifyAsignee checker (parent);
assignee->accept_vis (checker);
if (!checker.ok)
rust_error_at (assignee->get_locus (),
"invalid left-hand side of assignment");
return checker.ok;
}
void visit (AST::ArrayIndexExpr &expr) override
{
expr.get_array_expr ()->accept_vis (*this);
}
void visit (AST::FieldAccessExpr &expr) override
{
expr.get_receiver_expr ()->accept_vis (*this);
}
void visit (AST::TupleIndexExpr &expr) override
{
expr.get_tuple_expr ()->accept_vis (*this);
}
void visit (AST::IdentifierExpr &expr) override
{
if (!resolver->get_name_scope ().lookup (
CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
&resolved_node))
return;
ok = true;
}
void visit (AST::DereferenceExpr &expr) override
{
expr.get_dereferenced_expr ()->accept_vis (*this);
}
void visit (AST::PathInExpression &expr) override { ok = true; }
private:
VerifyAsignee (NodeId parent) : ResolverBase (), ok (false) {}
bool ok;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_VERIFY_ASSIGNEE

View File

@@ -0,0 +1,503 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "rust-name-resolver.h"
#include "rust-ast-full.h"
#define MKBUILTIN_TYPE(_X, _R, _TY) \
do \
{ \
AST::PathIdentSegment seg (_X, Linemap::predeclared_location ()); \
auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \
new AST::TypePathSegment (::std::move (seg), false, \
Linemap::predeclared_location ())); \
::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \
segs.push_back (::std::move (typePath)); \
auto builtin_type \
= new AST::TypePath (::std::move (segs), \
Linemap::predeclared_location (), false); \
_R.push_back (builtin_type); \
tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \
_TY); \
mappings->insert_node_to_hir (builtin_type->get_node_id (), \
_TY->get_ref ()); \
mappings->insert_canonical_path ( \
builtin_type->get_node_id (), \
CanonicalPath::new_seg (builtin_type->get_node_id (), _X)); \
} \
while (0)
namespace Rust {
namespace Resolver {
Rib::Rib (CrateNum crateNum, NodeId node_id)
: crate_num (crateNum), node_id (node_id),
mappings (Analysis::Mappings::get ())
{}
void
Rib::insert_name (
const CanonicalPath &path, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
{
auto it = path_mappings.find (path);
bool path_already_exists = it != path_mappings.end ();
if (path_already_exists && !shadow)
{
const auto &decl = decls_within_rib.find (it->second);
if (decl != decls_within_rib.end ())
dup_cb (path, it->second, decl->second);
else
dup_cb (path, it->second, locus);
return;
}
path_mappings[path] = id;
reverse_path_mappings.insert (std::pair<NodeId, CanonicalPath> (id, path));
decls_within_rib.insert (std::pair<NodeId, Location> (id, locus));
references[id] = {};
}
bool
Rib::lookup_name (const CanonicalPath &ident, NodeId *id)
{
auto it = path_mappings.find (ident);
if (it == path_mappings.end ())
return false;
*id = it->second;
return true;
}
void
Rib::clear_name (const CanonicalPath &ident, NodeId id)
{
auto ii = path_mappings.find (ident);
if (ii != path_mappings.end ())
path_mappings.erase (ii);
auto ij = reverse_path_mappings.find (id);
if (ij != reverse_path_mappings.end ())
reverse_path_mappings.erase (ij);
auto ik = decls_within_rib.find (id);
if (ik != decls_within_rib.end ())
decls_within_rib.erase (ik);
}
void
Rib::append_reference_for_def (NodeId def, NodeId ref)
{
references[def].insert (ref);
}
bool
Rib::have_references_for_node (NodeId def) const
{
auto it = references.find (def);
if (it == references.end ())
return false;
return !it->second.empty ();
}
bool
Rib::decl_was_declared_here (NodeId def) const
{
for (auto &it : decls_within_rib)
{
if (it.first == def)
return true;
}
return false;
}
void
Rib::debug () const
{
fprintf (stderr, "%s\n", debug_str ().c_str ());
}
std::string
Rib::debug_str () const
{
std::string buffer;
for (const auto &it : path_mappings)
{
buffer += it.first.get () + "=" + std::to_string (it.second);
buffer += ",";
}
return "{" + buffer + "}";
}
Scope::Scope (CrateNum crate_num) : crate_num (crate_num) {}
void
Scope::insert (
const CanonicalPath &ident, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
{
peek ()->insert_name (ident, id, locus, shadow, dup_cb);
}
void
Scope::insert (const CanonicalPath &ident, NodeId id, Location locus)
{
peek ()->insert_name (ident, id, locus, true,
[] (const CanonicalPath &, NodeId, Location) -> void {
});
}
bool
Scope::lookup (const CanonicalPath &ident, NodeId *id)
{
NodeId lookup = UNKNOWN_NODEID;
iterate ([&] (Rib *r) mutable -> bool {
if (r->lookup_name (ident, &lookup))
return false;
return true;
});
*id = lookup;
return lookup != UNKNOWN_NODEID;
}
void
Scope::iterate (std::function<bool (Rib *)> cb)
{
for (auto it = stack.rbegin (); it != stack.rend (); ++it)
{
if (!cb (*it))
return;
}
}
void
Scope::iterate (std::function<bool (const Rib *)> cb) const
{
for (auto it = stack.rbegin (); it != stack.rend (); ++it)
{
if (!cb (*it))
return;
}
}
Rib *
Scope::peek ()
{
return stack.back ();
}
void
Scope::push (NodeId id)
{
stack.push_back (new Rib (get_crate_num (), id));
}
Rib *
Scope::pop ()
{
Rib *r = peek ();
stack.pop_back ();
return r;
}
void
Scope::append_reference_for_def (NodeId refId, NodeId defId)
{
bool ok = false;
iterate ([&] (Rib *r) mutable -> bool {
if (r->decl_was_declared_here (defId))
{
ok = true;
r->append_reference_for_def (defId, refId);
}
return true;
});
rust_assert (ok);
}
bool
Scope::decl_was_declared_here (NodeId def) const
{
bool found = false;
iterate ([&] (const Rib *r) -> bool {
if (r->decl_was_declared_here (def))
{
found = true;
return false;
}
return true;
});
return found;
}
Resolver::Resolver ()
: mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()),
name_scope (Scope (mappings->get_current_crate ())),
type_scope (Scope (mappings->get_current_crate ())),
label_scope (Scope (mappings->get_current_crate ())),
macro_scope (Scope (mappings->get_current_crate ())),
global_type_node_id (UNKNOWN_NODEID), unit_ty_node_id (UNKNOWN_NODEID)
{
generate_builtins ();
}
Resolver *
Resolver::get ()
{
static Resolver *instance;
if (instance == nullptr)
instance = new Resolver ();
return instance;
}
void
Resolver::push_new_name_rib (Rib *r)
{
rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ());
name_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_type_rib (Rib *r)
{
if (type_ribs.size () == 0)
global_type_node_id = r->get_node_id ();
rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ());
type_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_label_rib (Rib *r)
{
rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
label_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_macro_rib (Rib *r)
{
rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
macro_ribs[r->get_node_id ()] = r;
}
bool
Resolver::find_name_rib (NodeId id, Rib **rib)
{
auto it = name_ribs.find (id);
if (it == name_ribs.end ())
return false;
*rib = it->second;
return true;
}
bool
Resolver::find_type_rib (NodeId id, Rib **rib)
{
auto it = type_ribs.find (id);
if (it == type_ribs.end ())
return false;
*rib = it->second;
return true;
}
bool
Resolver::find_macro_rib (NodeId id, Rib **rib)
{
auto it = macro_ribs.find (id);
if (it == macro_ribs.end ())
return false;
*rib = it->second;
return true;
}
void
Resolver::insert_builtin_types (Rib *r)
{
auto builtins = get_builtin_types ();
for (auto &builtin : builtins)
{
CanonicalPath builtin_path
= CanonicalPath::new_seg (builtin->get_node_id (),
builtin->as_string ());
r->insert_name (builtin_path, builtin->get_node_id (),
Linemap::predeclared_location (), false,
[] (const CanonicalPath &, NodeId, Location) -> void {});
}
}
std::vector<AST::Type *> &
Resolver::get_builtin_types ()
{
return builtins;
}
void
Resolver::generate_builtins ()
{
auto u8
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U8);
auto u16
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16);
auto u32
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32);
auto u64
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U64);
auto u128
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U128);
auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8);
auto i16
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16);
auto i32
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32);
auto i64
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I64);
auto i128
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I128);
auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ());
auto f32
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32);
auto f64
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64);
auto usize = new TyTy::USizeType (mappings->get_next_hir_id ());
auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ());
auto char_tyty = new TyTy::CharType (mappings->get_next_hir_id ());
auto str = new TyTy::StrType (mappings->get_next_hir_id ());
auto never = new TyTy::NeverType (mappings->get_next_hir_id ());
MKBUILTIN_TYPE ("u8", builtins, u8);
MKBUILTIN_TYPE ("u16", builtins, u16);
MKBUILTIN_TYPE ("u32", builtins, u32);
MKBUILTIN_TYPE ("u64", builtins, u64);
MKBUILTIN_TYPE ("u128", builtins, u128);
MKBUILTIN_TYPE ("i8", builtins, i8);
MKBUILTIN_TYPE ("i16", builtins, i16);
MKBUILTIN_TYPE ("i32", builtins, i32);
MKBUILTIN_TYPE ("i64", builtins, i64);
MKBUILTIN_TYPE ("i128", builtins, i128);
MKBUILTIN_TYPE ("bool", builtins, rbool);
MKBUILTIN_TYPE ("f32", builtins, f32);
MKBUILTIN_TYPE ("f64", builtins, f64);
MKBUILTIN_TYPE ("usize", builtins, usize);
MKBUILTIN_TYPE ("isize", builtins, isize);
MKBUILTIN_TYPE ("char", builtins, char_tyty);
MKBUILTIN_TYPE ("str", builtins, str);
MKBUILTIN_TYPE ("!", builtins, never);
// unit type ()
TyTy::TupleType *unit_tyty
= TyTy::TupleType::get_unit_type (mappings->get_next_hir_id ());
std::vector<std::unique_ptr<AST::Type> > elems;
AST::TupleType *unit_type
= new AST::TupleType (std::move (elems), Linemap::predeclared_location ());
builtins.push_back (unit_type);
tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (),
unit_tyty);
set_unit_type_node_id (unit_type->get_node_id ());
}
void
Resolver::insert_resolved_name (NodeId refId, NodeId defId)
{
resolved_names[refId] = defId;
get_name_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_name (NodeId refId, NodeId *defId)
{
auto it = resolved_names.find (refId);
if (it == resolved_names.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_type (NodeId refId, NodeId defId)
{
// auto it = resolved_types.find (refId);
// rust_assert (it == resolved_types.end ());
resolved_types[refId] = defId;
get_type_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_type (NodeId refId, NodeId *defId)
{
auto it = resolved_types.find (refId);
if (it == resolved_types.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_label (NodeId refId, NodeId defId)
{
auto it = resolved_labels.find (refId);
rust_assert (it == resolved_labels.end ());
resolved_labels[refId] = defId;
get_label_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_label (NodeId refId, NodeId *defId)
{
auto it = resolved_labels.find (refId);
if (it == resolved_labels.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_macro (NodeId refId, NodeId defId)
{
auto it = resolved_macros.find (refId);
rust_assert (it == resolved_macros.end ());
resolved_labels[refId] = defId;
get_label_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_macro (NodeId refId, NodeId *defId)
{
auto it = resolved_macros.find (refId);
if (it == resolved_macros.end ())
return false;
*defId = it->second;
return true;
}
} // namespace Resolver
} // namespace Rust

View File

@@ -0,0 +1,212 @@
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC 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 General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_NAME_RESOLVER_H
#define RUST_NAME_RESOLVER_H
#include "rust-system.h"
#include "rust-canonical-path.h"
#include "rust-hir-map.h"
#include "rust-hir-type-check.h"
namespace Rust {
namespace Resolver {
class Rib
{
public:
// Rust uses local_def_ids assigned by def_collector on the AST
// lets use NodeId instead
Rib (CrateNum crateNum, NodeId node_id);
// this takes the relative paths of items within a compilation unit for lookup
void insert_name (
const CanonicalPath &path, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb);
bool lookup_canonical_path (const NodeId &id, CanonicalPath *ident);
bool lookup_name (const CanonicalPath &ident, NodeId *id);
void clear_name (const CanonicalPath &ident, NodeId id);
void append_reference_for_def (NodeId def, NodeId ref);
bool have_references_for_node (NodeId def) const;
bool decl_was_declared_here (NodeId def) const;
void debug () const;
std::string debug_str () const;
CrateNum get_crate_num () const { return crate_num; }
NodeId get_node_id () const { return node_id; }
std::map<NodeId, Location> &get_declarations () { return decls_within_rib; }
private:
CrateNum crate_num;
NodeId node_id;
std::map<CanonicalPath, NodeId> path_mappings;
std::map<NodeId, CanonicalPath> reverse_path_mappings;
std::map<NodeId, Location> decls_within_rib;
std::map<NodeId, std::set<NodeId>> references;
Analysis::Mappings *mappings;
};
class Scope
{
public:
Scope (CrateNum crate_num);
void
insert (const CanonicalPath &ident, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb);
void insert (const CanonicalPath &ident, NodeId id, Location locus);
bool lookup (const CanonicalPath &ident, NodeId *id);
void iterate (std::function<bool (Rib *)> cb);
void iterate (std::function<bool (const Rib *)> cb) const;
Rib *peek ();
void push (NodeId id);
Rib *pop ();
bool decl_was_declared_here (NodeId def) const;
void append_reference_for_def (NodeId refId, NodeId defId);
CrateNum get_crate_num () const { return crate_num; }
private:
CrateNum crate_num;
std::vector<Rib *> stack;
};
class Resolver
{
public:
static Resolver *get ();
~Resolver () {}
// these builtin types
void insert_builtin_types (Rib *r);
// these will be required for type resolution passes to
// map back to tyty nodes
std::vector<AST::Type *> &get_builtin_types ();
void push_new_name_rib (Rib *r);
void push_new_type_rib (Rib *r);
void push_new_label_rib (Rib *r);
void push_new_macro_rib (Rib *r);
bool find_name_rib (NodeId id, Rib **rib);
bool find_type_rib (NodeId id, Rib **rib);
bool find_label_rib (NodeId id, Rib **rib);
bool find_macro_rib (NodeId id, Rib **rib);
void insert_resolved_name (NodeId refId, NodeId defId);
bool lookup_resolved_name (NodeId refId, NodeId *defId);
void insert_resolved_type (NodeId refId, NodeId defId);
bool lookup_resolved_type (NodeId refId, NodeId *defId);
void insert_resolved_label (NodeId refId, NodeId defId);
bool lookup_resolved_label (NodeId refId, NodeId *defId);
void insert_resolved_macro (NodeId refId, NodeId defId);
bool lookup_resolved_macro (NodeId refId, NodeId *defId);
// proxy for scoping
Scope &get_name_scope () { return name_scope; }
Scope &get_type_scope () { return type_scope; }
Scope &get_label_scope () { return label_scope; }
Scope &get_macro_scope () { return macro_scope; }
NodeId get_global_type_node_id () { return global_type_node_id; }
void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; }
NodeId get_unit_type_node_id () { return unit_ty_node_id; }
void push_new_module_scope (NodeId module_id)
{
current_module_stack.push_back (module_id);
}
void pop_module_scope ()
{
rust_assert (!current_module_stack.empty ());
current_module_stack.pop_back ();
}
NodeId peek_current_module_scope () const
{
rust_assert (!current_module_stack.empty ());
return current_module_stack.back ();
}
NodeId peek_crate_module_scope () const
{
rust_assert (!current_module_stack.empty ());
return current_module_stack.front ();
}
NodeId peek_parent_module_scope () const
{
rust_assert (current_module_stack.size () > 1);
return current_module_stack.at (current_module_stack.size () - 2);
}
private:
Resolver ();
void generate_builtins ();
Analysis::Mappings *mappings;
TypeCheckContext *tyctx;
std::vector<AST::Type *> builtins;
Scope name_scope;
Scope type_scope;
Scope label_scope;
Scope macro_scope;
NodeId global_type_node_id;
NodeId unit_ty_node_id;
// map a AST Node to a Rib
std::map<NodeId, Rib *> name_ribs;
std::map<NodeId, Rib *> type_ribs;
std::map<NodeId, Rib *> label_ribs;
std::map<NodeId, Rib *> macro_ribs;
// Rust uses DefIds to namespace these under a crate_num
// but then it uses the def_collector to assign local_defids
// to each ast node as well. not sure if this is going to fit
// with gcc very well to compile a full crate in one go but we will
// see.
// these are of the form ref->Def-NodeId
// we need two namespaces one for names and ones for types
std::map<NodeId, NodeId> resolved_names;
std::map<NodeId, NodeId> resolved_types;
std::map<NodeId, NodeId> resolved_labels;
std::map<NodeId, NodeId> resolved_macros;
// keep track of the current module scope ids
std::vector<NodeId> current_module_stack;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_NAME_RESOLVER_H