Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gcc/rust/Make-lang.in
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ GRS_OBJS = \
rust/rust-finalize-imports-2.0.o \
rust/rust-ice-finalizer.o \
rust/rust-late-name-resolver-2.0.o \
rust/rust-identifier-path.o \
rust/rust-immutable-name-resolution-context.o \
rust/rust-name-resolver.o \
rust/rust-resolve-builtins.o \
Expand Down
8 changes: 6 additions & 2 deletions gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,9 @@ PlaceInfo::specialize (const Constructor &c) const
TyTy::VariantDef *variant
= adt->get_variants ().at (c.get_variant_index ());
if (variant->get_variant_type ()
== TyTy::VariantDef::VariantType::NUM)
== TyTy::VariantDef::VariantType::NUM
|| variant->get_variant_type ()
== TyTy::VariantDef::VariantType::UNIT)
return {};

std::vector<PlaceInfo> new_place_infos;
Expand Down Expand Up @@ -1050,6 +1052,7 @@ WitnessPat::to_string () const

switch (variant->get_variant_type ())
{
case TyTy::VariantDef::VariantType::UNIT:
case TyTy::VariantDef::VariantType::NUM:
{
return buf;
Expand Down Expand Up @@ -1145,7 +1148,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
TyTy::VariantDef *variant
= adt->get_variants ().at (ctor.get_variant_index ());
if (variant->get_variant_type () == TyTy::VariantDef::NUM)
if (variant->get_variant_type () == TyTy::VariantDef::NUM
|| variant->get_variant_type () == TyTy::VariantDef::UNIT)
arity = 0;
else
arity = variant->get_fields ().size ();
Expand Down
28 changes: 28 additions & 0 deletions gcc/rust/resolve/rust-early-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "rust-attributes.h"
#include "rust-finalize-imports-2.0.h"
#include "rust-attribute-values.h"
#include "rust-identifier-path.h"

namespace Rust {
namespace Resolver2_0 {
Expand Down Expand Up @@ -70,6 +71,9 @@ Early::go (AST::Crate &crate)
visit (crate);

textual_scope.pop ();

// handle IdentifierPattern vs PathInExpression disambiguation
IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
}

bool
Expand Down Expand Up @@ -543,5 +547,29 @@ Early::visit (AST::UseTreeList &use_list)
DefaultResolver::visit (use_list);
}

void
Early::visit (AST::IdentifierPattern &identifier)
{
// check if this is *really* a path pattern
if (!identifier.get_is_ref () && !identifier.get_is_mut ()
&& !identifier.has_subpattern ())
{
auto res = ctx.values.get (identifier.get_ident ());
if (res)
{
if (res->is_ambiguous ())
rust_error_at (identifier.get_locus (), ErrorCode::E0659,
"%qs is ambiguous",
identifier.get_ident ().as_string ().c_str ());
else
{
// HACK: bail out if the definition is a function
if (!ctx.mappings.is_function_node (res->get_node_id ()))
ident_path_to_convert.insert (identifier.get_node_id ());
}
}
}
}

} // namespace Resolver2_0
} // namespace Rust
6 changes: 6 additions & 0 deletions gcc/rust/resolve/rust-early-name-resolver-2.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "rust-default-resolver.h"
#include "rust-rib.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-pattern.h"

namespace Rust {
namespace Resolver2_0 {
Expand Down Expand Up @@ -67,6 +68,8 @@ class Early : public DefaultResolver

void visit (AST::Attribute &) override;

void visit (AST::IdentifierPattern &) override;

struct ImportData
{
enum class Kind
Expand Down Expand Up @@ -266,6 +269,9 @@ class Early : public DefaultResolver
const Early::ImportPair &mapping);

void finalize_rebind_import (const Early::ImportPair &mapping);

/* used to help conversion from IdentifierPattern to PathInExpression */
std::set<NodeId> ident_path_to_convert;
};

} // namespace Resolver2_0
Expand Down
9 changes: 7 additions & 2 deletions gcc/rust/resolve/rust-finalize-imports-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,13 @@ void
GlobbingVisitor::visit_enum_container (AST::Enum &item)
{
for (auto &variant : item.get_variants ())
ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
Namespace::Types);
{
ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
Namespace::Types);
if (variant->get_enum_item_kind () != AST::EnumItem::Kind::Struct)
ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
Namespace::Values);
}
}

