mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 20:01:22 -05:00
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:
committed by
Arthur Cohen
parent
1841081a8a
commit
85a8fe00f8
658
gcc/rust/resolve/rust-ast-resolve-base.cc
Normal file
658
gcc/rust/resolve/rust-ast-resolve-base.cc
Normal 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
|
||||
221
gcc/rust/resolve/rust-ast-resolve-base.h
Normal file
221
gcc/rust/resolve/rust-ast-resolve-base.h
Normal 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
|
||||
574
gcc/rust/resolve/rust-ast-resolve-expr.cc
Normal file
574
gcc/rust/resolve/rust-ast-resolve-expr.cc
Normal 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 ¶m : 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 ¶m : 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
|
||||
133
gcc/rust/resolve/rust-ast-resolve-expr.h
Normal file
133
gcc/rust/resolve/rust-ast-resolve-expr.h
Normal 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
|
||||
275
gcc/rust/resolve/rust-ast-resolve-implitem.h
Normal file
275
gcc/rust/resolve/rust-ast-resolve-implitem.h
Normal 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
|
||||
1237
gcc/rust/resolve/rust-ast-resolve-item.cc
Normal file
1237
gcc/rust/resolve/rust-ast-resolve-item.cc
Normal file
File diff suppressed because it is too large
Load Diff
149
gcc/rust/resolve/rust-ast-resolve-item.h
Normal file
149
gcc/rust/resolve/rust-ast-resolve-item.h
Normal 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
|
||||
384
gcc/rust/resolve/rust-ast-resolve-path.cc
Normal file
384
gcc/rust/resolve/rust-ast-resolve-path.cc
Normal 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
|
||||
52
gcc/rust/resolve/rust-ast-resolve-path.h
Normal file
52
gcc/rust/resolve/rust-ast-resolve-path.h
Normal 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
|
||||
163
gcc/rust/resolve/rust-ast-resolve-pattern.cc
Normal file
163
gcc/rust/resolve/rust-ast-resolve-pattern.cc
Normal 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
|
||||
98
gcc/rust/resolve/rust-ast-resolve-pattern.h
Normal file
98
gcc/rust/resolve/rust-ast-resolve-pattern.h
Normal 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
|
||||
38
gcc/rust/resolve/rust-ast-resolve-stmt.cc
Normal file
38
gcc/rust/resolve/rust-ast-resolve-stmt.cc
Normal 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
|
||||
378
gcc/rust/resolve/rust-ast-resolve-stmt.h
Normal file
378
gcc/rust/resolve/rust-ast-resolve-stmt.h
Normal 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 ¶m : 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
|
||||
61
gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc
Normal file
61
gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc
Normal 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
|
||||
55
gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
Normal file
55
gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
Normal 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
|
||||
460
gcc/rust/resolve/rust-ast-resolve-toplevel.h
Normal file
460
gcc/rust/resolve/rust-ast-resolve-toplevel.h
Normal 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
|
||||
582
gcc/rust/resolve/rust-ast-resolve-type.cc
Normal file
582
gcc/rust/resolve/rust-ast-resolve-type.cc
Normal 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
|
||||
290
gcc/rust/resolve/rust-ast-resolve-type.h
Normal file
290
gcc/rust/resolve/rust-ast-resolve-type.h
Normal 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 ¶m : 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 ¶m) 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 ¶m) 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
|
||||
115
gcc/rust/resolve/rust-ast-resolve.cc
Normal file
115
gcc/rust/resolve/rust-ast-resolve.cc
Normal 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
|
||||
50
gcc/rust/resolve/rust-ast-resolve.h
Normal file
50
gcc/rust/resolve/rust-ast-resolve.h
Normal 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
|
||||
84
gcc/rust/resolve/rust-ast-verify-assignee.h
Normal file
84
gcc/rust/resolve/rust-ast-verify-assignee.h
Normal 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
|
||||
503
gcc/rust/resolve/rust-name-resolver.cc
Normal file
503
gcc/rust/resolve/rust-name-resolver.cc
Normal 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
|
||||
212
gcc/rust/resolve/rust-name-resolver.h
Normal file
212
gcc/rust/resolve/rust-name-resolver.h
Normal 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
|
||||
Reference in New Issue
Block a user