diff options
Diffstat (limited to 'gcc/rust/checks/errors')
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; |