void
Expand Down
8 changes: 8 additions & 0 deletions gcc/rust/resolve/rust-forever-stack.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ ForeverStack<Namespace::Types>::insert_variant (Identifier name, NodeId node)
Rib::Definition::NonShadowable (node, true));
}

template <>
inline tl::expected<NodeId, DuplicateNameError>
ForeverStack<Namespace::Values>::insert_variant (Identifier name, NodeId node)
{
return insert_inner (peek (), name.as_string (),
Rib::Definition::NonShadowable (node, true));
}

template <Namespace N>
inline void
ForeverStack<N>::insert_lang_prelude (Identifier name, NodeId id)
Expand Down
61 changes: 61 additions & 0 deletions gcc/rust/resolve/rust-identifier-path.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (C) 2026 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-system.h"
#include "rust-identifier-path.h"
#include "rust-pattern.h"

namespace Rust {
namespace Resolver2_0 {

IdentifierPathPass::IdentifierPathPass (NameResolutionContext &ctx,
std::set<NodeId> ident_path_to_convert)
: ctx (&ctx), ident_path_to_convert (std::move (ident_path_to_convert))
{}

void
IdentifierPathPass::go (AST::Crate &crate, NameResolutionContext &ctx,
std::set<NodeId> ident_path_to_convert)
{
IdentifierPathPass pass (ctx, std::move (ident_path_to_convert));
pass.visit (crate);
}

void
IdentifierPathPass::reseat (std::unique_ptr<AST::Pattern> &ptr)
{
AST::IdentifierPattern *ident_pat;
if (ptr->get_pattern_kind () == AST::Pattern::Kind::Identifier)
ident_pat = static_cast<AST::IdentifierPattern *> (ptr.get ());
else
return;

if (ident_path_to_convert.find (ident_pat->get_node_id ())
!= ident_path_to_convert.end ())
{
std::vector<AST::PathExprSegment> segments;
segments.emplace_back (ident_pat->get_ident ().as_string (),
ident_pat->get_locus ());
ptr = std::make_unique<AST::PathInExpression> (
std::move (segments), std::vector<AST::Attribute> (),
ident_pat->get_locus ());
}
}

} // namespace Resolver2_0
} // namespace Rust
50 changes: 50 additions & 0 deletions gcc/rust/resolve/rust-identifier-path.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (C) 2026 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_IDENTIFIER_PATH_H
#define RUST_RESOLVE_IDENTIFIER_PATH_H

#include "rust-ast-pointer-visitor.h"
#include "rust-name-resolution-context.h"

namespace Rust {
namespace Resolver2_0 {

// changes IdentifierPattern instances to PathInExpression instances
class IdentifierPathPass : public AST::PointerVisitor
{
public:
IdentifierPathPass (NameResolutionContext &ctx,
std::set<NodeId> ident_path_to_convert);

static void go (AST::Crate &crate, NameResolutionContext &ctx,
std::set<NodeId> ident_path_to_convert);

using AST::PointerVisitor::reseat;

void reseat (std::unique_ptr<AST::Pattern> &ptr) override;

private:
NameResolutionContext *ctx;
std::set<NodeId> ident_path_to_convert;
};

} // namespace Resolver2_0
} // namespace Rust

#endif // ! RUST_RESOLVE_IDENTIFIER_PATH_H
8 changes: 6 additions & 2 deletions gcc/rust/resolve/rust-name-resolution-context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,13 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
}

