1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
2
3 // This file is part of GCC.
4
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
8 // version.
9
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
18
19 #ifndef RUST_AUTODEREF
20 #define RUST_AUTODEREF
21
22 #include "rust-tyty.h"
23
24 namespace Rust {
25 namespace Resolver {
26
27 class Adjustment
28 {
29 public:
30 enum AdjustmentType
31 {
32 ERROR,
33
34 IMM_REF,
35 MUT_REF,
36 DEREF,
37 DEREF_MUT,
38 INDIRECTION,
39 UNSIZE,
40 };
41
42 // ctor for all adjustments except derefs
43 Adjustment (AdjustmentType type, const TyTy::BaseType *actual,
44 const TyTy::BaseType *expected)
45 : Adjustment (type, actual, expected, nullptr, nullptr,
46 AdjustmentType::ERROR)
47 {}
48
49 static Adjustment get_op_overload_deref_adjustment (
50 AdjustmentType type, const TyTy::BaseType *actual,
51 const TyTy::BaseType *expected, TyTy::FnType *fn, HIR::ImplItem *deref_item,
52 Adjustment::AdjustmentType requires_ref_adjustment)
53 {
54 rust_assert (type == DEREF || type == DEREF_MUT);
55 return Adjustment (type, actual, expected, fn, deref_item,
56 requires_ref_adjustment);
57 }
58
59 AdjustmentType get_type () const { return type; }
60
61 const TyTy::BaseType *get_actual () const { return actual; }
62 const TyTy::BaseType *get_expected () const { return expected; }
63
64 std::string as_string () const
65 {
66 return Adjustment::type_string (get_type ()) + "->"
67 + get_expected ()->debug_str ();
68 }
69
70 static std::string type_string (AdjustmentType type)
71 {
72 switch (type)
73 {
74 case AdjustmentType::ERROR:
75 return "ERROR";
76 case AdjustmentType::IMM_REF:
77 return "IMM_REF";
78 case AdjustmentType::MUT_REF:
79 return "MUT_REF";
80 case AdjustmentType::DEREF:
81 return "DEREF";
82 case AdjustmentType::DEREF_MUT:
83 return "DEREF_MUT";
84 case AdjustmentType::INDIRECTION:
85 return "INDIRECTION";
86 case AdjustmentType::UNSIZE:
87 return "UNSIZE";
88 }
89 gcc_unreachable ();
90 return "";
91 }
92
93 static Adjustment get_error () { return Adjustment{ERROR, nullptr, nullptr}; }
94
95 bool is_error () const { return type == ERROR; }
96
97 bool is_deref_adjustment () const { return type == DEREF; }
98
99 bool is_deref_mut_adjustment () const { return type == DEREF_MUT; }
100
101 bool has_operator_overload () const { return deref_operator_fn != nullptr; }
102
103 TyTy::FnType *get_deref_operator_fn () const { return deref_operator_fn; }
104
105 AdjustmentType get_deref_adjustment_type () const
106 {
107 return requires_ref_adjustment;
108 }
109
110 HIR::ImplItem *get_deref_hir_item () const { return deref_item; }
111
112 private:
113 Adjustment (AdjustmentType type, const TyTy::BaseType *actual,
114 const TyTy::BaseType *expected, TyTy::FnType *deref_operator_fn,
115 HIR::ImplItem *deref_item,
116 Adjustment::AdjustmentType requires_ref_adjustment)
117 : type (type), actual (actual), expected (expected),
118 deref_operator_fn (deref_operator_fn), deref_item (deref_item),
119 requires_ref_adjustment (requires_ref_adjustment)
120 {}
121
122 AdjustmentType type;
123 const TyTy::BaseType *actual;
124 const TyTy::BaseType *expected;
125
126 // - only used for deref operator_overloads
127 //
128 // the fn that we are calling
129 TyTy::FnType *deref_operator_fn;
130 HIR::ImplItem *deref_item;
131 // operator overloads can requre a reference
132 Adjustment::AdjustmentType requires_ref_adjustment;
133 };
134
135 class Adjuster
136 {
137 public:
138 Adjuster (const TyTy::BaseType *ty) : base (ty) {}
139
140 TyTy::BaseType *adjust_type (const std::vector<Adjustment> &adjustments);
141
142 static Adjustment
143 try_deref_type (const TyTy::BaseType *ty,
144 Analysis::RustLangItem::ItemType deref_lang_item);
145
146 static Adjustment try_raw_deref_type (const TyTy::BaseType *ty);
147
148 static Adjustment try_unsize_type (const TyTy::BaseType *ty);
149
150 private:
151 const TyTy::BaseType *base;
152 };
153
154 class AutoderefCycle
155 {
156 protected:
157 AutoderefCycle (bool autoderef_flag);
158
159 virtual ~AutoderefCycle ();
160
161 virtual bool select (const TyTy::BaseType &autoderefed) = 0;
162
163 // optional: this is a chance to hook in to grab predicate items on the raw
164 // type
165 virtual void try_hook (const TyTy::BaseType &);
166
167 virtual bool cycle (const TyTy::BaseType *receiver);
168
169 bool try_autoderefed (const TyTy::BaseType *r);
170
171 bool autoderef_flag;
172 std::vector<Adjustment> adjustments;
173 };
174
175 } // namespace Resolver
176 } // namespace Rust
177
178 #endif // RUST_AUTODEREF