diff options
Diffstat (limited to 'gcc/rust/resolve')
28 files changed, 245 insertions, 7870 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc deleted file mode 100644 index 3c7b425..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ /dev/null @@ -1,691 +0,0 @@ -// Copyright (C) 2020-2025 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" -#include "rust-path.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::AttrInputMacro &) -{} - -void -ResolverBase::visit (AST::MetaItemLitExpr &) -{} - -void -ResolverBase::visit (AST::MetaItemPathExpr &) -{} - -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::AnonConst &) -{} - -void -ResolverBase::visit (AST::ConstBlock &) -{} - -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::BoxExpr &) -{} - -void -ResolverBase::visit (AST::ReturnExpr &) -{} - -void -ResolverBase::visit (AST::TryExpr &) -{} - -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::IfLetExpr &) -{} - -void -ResolverBase::visit (AST::IfLetExprConseqElse &) -{} - -void -ResolverBase::visit (AST::MatchExpr &) -{} - -void -ResolverBase::visit (AST::AwaitExpr &) -{} - -void -ResolverBase::visit (AST::AsyncBlockExpr &) -{} - -void -ResolverBase::visit (AST::InlineAsm &) -{} - -void -ResolverBase::visit (AST::LlvmInlineAsm &) -{} - -void -ResolverBase::visit (AST::TypeParam &) -{} - -void -ResolverBase::visit (AST::LifetimeWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::TypeBoundWhereClauseItem &) -{} - -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::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::ExternalTypeItem &) -{} - -void -ResolverBase::visit (AST::ExternalStaticItem &) -{} - -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::RestPattern &) -{} - -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::SlicePatternItemsNoRest &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsHasRest &) -{} - -void -ResolverBase::visit (AST::SlicePattern &) -{} - -void -ResolverBase::visit (AST::AltPattern &) -{} - -void -ResolverBase::visit (AST::EmptyStmt &) -{} - -void -ResolverBase::visit (AST::LetStmt &) -{} - -void -ResolverBase::visit (AST::ExprStmt &) -{} - -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 &) -{} - -void -ResolverBase::visit (AST::SelfParam &) -{} - -void -ResolverBase::visit (AST::VariadicParam &) -{} - -void -ResolverBase::visit (AST::FunctionParam &) -{} - -void -ResolverBase::visit (AST::FormatArgs &fmt) -{} - -void -ResolverBase::visit (AST::OffsetOf &offset_of) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h deleted file mode 100644 index 89c5c35..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (C) 2020-2025 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-ast.h" -#include "rust-builtin-ast-nodes.h" -#include "rust-expr.h" -#include "rust-name-resolver.h" -#include "rust-diagnostics.h" -#include "rust-location.h" - -namespace Rust { -namespace Resolver { -inline void -redefined_error (const rich_location &loc) -{ - rust_error_at (loc, "redefined multiple times"); -} - -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::AttrInputMacro &); - void visit (AST::MetaItemLitExpr &); - void visit (AST::MetaItemPathExpr &); - 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::AnonConst &); - void visit (AST::ConstBlock &); - 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::BoxExpr &); - void visit (AST::ReturnExpr &); - void visit (AST::TryExpr &); - 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::IfLetExpr &); - void visit (AST::IfLetExprConseqElse &); - - void visit (AST::MatchExpr &); - void visit (AST::AwaitExpr &); - void visit (AST::AsyncBlockExpr &); - void visit (AST::InlineAsm &); - void visit (AST::LlvmInlineAsm &); - - void visit (AST::TypeParam &); - - void visit (AST::LifetimeWhereClauseItem &); - void visit (AST::TypeBoundWhereClauseItem &); - 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::TraitItemConst &); - void visit (AST::TraitItemType &); - void visit (AST::Trait &); - void visit (AST::InherentImpl &); - void visit (AST::TraitImpl &); - - void visit (AST::ExternalTypeItem &); - void visit (AST::ExternalStaticItem &); - 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::RestPattern &); - - 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::SlicePatternItemsNoRest &); - void visit (AST::SlicePatternItemsHasRest &); - void visit (AST::SlicePattern &); - void visit (AST::AltPattern &); - - void visit (AST::EmptyStmt &); - void visit (AST::LetStmt &); - void visit (AST::ExprStmt &); - - 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 &); - void visit (AST::FunctionParam ¶m); - void visit (AST::VariadicParam ¶m); - void visit (AST::SelfParam ¶m); - - void visit (AST::FormatArgs &fmt); - void visit (AST::OffsetOf &offset_of); - -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 diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc deleted file mode 100644 index a410193..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright (C) 2020-2025 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-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" -#include "rust-expr.h" -#include "rust-ice-finalizer.h" - -namespace Rust { -namespace Resolver { - -void -ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error) -{ - ResolveExpr resolver (prefix, canonical_prefix, funny_error); - expr.accept_vis (resolver); -} - -void -ResolveExpr::visit (AST::TupleIndexExpr &expr) -{ - ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TupleExpr &expr) -{ - if (expr.is_unit ()) - return; - - for (auto &elem : expr.get_tuple_elems ()) - ResolveExpr::go (*elem, 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 (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CallExpr &expr) -{ - ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix); - for (auto ¶m : expr.get_params ()) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MethodCallExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), 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, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ErrorPropagationExpr &expr) -{ - ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::AssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -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 if (funny_error) - { - /* This was a "break rust" or "break gcc", and the identifier failed to - resolve. Emit a funny ICE. We set the finalizer to our custom one, - and use the lower-level emit_diagnostic () instead of the more common - internal_error_no_backtrace () in order to pass our locus. */ - diagnostics::text_finalizer (global_dc) = funny_ice_text_finalizer; - emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1, - "are you trying to break %s? how dare you?", - expr.as_string ().c_str ()); - } - else - { - rust_error_at (expr.get_locus (), ErrorCode::E0425, - "cannot find value %qs in this scope", - expr.as_string ().c_str ()); - } -} - -void -ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CompoundAssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ComparisonExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LazyBooleanExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::NegationExpr &expr) -{ - ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TypeCastExpr &expr) -{ - ResolveType::go (expr.get_type_to_cast_to ()); - ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExpr &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfLetExpr &expr) -{ - ResolveExpr::go (expr.get_value_expr (), 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_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::IfLetExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_value_expr (), 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_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), 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_label_scope ().peek ()); - - if (expr.has_label ()) - { - auto label = expr.get_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, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - for (auto &s : expr.get_statements ()) - { - if (s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - for (auto &s : expr.get_statements ()) - { - if (!s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - if (expr.has_tail_expr ()) - ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::AnonConst &expr) -{ - ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ConstBlock &expr) -{ - ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix); -} - -void -translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - const auto &operands = expr.get_operands (); - using RegisterType = AST::InlineAsmOperand::RegisterType; - for (auto &operand : operands) - { - switch (operand.get_register_type ()) - { - case RegisterType::In: - { - auto in = operand.get_in (); - ResolveExpr::go (*in.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Out: - { - auto out = operand.get_out (); - ResolveExpr::go (*out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::InOut: - { - auto in_out = operand.get_in_out (); - ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::SplitInOut: - { - auto split_in_out = operand.get_split_in_out (); - ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix); - ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix); - break; - } - case RegisterType::Const: - { - auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (anon_const.get_inner_expr (), prefix, - canonical_prefix); - break; - } - case RegisterType::Sym: - { - auto sym = operand.get_sym (); - ResolveExpr::go (*sym.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Label: - { - auto label = operand.get_label (); - ResolveExpr::go (*label.expr, prefix, canonical_prefix); - break; - } - } - } -} -void -ResolveExpr::visit (AST::InlineAsm &expr) -{ - translate_operand (expr, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LlvmInlineAsm &expr) -{ - for (auto &output : expr.get_outputs ()) - ResolveExpr::go (*output.expr, prefix, canonical_prefix); - - for (auto &input : expr.get_inputs ()) - ResolveExpr::go (*input.expr, prefix, canonical_prefix); -} - -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, 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 (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayElemsCopied &expr) -{ - ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_elem_to_copy (), 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 (), prefix, canonical_prefix); - } - - auto const &struct_fields = struct_expr.get_fields (); - for (auto &struct_field : struct_fields) - { - ResolveStructExprField::go (*struct_field, prefix, canonical_prefix); - } -} - -void -ResolveExpr::visit (AST::GroupedExpr &expr) -{ - ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::FieldAccessExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), 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, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::BreakExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label_unchecked ().get_lifetime (); - 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 (label.get_locus (), ErrorCode::E0426, - "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } - - if (expr.has_break_expr ()) - { - bool funny_error = false; - auto &break_expr = expr.get_break_expr (); - if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) - { - /* This is a break with an expression, and the expression is - just a single identifier. See if the identifier is either - "rust" or "gcc", in which case we have "break rust" or "break - gcc", and so may need to emit our funny error. We cannot yet - emit the error here though, because the identifier may still - be in scope, and ICE'ing on valid programs would not be very - funny. */ - std::string ident - = static_cast<AST::IdentifierExpr &> (break_expr).as_string (); - if (ident == "rust" || ident == "gcc") - funny_error = true; - } - ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error); - } -} - -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, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), 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, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined 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_label_scope ().peek ()); - - // resolve the expression - PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var); - ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), 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_unchecked (); - 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_unchecked ().get_locus (), - ErrorCode::E0426, "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } -} - -void -ResolveExpr::visit (AST::BorrowExpr &expr) -{ - ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::DereferenceExpr &expr) -{ - ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MatchExpr &expr) -{ - ResolveExpr::go (expr.get_scrutinee_expr (), 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_label_scope ().peek ()); - - // resolve - AST::MatchArm &arm = match_case.get_arm (); - if (arm.has_match_arm_guard ()) - ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // insert any possible new patterns - for (auto &pattern : arm.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - // resolve the body - ResolveExpr::go (match_case.get_expr (), 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 (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFromExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeToExpr &expr) -{ - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFullExpr &) -{ - // nothing to do -} - -void -ResolveExpr::visit (AST::RangeFromToInclExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ClosureExprInner &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_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ClosureExprInnerTyped &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_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - ResolveType::go (expr.get_return_type ()); - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings); - - if (param.has_type_given ()) - ResolveType::go (param.get_type ()); -} - -ResolveExpr::ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - funny_error (funny_error) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h deleted file mode 100644 index aad1605..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2020-2025 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.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-expr.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, - bool funny_error = false); - - 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::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::AnonConst &expr) override; - void visit (AST::ConstBlock &expr) override; - void visit (AST::InlineAsm &expr) override; - void visit (AST::LlvmInlineAsm &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; - void visit (AST::StructExprStruct &struct_expr) override; - 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; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - -protected: - void resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings); - -private: - ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - bool funny_error; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_EXPR_H diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h deleted file mode 100644 index 2081697..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (C) 2020-2025 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::AssociatedItem &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 ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - - 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, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - -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::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveTopLevelTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); - }; - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - 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, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::TraitItemConst &constant) override - { - auto decl - = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - 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, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, - Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - - void visit (AST::ExternalTypeItem &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc deleted file mode 100644 index 1d5ebed..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ /dev/null @@ -1,1247 +0,0 @@ -// Copyright (C) 2020-2025 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-full-decls.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -#include "rust-item.h" -#include "selftest.h" - -namespace Rust { -namespace Resolver { - -ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item->is_marked_for_strip ()) - return; - - ResolveTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); -} - -void -ResolveTraitItems::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - 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_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // self turns into (self: Self) as a function param - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto param = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - param.get_node_id (), {"self"}, param.get_locus (), - param.get_has_ref (), param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!param.get_has_ref ()); - ResolveType::go (param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - param.get_locus ()); - ResolveType::go (self_type_path); - } - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - // trait items have an optional body - if (function.has_body ()) - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} -void -ResolveTraitItems::visit (AST::TraitItemType &type) -{ - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (type.get_node_id (), cpath); - - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveTraitItems::visit (AST::TraitItemConst &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - ResolveType::go (constant.get_type ()); - - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -ResolveItem::ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveItem::go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveItem::visit (AST::TypeAlias &alias) -{ - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - - NodeId scope_node_id = alias.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (alias.has_generics ()) - ResolveGenericParams::go (alias.get_generic_params (), prefix, - canonical_prefix); - - if (alias.has_where_clause ()) - ResolveWhereClause::Resolve (alias.get_where_clause ()); - - ResolveType::go (alias.get_type_aliased ()); - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Module &module) -{ - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - mappings.insert_canonical_path (module.get_node_id (), cpath); - - resolve_visibility (module.get_visibility ()); - - NodeId scope_node_id = module.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_label_scope ().peek ()); - - // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go - // in ResolveTopLevel::visit (AST::Module) as well as here? - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveItem::go (*item, path, cpath); - - resolver->pop_module_scope (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::TupleStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::TupleField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Enum &enum_decl) -{ - auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolve_visibility (enum_decl.get_visibility ()); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - if (enum_decl.has_where_clause ()) - ResolveWhereClause::Resolve (enum_decl.get_where_clause ()); - - /* The actual fields are inside the variants. */ - for (auto &variant : enum_decl.get_variants ()) - ResolveItem::go (*variant, path, cpath); - - resolver->get_type_scope ().pop (); -} - -/* EnumItem doesn't need to be handled, no fields. */ -void -ResolveItem::visit (AST::EnumItem &item) -{ - // Since at this point we cannot have visibilities on enum items anymore, we - // can skip handling them - - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); -} - -void -ResolveItem::visit (AST::EnumItemTuple &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemStruct &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemDiscriminant &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - ResolveExpr::go (item.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::StructStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Union &union_decl) -{ - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolve_visibility (union_decl.get_visibility ()); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - if (union_decl.has_where_clause ()) - ResolveWhereClause::Resolve (union_decl.get_where_clause ()); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::ConstantItem &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolve_visibility (constant.get_visibility ()); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - 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_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - if (function.has_self_param ()) - { - // self turns into (self: Self) as a function param - AST::Param &s_param = function.get_self_param (); - auto &self_param = static_cast<AST::SelfParam &> (s_param); - - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), {"self"}, self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (self_param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); - ResolveType::go (self_type_path); - } - } - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - if (param.has_pattern ()) - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - if (param.has_type ()) - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::InherentImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_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 ()); - - resolve_visibility (impl_block.get_visibility ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // FIXME this needs to be protected behind nominal type-checks see: - // rustc --explain E0118 - // issue #2634 - ResolveType::go (impl_block.get_type ()); - - // Setup paths - CanonicalPath self_cpath = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::InherentImpl resolve Self: {%s}", - self_cpath.get ().c_str ()); - - CanonicalPath impl_type = self_cpath; - CanonicalPath impl_type_seg - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - // see https://godbolt.org/z/a3vMbsT6W - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = impl_prefix; - } - else - { - cpath = canonical_prefix.append (impl_type_seg); - } - - // done setup paths - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - resolver->get_type_scope ().peek ()->clear_name ( - Self, impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::TraitImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - - resolve_visibility (impl_block.get_visibility ()); - - 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_label_scope ().peek ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ()); - if (trait_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - // CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - NodeId type_resolved_node = ResolveType::go (impl_block.get_type ()); - if (type_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - bool ok = true; - - // setup paths - CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - - ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), - canonical_trait_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve trait type: {%s}", - canonical_trait_type.get ().c_str ()); - - CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), - canonical_impl_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve self: {%s}", - canonical_impl_type.get ().c_str ()); - - // raw paths - CanonicalPath impl_type_seg = canonical_impl_type; - CanonicalPath trait_type_seg = canonical_trait_type; - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - // setup canonical-path - CanonicalPath canonical_projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - canonical_trait_type, - canonical_impl_type); - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = canonical_projection; - } - else - { - cpath = canonical_prefix.append (canonical_projection); - } - - // DONE setup canonical-path - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - Rib *r = resolver->get_type_scope ().peek (); - r->clear_name (Self, impl_block.get_type ().get_node_id ()); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::Trait &trait) -{ - NodeId scope_node_id = trait.get_node_id (); - - resolve_visibility (trait.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_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 ()); - - ResolveGenericParams::go_single (trait.get_implicit_self (), prefix, - canonical_prefix); - ResolveGenericParams::go (trait.get_generic_params (), prefix, - canonical_prefix); - - // Self is an implicit TypeParam so lets mark it as such - resolver->get_type_scope ().append_reference_for_def ( - trait.get_node_id (), trait.get_implicit_self ().get_node_id ()); - - if (trait.has_type_param_bounds ()) - { - for (auto &bound : trait.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - - // resolve any where clause items - if (trait.has_where_clause ()) - ResolveWhereClause::Resolve (trait.get_where_clause ()); - - // resolve the paths - CanonicalPath path = CanonicalPath::create_empty (); - CanonicalPath cpath = CanonicalPath::create_empty (); - // - - for (auto &item : trait.get_trait_items ()) - { - ResolveTraitItems::go (item.get (), path, cpath); - } - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - - for (auto &item : extern_block.get_extern_items ()) - { - resolve_extern_item (*item); - } -} - -void -ResolveItem::resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveImplItems::go (item, prefix, canonical_prefix); -} - -void -ResolveItem::resolve_extern_item (AST::ExternalItem &item) -{ - ResolveExternItem::go (item, prefix, canonical_prefix); -} - -static void flatten_glob (const AST::UseTreeGlob &glob, - std::vector<Import> &imports); -static void flatten_rebind (const AST::UseTreeRebind &glob, - std::vector<Import> &imports); -static void flatten_list (const AST::UseTreeList &glob, - std::vector<Import> &imports); - -static void -flatten (const AST::UseTree *tree, std::vector<Import> &imports) -{ - switch (tree->get_kind ()) - { - case AST::UseTree::Glob: - { - auto glob = static_cast<const AST::UseTreeGlob *> (tree); - flatten_glob (*glob, imports); - break; - } - case AST::UseTree::Rebind: - { - auto rebind = static_cast<const AST::UseTreeRebind *> (tree); - flatten_rebind (*rebind, imports); - break; - } - case AST::UseTree::List: - { - auto list = static_cast<const AST::UseTreeList *> (tree); - flatten_list (*list, imports); - break; - } - break; - } -} - -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports) -{ - if (glob.has_path ()) - imports.emplace_back (glob.get_path (), true, std::string ()); -} - -static void -flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports) -{ - auto path = rebind.get_path (); - - std::string label; - if (rebind.has_identifier ()) - label = rebind.get_identifier ().as_string (); - else - label = path.get_final_segment ().as_string (); - - imports.emplace_back (path, false, label); -} - -static void -flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports) -{ - auto prefix = AST::SimplePath::create_empty (); - if (list.has_path ()) - prefix = list.get_path (); - - for (const auto &tree : list.get_trees ()) - { - // append imports to the main list, then modify them in-place - auto start_idx = imports.size (); - flatten (tree.get (), imports); - - for (auto import = imports.begin () + start_idx; import != imports.end (); - import++) - { - // avoid duplicate node ids - auto prefix_copy - = AST::SimplePath ({}, prefix.has_opening_scope_resolution (), - prefix.get_locus ()); - for (auto &seg : prefix.get_segments ()) - prefix_copy.get_segments ().push_back ( - AST::SimplePathSegment (seg.get_segment_name (), - seg.get_locus ())); - - import->add_prefix (std::move (prefix_copy)); - } - } -} - -void -Import::add_prefix (AST::SimplePath prefix) -{ - AST::SimplePath old_path (std::move (path)); - path = std::move (prefix); - std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (), - std::back_inserter (path.get_segments ())); -} - -/** - * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve. - * - * Given the following use declarations: - * ``` - * use some::path::to_resolve; #1 - * use some::path::to_glob::*; #2 - * use some::path::{one, two}; #2 - * ``` - * - * In the first case, we simply want to return a vector with a single - * SimplePath: - * [some::path::to_resolve] - * - * In the second case, we want to resolve the glob's "origin path": - * [some::path::to_glob] - * - * Finally in the third case, we want to create two SimplePaths to resolve: - * [some::path::one, some::path::two] - */ -static std::vector<Import> -flatten_use_dec_to_imports (const AST::UseDeclaration &use_item) -{ - auto imports = std::vector<Import> (); - - const auto &tree = use_item.get_tree (); - flatten (tree.get (), imports); - - return imports; -} - -void -ResolveItem::visit (AST::UseDeclaration &use_item) -{ - std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item); - - // FIXME: I think this does not actually resolve glob use-decls and is going - // the wrong way about it. RFC #1560 specifies the following: - // - // > When we find a glob import, we have to record a 'back link', so that when - // a public name is added for the supplying module, we can add it for the - // importing module. - // - // Which is the opposite of what we're doing if I understand correctly? - - NodeId current_module = resolver->peek_current_module_scope (); - for (auto &import : to_resolve) - { - auto &path = import.get_path (); - - rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ()); - NodeId resolved_node_id = ResolvePath::go (path); - bool ok = resolved_node_id != UNKNOWN_NODEID; - if (!ok) - continue; - - if (import.is_glob ()) - continue; - - auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ()); - mappings.insert_module_child_item (current_module, decl); - - resolver->get_type_scope ().insert (decl, resolved_node_id, - path.get_locus (), - Rib::ItemType::Type); - rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ()); - } -} - -ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolveItem (prefix, canonical_prefix) -{} - -void -ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item.is_marked_for_strip ()) - return; - - ResolveImplItems resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveImplItems::visit (AST::TypeAlias &alias) -{ - ResolveItem::visit (alias); - - resolve_visibility (alias.get_visibility ()); - - // FIXME this stops the erronious unused decls which will be fixed later on - resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (), - alias.get_node_id ()); -} - -void -ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveExternItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveExternItem::visit (AST::Function &function) -{ - NodeId scope_node_id = function.get_node_id (); - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - 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_label_scope ().peek ()); - - // resolve the generics - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) - if (!param->is_variadic ()) - { - auto &p = static_cast<AST::FunctionParam &> (*param); - ResolveType::go (p.get_type ()); - } - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExternItem::visit (AST::ExternalStaticItem &item) -{ - resolve_visibility (item.get_visibility ()); - - ResolveType::go (item.get_type ()); -} - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { - -static void -rust_flatten_nested_glob (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_glob (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - frob, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); -} - -static void -rust_flatten_rebind_none (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_rebind (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - frob, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_rebind_nested (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION); - - auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz}); - - auto rebind - = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - foo_bar_baz, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_list (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foo_bar = Rust::AST::SimplePath ({foo, bar}); - - auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION); - auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION); - - // use foo::bar::{baz, bul}; - - auto use0 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz, - UNDEF_LOCATION)); - auto use1 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul, - UNDEF_LOCATION)); - - auto uses = std::vector<std::unique_ptr<Rust::AST::UseTree>> (); - uses.emplace_back (std::move (use0)); - uses.emplace_back (std::move (use1)); - - auto list - = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar, - std::move (uses), UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_list (list, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 2); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul"); -} - -static void -rust_use_dec_flattening (void) -{ - rust_flatten_glob (); - rust_flatten_nested_glob (); - rust_flatten_rebind_none (); - rust_flatten_rebind (); - rust_flatten_rebind_nested (); - rust_flatten_list (); -} - -void -rust_simple_path_resolve_test (void) -{ - rust_use_dec_flattening (); -} - -} // namespace selftest - -#endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h deleted file mode 100644 index d31f910..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (C) 2020-2025 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 "config.h" - -namespace Rust { -namespace Resolver { - -class ResolveTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &type) override; - void visit (AST::TraitItemType &type) 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::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::AssociatedItem &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::AssociatedItem &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::Function &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; -}; - -class Import -{ -public: - Import (AST::SimplePath path, bool is_glob, std::string name) - : path (path), is_glob_f (is_glob), name (name) - {} - - AST::SimplePath &get_path () { return path; } - - const AST::SimplePath &get_path () const { return path; } - - bool is_glob () const { return is_glob_f; } - - const std::string &get_name () const { return name; } - - void add_prefix (AST::SimplePath prefix); - -private: - AST::SimplePath path; - bool is_glob_f; - std::string name; -}; - -} // 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 diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc deleted file mode 100644 index fb6715d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (C) 2020-2024 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-hir-map.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -ResolvePath::ResolvePath () : ResolverBase () {} - -NodeId -ResolvePath::go (AST::PathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::QualifiedPathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::SimplePath &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::resolve_path (AST::PathInExpression &expr) -{ - if (expr.is_lang_item ()) - return Analysis::Mappings::get ().get_lang_item_node ( - expr.get_lang_item ()); - - 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 ()) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - 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 UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - 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) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - ident_seg.as_string ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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 UNKNOWN_NODEID; - } - } - } - - 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 (), ErrorCode::E0433, - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -NodeId -ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr) -{ - auto &root_segment = expr.get_qualified_path_type (); - ResolveType::go (root_segment.get_type ()); - 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 ()); - } - - // cannot fully resolve a qualified path as it is dependant on associated - // items - return UNKNOWN_NODEID; -} - -NodeId -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 previous_resolved_node_id = UNKNOWN_NODEID; - NodeId resolved_node_id = UNKNOWN_NODEID; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - AST::SimplePathSegment &segment = expr.get_segments ().at (i); - bool is_first_segment = i == 0; - bool is_final_segment = i >= (expr.get_segments ().size () - 1); - 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; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - else if (segment.is_super_path_seg ()) - { - if (!is_first_segment) - { - rust_error_at ( - segment.get_locus (), ErrorCode::E0433, - "%<super%> in paths can only be used in start position"); - return UNKNOWN_NODEID; - } - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use %<super%> at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - segment.get_segment_name ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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 UNKNOWN_NODEID; - } - } - - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - } - - // if we still have not resolved and this is the final segment and the - // final segment is self its likely the case: pub use - // - // result::Result::{self, Err, Ok}; - // - // Then the resolved_node_id is just the previous one so long as it is a - // resolved node id - // rust_debug_loc (segment.get_locus (), - // "trying to resolve seg: [%s] first [%s] last [%s]", - // segment.get_segment_name ().c_str (), - // is_first_segment ? "true" : "false", - // is_final_segment ? "true" : "false"); - if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment - && is_final_segment && segment.is_lower_self_seg ()) - resolved_node_id = previous_resolved_node_id; - - // final check - 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 UNKNOWN_NODEID; - } - - if (mappings.node_is_module (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - - previous_resolved_node_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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h deleted file mode 100644 index cddb54a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020-2025 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 NodeId go (AST::PathInExpression &expr); - static NodeId go (AST::QualifiedPathInExpression &expr); - static NodeId go (AST::SimplePath &expr); - -private: - ResolvePath (); - - NodeId resolve_path (AST::PathInExpression &expr); - NodeId resolve_path (AST::QualifiedPathInExpression &expr); - NodeId 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_t expr_locus); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // !RUST_AST_RESOLVE_PATH_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc deleted file mode 100644 index 3b80f9f..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (C) 2020-2025 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" - -namespace Rust { -namespace Resolver { - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type) -{ - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - PatternDeclaration::go (pattern, type, bindings); -} - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration resolver (bindings, type); - pattern.accept_vis (resolver); - - for (auto &map_entry : resolver.missing_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at (info.get_locus (), ErrorCode::E0408, - "variable '%s' is not bound in all patterns", - ident.as_string ().c_str ()); - } - - for (auto &map_entry : resolver.inconsistent_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at ( - info.get_locus (), ErrorCode::E0409, - "variable '%s' is bound inconsistently across pattern alternatives", - ident.as_string ().c_str ()); - } -} - -void -PatternDeclaration::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_subpattern ()) - { - pattern.get_subpattern ().accept_vis (*this); - } - - Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; - add_new_binding (pattern.get_ident (), pattern.get_node_id (), - BindingTypeInfo (mut, pattern.get_is_ref (), - pattern.get_locus ())); -} - -void -PatternDeclaration::visit (AST::GroupedPattern &pattern) -{ - pattern.get_pattern_in_parens ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::ReferencePattern &pattern) -{ - pattern.get_referenced_pattern ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::PathInExpression &pattern) -{ - ResolvePath::go (pattern); -} - -void -PatternDeclaration::visit (AST::TupleStructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - AST::TupleStructItems &items = pattern.get_items (); - switch (items.get_item_type ()) - { - case AST::TupleStructItems::RANGE: - { - // TODO - rust_unreachable (); - } - break; - - case AST::TupleStructItems::NO_RANGE: - { - auto &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); - - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - inner_pattern->accept_vis (*this); - } - } - 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: - { - AST::StructPatternFieldTuplePat &tuple - = static_cast<AST::StructPatternFieldTuplePat &> (*field); - - tuple.get_index_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT_PAT: - { - AST::StructPatternFieldIdentPat &ident - = static_cast<AST::StructPatternFieldIdentPat &> (*field); - - ident.get_ident_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT: - { - auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field); - - Mutability mut - = ident.is_mut () ? Mutability::Mut : Mutability::Imm; - - add_new_binding (ident.get_identifier (), ident.get_node_id (), - BindingTypeInfo (mut, ident.is_ref (), - ident.get_locus ())); - } - break; - } - } -} - -void -PatternDeclaration::visit (AST::TuplePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: - { - auto &ref = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::TuplePatternItems::TuplePatternItemType::RANGED: - { - auto &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -void -PatternDeclaration::visit (AST::AltPattern &pattern) -{ - // push a new set of 'Or' bindings to the stack. Accounts for the - // alternatives. e.g. in `p_0 | p_1`, bindings to the same identifier between - // p_0 and p_1 shouldn't cause an error. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ())); - - // This is a hack to avoid creating a separate visitor class for the - // consistency checks. We empty out the binding_info_map before each iteration - // to separate between the alts' binding_maps. And right after the alt - // visit... - auto tmp_binding_map = binding_info_map; - binding_info_map.clear (); - - std::vector<BindingMap> alts_binding_maps; - - for (auto &alt : pattern.get_alts ()) - { - // before this visit, the binding_info_map is guaranteed to be empty - rust_assert (binding_info_map.empty ()); - - // push a new `Product` context to correctly reject multiple bindings - // within this single alt. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())); - - alt->accept_vis (*this); - - // ...the binding_info_map is (potentially) populated. We copy it to the - // vector, and empty it out to be ready for the next iteration. And after - // all the iterations are finished... - alts_binding_maps.push_back (binding_info_map); - binding_info_map.clear (); - - // Remove the last (i.e. `Product`) context and add the bindings from the - // visited alt to the one before last (i.e. `Or`). Now (after checking - // with the alt internally), the bindings from this alt will reside in the - // `Or` context. - auto last_bound_idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - - for (auto &ident : last_bound_idents) - { - bindings_with_ctx.back ().idents.insert (ident); - } - } - - // Now we can finally check for consistency. - check_bindings_consistency (alts_binding_maps); - - // Now we remove the `Or` context we pushed earlier. - // e.g. in `(a, (p_0 | p_1), c)`: after finishing up inside the alt pattern, - // we return to the tuple (`Product`) context and push the new bindings. - auto idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - for (auto &ident : idents) - bindings_with_ctx.back ().idents.insert (ident.as_string ()); - - // ...we repopulate the binding_info_map correctly (the initial bindings - // stored in the tmp_binding_map + all the bindings from all the alts) - binding_info_map = tmp_binding_map; - for (auto &alt_map : alts_binding_maps) - for (auto &map_entry : alt_map) - binding_info_map.insert (map_entry); -} - -void -PatternDeclaration::add_new_binding (Identifier ident, NodeId node_id, - BindingTypeInfo info) -{ - bool has_binding_ctx = bindings_with_ctx.size () > 0; - rust_assert (has_binding_ctx); - - bool identifier_or_bound = false, identifier_product_bound = false; - - for (auto binding : bindings_with_ctx) - { - bool identifier_bound_here - = (binding.idents.find (ident) != binding.idents.end ()); - if (identifier_bound_here) - { - identifier_product_bound |= binding.ctx == PatternBoundCtx::Product; - identifier_or_bound |= binding.ctx == PatternBoundCtx::Or; - } - } - - if (identifier_product_bound) - { - if (type == Rib::ItemType::Param) - { - rust_error_at (info.get_locus (), ErrorCode::E0415, - "identifier '%s' is bound more than once in the " - "same parameter list", - ident.as_string ().c_str ()); - } - else - { - rust_error_at ( - info.get_locus (), ErrorCode::E0416, - "identifier '%s' is bound more than once in the same pattern", - ident.as_string ().c_str ()); - } - - return; - } - - if (!identifier_or_bound) - { - bindings_with_ctx.back ().idents.insert (ident); - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (node_id, ident.as_string ()), node_id, - info.get_locus (), type); - } - - binding_info_map.insert ({ident, info}); -} - -// Verifies that all the alts in an AltPattern have the same set of bindings -// with the same mutability and reference states. -void -PatternDeclaration::check_bindings_consistency ( - std::vector<BindingMap> &binding_maps) -{ - for (size_t i = 0; i < binding_maps.size (); i++) - { - auto &outer_bindings_map = binding_maps[i]; - - for (size_t j = 0; j < binding_maps.size (); j++) - { - // skip comparing the current outer map with itself. - if (j == i) - continue; - - auto &inner_bindings_map = binding_maps[j]; - - // iterate over the inner map entries and check if they exist in outer - // map - for (auto map_entry : inner_bindings_map) - { - auto ident = map_entry.first; // key - auto inner_info = map_entry.second; // value - bool ident_is_outer_bound = outer_bindings_map.count (ident); - - if (!ident_is_outer_bound && !missing_bindings.count (ident)) - missing_bindings.insert ({ident, inner_info}); - - else if (outer_bindings_map.count (ident) - && outer_bindings_map[ident] != inner_info - && !inconsistent_bindings.count (ident)) - inconsistent_bindings.insert ({ident, inner_info}); - } - } - } -} - -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: - { - auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); - - ResolvePath::go (ref.get_path ()); - } - break; - - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: - { - auto &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 ()); - resolve_range_pattern_bound (pattern.get_lower_bound ()); -} - -void -PatternDeclaration::visit (AST::SlicePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h deleted file mode 100644 index 876de16..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 2020-2025 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 { - -// Specifies whether the set of already bound patterns are related by 'Or' or -// 'Product'. Used to check for multiple bindings to the same identifier. -enum PatternBoundCtx -{ - // A product pattern context (e.g. struct and tuple patterns) - Product, - // An or-pattern context (e.g. p_0 | p_1 | ...) - Or, -}; - -struct PatternBinding -{ - PatternBoundCtx ctx; - std::set<Identifier> idents; - - PatternBinding (PatternBoundCtx ctx, std::set<Identifier> idents) - : ctx (ctx), idents (idents) - {} -}; - -// Info that gets stored in the map. Helps us detect if two bindings to the same -// identifier have different mutability or ref states. -class BindingTypeInfo -{ - Mutability mut; - bool is_ref; - location_t locus; - -public: - BindingTypeInfo (Mutability mut, bool is_ref, location_t locus) - : mut (mut), is_ref (is_ref), locus (locus) - {} - - BindingTypeInfo (BindingTypeInfo const &other) - : mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ()) - {} - - BindingTypeInfo (){}; - - location_t get_locus () const { return locus; } - Mutability get_mut () const { return mut; } - bool get_is_ref () const { return is_ref; } - - BindingTypeInfo operator= (BindingTypeInfo const &other) - { - mut = other.mut; - is_ref = other.is_ref; - locus = other.get_locus (); - - return *this; - } - - bool operator== (BindingTypeInfo const &other) - { - return mut == other.mut && is_ref == other.is_ref; - } - - bool operator!= (BindingTypeInfo const &other) - { - return !BindingTypeInfo::operator== (other); - } -}; - -typedef std::map<Identifier, BindingTypeInfo> BindingMap; - -class PatternDeclaration : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Pattern &pattern, Rib::ItemType type); - static void go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings); - - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - 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; - void visit (AST::AltPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info); - void check_bindings_consistency (std::vector<BindingMap> &binding_maps); - -private: - PatternDeclaration (std::vector<PatternBinding> &bindings_with_ctx, - Rib::ItemType type) - : ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type) - {} - - // To avoid having a separate visitor for consistency checks, we store - // bindings in two forms: - - // 1) Bindings as a vector of context-related sets. - // Used for checking multiple bindings to the same identifier (i.e. E0415, - // E0416). - std::vector<PatternBinding> &bindings_with_ctx; - - // 2) Bindings as a map between identifiers and binding info. - // Used for checking consistency between alt patterns (i.e. E0408, E0409). - BindingMap binding_info_map; - - // we need to insert the missing and inconsistent bindings (found in - // check_bindings_consistency) into maps to avoid duplication of error - // messages. - BindingMap inconsistent_bindings; - BindingMap missing_bindings; - - Rib::ItemType type; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc deleted file mode 100644 index bfba302..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020-2025 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-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-implitem.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, CanonicalPath::create_empty ()); - ResolveExternItem::go (*item, prefix, canonical_prefix); - } -} - -void -ResolveStmt::visit (AST::Trait &trait) -{ - ResolveTopLevel::go (trait, prefix, canonical_prefix); - ResolveItem::go (trait, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::InherentImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::TraitImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = decl; - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h deleted file mode 100644 index d714511..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright (C) 2020-2025 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-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-expr.h" -#include "rust-item.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::ExprStmt &stmt) override - { - ResolveExpr::go (stmt.get_expr (), 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, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::LetStmt &stmt) override - { - if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix); - - if (stmt.has_else_expr ()) - ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix); - - PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var); - if (stmt.has_type ()) - ResolveType::go (stmt.get_type ()); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::TupleField &field : struct_decl.get_fields ()) - ResolveType::go (field.get_field_type ()); - - 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - for (auto &variant : enum_decl.get_variants ()) - ResolveStmt::go (*variant, 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 ().as_string ())); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), 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 ()); - } - - 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), 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 ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - 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, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } - - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::StaticItem &var) 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 diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc deleted file mode 100644 index 9b38e6a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2020-2025 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 (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) -{ - ResolveExpr::go (field.get_value (), 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 diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h deleted file mode 100644 index 87fa60d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020-2025 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" - -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 diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h deleted file mode 100644 index f52fb8a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (C) 2020-2025 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-implitem.h" -#include "rust-name-resolver.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 ().as_string ()); - 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, - Rib::ItemType::Module, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, module.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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, 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, alias.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - resolver->push_new_module_scope (enum_decl.get_node_id ()); - for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (*variant, path, cpath); - - resolver->pop_module_scope (); - - 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 ().as_string ()); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - 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, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - auto duplicate_item - = [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }; - - resolver->get_type_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - if (struct_decl.is_unit_struct ()) - resolver->get_name_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - 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 ().as_string ()); - 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, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - 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, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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 ().as_string ()); - 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, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - CanonicalPath impl_type - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, 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, - Rib::ItemType::TraitImpl, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, impl_block.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::Trait &trait) override - { - auto decl = CanonicalPath::new_seg (trait.get_node_id (), - trait.get_identifier ().as_string ()); - 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, - Rib::ItemType::Trait, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, trait.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - 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, 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 (); - resolved_crate = mappings.crate_num_to_nodeid (crate_num).value (); - } - else - { - auto cnum - = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()); - if (!cnum) - { - rust_error_at (extern_crate.get_locus (), "unknown crate %qs", - extern_crate.get_referenced_crate ().c_str ()); - return; - } - if (auto resolved = mappings.crate_num_to_nodeid (*cnum)) - resolved_crate = resolved.value (); - else - { - 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, - Rib::ItemType::ExternCrate, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, extern_crate.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - -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 diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc deleted file mode 100644 index a040228..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright (C) 2020-2025 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" -#include "rust-canonical-path.h" -#include "rust-type.h" -#include "rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -// rust-ast-resolve-type.h - -NodeId -ResolveType::go (AST::Type &type) -{ - ResolveType resolver; - type.accept_vis (resolver); - return resolver.resolved_node; -} - -void -ResolveType::visit (AST::BareFunctionType &fntype) -{ - for (auto ¶m : fntype.get_function_params ()) - ResolveType::go (param.get_type ()); - - if (fntype.has_return_type ()) - ResolveType::go (fntype.get_return_type ()); -} - -void -ResolveType::visit (AST::TupleType &tuple) -{ - if (tuple.is_unit_type ()) - { - resolved_node = resolver->get_unit_type_node_id (); - return; - } - - for (auto &elem : tuple.get_elems ()) - ResolveType::go (*elem); -} - -void -ResolveType::visit (AST::TypePath &path) -{ - ResolveRelativeTypePath::go (path, resolved_node); -} - -void -ResolveType::visit (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath::go (path); -} - -void -ResolveType::visit (AST::ArrayType &type) -{ - type.get_elem_type ().accept_vis (*this); - ResolveExpr::go (type.get_size_expr (), 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); - } -} - -void -ResolveType::visit (AST::ParenthesisedType &type) -{ - resolved_node = ResolveType::go (*type.get_type_in_parens ()); -} - -void -ResolveType::visit (AST::ReferenceType &type) -{ - resolved_node = ResolveType::go (type.get_type_referenced ()); -} - -void -ResolveType::visit (AST::RawPointerType &type) -{ - resolved_node = ResolveType::go (type.get_type_pointed_to ()); -} - -void -ResolveType::visit (AST::InferredType &) -{ - // nothing to do -} - -void -ResolveType::visit (AST::NeverType &) -{ - resolved_node = resolver->get_never_type_node_id (); -} - -void -ResolveType::visit (AST::SliceType &type) -{ - resolved_node = ResolveType::go (type.get_elem_type ()); -} - -void -ResolveType::visit (AST::ImplTraitType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveType::visit (AST::ImplTraitTypeOneBound &type) -{ - ResolveTypeBound::go (*type.get_trait_bound ().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); - bool is_first_segment = i == 0; - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - auto ident_string = segment->is_lang_item () - ? LangItem::PrettyString (segment->get_lang_item ()) - : segment->get_ident_segment ().as_string (); - - resolved_node_id = UNKNOWN_NODEID; - - if (segment->is_lang_item ()) - { - resolved_node_id = Analysis::Mappings::get ().get_lang_item_node ( - segment->get_lang_item ()); - previous_resolved_node_id = resolved_node_id; - } - else - { - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment->is_lower_self_seg ()) - { - rust_error_at (segment->get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment->as_string ().c_str ()); - return false; - } - - 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: - AST::TypePathSegmentFunction *fnseg - = static_cast<AST::TypePathSegmentFunction *> (segment.get ()); - - AST::TypePathFunction &fn = fnseg->get_type_path_function (); - for (auto ¶m : fn.get_params ()) - { - ResolveType::go (*param); - } - - if (fn.has_return_type ()) - { - ResolveType::go (fn.get_return_type ()); - } - - break; - } - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), ident_string); - if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (!segment->is_lang_item () && 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - 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) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, ident_string); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - 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; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment->get_locus (), - "Cannot find path %qs 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 (), ErrorCode::E0412, - "could not resolve type path %qs", - segment->get_ident_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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - 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)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (path.get_node_id (), - resolved_node_id); - } - else - { - rust_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 (); - ResolveType::go (type); - - if (seg.has_as_clause ()) - ResolveType::go (seg.get_as_type_path ()); - - 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; - - if (auto type_path = mappings.lookup_canonical_path (resolved_node)) - { - 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 `rust_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 (), - 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 (), 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 (), 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 (), 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) -{ - rust_assert (!type.get_type_param_bounds ().empty ()); - - auto &first_bound = type.get_type_param_bounds ().front (); - - // Is it allowed or even possible to have a lifetime bound as a first bound? - if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME) - rust_unreachable (); - - auto &trait = static_cast<AST::TraitBound &> (*first_bound); - - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path); - - // right? - rust_assert (ok); - - auto slice_path = "<dyn " + path.get (); - - for (size_t idx = 1; idx < type.get_type_param_bounds ().size (); idx++) - { - auto &additional_bound = type.get_type_param_bounds ()[idx]; - - std::string str; - - switch (additional_bound->get_bound_type ()) - { - case AST::TypeParamBound::TRAIT: - { - auto bound_path = CanonicalPath::create_empty (); - - auto &bound_type_path - = static_cast<AST::TraitBound &> (*additional_bound) - .get_type_path (); - bool ok - = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path); - - if (!ok) - continue; - - str = bound_path.get (); - break; - } - case AST::TypeParamBound::LIFETIME: - rust_unreachable (); - break; - } - slice_path += " + " + str; - } - - slice_path += ">"; - - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); -} - -void -ResolveTypeToCanonicalPath::visit (AST::NeverType &type) -{ - result = CanonicalPath::new_seg (type.get_node_id (), "!"); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TupleType &type) -{ - if (!type.is_unit_type ()) - rust_unreachable (); - - result = CanonicalPath::new_seg (type.get_node_id (), "()"); -} - -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 (), prefix, canonical_prefix); - break; - case AST::GenericArg::Kind::Type: - ResolveType::go (arg.get_type ()); - break; - default: - rust_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); - } - - for (auto &binding : generic_args.get_binding_args ()) - { - ResolveType::go (binding.get_type ()); - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h deleted file mode 100644 index f1481fc..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 2020-2025 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-diagnostics.h" -#include "rust-hir-map.h" -#include "rust-path.h" -#include "rust-type.h" -#include "util/rust-hir-map.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); - - void visit (AST::BareFunctionType &fntype) override; - void visit (AST::TupleType &tuple) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInType &path) override; - 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::ParenthesisedType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::ImplTraitTypeOneBound &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 ResolveGenericParams : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (std::vector<std::unique_ptr<AST::GenericParam>> ¶ms, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - // this needs to be done in two phases as they can be used and defined later - // in bounds - for (auto ¶m : params) - param->accept_vis (resolver); - - resolver.first_pass = false; - - for (auto ¶m : params) - param->accept_vis (resolver); - } - - static void go_single (AST::GenericParam ¶m, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - param.accept_vis (resolver); - resolver.first_pass = false; - param.accept_vis (resolver); - } - - void visit (AST::ConstGenericParam ¶m) override - { - if (first_pass) - ResolveType::go (param.get_type ()); - else if (param.has_default_value ()) - ResolveExpr::go (param.get_default_value_unchecked ().get_expression (), - prefix, canonical_prefix); - } - - void visit (AST::TypeParam ¶m) override - { - if (first_pass) - { - // if it has a type lets resolve it - if (param.has_type ()) - ResolveType::go (param.get_type ()); - - auto seg = CanonicalPath::new_seg ( - param.get_node_id (), param.get_type_representation ().as_string ()); - resolver->get_type_scope ().insert ( - seg, param.get_node_id (), param.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (param.get_locus (), - "generic param defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - - mappings.insert_canonical_path (param.get_node_id (), seg); - } - else if (param.has_type_param_bounds ()) - { - for (auto &bound : param.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); - } - } - -private: - ResolveGenericParams (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), first_pass (true), prefix (prefix), - canonical_prefix (canonical_prefix) - {} - - bool first_pass; - 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 ()); - if (item.has_type_param_bounds ()) - { - for (auto &bound : item.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - } - -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; - - void visit (AST::NeverType &type) override; - - void visit (AST::TupleType &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 diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc deleted file mode 100644 index 2208f70..0000000 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 2020-2025 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 (); - - // Clones the crate name instead of references due to gcc's possibly - // dangling references warnings - const auto crate_name = mappings.get_crate_name (cnum).value (); - - // 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_label_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 (), UNDEF_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 &item : crate.items) - ResolveTopLevel::go (*item, 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 &item : crate.items) - ResolveItem::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // done - resolver->pop_module_scope (); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 4fd1dd2..0dff831 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -438,7 +438,9 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) // We don't want to insert `self` with `use module::self` if (path.get_final_segment ().is_lower_self_seg ()) { - rust_assert (segments.size () > 1); + // Erroneous `self` or `{self}` use declaration + if (segments.size () == 1) + break; declared_name = segments[segments.size () - 2].as_string (); } else @@ -447,8 +449,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) break; } case AST::UseTreeRebind::NewBindType::WILDCARD: - rust_unreachable (); - break; + // We don't want to insert it into the trie + return; } for (auto &&definition : data.definitions ()) @@ -459,6 +461,19 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) void Early::visit (AST::UseDeclaration &decl) { + // We do not want to visit the use trees, we're only looking for top level + // rebind. eg. `use something;` or `use something::other;` + if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ()); + if (rebind.get_path ().get_final_segment ().is_lower_self_seg ()) + { + collect_error ( + Error (decl.get_locus (), ErrorCode::E0429, + "%<self%> imports are only allowed within a { } list")); + } + } + auto &imports = toplevel.get_imports_to_resolve (); auto current_import = imports.find (decl.get_node_id ()); if (current_import != imports.end ()) @@ -484,5 +499,31 @@ Early::visit (AST::UseDeclaration &decl) DefaultResolver::visit (decl); } +void +Early::visit (AST::UseTreeList &use_list) +{ + if (!use_list.has_path ()) + { + for (auto &&tree : use_list.get_trees ()) + { + if (tree->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*tree); + auto path_size = rebind.get_path ().get_segments ().size (); + if (path_size == 1 + && rebind.get_path () + .get_final_segment () + .is_lower_self_seg ()) + { + collect_error (Error (rebind.get_locus (), ErrorCode::E0431, + "%<self%> import can only appear in an " + "import list with a non-empty prefix")); + } + } + } + } + DefaultResolver::visit (use_list); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index 960de0e..3940386 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -61,6 +61,7 @@ public: void visit (AST::Function &) override; void visit (AST::StructStruct &) override; void visit (AST::UseDeclaration &) override; + void visit (AST::UseTreeList &) override; struct ImportData { diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc deleted file mode 100644 index 7b365ef..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright (C) 2020-2025 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-early-name-resolver.h" -#include "rust-pattern.h" -#include "rust-name-resolver.h" -#include "rust-macro-builtins.h" -#include "rust-attribute-values.h" - -namespace Rust { -namespace Resolver { - -// Check if a module contains the `#[macro_use]` attribute -static bool -is_macro_use_module (const AST::Module &mod) -{ - for (const auto &attr : mod.get_outer_attrs ()) - if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE) - return true; - - return false; -} - -std::vector<std::unique_ptr<AST::Item>> -EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) -{ - if (!is_macro_use_module (module)) - return {}; - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive) - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - std::vector<std::unique_ptr<AST::Item>> escaped_macros; - - scoped (module.get_node_id (), [&module, &escaped_macros, this] { - for (auto &item : module.get_items ()) - { - if (item->get_item_kind () == AST::Item::Kind::Module) - { - auto &module = *static_cast<AST::Module *> (item.get ()); - auto new_macros = accumulate_escaped_macros (module); - - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (escaped_macros)); - - continue; - } - - if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition) - escaped_macros.emplace_back (item->clone_item ()); - } - }); - - return escaped_macros; -} - -EarlyNameResolver::EarlyNameResolver () - : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()), - mappings (Analysis::Mappings::get ()) -{} - -void -EarlyNameResolver::go (AST::Crate &crate) -{ - visit (crate); -} - -void -EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) -{ - for (auto &arg : generic_args.get_generic_args ()) - arg.accept_vis (*this); - - for (auto &arg : generic_args.get_binding_args ()) - arg.get_type ().accept_vis (*this); -} - -void -EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) -{ - path.get_type ().accept_vis (*this); - - if (path.has_as_clause ()) - path.get_as_type_path ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Crate &crate) -{ - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = crate.take_items (); - - scoped (crate.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - crate.set_items (std::move (new_items)); - - scoped (crate.get_node_id (), [&crate, this] () { - for (auto &item : crate.items) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::DelimTokenTree &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &) -{} - -void -EarlyNameResolver::visit (AST::IdentifierExpr &) -{} - -void -EarlyNameResolver::visit (AST::LifetimeParam &) -{} - -void -EarlyNameResolver::visit (AST::ConstGenericParam &) -{} - -// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well? -// std::arch::asm!()? -void -EarlyNameResolver::visit (AST::PathInExpression &path) -{ - if (!path.is_lang_item ()) - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) -{ - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInExpression &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInType &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LiteralExpr &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputLiteral &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMacro &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemLitExpr &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemPathExpr &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStruct &) -{} - -void -EarlyNameResolver::visit (AST::StructExprFieldIdentifier &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStructBase &) -{} - -void -EarlyNameResolver::visit (AST::BlockExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &stmt : expr.get_statements ()) - stmt->accept_vis (*this); - - if (expr.has_tail_expr ()) - expr.get_tail_expr ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ContinueExpr &) -{} - -void -EarlyNameResolver::visit (AST::RangeFullExpr &) -{} - -void -EarlyNameResolver::visit (AST::ForLoopExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - expr.get_pattern ().accept_vis (*this); - expr.get_iterator_expr ().accept_vis (*this); - expr.get_loop_block ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::IfLetExpr &expr) -{ - expr.get_value_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), - [&expr, this] () { expr.get_if_block ().accept_vis (*this); }); -} - -void -EarlyNameResolver::visit (AST::MatchExpr &expr) -{ - expr.get_scrutinee_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &arm : expr.get_match_cases ()) - { - scoped (arm.get_node_id (), [&arm, this] () { - if (arm.get_arm ().has_match_arm_guard ()) - arm.get_arm ().get_guard_expr ().accept_vis (*this); - - for (auto &pattern : arm.get_arm ().get_patterns ()) - pattern->accept_vis (*this); - - arm.get_expr ().accept_vis (*this); - }); - } - }); -} - -void -EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &) -{} - -void -EarlyNameResolver::visit (AST::Module &module) -{ - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - // so we need to only go "one scope down" for fetching macros. Macros within - // functions are still scoped only within that function. But we have to be - // careful because nested modules with #[macro_use] actually works! - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = module.take_items (); - - scoped (module.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - module.set_items (std::move (new_items)); - - scoped (module.get_node_id (), [&module, this] () { - for (auto &item : module.get_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternCrate &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeGlob &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeList &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeRebind &) -{} - -void -EarlyNameResolver::visit (AST::UseDeclaration &) -{} - -void -EarlyNameResolver::visit (AST::EnumItem &) -{} - -void -EarlyNameResolver::visit (AST::Union &) -{} - -void -EarlyNameResolver::visit (AST::TraitItemType &) -{} - -void -EarlyNameResolver::visit (AST::Trait &trait) -{ - // shouldn't need to visit trait.get_implicit_self () - - for (auto &generic : trait.get_generic_params ()) - generic->accept_vis (*this); - - scoped (trait.get_node_id (), [&trait, this] () { - for (auto &item : trait.get_trait_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::InherentImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::TraitImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternalTypeItem &item) -{ - // nothing to do? -} - -void -EarlyNameResolver::visit (AST::ExternBlock &block) -{ - scoped (block.get_node_id (), [&block, this] () { - for (auto &item : block.get_extern_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::MacroMatchRepetition &) -{} - -void -EarlyNameResolver::visit (AST::MacroMatcher &) -{} - -void -EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def) -{ - auto path = CanonicalPath::new_seg (rules_def.get_node_id (), - rules_def.get_rule_name ().as_string ()); - resolver.get_macro_scope ().insert (path, rules_def.get_node_id (), - rules_def.get_locus ()); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_def (rules_def.get_node_id ())) - return; - - mappings.insert_macro_def (&rules_def); - rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]", - path.get ().c_str ()); -} - -void -EarlyNameResolver::visit (AST::MacroInvocation &invoc) -{ - auto &invoc_data = invoc.get_invoc_data (); - auto has_semicolon = invoc.has_semicolon (); - - if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) - for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) - pending_invoc->accept_vis (*this); - - // ?? - // switch on type of macro: - // - '!' syntax macro (inner switch) - // - procedural macro - "A token-based function-like macro" - // - 'macro_rules' (by example/pattern-match) macro? or not? "an - // AST-based function-like macro" - // - else is unreachable - // - attribute syntax macro (inner switch) - // - procedural macro attribute syntax - "A token-based attribute - // macro" - // - legacy macro attribute syntax? - "an AST-based attribute macro" - // - non-macro attribute: mark known - // - else is unreachable - // - derive macro (inner switch) - // - derive or legacy derive - "token-based" vs "AST-based" - // - else is unreachable - // - derive container macro - unreachable - - // lookup the rules for this macro - NodeId resolved_node = UNKNOWN_NODEID; - NodeId source_node = UNKNOWN_NODEID; - if (has_semicolon) - source_node = invoc.get_macro_node_id (); - else - source_node = invoc.get_node_id (); - auto seg - = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ()); - - bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node); - if (!found) - { - rust_error_at (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - seg.get ().c_str ()); - return; - } - - // lookup the rules - auto rules_def = mappings.lookup_macro_def (resolved_node); - - auto &outer_attrs = rules_def.value ()->get_outer_attrs (); - bool is_builtin - = std::any_of (outer_attrs.begin (), outer_attrs.end (), - [] (AST::Attribute attr) { - return attr.get_path () - == Values::Attributes::RUSTC_BUILTIN_MACRO; - }); - - if (is_builtin) - { - auto builtin_kind = builtin_macro_from_string ( - rules_def.value ()->get_rule_name ().as_string ()); - invoc.map_to_builtin (builtin_kind.value ()); - } - - auto attributes = rules_def.value ()->get_outer_attrs (); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_invocation (invoc)) - return; - - mappings.insert_macro_invocation (invoc, *rules_def); -} - -// FIXME: ARTHUR: Do we need to resolve these as well here? - -void -EarlyNameResolver::visit (AST::MetaItemPath &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemSeq &) -{} - -void -EarlyNameResolver::visit (AST::MetaNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::MetaListPaths &) -{} - -void -EarlyNameResolver::visit (AST::MetaListNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundLiteral &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundPath &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundQualPath &) -{} - -void -EarlyNameResolver::visit (AST::StructPatternFieldIdent &) -{} - -void -EarlyNameResolver::visit (AST::StructPattern &) -{} - -void -EarlyNameResolver::visit (AST::TupleStructPattern &pattern) -{ - pattern.get_items ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleType &) -{} - -void -EarlyNameResolver::visit (AST::RawPointerType &) -{} - -void -EarlyNameResolver::visit (AST::ReferenceType &) -{} - -void -EarlyNameResolver::visit (AST::ArrayType &) -{} - -void -EarlyNameResolver::visit (AST::SliceType &) -{} - -void -EarlyNameResolver::visit (AST::InferredType &) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h deleted file mode 100644 index d3c5225..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2020-2025 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_EARLY_NAME_RESOLVER_H -#define RUST_EARLY_NAME_RESOLVER_H - -#include "rust-name-resolver.h" -#include "rust-system.h" -#include "rust-ast.h" -#include "rust-ast-visitor.h" - -namespace Rust { -namespace Resolver { - -class EarlyNameResolver : public AST::DefaultASTVisitor -{ -public: - EarlyNameResolver (); - - void go (AST::Crate &crate); - -private: - using AST::DefaultASTVisitor::visit; - - /** - * Execute a lambda within a scope. This is equivalent to calling - * `enter_scope` before your code and `exit_scope` after. This ensures - * no errors can be committed - */ - void scoped (NodeId scope_id, std::function<void ()> fn) - { - auto old_scope = current_scope; - current_scope = scope_id; - resolver.get_macro_scope ().push (scope_id); - resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ()); - - fn (); - - resolver.get_macro_scope ().pop (); - current_scope = old_scope; - } - - /** - * Accumulate all of the nested macros which escape their module through the - * use of the #[macro_use] attribute. - * - * This function recursively accumulates macros in all of the nested modules - * of an item container (an AST::Crate or an AST::Module) and returns this new - * list of items. You can then use the `take_items` and `set_items` functions - * on these containers to replace their list of items. - */ - std::vector<std::unique_ptr<AST::Item>> - accumulate_escaped_macros (AST::Module &module); - - /** - * The "scope" we are currently in. - * - * This involves lexical scopes: - * - * ```rust - * // current_scope = crate_id; - * macro_rules! foo { () => {} ) - * - * { - * // current_scope = current_block_id; - * macro_rules! foo { () => { something!(); } } - * } - * // current_scope = crate_id; - * ``` - * - * as well as any sort of scope-like structure that might impact import name - * resolution or macro name resolution: - * - * ```rust - * macro_rules! foo { - * () => { fn empty() {} } - * } - * - * - * trait Foo { - * fn foo() { - * fn inner_foo() { - * macro_rules! foo { () => {} ) - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * ``` - */ - NodeId current_scope; - - /* The crate's scope */ - NodeId crate_scope; - - Resolver &resolver; - Analysis::Mappings &mappings; - - /** - * Early name-resolve generic args, which can be macro invocations - */ - void resolve_generic_args (AST::GenericArgs &generic_args); - - /** - * Early name-resolve a qualified path type, which can contain macro - * invocations - */ - void resolve_qualified_path_type (AST::QualifiedPathType &path); - - virtual void visit (AST::Crate &crate); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - virtual void visit (AST::IdentifierExpr &ident_expr); - virtual void visit (AST::LifetimeParam &lifetime_param); - virtual void visit (AST::ConstGenericParam &const_param); - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::AttrInputMacro &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathExpr &meta_item); - virtual void visit (AST::StructExprStruct &expr); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::Module &module); - virtual void visit (AST::ExternCrate &crate); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - virtual void visit (AST::ExternalTypeItem &item); - virtual void visit (AST::ExternBlock &block); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - virtual void visit (AST::TupleStructPattern &pattern); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_EARLY_NAME_RESOLVER_H diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 1ed87b3..848f5e6 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -531,7 +531,7 @@ ForeverStack<N>::resolve_segments ( || seg.is_lower_self_seg ())) return tl::nullopt; - tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt; + tl::optional<std::reference_wrapper<Node>> child = tl::nullopt; /* * On every iteration this loop either @@ -583,10 +583,17 @@ ForeverStack<N>::resolve_segments ( break; } - if (N == Namespace::Types) + auto rib_lookup = current_node->rib.get (seg.as_string ()); + if (rib_lookup && !rib_lookup->is_ambiguous ()) { - auto rib_lookup = current_node->rib.get (seg.as_string ()); - if (rib_lookup && !rib_lookup->is_ambiguous ()) + if (Analysis::Mappings::get () + .lookup_glob_container (rib_lookup->get_node_id ()) + .has_value ()) + { + child = dfs_node (root, rib_lookup->get_node_id ()).value (); + break; + } + else { insert_segment_resolution (outer_seg, rib_lookup->get_node_id ()); @@ -611,9 +618,9 @@ ForeverStack<N>::resolve_segments ( current_node = ¤t_node->parent.value (); } - // if child didn't contain a value - // the while loop above should have return'd or kept looping - current_node = &child.value (); + // if child didn't point to a value + // the while loop above would have returned or kept looping + current_node = &child->get (); insert_segment_resolution (outer_seg, current_node->id); } diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index e39ca15..96b38f4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -24,6 +24,7 @@ #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" #include "rust-name-resolution-context.h" +#include "rust-resolve-builtins.h" #include "rust-path.h" #include "rust-system.h" #include "rust-tyty.h" @@ -38,84 +39,10 @@ Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx), funny_error (false), block_big_self (false) {} -static NodeId -next_node_id () -{ - return Analysis::Mappings::get ().get_next_node_id (); -}; - -static HirId -next_hir_id () -{ - return Analysis::Mappings::get ().get_next_hir_id (); -}; - -void -Late::setup_builtin_types () -{ - // access the global type context to setup the TyTys - auto &ty_ctx = *Resolver::TypeCheckContext::get (); - - // Late builtin type struct helper - struct LType - { - std::string name; - NodeId node_id; - NodeId hir_id; - TyTy::BaseType *type; - - explicit LType (std::string name, TyTy::BaseType *type) - : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()), - type (type) - {} - }; - - static const LType builtins[] = { - {LType ("bool", new TyTy::BoolType (next_hir_id ()))}, - {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, - {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, - {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, - {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))}, - {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))}, - {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))}, - {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))}, - {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))}, - {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))}, - {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))}, - {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))}, - {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))}, - {LType ("usize", new TyTy::USizeType (next_hir_id ()))}, - {LType ("isize", new TyTy::ISizeType (next_hir_id ()))}, - {LType ("char", new TyTy::CharType (next_hir_id ()))}, - {LType ("str", new TyTy::StrType (next_hir_id ()))}, - {LType ("!", new TyTy::NeverType (next_hir_id ()))}, - - // the unit type `()` does not play a part in name-resolution - so we only - // insert it in the type context... - }; - - // There's a special Rib for putting prelude items, since prelude items need - // to satisfy certain special rules. - ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void { - for (const auto &builtin : builtins) - { - auto ok = ctx.types.insert (builtin.name, builtin.node_id); - rust_assert (ok); - - ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); - ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); - } - }); - - // ...here! - auto *unit_type = TyTy::TupleType::get_unit_type (); - ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type); -} - void Late::go (AST::Crate &crate) { - setup_builtin_types (); + Builtins::setup_type_ctx (); visit (crate); } @@ -521,20 +448,22 @@ Late::visit_impl_type (AST::Type &type) block_big_self = false; } -void -Late::visit (AST::TypePath &type) +template <typename P> +static void +resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self, + P &type) { // should we add type path resolution in `ForeverStack` directly? Since it's // quite more complicated. // maybe we can overload `resolve_path<Namespace::Types>` to only do // typepath-like path resolution? that sounds good - DefaultResolver::visit (type); - // prevent "impl Self {}" and similar if (type.get_segments ().size () == 1 - && !type.get_segments ().front ()->is_lang_item () - && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + && !unwrap_segment_get_lang_item (type.get_segments ().front ()) + .has_value () + && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg () + && block_big_self) { rust_error_at (type.get_locus (), "%<Self%> is not valid in the self type of an impl block"); @@ -547,17 +476,17 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { - if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) + if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()))) rust_error_at (type.get_locus (), ErrorCode::E0412, "could not resolve type path %qs", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } @@ -574,6 +503,14 @@ Late::visit (AST::TypePath &type) } void +Late::visit (AST::TypePath &type) +{ + DefaultResolver::visit (type); + + resolve_type_path_like (ctx, block_big_self, type); +} + +void Late::visit (AST::Visibility &vis) { if (!vis.has_path ()) @@ -649,10 +586,7 @@ Late::visit (AST::StructExprStruct &s) visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -663,10 +597,7 @@ Late::visit (AST::StructExprStructBase &s) DefaultResolver::visit (s.get_struct_name ()); visit (s.get_struct_base ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -680,10 +611,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } // needed because Late::visit (AST::GenericArg &) is non-virtual diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 95540e3..608ae38 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -75,9 +75,6 @@ public: private: void resolve_label (AST::Lifetime &lifetime); - /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ - void setup_builtin_types (); - bool funny_error; /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ diff --git a/gcc/rust/resolve/rust-resolve-builtins.cc b/gcc/rust/resolve/rust-resolve-builtins.cc new file mode 100644 index 0000000..b16db9a --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.cc @@ -0,0 +1,125 @@ +// Copyright (C) 2025 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-resolve-builtins.h" +#include "rust-name-resolution-context.h" +#include "rust-tyty.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver2_0 { +namespace Builtins { + +// Use X-macros + +#define TYPE_UINT(n, enum_ident) TYPE1 (n, UintType, UintType::enum_ident) +#define TYPE_INT(n, enum_ident) TYPE1 (n, IntType, IntType::enum_ident) + +#define BUILTIN_TYPES \ + TYPE0 ("bool", BoolType) \ + TYPE_UINT ("u8", U8) \ + TYPE_UINT ("u16", U16) \ + TYPE_UINT ("u32", U32) \ + TYPE_UINT ("u64", U64) \ + TYPE_UINT ("u128", U128) \ + TYPE_INT ("i8", I8) \ + TYPE_INT ("i16", I16) \ + TYPE_INT ("i32", I32) \ + TYPE_INT ("i64", I64) \ + TYPE_INT ("i128", I128) \ + TYPE1 ("f32", FloatType, FloatType::F32) \ + TYPE1 ("f64", FloatType, FloatType::F64) \ + TYPE0 ("usize", USizeType) \ + TYPE0 ("isize", ISizeType) \ + TYPE0 ("char", CharType) \ + TYPE0 ("str", StrType) \ + TYPE0 ("!", NeverType) + +// Define constants using X macros + +#define TYPE0(...) 1 + +#define TYPE1(...) 1 + +static constexpr size_t builtin_count = BUILTIN_TYPES 0; +#undef TYPE0 +#undef TYPE1 + +#define TYPE0(n, ...) n, +#define TYPE1(n, ...) n, +static constexpr const char *builtin_names[] = {BUILTIN_TYPES}; +#undef TYPE0 +#undef TYPE1 + +static NodeId builtin_node_ids[builtin_count]; + +void +setup_lang_prelude (NameResolutionContext &ctx) +{ + auto &mappings = Analysis::Mappings::get (); + + // insert into prelude rib + ctx.scoped (Rib::Kind::Prelude, 0, [&mappings, &ctx] (void) -> void { + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = mappings.get_next_node_id (); + rust_assert (ctx.types.insert (Identifier (builtin_names[i]), node_id)); + builtin_node_ids[i] = node_id; + } + }); +} + +void +setup_type_ctx () +{ + auto &mappings = Analysis::Mappings::get (); + auto &ty_ctx = *Resolver::TypeCheckContext::get (); + + HirId hir_ids[builtin_count]; + for (size_t i = 0; i < builtin_count; i++) + hir_ids[i] = mappings.get_next_hir_id (); + + TyTy::BaseType *types[builtin_count]; + { + size_t i = 0; +#define TYPE_BASE(stub) \ + types[i] = new TyTy::stub; \ + i++; +#define TYPE0(n, ty) TYPE_BASE (ty (hir_ids[i])) +#define TYPE1(n, ty, p1) TYPE_BASE (ty (hir_ids[i], TyTy::p1)) + BUILTIN_TYPES +#undef TYPE_BASE +#undef TYPE0 +#undef TYPE1 + } + + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = builtin_node_ids[i]; + HirId hir_id = hir_ids[i]; + mappings.insert_node_to_hir (node_id, hir_id); + ty_ctx.insert_builtin (hir_id, node_id, types[i]); + } + + // handle unit type separately + auto *unit_type = TyTy::TupleType::get_unit_type (); + ty_ctx.insert_builtin (unit_type->get_ref (), mappings.get_next_node_id (), + unit_type); +} + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-resolve-builtins.h b/gcc/rust/resolve/rust-resolve-builtins.h new file mode 100644 index 0000000..e7e1bd2 --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.h @@ -0,0 +1,37 @@ +// Copyright (C) 2025 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_RESOLVE_BUILTINS_H +#define RUST_RESOLVE_BUILTINS_H + +namespace Rust { +namespace Resolver2_0 { + +// forward declare +class NameResolutionContext; + +namespace Builtins { + +void setup_lang_prelude (NameResolutionContext &ctx); +void setup_type_ctx (); + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust + +#endif // RUST_RESOLVE_BUILTINS_H |