tl::expected<NodeId, DuplicateNameError>
NameResolutionContext::insert_variant (Identifier name, NodeId id)
NameResolutionContext::insert_variant (Identifier name, NodeId id,
bool is_also_value)
{
return types.insert_variant (name, id);
auto res = types.insert_variant (name, id);
if (res.has_value () && is_also_value)
res = values.insert_variant (name, id);
return res;
}

tl::expected<NodeId, DuplicateNameError>
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/resolve/rust-name-resolution-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,8 @@ class NameResolutionContext
tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id,
Namespace ns);

tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
NodeId id);
tl::expected<NodeId, DuplicateNameError>
insert_variant (Identifier name, NodeId id, bool is_also_value);

tl::expected<NodeId, DuplicateNameError>
insert_shadowable (Identifier name, NodeId id, Namespace ns);
Expand Down
19 changes: 11 additions & 8 deletions gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ TopLevel::TopLevel (NameResolutionContext &resolver)
template <typename T>
void
TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
const T &node)
const T &node, bool is_also_value)
{
insert_enum_variant_or_error_out (identifier, node.get_locus (),
node.get_node_id ());
node.get_node_id (), is_also_value);
}

void
Expand All @@ -58,12 +58,13 @@ TopLevel::check_multiple_insertion_error (
void
TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
const location_t &locus,
const NodeId node_id)
const NodeId node_id,
bool is_also_value)
{
// keep track of each node's location to provide useful errors
node_locations.emplace (node_id, locus);

auto result = ctx.insert_variant (identifier, node_id);
auto result = ctx.insert_variant (identifier, node_id, is_also_value);
check_multiple_insertion_error (result, identifier, locus, node_id);
}

Expand Down Expand Up @@ -240,6 +241,8 @@ TopLevel::visit (AST::Function &function)
insert_or_error_out (function.get_function_name (), function,
Namespace::Values);

Analysis::Mappings::get ().add_function_node (function.get_node_id ());

DefaultResolver::visit (function);
}

Expand Down Expand Up @@ -309,31 +312,31 @@ TopLevel::visit (AST::TupleStruct &tuple_struct)
void
TopLevel::visit (AST::EnumItem &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);

DefaultResolver::visit (variant);
}

void
TopLevel::visit (AST::EnumItemTuple &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);

DefaultResolver::visit (variant);
}

void
TopLevel::visit (AST::EnumItemStruct &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
insert_enum_variant_or_error_out (variant.get_identifier (), variant, false);

DefaultResolver::visit (variant);
}

void
TopLevel::visit (AST::EnumItemDiscriminant &variant)
{
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
insert_enum_variant_or_error_out (variant.get_identifier (), variant, true);

DefaultResolver::visit (variant);
}
Expand Down
5 changes: 3 additions & 2 deletions gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,12 @@ class TopLevel : public DefaultResolver

template <typename T>
void insert_enum_variant_or_error_out (const Identifier &identifier,
const T &node);
const T &node, bool is_also_value);

void insert_enum_variant_or_error_out (const Identifier &identifier,
const location_t &locus,
const NodeId node_id);
const NodeId node_id,
bool is_also_value);

private:
// If a new export has been defined whilst visiting the visitor is considered
Expand Down
6 changes: 4 additions & 2 deletions gcc/rust/typecheck/rust-hir-type-check-item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,15 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
RustIdent ident{path, struct_decl.get_locus ()};

// its a single variant ADT
auto variant_type = struct_decl.is_unit_struct ()
? TyTy::VariantDef::VariantType::UNIT
: TyTy::VariantDef::VariantType::STRUCT;
std::vector<TyTy::VariantDef *> variants;
variants.push_back (
new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
struct_decl.get_mappings ().get_defid (),
struct_decl.get_identifier ().as_string (), ident,
TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
std::move (fields)));
variant_type, tl::nullopt, std::move (fields)));

// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
Expand Down
Loading
Loading