aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/checks/errors
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/checks/errors')
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h65
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc47
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h16
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-function-collector.h10
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature-gate.cc (renamed from gcc/rust/checks/errors/rust-feature-gate.cc)0
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature-gate.h (renamed from gcc/rust/checks/errors/rust-feature-gate.h)0
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature.cc (renamed from gcc/rust/checks/errors/rust-feature.cc)0
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature.h (renamed from gcc/rust/checks/errors/rust-feature.h)0
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-check.cc9
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc56
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h7
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc29
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.h6
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc16
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h10
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc86
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.h14
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check.cc340
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check.h59
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.cc253
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.h67
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc16
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h10
23 files changed, 444 insertions, 672 deletions
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
index e2cc2dd..de8a830 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -24,7 +24,6 @@
#include "rust-hir-item.h"
#include "rust-hir-type-check.h"
#include "rust-hir-visitor.h"
-#include "rust-name-resolver.h"
#include "rust-bir.h"
#include "rust-bir-free-region.h"
#include "rust-immutable-name-resolution-context.h"
@@ -75,7 +74,7 @@ struct BuilderContext
// External context.
Resolver::TypeCheckContext &tyctx;
- Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
// BIR output
BasicBlocks basic_blocks;
@@ -104,7 +103,7 @@ struct BuilderContext
public:
BuilderContext ()
: tyctx (*Resolver::TypeCheckContext::get ()),
- resolver (*Resolver::Resolver::get ())
+ resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ())
{
basic_blocks.emplace_back (); // StartBB
}
@@ -403,69 +402,31 @@ protected: // HIR resolution helpers
template <typename T> NodeId resolve_label (T &expr)
{
- NodeId resolved_label;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
- rust_assert (res.has_value ());
- resolved_label = res.value ();
- }
- else
- {
- bool ok = ctx.resolver.lookup_resolved_label (
- expr.get_mappings ().get_nodeid (), &resolved_label);
- rust_assert (ok);
- }
- return resolved_label;
+ auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return res.value ();
}
template <typename T> PlaceId resolve_variable (T &variable)
{
- NodeId variable_id;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
- rust_assert (res.has_value ());
- variable_id = res.value ();
- }
- else
- {
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
- }
- return ctx.place_db.lookup_variable (variable_id);
+ auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return ctx.place_db.lookup_variable (res.value ());
}
template <typename T>
PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty)
{
ty = (ty) ? ty : lookup_type (variable);
+
// Unlike variables,
// functions do not have to be declared in PlaceDB before use.
- NodeId variable_id;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
- rust_assert (res.has_value ());
- variable_id = res.value ();
- }
- else
- {
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
- }
if (ty->is<TyTy::FnType> ())
return ctx.place_db.get_constant (ty);
- else
- return ctx.place_db.lookup_or_add_variable (variable_id, ty);
+
+ auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return ctx.place_db.lookup_or_add_variable (res.value (), ty);
}
protected: // Implicit conversions.
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
index 2d655f9..e78d750 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern)
return ty->as<TyTy::SliceType> ()->get_element_type ();
});
- // Regions are unchnaged.
+ // Regions are unchanged.
- for (auto &item : pattern.get_items ())
+ switch (pattern.get_items ().get_item_type ())
{
- item->accept_vis (*this);
+ case HIR::SlicePatternItems::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &member : items.get_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ break;
+ }
+ case HIR::SlicePatternItems::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+ for (auto &member : items.get_lower_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ for (auto &member : items.get_upper_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ break;
+ }
}
}
@@ -202,17 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::MULTIPLE:
+ case HIR::TuplePatternItems::NO_REST:
{
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
- case HIR::TuplePatternItems::RANGED:
+ case HIR::TuplePatternItems::HAS_REST:
{
auto &items
- = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
auto tyty = ctx.place_db[init.value ()].tyty;
rust_assert (tyty->get_kind () == TyTy::TUPLE);
@@ -249,10 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TupleStructItems::RANGED:
+ case HIR::TupleStructItems::HAS_REST:
{
auto &items
- = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ());
+ = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ());
rust_assert (type->get_kind () == TyTy::ADT);
auto adt_ty = static_cast<TyTy::ADTType *> (type);
@@ -267,10 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
visit_tuple_fields (items.get_upper_patterns (), saved, index);
break;
}
- case HIR::TupleStructItems::MULTIPLE:
+ case HIR::TupleStructItems::NO_REST:
{
auto &items
- = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ());
+ = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index d87ff8c..6cb87c7 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -225,11 +225,11 @@ protected:
rust_unreachable ();
}
void visit (HIR::StructPattern &pattern) override { rust_unreachable (); }
- void visit (HIR::TupleStructItemsNoRange &tuple_items) override
+ void visit (HIR::TupleStructItemsNoRest &tuple_items) override
{
rust_unreachable ();
}
- void visit (HIR::TupleStructItemsRange &tuple_items) override
+ void visit (HIR::TupleStructItemsHasRest &tuple_items) override
{
rust_unreachable ();
}
@@ -237,15 +237,23 @@ protected:
{
rust_unreachable ();
}
- void visit (HIR::TuplePatternItemsMultiple &tuple_items) override
+ void visit (HIR::TuplePatternItemsNoRest &tuple_items) override
{
rust_unreachable ();
}
- void visit (HIR::TuplePatternItemsRanged &tuple_items) override
+ void visit (HIR::TuplePatternItemsHasRest &tuple_items) override
{
rust_unreachable ();
}
void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); }
+ void visit (HIR::SlicePatternItemsNoRest &tuple_items) override
+ {
+ rust_unreachable ();
+ }
+ void visit (HIR::SlicePatternItemsHasRest &tuple_items) override
+ {
+ rust_unreachable ();
+ }
void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); }
void visit (HIR::AltPattern &pattern) override { rust_unreachable (); }
void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); }
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index 86f96c1..63f2a95 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -170,12 +170,14 @@ public:
void visit (HIR::StructPatternFieldIdentPat &field) override {}
void visit (HIR::StructPatternFieldIdent &field) override {}
void visit (HIR::StructPattern &pattern) override {}
- void visit (HIR::TupleStructItemsNoRange &tuple_items) override {}
- void visit (HIR::TupleStructItemsRange &tuple_items) override {}
+ void visit (HIR::TupleStructItemsNoRest &tuple_items) override {}
+ void visit (HIR::TupleStructItemsHasRest &tuple_items) override {}
void visit (HIR::TupleStructPattern &pattern) override {}
- void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {}
- void visit (HIR::TuplePatternItemsRanged &tuple_items) override {}
+ void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {}
+ void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {}
void visit (HIR::TuplePattern &pattern) override {}
+ void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {}
+ void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {}
void visit (HIR::SlicePattern &pattern) override {}
void visit (HIR::AltPattern &pattern) override {}
void visit (HIR::EmptyStmt &stmt) override {}
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
index 44007f9..44007f9 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h
index f1011e5..f1011e5 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc
index 071d3f8..071d3f8 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature.cc
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h
index e7cb0af..e7cb0af 100644
--- a/gcc/rust/checks/errors/rust-feature.h
+++ b/gcc/rust/checks/errors/feature/rust-feature.h
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
index 5291276..90248d3 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
@@ -20,7 +20,7 @@
#include "rust-reachability.h"
#include "rust-hir-type-check.h"
#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
+#include "rust-immutable-name-resolution-context.h"
#include "rust-visibility-resolver.h"
#include "rust-pub-restricted-visitor.h"
#include "rust-privacy-reporter.h"
@@ -35,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate)
{
PrivacyContext ctx;
auto &mappings = Analysis::Mappings::get ();
- auto resolver = Rust::Resolver::Resolver::get ();
+ auto &resolver
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get ();
- VisibilityResolver (mappings, *resolver).go (crate);
+ VisibilityResolver (mappings, resolver).go (crate);
PubRestrictedVisitor (mappings).go (crate);
- PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate);
+ PrivacyReporter (mappings, resolver, *ty_ctx).go (crate);
auto visitor = ReachabilityVisitor (ctx, *ty_ctx);
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 4af9639..c1a3d45 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -28,7 +28,8 @@ namespace Rust {
namespace Privacy {
PrivacyReporter::PrivacyReporter (
- Analysis::Mappings &mappings, Resolver::Resolver &resolver,
+ Analysis::Mappings &mappings,
+ const Resolver2_0::NameResolutionContext &resolver,
const Rust::Resolver::TypeCheckContext &ty_ctx)
: mappings (mappings), resolver (resolver), ty_ctx (ty_ctx),
current_module (tl::nullopt)
@@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate)
}
}
-static bool
-is_child_module (Analysis::Mappings &mappings, NodeId parent,
- NodeId possible_child)
-{
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- return nr_ctx.values.is_module_descendant (parent, possible_child);
- }
-
- auto children = mappings.lookup_module_children (parent);
-
- if (!children)
- return false;
-
- // Visit all toplevel children
- for (auto &child : *children)
- if (child == possible_child)
- return true;
-
- // Now descend recursively in the child module tree
- for (auto &child : *children)
- if (is_child_module (mappings, child, possible_child))
- return true;
-
- return false;
-}
-
// FIXME: This function needs a lot of refactoring
void
PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
const location_t locus)
{
- NodeId ref_node_id = UNKNOWN_NODEID;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- if (auto id = nr_ctx.lookup (use_id))
- ref_node_id = *id;
- }
- // FIXME: Don't assert here - we might be dealing with a type
- else if (!resolver.lookup_resolved_name (use_id, &ref_node_id))
- resolver.lookup_resolved_type (use_id, &ref_node_id);
+ NodeId ref_node_id;
// FIXME: Assert here. For now, we return since this causes issues when
// checking inferred types (#1260)
- // rust_assert (ref_node_id != UNKNOWN_NODEID);
- if (ref_node_id == UNKNOWN_NODEID)
+ if (auto id = resolver.lookup (use_id))
+ ref_node_id = *id;
+ else
return;
auto vis = mappings.lookup_visibility (ref_node_id);
@@ -175,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
// FIXME: This needs a LOT of TLC: hinting about the definition, a
// string to say if it's a module, function, type, etc...
- if (!is_child_module (mappings, mod_node_id, current_module.value ()))
+
+ if (!resolver.values.is_module_descendant (mod_node_id,
+ current_module.value ()))
valid = false;
}
break;
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 72716a6..d64b7a7 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -22,8 +22,9 @@
#include "rust-hir-expr.h"
#include "rust-hir-map.h"
#include "rust-hir-visitor.h"
+#include "rust-hir-type-check.h"
#include "rust-mapping-common.h"
-#include "rust-name-resolver.h"
+#include "rust-name-resolution-context.h"
namespace Rust {
namespace Privacy {
@@ -38,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor,
{
public:
PrivacyReporter (Analysis::Mappings &mappings,
- Rust::Resolver::Resolver &resolver,
+ const Resolver2_0::NameResolutionContext &resolver,
const Rust::Resolver::TypeCheckContext &ty_ctx);
/**
@@ -157,7 +158,7 @@ types
virtual void visit (HIR::ExprStmt &stmt);
Analysis::Mappings &mappings;
- Rust::Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
const Rust::Resolver::TypeCheckContext &ty_ctx;
// `None` means we're in the root module - the crate
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
index c59763d..4240673 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -20,16 +20,14 @@
#include "rust-ast.h"
#include "rust-hir.h"
#include "rust-hir-item.h"
-#include "rust-immutable-name-resolution-context.h"
-
-// for flag_name_resolution_2_0
-#include "options.h"
+#include "rust-name-resolution-context.h"
namespace Rust {
namespace Privacy {
-VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings,
- Resolver::Resolver &resolver)
+VisibilityResolver::VisibilityResolver (
+ Analysis::Mappings &mappings,
+ const Resolver2_0::NameResolutionContext &resolver)
: mappings (mappings), resolver (resolver)
{}
@@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
= Error (restriction.get_locus (),
"cannot use non-module path as privacy restrictor");
- NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
+ NodeId ref_node_id;
+ if (auto id = resolver.lookup (ast_node_id))
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- if (auto id = nr_ctx.lookup (ast_node_id))
- {
- ref_node_id = *id;
- }
- else
- {
- invalid_path.emit ();
- return false;
- }
+ ref_node_id = *id;
}
- else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+ else
{
invalid_path.emit ();
return false;
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
index 4dfba4c..ddd70a8 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
@@ -24,7 +24,7 @@
#include "rust-hir-stmt.h"
#include "rust-hir-item.h"
#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
+#include "rust-name-resolution-context.h"
#include "rust-hir-visitor.h"
namespace Rust {
@@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor
{
public:
VisibilityResolver (Analysis::Mappings &mappings,
- Rust::Resolver::Resolver &resolver);
+ const Resolver2_0::NameResolutionContext &resolver);
/**
* Perform visibility resolving on an entire crate
@@ -93,7 +93,7 @@ public:
private:
Analysis::Mappings &mappings;
- Rust::Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
DefId current_module;
};
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index c40f9db..782d694 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -813,11 +813,11 @@ ConstChecker::visit (StructPattern &)
{}
void
-ConstChecker::visit (TupleStructItemsNoRange &)
+ConstChecker::visit (TupleStructItemsNoRest &)
{}
void
-ConstChecker::visit (TupleStructItemsRange &)
+ConstChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -825,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &)
{}
void
-ConstChecker::visit (TuplePatternItemsMultiple &)
+ConstChecker::visit (TuplePatternItemsNoRest &)
{}
void
-ConstChecker::visit (TuplePatternItemsRanged &)
+ConstChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -837,6 +837,14 @@ ConstChecker::visit (TuplePattern &)
{}
void
+ConstChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+ConstChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
ConstChecker::visit (SlicePattern &)
{}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index eb63095..d464b7b 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -180,12 +180,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 2566971..f132e04 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -28,15 +28,12 @@
#include "rust-tyty.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Analysis {
PatternChecker::PatternChecker ()
: tyctx (*Resolver::TypeCheckContext::get ()),
- resolver (*Resolver::Resolver::get ()),
+ resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
mappings (Analysis::Mappings::get ())
{}
@@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr)
NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid ();
NodeId ref_node_id;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- if (auto id = nr_ctx.lookup (ast_node_id))
- ref_node_id = *id;
- else
- return;
- }
- else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+ if (auto id = resolver.lookup (ast_node_id))
+ ref_node_id = *id;
+ else
return;
if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id))
@@ -640,11 +629,11 @@ PatternChecker::visit (StructPattern &)
{}
void
-PatternChecker::visit (TupleStructItemsNoRange &)
+PatternChecker::visit (TupleStructItemsNoRest &)
{}
void
-PatternChecker::visit (TupleStructItemsRange &)
+PatternChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -652,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &)
{}
void
-PatternChecker::visit (TuplePatternItemsMultiple &)
+PatternChecker::visit (TuplePatternItemsNoRest &)
{}
void
-PatternChecker::visit (TuplePatternItemsRanged &)
+PatternChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -664,6 +653,14 @@ PatternChecker::visit (TuplePattern &)
{}
void
+PatternChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+PatternChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
PatternChecker::visit (SlicePattern &)
{}
@@ -980,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const
if (ctor.is_covered_by (hd.ctor ()))
{
pats.pop_head_constructor (ctor, subfields_place_info.size ());
- new_rows.push_back (MatrixRow (pats, row.is_under_guard ()));
+ new_rows.emplace_back (pats, row.is_under_guard ());
}
}
@@ -1186,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
}
}
- stack.push_back (WitnessPat (ctor, subfield, ty));
+ stack.emplace_back (ctor, subfield, ty);
}
}
@@ -1213,27 +1210,54 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
std::vector<DeconstructedPat> fields;
switch (elems.get_item_type ())
{
- case HIR::TupleStructItems::ItemType::MULTIPLE:
+ case HIR::TupleStructItems::ItemType::NO_REST:
{
- HIR::TupleStructItemsNoRange &multiple
- = static_cast<HIR::TupleStructItemsNoRange &> (elems);
+ HIR::TupleStructItemsNoRest &items_no_rest
+ = static_cast<HIR::TupleStructItemsNoRest &> (elems);
rust_assert (variant->get_fields ().size ()
- == multiple.get_patterns ().size ());
+ == items_no_rest.get_patterns ().size ());
- for (size_t i = 0; i < multiple.get_patterns ().size (); i++)
+ for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
{
fields.push_back (
- lower_pattern (ctx, *multiple.get_patterns ().at (i),
+ lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
variant->get_fields ().at (i)->get_field_type ()));
}
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
- case HIR::TupleStructItems::ItemType::RANGED:
+ case HIR::TupleStructItems::ItemType::HAS_REST:
{
- // TODO: ranged tuple struct items
- rust_unreachable ();
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (elems);
+
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ rust_assert (num_patterns <= variant->num_fields ());
+
+ size_t i = 0;
+ for (auto &pattern_member : items_has_rest.get_lower_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ while (i < variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ())
+ {
+ fields.push_back (
+ DeconstructedPat::make_wildcard (pattern.get_locus ()));
+ i++;
+ }
+ for (auto &pattern_member : items_has_rest.get_upper_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
default:
@@ -1597,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx,
MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty);
PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ());
pats.push (pat);
- rows.push_back (MatrixRow (pats, lowered.has_guard ()));
+ rows.emplace_back (pats, lowered.has_guard ());
}
std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}};
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index dd44abc..645e61d 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -26,7 +26,7 @@
#include "rust-tyty.h"
#include "optional.h"
#include "rust-hir-visitor.h"
-#include "rust-name-resolver.h"
+#include "rust-immutable-name-resolution-context.h"
namespace Rust {
namespace Analysis {
@@ -46,7 +46,7 @@ public:
private:
Resolver::TypeCheckContext &tyctx;
- Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
Analysis::Mappings &mappings;
virtual void visit (Lifetime &lifetime) override;
@@ -153,12 +153,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc
index c128933..f484047 100644
--- a/gcc/rust/checks/errors/rust-readonly-check.cc
+++ b/gcc/rust/checks/errors/rust-readonly-check.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -17,184 +17,252 @@
// <http://www.gnu.org/licenses/>.
#include "rust-readonly-check.h"
-#include "rust-tree.h"
-#include "rust-gcc.h"
-#include "print-tree.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-node.h"
+#include "rust-hir-path.h"
+#include "rust-hir-map.h"
+#include "rust-hir-pattern.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "rust-tyty.h"
namespace Rust {
-namespace Analysis {
+namespace HIR {
-static std::map<tree, int> assignment_map = {};
+static std::set<HirId> already_assigned_variables = {};
+
+ReadonlyChecker::ReadonlyChecker ()
+ : resolver (*Resolver::Resolver::get ()),
+ mappings (Analysis::Mappings::get ()),
+ context (*Resolver::TypeCheckContext::get ())
+{}
+
+void
+ReadonlyChecker::go (Crate &crate)
+{
+ for (auto &item : crate.get_items ())
+ item->accept_vis (*this);
+}
-// ported over from c-family/c-warn.cc
void
-readonly_error (location_t loc, tree arg, enum lvalue_use use)
+ReadonlyChecker::visit (AssignmentExpr &expr)
{
- gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
- || use == lv_asm);
- STRIP_ANY_LOCATION_WRAPPER (arg);
- /* Using this macro rather than (for example) arrays of messages
- ensures that all the format strings are checked at compile
- time. */
-#define READONLY_MSG(A, I, D, AS) \
- (use == lv_assign \
- ? (A) \
- : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS))))
- if (TREE_CODE (arg) == COMPONENT_REF)
+ Expr &lhs = expr.get_lhs ();
+ mutable_context.enter (expr.get_mappings ().get_hirid ());
+ lhs.accept_vis (*this);
+ mutable_context.exit ();
+}
+
+void
+ReadonlyChecker::visit (PathInExpression &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+
+ NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+ NodeId def_id;
+
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ if (auto id = nr_ctx.lookup (ast_node_id))
+ def_id = *id;
+ else
+ return;
+
+ auto hir_id = mappings.lookup_node_to_hir (def_id);
+ if (!hir_id)
+ return;
+
+ // Check if the local variable is mutable.
+ auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id);
+ if (maybe_pattern
+ && maybe_pattern.value ()->get_pattern_type ()
+ == HIR::Pattern::PatternType::IDENTIFIER)
+ check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()),
+ expr.get_locus ());
+
+ // Check if the static item is mutable.
+ auto maybe_item = mappings.lookup_hir_item (*hir_id);
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static)
{
- if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- error_at (loc,
- READONLY_MSG (G_ ("assignment of member "
- "%qD in read-only object"),
- G_ ("increment of member "
- "%qD in read-only object"),
- G_ ("decrement of member "
- "%qD in read-only object"),
- G_ ("member %qD in read-only object "
- "used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
- else
- error_at (
- loc,
- READONLY_MSG (G_ ("assignment of read-only member %qD"),
- G_ ("increment of read-only member %qD"),
- G_ ("decrement of read-only member %qD"),
- G_ ("read-only member %qD used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
+ auto static_item = static_cast<HIR::StaticItem *> (*maybe_item);
+ if (!static_item->is_mut ())
+ rust_error_at (expr.get_locus (),
+ "assignment of read-only location '%s'",
+ static_item->get_identifier ().as_string ().c_str ());
}
- else if (VAR_P (arg))
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only variable %qD"),
- G_ ("increment of read-only variable %qD"),
- G_ ("decrement of read-only variable %qD"),
- G_ (
- "read-only variable %qD used as %<asm%> output")),
- arg);
- else if (TREE_CODE (arg) == PARM_DECL)
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only parameter %qD"),
- G_ ("increment of read-only parameter %qD"),
- G_ ("decrement of read-only parameter %qD"),
- G_ (
- "read-only parameter %qD use as %<asm%> output")),
- arg);
- else if (TREE_CODE (arg) == RESULT_DECL)
+
+ // Check if the constant item is mutable.
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
{
- error_at (loc,
- READONLY_MSG (G_ ("assignment of "
- "read-only named return value %qD"),
- G_ ("increment of "
- "read-only named return value %qD"),
- G_ ("decrement of "
- "read-only named return value %qD"),
- G_ ("read-only named return value %qD "
- "used as %<asm%>output")),
- arg);
+ auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item);
+ rust_error_at (expr.get_locus (), "assignment of read-only location '%s'",
+ const_item->get_identifier ().as_string ().c_str ());
}
- else if (TREE_CODE (arg) == FUNCTION_DECL)
- error_at (loc,
- READONLY_MSG (G_ ("assignment of function %qD"),
- G_ ("increment of function %qD"),
- G_ ("decrement of function %qD"),
- G_ ("function %qD used as %<asm%> output")),
- arg);
- else
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only location %qE"),
- G_ ("increment of read-only location %qE"),
- G_ ("decrement of read-only location %qE"),
- G_ (
- "read-only location %qE used as %<asm%> output")),
- arg);
}
-static void
-emit_error (tree *t, tree lhs, enum lvalue_use use)
+void
+ReadonlyChecker::check_variable (IdentifierPattern *pattern,
+ location_t assigned_loc)
{
- readonly_error (EXPR_LOCATION (*t), lhs, use);
- TREE_OPERAND (*t, 0) = error_mark_node;
+ if (!mutable_context.is_in_context ())
+ return;
+
+ TyTy::BaseType *type;
+ if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type)
+ && is_mutable_type (type))
+ return;
+ if (pattern->is_mut ())
+ return;
+
+ auto hir_id = pattern->get_mappings ().get_hirid ();
+ if (already_assigned_variables.count (hir_id) > 0)
+ rust_error_at (assigned_loc, "assignment of read-only variable '%s'",
+ pattern->as_string ().c_str ());
+ already_assigned_variables.insert (hir_id);
}
-static void
-check_modify_expr (tree *t)
+void
+ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr)
{
- tree lhs = TREE_OPERAND (*t, 0);
- if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF)
- lhs = TREE_OPERAND (lhs, 0);
-
- tree lhs_type = TREE_TYPE (lhs);
- if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs))
+ if (has_init_expr)
{
- if (TREE_CODE (lhs) != VAR_DECL)
- emit_error (t, lhs, lv_assign);
- else if (!DECL_ARTIFICIAL (lhs))
- {
- if (DECL_INITIAL (lhs) != NULL)
- emit_error (t, lhs, lv_assign);
- else
- {
- if (assignment_map.find (lhs) == assignment_map.end ())
- {
- assignment_map.insert ({lhs, 0});
- }
- assignment_map[lhs]++;
-
- if (assignment_map[lhs] > 1)
- emit_error (t, lhs, lv_assign);
- }
- }
+ HirId pattern_id = pattern.get_mappings ().get_hirid ();
+ already_assigned_variables.insert (pattern_id);
}
}
-static void
-check_decl (tree *t)
+void
+ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
+ bool has_init_expr)
{
- switch (TREE_CODE (*t))
+ switch (tuple_pattern.get_items ().get_item_type ())
{
- case MODIFY_EXPR:
- check_modify_expr (t);
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items_no_rest.get_patterns ())
+ {
+ collect_assignment (*sub, has_init_expr);
+ }
+ }
+ break;
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
+ auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items_has_rest.get_lower_patterns ())
+ collect_assignment (*sub, has_init_expr);
+ for (auto &sub : items_has_rest.get_upper_patterns ())
+ collect_assignment (*sub, has_init_expr);
+ }
+ break;
+ default:
break;
+ }
+}
+void
+ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr)
+{
+ switch (pattern.get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
+ collect_assignment_identifier (static_cast<IdentifierPattern &> (
+ pattern),
+ has_init_expr);
+ }
+ break;
+ case HIR::Pattern::PatternType::TUPLE:
+ {
+ auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern);
+ collect_assignment_tuple (tuple_pattern, has_init_expr);
+ }
+ break;
default:
break;
}
}
-static tree
-readonly_walk_fn (tree *t, int *, void *)
+void
+ReadonlyChecker::visit (LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ collect_assignment (pattern, stmt.has_init_expr ());
+}
+
+void
+ReadonlyChecker::visit (FieldAccessExpr &expr)
{
- check_decl (t);
- return NULL_TREE;
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_receiver_expr ().accept_vis (*this);
+ }
}
void
-ReadonlyCheck::Lint (Compile::Context &ctx)
+ReadonlyChecker::visit (TupleIndexExpr &expr)
{
- assignment_map.clear ();
- for (auto &fndecl : ctx.get_func_decls ())
+ if (mutable_context.is_in_context ())
{
- for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p))
- {
- check_decl (&p);
- }
+ expr.get_tuple_expr ().accept_vis (*this);
+ }
+}
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
- &readonly_walk_fn, &ctx);
+void
+ReadonlyChecker::visit (ArrayIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_array_expr ().accept_vis (*this);
}
+}
- assignment_map.clear ();
- for (auto &var : ctx.get_var_decls ())
+void
+ReadonlyChecker::visit (TupleExpr &expr)
+{
+ if (mutable_context.is_in_context ())
{
- tree decl = var->get_decl ();
- check_decl (&decl);
+ // TODO: Add check for tuple expression
}
+}
- assignment_map.clear ();
- for (auto &const_decl : ctx.get_const_decls ())
+void
+ReadonlyChecker::visit (LiteralExpr &expr)
+{
+ if (mutable_context.is_in_context ())
{
- check_decl (&const_decl);
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
}
}
-} // namespace Analysis
+void
+ReadonlyChecker::visit (DereferenceExpr &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+ TyTy::BaseType *to_deref_type;
+ auto to_deref = expr.get_expr ().get_mappings ().get_hirid ();
+ if (!context.lookup_type (to_deref, &to_deref_type))
+ return;
+ if (!is_mutable_type (to_deref_type))
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+}
+
+bool
+ReadonlyChecker::is_mutable_type (TyTy::BaseType *type)
+{
+ if (type->get_kind () == TyTy::TypeKind::REF)
+ return static_cast<TyTy::ReferenceType *> (type)->is_mutable ();
+ if (type->get_kind () == TyTy::TypeKind::POINTER)
+ return static_cast<TyTy::PointerType *> (type)->is_mutable ();
+ return false;
+}
+} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h
index b39eee3..3525620 100644
--- a/gcc/rust/checks/errors/rust-readonly-check.h
+++ b/gcc/rust/checks/errors/rust-readonly-check.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,21 +16,54 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#ifndef RUST_READONLY_CHECK
-#define RUST_READONLY_CHECK
-
-#include "rust-compile-context.h"
+#include "rust-hir-visitor.h"
+#include "rust-name-resolver.h"
+#include "rust-stacked-contexts.h"
+#include "rust-hir-type-check.h"
namespace Rust {
-namespace Analysis {
-
-class ReadonlyCheck
+namespace HIR {
+class ReadonlyChecker : public DefaultHIRVisitor
{
public:
- static void Lint (Compile::Context &ctx);
-};
+ ReadonlyChecker ();
+
+ void go (HIR::Crate &crate);
+
+private:
+ enum class lvalue_use
+ {
+ assign,
+ increment,
+ decrement,
+ };
+
+ Resolver::Resolver &resolver;
+ Analysis::Mappings &mappings;
+ Resolver::TypeCheckContext &context;
+ StackedContexts<HirId> mutable_context;
-} // namespace Analysis
-} // namespace Rust
+ using DefaultHIRVisitor::visit;
+
+ virtual void visit (AssignmentExpr &expr) override;
+ virtual void visit (PathInExpression &expr) override;
+ virtual void visit (FieldAccessExpr &expr) override;
+ virtual void visit (ArrayIndexExpr &expr) override;
+ virtual void visit (TupleExpr &expr) override;
+ virtual void visit (TupleIndexExpr &expr) override;
+ virtual void visit (LetStmt &stmt) override;
+ virtual void visit (LiteralExpr &expr) override;
+ virtual void visit (DereferenceExpr &expr) override;
+
+ void collect_assignment (Pattern &pattern, bool has_init_expr);
+ void collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr);
+ void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr);
+
+ void check_variable (IdentifierPattern *pattern, location_t assigned_loc);
+
+ bool is_mutable_type (TyTy::BaseType *type);
+};
-#endif // RUST_READONLY_CHECK
+} // namespace HIR
+} // namespace Rust \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc
deleted file mode 100644
index 2fa92ae..0000000
--- a/gcc/rust/checks/errors/rust-readonly-check2.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-// 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-readonly-check2.h"
-#include "rust-hir-expr.h"
-#include "rust-hir-node.h"
-#include "rust-hir-path.h"
-#include "rust-hir-map.h"
-#include "rust-hir-pattern.h"
-#include "rust-mapping-common.h"
-#include "rust-system.h"
-#include "rust-immutable-name-resolution-context.h"
-#include "rust-tyty.h"
-
-namespace Rust {
-namespace HIR {
-
-static std::set<HirId> already_assigned_variables = {};
-
-ReadonlyChecker::ReadonlyChecker ()
- : resolver (*Resolver::Resolver::get ()),
- mappings (Analysis::Mappings::get ()),
- context (*Resolver::TypeCheckContext::get ())
-{}
-
-void
-ReadonlyChecker::go (Crate &crate)
-{
- for (auto &item : crate.get_items ())
- item->accept_vis (*this);
-}
-
-void
-ReadonlyChecker::visit (AssignmentExpr &expr)
-{
- Expr &lhs = expr.get_lhs ();
- mutable_context.enter (expr.get_mappings ().get_hirid ());
- lhs.accept_vis (*this);
- mutable_context.exit ();
-}
-
-void
-ReadonlyChecker::visit (PathInExpression &expr)
-{
- if (!mutable_context.is_in_context ())
- return;
-
- NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
- NodeId def_id;
-
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id = nr_ctx.lookup (ast_node_id))
- def_id = *id;
- else
- return;
-
- auto hir_id = mappings.lookup_node_to_hir (def_id);
- if (!hir_id)
- return;
-
- // Check if the local variable is mutable.
- auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id);
- if (maybe_pattern
- && maybe_pattern.value ()->get_pattern_type ()
- == HIR::Pattern::PatternType::IDENTIFIER)
- check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()),
- expr.get_locus ());
-
- // Check if the static item is mutable.
- auto maybe_item = mappings.lookup_hir_item (*hir_id);
- if (maybe_item
- && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static)
- {
- auto static_item = static_cast<HIR::StaticItem *> (*maybe_item);
- if (!static_item->is_mut ())
- rust_error_at (expr.get_locus (),
- "assignment of read-only location '%s'",
- static_item->get_identifier ().as_string ().c_str ());
- }
-
- // Check if the constant item is mutable.
- if (maybe_item
- && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
- {
- auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item);
- rust_error_at (expr.get_locus (), "assignment of read-only location '%s'",
- const_item->get_identifier ().as_string ().c_str ());
- }
-}
-
-void
-ReadonlyChecker::check_variable (IdentifierPattern *pattern,
- location_t assigned_loc)
-{
- if (!mutable_context.is_in_context ())
- return;
- if (pattern->is_mut ())
- return;
-
- auto hir_id = pattern->get_mappings ().get_hirid ();
- if (already_assigned_variables.count (hir_id) > 0)
- rust_error_at (assigned_loc, "assignment of read-only variable '%s'",
- pattern->as_string ().c_str ());
- already_assigned_variables.insert (hir_id);
-}
-
-void
-ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
- bool has_init_expr)
-{
- if (has_init_expr)
- {
- HirId pattern_id = pattern.get_mappings ().get_hirid ();
- already_assigned_variables.insert (pattern_id);
- }
-}
-
-void
-ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
- bool has_init_expr)
-{
- switch (tuple_pattern.get_items ().get_item_type ())
- {
- case HIR::TuplePatternItems::ItemType::MULTIPLE:
- {
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- tuple_pattern.get_items ());
- for (auto &sub : items.get_patterns ())
- {
- collect_assignment (*sub, has_init_expr);
- }
- }
- break;
- default:
- break;
- }
-}
-
-void
-ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr)
-{
- switch (pattern.get_pattern_type ())
- {
- case HIR::Pattern::PatternType::IDENTIFIER:
- {
- collect_assignment_identifier (static_cast<IdentifierPattern &> (
- pattern),
- has_init_expr);
- }
- break;
- case HIR::Pattern::PatternType::TUPLE:
- {
- auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern);
- collect_assignment_tuple (tuple_pattern, has_init_expr);
- }
- break;
- default:
- break;
- }
-}
-
-void
-ReadonlyChecker::visit (LetStmt &stmt)
-{
- HIR::Pattern &pattern = stmt.get_pattern ();
- collect_assignment (pattern, stmt.has_init_expr ());
-}
-
-void
-ReadonlyChecker::visit (FieldAccessExpr &expr)
-{
- if (mutable_context.is_in_context ())
- {
- expr.get_receiver_expr ().accept_vis (*this);
- }
-}
-
-void
-ReadonlyChecker::visit (TupleIndexExpr &expr)
-{
- if (mutable_context.is_in_context ())
- {
- expr.get_tuple_expr ().accept_vis (*this);
- }
-}
-
-void
-ReadonlyChecker::visit (ArrayIndexExpr &expr)
-{
- if (mutable_context.is_in_context ())
- {
- expr.get_array_expr ().accept_vis (*this);
- }
-}
-
-void
-ReadonlyChecker::visit (TupleExpr &expr)
-{
- if (mutable_context.is_in_context ())
- {
- // TODO: Add check for tuple expression
- }
-}
-
-void
-ReadonlyChecker::visit (LiteralExpr &expr)
-{
- if (mutable_context.is_in_context ())
- {
- rust_error_at (expr.get_locus (), "assignment of read-only location");
- }
-}
-
-void
-ReadonlyChecker::visit (DereferenceExpr &expr)
-{
- if (!mutable_context.is_in_context ())
- return;
- TyTy::BaseType *to_deref_type;
- auto to_deref = expr.get_expr ().get_mappings ().get_hirid ();
- if (!context.lookup_type (to_deref, &to_deref_type))
- return;
- if (to_deref_type->get_kind () == TyTy::TypeKind::REF)
- {
- auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type);
- if (!ref_type->is_mutable ())
- rust_error_at (expr.get_locus (), "assignment of read-only location");
- }
- if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER)
- {
- auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type);
- if (!ptr_type->is_mutable ())
- rust_error_at (expr.get_locus (), "assignment of read-only location");
- }
-}
-} // namespace HIR
-} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h
deleted file mode 100644
index 06af9db..0000000
--- a/gcc/rust/checks/errors/rust-readonly-check2.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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-hir-visitor.h"
-#include "rust-name-resolver.h"
-#include "rust-stacked-contexts.h"
-#include "rust-hir-type-check.h"
-
-namespace Rust {
-namespace HIR {
-class ReadonlyChecker : public DefaultHIRVisitor
-{
-public:
- ReadonlyChecker ();
-
- void go (HIR::Crate &crate);
-
-private:
- enum class lvalue_use
- {
- assign,
- increment,
- decrement,
- };
-
- Resolver::Resolver &resolver;
- Analysis::Mappings &mappings;
- Resolver::TypeCheckContext &context;
- StackedContexts<HirId> mutable_context;
-
- using DefaultHIRVisitor::visit;
-
- virtual void visit (AssignmentExpr &expr) override;
- virtual void visit (PathInExpression &expr) override;
- virtual void visit (FieldAccessExpr &expr) override;
- virtual void visit (ArrayIndexExpr &expr) override;
- virtual void visit (TupleExpr &expr) override;
- virtual void visit (TupleIndexExpr &expr) override;
- virtual void visit (LetStmt &stmt) override;
- virtual void visit (LiteralExpr &expr) override;
- virtual void visit (DereferenceExpr &expr) override;
-
- void collect_assignment (Pattern &pattern, bool has_init_expr);
- void collect_assignment_identifier (IdentifierPattern &pattern,
- bool has_init_expr);
- void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr);
-
- void check_variable (IdentifierPattern *pattern, location_t assigned_loc);
-};
-
-} // namespace HIR
-} // namespace Rust \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 405c59b..607d20f 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -926,11 +926,11 @@ UnsafeChecker::visit (StructPattern &)
{}
void
-UnsafeChecker::visit (TupleStructItemsNoRange &)
+UnsafeChecker::visit (TupleStructItemsNoRest &)
{}
void
-UnsafeChecker::visit (TupleStructItemsRange &)
+UnsafeChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -938,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &)
{}
void
-UnsafeChecker::visit (TuplePatternItemsMultiple &)
+UnsafeChecker::visit (TuplePatternItemsNoRest &)
{}
void
-UnsafeChecker::visit (TuplePatternItemsRanged &)
+UnsafeChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -950,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &)
{}
void
+UnsafeChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+UnsafeChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
UnsafeChecker::visit (SlicePattern &)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index dc3b482..420668f 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -161,12 +161,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;