// Copyright (C) 2020-2024 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// .
#ifndef RUST_AST_RESOLVE_PATTERN_H
#define RUST_AST_RESOLVE_PATTERN_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Resolver {
// Specifies whether the set of already bound patterns are related by 'Or' or
// 'Product'. Used to check for multiple bindings to the same identifier.
enum PatternBoundCtx
{
// A product pattern context (e.g. struct and tuple patterns)
Product,
// An or-pattern context (e.g. p_0 | p_1 | ...)
Or,
};
struct PatternBinding
{
PatternBoundCtx ctx;
std::set idents;
PatternBinding (PatternBoundCtx ctx, std::set idents)
: ctx (ctx), idents (idents)
{}
};
// Info that gets stored in the map. Helps us detect if two bindings to the same
// identifier have different mutability or ref states.
class BindingTypeInfo
{
Mutability mut;
bool is_ref;
location_t locus;
public:
BindingTypeInfo (Mutability mut, bool is_ref, location_t locus)
: mut (mut), is_ref (is_ref), locus (locus)
{}
BindingTypeInfo (BindingTypeInfo const &other)
: mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ())
{}
BindingTypeInfo (){};
location_t get_locus () const { return locus; }
Mutability get_mut () const { return mut; }
bool get_is_ref () const { return is_ref; }
BindingTypeInfo operator= (BindingTypeInfo const &other)
{
mut = other.mut;
is_ref = other.is_ref;
locus = other.get_locus ();
return *this;
}
bool operator== (BindingTypeInfo const &other)
{
return mut == other.mut && is_ref == other.is_ref;
}
bool operator!= (BindingTypeInfo const &other)
{
return !BindingTypeInfo::operator== (other);
}
};
typedef std::map BindingMap;
class PatternDeclaration : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Pattern *pattern, Rib::ItemType type);
static void go (AST::Pattern *pattern, Rib::ItemType type,
std::vector &bindings);
void visit (AST::IdentifierPattern &pattern) override;
void visit (AST::GroupedPattern &pattern) override;
void visit (AST::ReferencePattern &pattern) override;
void visit (AST::PathInExpression &pattern) override;
void visit (AST::StructPattern &pattern) override;
void visit (AST::TupleStructPattern &pattern) override;
void visit (AST::TuplePattern &pattern) override;
void visit (AST::RangePattern &pattern) override;
void visit (AST::AltPattern &pattern) override;
void visit (AST::SlicePattern &pattern) override;
void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info);
void check_bindings_consistency (std::vector &binding_maps);
private:
PatternDeclaration (std::vector &bindings_with_ctx,
Rib::ItemType type)
: ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type)
{}
// To avoid having a separate visitor for consistency checks, we store
// bindings in two forms:
// 1) Bindings as a vector of context-related sets.
// Used for checking multiple bindings to the same identifier (i.e. E0415,
// E0416).
std::vector &bindings_with_ctx;
// 2) Bindings as a map between identifiers and binding info.
// Used for checking consistency between alt patterns (i.e. E0408, E0409).
BindingMap binding_info_map;
// we need to insert the missing and inconsistent bindings (found in
// check_bindings_consistency) into maps to avoid duplication of error
// messages.
BindingMap inconsistent_bindings;
BindingMap missing_bindings;
Rib::ItemType type;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_PATTERN_H