Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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_HIR_PATH_H
20 : : #define RUST_HIR_PATH_H
21 : :
22 : : #include "rust-hir.h"
23 : :
24 : : namespace Rust {
25 : : namespace HIR {
26 : :
27 : : // The "identifier" (not generic args) aspect of each path expression segment
28 : 289019 : class PathIdentSegment
29 : : {
30 : : std::string segment_name;
31 : :
32 : : // TODO: should this have location info stored?
33 : :
34 : : // only allow identifiers, "super", "self", "Self", "crate", or "$crate"
35 : : public:
36 : 67389 : PathIdentSegment (std::string segment_name)
37 : 67389 : : segment_name (std::move (segment_name))
38 : : {}
39 : :
40 : : /* TODO: insert check in constructor for this? Or is this a semantic error
41 : : * best handled then? */
42 : :
43 : : /* TODO: does this require visitor? pretty sure this isn't polymorphic, but
44 : : * not entirely sure */
45 : :
46 : : // Creates an error PathIdentSegment.
47 : : static PathIdentSegment create_error () { return PathIdentSegment (""); }
48 : :
49 : : // Returns whether PathIdentSegment is in an error state.
50 : 5840 : bool is_error () const { return segment_name.empty (); }
51 : :
52 : 57687 : std::string as_string () const { return segment_name; }
53 : : };
54 : :
55 : : // A binding of an identifier to a type used in generic arguments in paths
56 : : class GenericArgsBinding
57 : : {
58 : : Identifier identifier;
59 : : std::unique_ptr<Type> type;
60 : :
61 : : location_t locus;
62 : :
63 : : public:
64 : : // Returns whether binding is in an error state.
65 : : bool is_error () const
66 : : {
67 : : return type == nullptr;
68 : : // and also identifier is empty, but cheaper computation
69 : : }
70 : :
71 : : // Creates an error state generic args binding.
72 : : static GenericArgsBinding create_error ()
73 : : {
74 : : return GenericArgsBinding ({""}, nullptr);
75 : : }
76 : :
77 : : // Pointer type for type in constructor to enable polymorphism
78 : 45 : GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
79 : : location_t locus = UNDEF_LOCATION)
80 : 45 : : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
81 : : {}
82 : :
83 : : // Copy constructor has to deep copy the type as it is a unique pointer
84 : 121 : GenericArgsBinding (GenericArgsBinding const &other)
85 : 121 : : identifier (other.identifier), type (other.type->clone_type ()),
86 : 121 : locus (other.locus)
87 : 121 : {}
88 : :
89 : : // default destructor
90 : 158 : ~GenericArgsBinding () = default;
91 : :
92 : : // Overload assignment operator to deep copy the pointed-to type
93 : 0 : GenericArgsBinding &operator= (GenericArgsBinding const &other)
94 : : {
95 : 0 : identifier = other.identifier;
96 : 0 : type = other.type->clone_type ();
97 : 0 : locus = other.locus;
98 : 0 : return *this;
99 : : }
100 : :
101 : : // move constructors
102 : 46 : GenericArgsBinding (GenericArgsBinding &&other) = default;
103 : : GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
104 : :
105 : : std::string as_string () const;
106 : :
107 : : Identifier &get_identifier () { return identifier; }
108 : : const Identifier &get_identifier () const { return identifier; }
109 : :
110 : 43 : std::unique_ptr<Type> &get_type () { return type; }
111 : : const std::unique_ptr<Type> &get_type () const { return type; }
112 : :
113 : 2 : location_t get_locus () const { return locus; }
114 : : };
115 : :
116 : 8 : class ConstGenericArg
117 : : {
118 : : // FIXME: Do we need to disambiguate or no? We should be able to disambiguate
119 : : // at name-resolution, hence no need for ambiguities here
120 : :
121 : : public:
122 : 4 : ConstGenericArg (std::unique_ptr<Expr> expression, location_t locus)
123 : 4 : : expression (std::move (expression)), locus (locus)
124 : : {}
125 : :
126 : 8 : ConstGenericArg (const ConstGenericArg &other) : locus (other.locus)
127 : : {
128 : 8 : expression = other.expression->clone_expr ();
129 : 8 : }
130 : :
131 : 0 : ConstGenericArg operator= (const ConstGenericArg &other)
132 : : {
133 : 0 : expression = other.expression->clone_expr ();
134 : 0 : locus = other.locus;
135 : :
136 : 0 : return *this;
137 : : }
138 : :
139 : 0 : std::unique_ptr<Expr> &get_expression () { return expression; }
140 : :
141 : : private:
142 : : std::unique_ptr<Expr> expression;
143 : : location_t locus;
144 : : };
145 : :
146 : : class GenericArgs
147 : : {
148 : : std::vector<Lifetime> lifetime_args;
149 : : std::vector<std::unique_ptr<Type> > type_args;
150 : : std::vector<GenericArgsBinding> binding_args;
151 : : std::vector<ConstGenericArg> const_args;
152 : : location_t locus;
153 : :
154 : : public:
155 : : // Returns true if there are any generic arguments
156 : 28369 : bool has_generic_args () const
157 : : {
158 : 28369 : return !(lifetime_args.empty () && type_args.empty ()
159 : 27389 : && binding_args.empty ());
160 : : }
161 : :
162 : 36670 : GenericArgs (std::vector<Lifetime> lifetime_args,
163 : : std::vector<std::unique_ptr<Type> > type_args,
164 : : std::vector<GenericArgsBinding> binding_args,
165 : : std::vector<ConstGenericArg> const_args, location_t locus)
166 : 36670 : : lifetime_args (std::move (lifetime_args)),
167 : 36670 : type_args (std::move (type_args)),
168 : 36670 : binding_args (std::move (binding_args)),
169 : 36670 : const_args (std::move (const_args)), locus (locus)
170 : 36670 : {}
171 : :
172 : : // copy constructor with vector clone
173 : 70900 : GenericArgs (GenericArgs const &other)
174 : 70900 : : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
175 : 70900 : const_args (other.const_args), locus (other.locus)
176 : : {
177 : 70900 : type_args.clear ();
178 : 70900 : type_args.reserve (other.type_args.size ());
179 : :
180 : 73531 : for (const auto &e : other.type_args)
181 : 2631 : type_args.push_back (e->clone_type ());
182 : 70900 : }
183 : :
184 : 124280 : ~GenericArgs () = default;
185 : :
186 : : // overloaded assignment operator to vector clone
187 : 426 : GenericArgs &operator= (GenericArgs const &other)
188 : : {
189 : 426 : lifetime_args = other.lifetime_args;
190 : 426 : binding_args = other.binding_args;
191 : 426 : const_args = other.const_args;
192 : 426 : locus = other.locus;
193 : :
194 : 426 : type_args.clear ();
195 : 426 : type_args.reserve (other.type_args.size ());
196 : 868 : for (const auto &e : other.type_args)
197 : 442 : type_args.push_back (e->clone_type ());
198 : :
199 : 426 : return *this;
200 : : }
201 : :
202 : : // move constructors
203 : 47777 : GenericArgs (GenericArgs &&other) = default;
204 : 2879 : GenericArgs &operator= (GenericArgs &&other) = default;
205 : :
206 : : // Creates an empty GenericArgs (no arguments)
207 : 31858 : static GenericArgs create_empty (location_t locus = UNDEF_LOCATION)
208 : : {
209 : 31858 : return GenericArgs ({}, {}, {}, {}, locus);
210 : : }
211 : :
212 : 3115 : bool is_empty () const
213 : : {
214 : 3115 : return lifetime_args.size () == 0 && type_args.size () == 0
215 : 3360 : && binding_args.size () == 0;
216 : : }
217 : :
218 : : std::string as_string () const;
219 : :
220 : 2862 : std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }
221 : : const std::vector<Lifetime> &get_lifetime_args () const
222 : : {
223 : 4555 : return lifetime_args;
224 : : }
225 : :
226 : 4623 : std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
227 : :
228 : 2906 : std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
229 : :
230 : 2862 : std::vector<ConstGenericArg> &get_const_args () { return const_args; }
231 : :
232 : 7688 : location_t get_locus () const { return locus; }
233 : : };
234 : :
235 : : /* A segment of a path in expression, including an identifier aspect and maybe
236 : : * generic args */
237 : 85834 : class PathExprSegment
238 : : {
239 : : private:
240 : : Analysis::NodeMapping mappings;
241 : : PathIdentSegment segment_name;
242 : : GenericArgs generic_args;
243 : : location_t locus;
244 : :
245 : : public:
246 : 29128 : PathExprSegment (Analysis::NodeMapping mappings,
247 : : PathIdentSegment segment_name, location_t locus,
248 : : GenericArgs generic_args)
249 : 29128 : : mappings (std::move (mappings)), segment_name (std::move (segment_name)),
250 : 29128 : generic_args (std::move (generic_args)), locus (locus)
251 : : {}
252 : :
253 : 69026 : PathExprSegment (PathExprSegment const &other)
254 : 69026 : : mappings (other.mappings), segment_name (other.segment_name),
255 : 69026 : generic_args (other.generic_args), locus (other.locus)
256 : 69026 : {}
257 : :
258 : : PathExprSegment &operator= (PathExprSegment const &other)
259 : : {
260 : : mappings = other.mappings;
261 : : segment_name = other.segment_name;
262 : : generic_args = other.generic_args;
263 : : locus = other.locus;
264 : :
265 : : return *this;
266 : : }
267 : :
268 : : // move constructors
269 : 17296 : PathExprSegment (PathExprSegment &&other) = default;
270 : : PathExprSegment &operator= (PathExprSegment &&other) = default;
271 : :
272 : : std::string as_string () const;
273 : :
274 : 16671 : location_t get_locus () const { return locus; }
275 : :
276 : 1852 : PathIdentSegment &get_segment () { return segment_name; }
277 : 23532 : const PathIdentSegment &get_segment () const { return segment_name; }
278 : :
279 : 581 : GenericArgs &get_generic_args () { return generic_args; }
280 : :
281 : 79465 : const Analysis::NodeMapping &get_mappings () const { return mappings; }
282 : :
283 : 55857 : bool has_generic_args () const { return generic_args.has_generic_args (); }
284 : : };
285 : :
286 : : // HIR node representing a pattern that involves a "path" - abstract base class
287 : : class PathPattern : public Pattern
288 : : {
289 : : std::vector<PathExprSegment> segments;
290 : :
291 : : protected:
292 : 25650 : PathPattern (std::vector<PathExprSegment> segments)
293 : 25650 : : segments (std::move (segments))
294 : 25650 : {}
295 : :
296 : : // Returns whether path has segments.
297 : 1 : bool has_segments () const { return !segments.empty (); }
298 : :
299 : : /* Converts path segments to their equivalent SimplePath segments if possible,
300 : : * and creates a SimplePath from them. */
301 : : AST::SimplePath
302 : : convert_to_simple_path (bool with_opening_scope_resolution) const;
303 : :
304 : : public:
305 : : /* Returns whether the path is a single segment (excluding qualified path
306 : : * initial as segment). */
307 : : bool is_single_segment () const { return segments.size () == 1; }
308 : :
309 : : std::string as_string () const override;
310 : :
311 : 31906 : void iterate_path_segments (std::function<bool (PathExprSegment &)> cb)
312 : : {
313 : 64960 : for (auto it = segments.begin (); it != segments.end (); it++)
314 : : {
315 : 33637 : if (!cb (*it))
316 : 31906 : return;
317 : : }
318 : : }
319 : :
320 : 80164 : size_t get_num_segments () const { return segments.size (); }
321 : :
322 : 27929 : std::vector<PathExprSegment> &get_segments () { return segments; }
323 : :
324 : : const std::vector<PathExprSegment> &get_segments () const { return segments; }
325 : :
326 : : PathExprSegment &get_root_seg () { return segments.at (0); }
327 : :
328 : 23532 : const PathExprSegment &get_final_segment () const { return segments.back (); }
329 : :
330 : 0 : PatternType get_pattern_type () const override final
331 : : {
332 : 0 : return PatternType::PATH;
333 : : }
334 : : };
335 : :
336 : : /* HIR node representing a path-in-expression pattern (path that allows generic
337 : : * arguments) */
338 : : class PathInExpression : public PathPattern, public PathExpr
339 : : {
340 : : bool has_opening_scope_resolution;
341 : : location_t locus;
342 : :
343 : : public:
344 : : std::string as_string () const override;
345 : :
346 : : // Constructor
347 : 25570 : PathInExpression (Analysis::NodeMapping mappings,
348 : : std::vector<PathExprSegment> path_segments,
349 : : location_t locus = UNDEF_LOCATION,
350 : : bool has_opening_scope_resolution = false,
351 : : std::vector<AST::Attribute> outer_attrs
352 : : = std::vector<AST::Attribute> ())
353 : 25570 : : PathPattern (std::move (path_segments)),
354 : : PathExpr (std::move (mappings), std::move (outer_attrs)),
355 : 25570 : has_opening_scope_resolution (has_opening_scope_resolution), locus (locus)
356 : 25570 : {}
357 : :
358 : : // Creates an error state path in expression.
359 : : static PathInExpression create_error ()
360 : : {
361 : : return PathInExpression (Analysis::NodeMapping::get_error (),
362 : : std::vector<PathExprSegment> ());
363 : : }
364 : :
365 : : // Returns whether path in expression is in an error state.
366 : : bool is_error () const { return !has_segments (); }
367 : :
368 : : /* Converts PathInExpression to SimplePath if possible (i.e. no generic
369 : : * arguments). Otherwise returns an empty SimplePath. */
370 : 1 : AST::SimplePath as_simple_path () const
371 : : {
372 : : /* delegate to parent class as can't access segments. however,
373 : : * QualifiedPathInExpression conversion to simple path wouldn't make sense,
374 : : * so the method in the parent class should be protected, not public. Have
375 : : * to pass in opening scope resolution as parent class has no access to it.
376 : : */
377 : 1 : return convert_to_simple_path (has_opening_scope_resolution);
378 : : }
379 : :
380 : 113267 : location_t get_locus () const override final { return locus; }
381 : :
382 : : void accept_vis (HIRFullVisitor &vis) override;
383 : : void accept_vis (HIRExpressionVisitor &vis) override;
384 : : void accept_vis (HIRPatternVisitor &vis) override;
385 : :
386 : 0 : bool opening_scope_resolution () { return has_opening_scope_resolution; }
387 : :
388 : : bool is_self () const
389 : : {
390 : : if (!is_single_segment ())
391 : : return false;
392 : :
393 : : return get_final_segment ().get_segment ().as_string ().compare ("self")
394 : : == 0;
395 : : }
396 : :
397 : 96336 : const Analysis::NodeMapping &get_mappings () const override final
398 : : {
399 : 95824 : return mappings;
400 : : }
401 : :
402 : : protected:
403 : : /* Use covariance to implement clone function as returning this object rather
404 : : * than base */
405 : 335 : PathInExpression *clone_pattern_impl () const override
406 : : {
407 : 335 : return new PathInExpression (*this);
408 : : }
409 : :
410 : : /* Use covariance to implement clone function as returning this object rather
411 : : * than base */
412 : 620 : PathInExpression *clone_expr_without_block_impl () const override
413 : : {
414 : 620 : return new PathInExpression (*this);
415 : : }
416 : : };
417 : :
418 : : /* Base class for segments used in type paths - not abstract (represents an
419 : : * ident-only segment) */
420 : : class TypePathSegment
421 : : {
422 : : public:
423 : : enum SegmentType
424 : : {
425 : : REG,
426 : : GENERIC,
427 : : FUNCTION
428 : : };
429 : :
430 : : private:
431 : : Analysis::NodeMapping mappings;
432 : : PathIdentSegment ident_segment;
433 : : location_t locus;
434 : :
435 : : protected:
436 : : bool has_separating_scope_resolution;
437 : : SegmentType type;
438 : :
439 : : public:
440 : : // Clone function implementation - not pure virtual as overrided by subclasses
441 : 7751 : virtual TypePathSegment *clone_type_path_segment_impl () const
442 : : {
443 : 7751 : return new TypePathSegment (*this);
444 : : }
445 : :
446 : : public:
447 : 7118 : virtual ~TypePathSegment () {}
448 : :
449 : 29697 : virtual SegmentType get_type () const { return SegmentType::REG; }
450 : :
451 : : // Unique pointer custom clone function
452 : 8262 : std::unique_ptr<TypePathSegment> clone_type_path_segment () const
453 : : {
454 : 8262 : return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
455 : : }
456 : :
457 : 31268 : TypePathSegment (Analysis::NodeMapping mappings,
458 : : PathIdentSegment ident_segment,
459 : : bool has_separating_scope_resolution, location_t locus)
460 : 31268 : : mappings (std::move (mappings)),
461 : 62536 : ident_segment (std::move (ident_segment)), locus (locus),
462 : 31268 : has_separating_scope_resolution (has_separating_scope_resolution),
463 : 29896 : type (SegmentType::REG)
464 : : {}
465 : :
466 : : TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name,
467 : : bool has_separating_scope_resolution, location_t locus)
468 : : : mappings (std::move (mappings)),
469 : : ident_segment (PathIdentSegment (std::move (segment_name))),
470 : : locus (locus),
471 : : has_separating_scope_resolution (has_separating_scope_resolution),
472 : : type (SegmentType::REG)
473 : : {}
474 : :
475 : 28880 : virtual std::string as_string () const { return ident_segment.as_string (); }
476 : :
477 : : /* Returns whether the type path segment is in an error state. May be virtual
478 : : * in future. */
479 : 0 : bool is_error () const { return ident_segment.is_error (); }
480 : :
481 : : /* Returns whether segment is identifier only (as opposed to generic args or
482 : : * function). Overriden in derived classes with other segments. */
483 : 0 : virtual bool is_ident_only () const { return true; }
484 : :
485 : 53 : location_t get_locus () const { return locus; }
486 : :
487 : : // not pure virtual as class not abstract
488 : : virtual void accept_vis (HIRFullVisitor &vis);
489 : :
490 : 27831 : const Analysis::NodeMapping &get_mappings () const { return mappings; }
491 : :
492 : 1423 : const PathIdentSegment &get_ident_segment () const { return ident_segment; }
493 : :
494 : 27796 : bool is_generic_segment () const
495 : : {
496 : 27796 : return get_type () == SegmentType::GENERIC;
497 : : }
498 : : };
499 : :
500 : : // Segment used in type path with generic args
501 : : class TypePathSegmentGeneric : public TypePathSegment
502 : : {
503 : : GenericArgs generic_args;
504 : :
505 : : public:
506 : 3700 : bool has_generic_args () const { return generic_args.has_generic_args (); }
507 : :
508 : 0 : bool is_ident_only () const override { return false; }
509 : :
510 : : // Constructor with PathIdentSegment and GenericArgs
511 : 1353 : TypePathSegmentGeneric (Analysis::NodeMapping mappings,
512 : : PathIdentSegment ident_segment,
513 : : bool has_separating_scope_resolution,
514 : : GenericArgs generic_args, location_t locus)
515 : 1353 : : TypePathSegment (std::move (mappings), std::move (ident_segment),
516 : : has_separating_scope_resolution, locus),
517 : 1353 : generic_args (std::move (generic_args))
518 : 1353 : {}
519 : :
520 : : // Constructor from segment name and all args
521 : : TypePathSegmentGeneric (Analysis::NodeMapping mappings,
522 : : std::string segment_name,
523 : : bool has_separating_scope_resolution,
524 : : std::vector<Lifetime> lifetime_args,
525 : : std::vector<std::unique_ptr<Type> > type_args,
526 : : std::vector<GenericArgsBinding> binding_args,
527 : : std::vector<ConstGenericArg> const_args,
528 : : location_t locus)
529 : : : TypePathSegment (std::move (mappings), std::move (segment_name),
530 : : has_separating_scope_resolution, locus),
531 : : generic_args (
532 : : GenericArgs (std::move (lifetime_args), std::move (type_args),
533 : : std::move (binding_args), std::move (const_args), locus))
534 : : {}
535 : :
536 : : std::string as_string () const override;
537 : :
538 : : void accept_vis (HIRFullVisitor &vis) override;
539 : :
540 : 1356 : GenericArgs &get_generic_args () { return generic_args; }
541 : :
542 : 1356 : virtual SegmentType get_type () const override final
543 : : {
544 : 1356 : return SegmentType::GENERIC;
545 : : }
546 : :
547 : : // Use covariance to override base class method
548 : 521 : TypePathSegmentGeneric *clone_type_path_segment_impl () const override
549 : : {
550 : 521 : return new TypePathSegmentGeneric (*this);
551 : : }
552 : : };
553 : :
554 : : // A function as represented in a type path
555 : : class TypePathFunction
556 : : {
557 : : std::vector<std::unique_ptr<Type> > inputs;
558 : : std::unique_ptr<Type> return_type;
559 : :
560 : : public:
561 : : // Returns whether the return type of the function has been specified.
562 : 17 : bool has_return_type () const { return return_type != nullptr; }
563 : :
564 : : // Returns whether the function has inputs.
565 : 0 : bool has_inputs () const { return !inputs.empty (); }
566 : :
567 : : // Constructor
568 : 19 : TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
569 : : std::unique_ptr<Type> type)
570 : 19 : : inputs (std::move (inputs)), return_type (std::move (type))
571 : : {}
572 : :
573 : : // Copy constructor with clone
574 : 19 : TypePathFunction (TypePathFunction const &other)
575 : 19 : {
576 : 19 : return_type = other.has_return_type ()
577 : 36 : ? other.get_return_type ()->clone_type ()
578 : 19 : : nullptr;
579 : :
580 : 19 : inputs.reserve (other.inputs.size ());
581 : 38 : for (const auto &e : other.inputs)
582 : 19 : inputs.push_back (e->clone_type ());
583 : 19 : }
584 : :
585 : 19 : ~TypePathFunction () = default;
586 : :
587 : : // Overloaded assignment operator to clone type
588 : : TypePathFunction &operator= (TypePathFunction const &other)
589 : : {
590 : : return_type = other.has_return_type ()
591 : : ? other.get_return_type ()->clone_type ()
592 : : : nullptr;
593 : :
594 : : inputs.reserve (other.inputs.size ());
595 : : for (const auto &e : other.inputs)
596 : : inputs.push_back (e->clone_type ());
597 : :
598 : : return *this;
599 : : }
600 : :
601 : : // move constructors
602 : 19 : TypePathFunction (TypePathFunction &&other) = default;
603 : : TypePathFunction &operator= (TypePathFunction &&other) = default;
604 : :
605 : : std::string as_string () const;
606 : :
607 : : const std::vector<std::unique_ptr<Type> > &get_params () const
608 : : {
609 : : return inputs;
610 : : };
611 : 17 : std::vector<std::unique_ptr<Type> > &get_params () { return inputs; };
612 : :
613 : 17 : const std::unique_ptr<Type> &get_return_type () const { return return_type; };
614 : 34 : std::unique_ptr<Type> &get_return_type () { return return_type; };
615 : : };
616 : :
617 : : // Segment used in type path with a function argument
618 : : class TypePathSegmentFunction : public TypePathSegment
619 : : {
620 : : TypePathFunction function_path;
621 : :
622 : : public:
623 : : // Constructor with PathIdentSegment and TypePathFn
624 : 19 : TypePathSegmentFunction (Analysis::NodeMapping mappings,
625 : : PathIdentSegment ident_segment,
626 : : bool has_separating_scope_resolution,
627 : : TypePathFunction function_path, location_t locus)
628 : 19 : : TypePathSegment (std::move (mappings), std::move (ident_segment),
629 : : has_separating_scope_resolution, locus),
630 : 19 : function_path (std::move (function_path))
631 : 19 : {}
632 : :
633 : : // Constructor with segment name and TypePathFn
634 : : TypePathSegmentFunction (Analysis::NodeMapping mappings,
635 : : std::string segment_name,
636 : : bool has_separating_scope_resolution,
637 : : TypePathFunction function_path, location_t locus)
638 : : : TypePathSegment (std::move (mappings), std::move (segment_name),
639 : : has_separating_scope_resolution, locus),
640 : : function_path (std::move (function_path))
641 : : {}
642 : :
643 : : std::string as_string () const override;
644 : :
645 : 0 : bool is_ident_only () const override { return false; }
646 : :
647 : : void accept_vis (HIRFullVisitor &vis) override;
648 : :
649 : 17 : SegmentType get_type () const override final { return SegmentType::FUNCTION; }
650 : :
651 : 17 : TypePathFunction &get_function_path () { return function_path; }
652 : :
653 : : // Use covariance to override base class method
654 : 19 : TypePathSegmentFunction *clone_type_path_segment_impl () const override
655 : : {
656 : 19 : return new TypePathSegmentFunction (*this);
657 : : }
658 : : };
659 : :
660 : : // Path used inside types
661 : 585 : class TypePath : public TypeNoBounds
662 : : {
663 : : public:
664 : : bool has_opening_scope_resolution;
665 : : std::vector<std::unique_ptr<TypePathSegment> > segments;
666 : :
667 : : protected:
668 : : /* Use covariance to implement clone function as returning this object rather
669 : : * than base */
670 : 7369 : TypePath *clone_type_impl () const override { return new TypePath (*this); }
671 : :
672 : : /* Use covariance to implement clone function as returning this object rather
673 : : * than base */
674 : 0 : TypePath *clone_type_no_bounds_impl () const override
675 : : {
676 : 0 : return new TypePath (*this);
677 : : }
678 : :
679 : : public:
680 : : /* Returns whether the TypePath has an opening scope resolution operator (i.e.
681 : : * is global path or crate-relative path, not module-relative) */
682 : 0 : bool has_opening_scope_resolution_op () const
683 : : {
684 : 0 : return has_opening_scope_resolution;
685 : : }
686 : :
687 : : // Returns whether the TypePath is in an invalid state.
688 : : bool is_error () const { return segments.empty (); }
689 : :
690 : : // Creates an error state TypePath.
691 : : static TypePath create_error ()
692 : : {
693 : : return TypePath (Analysis::NodeMapping::get_error (),
694 : : std::vector<std::unique_ptr<TypePathSegment> > (),
695 : : UNDEF_LOCATION);
696 : : }
697 : :
698 : : // Constructor
699 : 30576 : TypePath (Analysis::NodeMapping mappings,
700 : : std::vector<std::unique_ptr<TypePathSegment> > segments,
701 : : location_t locus, bool has_opening_scope_resolution = false)
702 : 30576 : : TypeNoBounds (mappings, locus),
703 : 30576 : has_opening_scope_resolution (has_opening_scope_resolution),
704 : 30576 : segments (std::move (segments))
705 : : {}
706 : :
707 : : // Copy constructor with vector clone
708 : 8348 : TypePath (TypePath const &other)
709 : 8348 : : TypeNoBounds (other.mappings, other.locus),
710 : 8348 : has_opening_scope_resolution (other.has_opening_scope_resolution)
711 : : {
712 : 8348 : segments.reserve (other.segments.size ());
713 : 16610 : for (const auto &e : other.segments)
714 : 8262 : segments.push_back (e->clone_type_path_segment ());
715 : 8348 : }
716 : :
717 : : // Overloaded assignment operator with clone
718 : : TypePath &operator= (TypePath const &other)
719 : : {
720 : : has_opening_scope_resolution = other.has_opening_scope_resolution;
721 : : locus = other.locus;
722 : : mappings = other.mappings;
723 : :
724 : : segments.reserve (other.segments.size ());
725 : : for (const auto &e : other.segments)
726 : : segments.push_back (e->clone_type_path_segment ());
727 : :
728 : : return *this;
729 : : }
730 : :
731 : : // move constructors
732 : 585 : TypePath (TypePath &&other) = default;
733 : : TypePath &operator= (TypePath &&other) = default;
734 : :
735 : : std::string as_string () const override;
736 : :
737 : : /* Converts TypePath to SimplePath if possible (i.e. no generic or function
738 : : * arguments). Otherwise returns an empty SimplePath. */
739 : : AST::SimplePath as_simple_path () const;
740 : :
741 : : // Creates a trait bound with a clone of this type path as its only element.
742 : : TraitBound *to_trait_bound (bool in_parens) const override;
743 : :
744 : : void accept_vis (HIRFullVisitor &vis) override;
745 : : void accept_vis (HIRTypeVisitor &vis) override;
746 : :
747 : 81622 : size_t get_num_segments () const { return segments.size (); }
748 : :
749 : 28586 : std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
750 : : {
751 : 28586 : return segments;
752 : : }
753 : :
754 : 3115 : std::unique_ptr<TypePathSegment> &get_final_segment ()
755 : : {
756 : 3115 : return segments.back ();
757 : : }
758 : : };
759 : :
760 : : class QualifiedPathType
761 : : {
762 : : std::unique_ptr<Type> type;
763 : : std::unique_ptr<TypePath> trait;
764 : : location_t locus;
765 : : Analysis::NodeMapping mappings;
766 : :
767 : : public:
768 : : // Constructor
769 : 239 : QualifiedPathType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
770 : : std::unique_ptr<TypePath> trait, location_t locus)
771 : 239 : : type (std::move (type)), trait (std::move (trait)), locus (locus),
772 : 239 : mappings (mappings)
773 : : {}
774 : :
775 : : // Copy constructor uses custom deep copy for Type to preserve polymorphism
776 : 348 : QualifiedPathType (QualifiedPathType const &other)
777 : 348 : : type (other.type->clone_type ()),
778 : 662 : trait (other.has_as_clause () ? std::unique_ptr<HIR::TypePath> (
779 : 314 : new HIR::TypePath (*other.trait))
780 : : : nullptr),
781 : 348 : locus (other.locus), mappings (other.mappings)
782 : 348 : {}
783 : :
784 : : // default destructor
785 : 717 : ~QualifiedPathType () = default;
786 : :
787 : : // overload assignment operator to use custom clone method
788 : : QualifiedPathType &operator= (QualifiedPathType const &other)
789 : : {
790 : : type = other.type->clone_type ();
791 : : locus = other.locus;
792 : : mappings = other.mappings;
793 : : trait
794 : : = other.has_as_clause ()
795 : : ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
796 : : : nullptr;
797 : :
798 : : return *this;
799 : : }
800 : :
801 : : // move constructor
802 : 239 : QualifiedPathType (QualifiedPathType &&other) = default;
803 : : QualifiedPathType &operator= (QualifiedPathType &&other) = default;
804 : :
805 : : // Returns whether the qualified path type has a rebind as clause.
806 : 593 : bool has_as_clause () const { return trait != nullptr; }
807 : :
808 : : std::string as_string () const;
809 : :
810 : 0 : location_t get_locus () const { return locus; }
811 : :
812 : 0 : Analysis::NodeMapping get_mappings () const { return mappings; }
813 : :
814 : 0 : std::unique_ptr<Type> &get_type () { return type; }
815 : :
816 : 0 : std::unique_ptr<TypePath> &get_trait () { return trait; }
817 : :
818 : : bool trait_has_generic_args () const
819 : : {
820 : : rust_assert (has_as_clause ());
821 : : bool is_generic_seg = trait->get_final_segment ()->get_type ()
822 : : == TypePathSegment::SegmentType::GENERIC;
823 : : if (!is_generic_seg)
824 : : return false;
825 : :
826 : : TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
827 : : trait->get_final_segment ().get ());
828 : : return seg->has_generic_args ();
829 : : }
830 : :
831 : : GenericArgs &get_trait_generic_args ()
832 : : {
833 : : rust_assert (trait_has_generic_args ());
834 : : TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
835 : : trait->get_final_segment ().get ());
836 : : return seg->get_generic_args ();
837 : : }
838 : : };
839 : :
840 : : /* HIR node representing a qualified path-in-expression pattern (path that
841 : : * allows specifying trait functions) */
842 : : class QualifiedPathInExpression : public PathPattern, public PathExpr
843 : : {
844 : : QualifiedPathType path_type;
845 : : location_t locus;
846 : :
847 : : public:
848 : : std::string as_string () const override;
849 : :
850 : 80 : QualifiedPathInExpression (Analysis::NodeMapping mappings,
851 : : QualifiedPathType qual_path_type,
852 : : std::vector<PathExprSegment> path_segments,
853 : : location_t locus = UNDEF_LOCATION,
854 : : std::vector<AST::Attribute> outer_attrs
855 : : = std::vector<AST::Attribute> ())
856 : 80 : : PathPattern (std::move (path_segments)),
857 : : PathExpr (std::move (mappings), std::move (outer_attrs)),
858 : 80 : path_type (std::move (qual_path_type)), locus (locus)
859 : 80 : {}
860 : :
861 : 108 : location_t get_locus () const override final { return locus; }
862 : :
863 : : void accept_vis (HIRFullVisitor &vis) override;
864 : : void accept_vis (HIRExpressionVisitor &vis) override;
865 : : void accept_vis (HIRPatternVisitor &vis) override;
866 : :
867 : 80 : QualifiedPathType &get_path_type () { return path_type; }
868 : :
869 : 151 : location_t get_locus () { return locus; }
870 : :
871 : 231 : const Analysis::NodeMapping &get_mappings () const override final
872 : : {
873 : 231 : return mappings;
874 : : }
875 : :
876 : : protected:
877 : : /* Use covariance to implement clone function as returning this object rather
878 : : * than base */
879 : 0 : QualifiedPathInExpression *clone_pattern_impl () const override
880 : : {
881 : 0 : return new QualifiedPathInExpression (*this);
882 : : }
883 : :
884 : : /* Use covariance to implement clone function as returning this object rather
885 : : * than base */
886 : 0 : QualifiedPathInExpression *clone_expr_without_block_impl () const override
887 : : {
888 : 0 : return new QualifiedPathInExpression (*this);
889 : : }
890 : : };
891 : :
892 : : /* Represents a qualified path in a type; used for disambiguating trait function
893 : : * calls */
894 : : class QualifiedPathInType : public TypeNoBounds
895 : : {
896 : : QualifiedPathType path_type;
897 : : std::unique_ptr<TypePathSegment> associated_segment;
898 : : std::vector<std::unique_ptr<TypePathSegment> > segments;
899 : :
900 : : protected:
901 : : /* Use covariance to implement clone function as returning this object rather
902 : : * than base */
903 : 29 : QualifiedPathInType *clone_type_impl () const override
904 : : {
905 : 29 : return new QualifiedPathInType (*this);
906 : : }
907 : :
908 : : /* Use covariance to implement clone function as returning this object rather
909 : : * than base */
910 : 0 : QualifiedPathInType *clone_type_no_bounds_impl () const override
911 : : {
912 : 0 : return new QualifiedPathInType (*this);
913 : : }
914 : :
915 : : public:
916 : 159 : QualifiedPathInType (
917 : : Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
918 : : std::unique_ptr<TypePathSegment> associated_segment,
919 : : std::vector<std::unique_ptr<TypePathSegment> > path_segments,
920 : : location_t locus = UNDEF_LOCATION)
921 : 159 : : TypeNoBounds (mappings, locus), path_type (std::move (qual_path_type)),
922 : 159 : associated_segment (std::move (associated_segment)),
923 : 159 : segments (std::move (path_segments))
924 : 159 : {}
925 : :
926 : : // Copy constructor with vector clone
927 : 29 : QualifiedPathInType (QualifiedPathInType const &other)
928 : 29 : : TypeNoBounds (other.mappings, other.locus), path_type (other.path_type)
929 : : {
930 : 29 : auto seg = other.associated_segment->clone_type_path_segment_impl ();
931 : 29 : associated_segment = std::unique_ptr<TypePathSegment> (seg);
932 : :
933 : 29 : segments.reserve (other.segments.size ());
934 : 29 : for (const auto &e : other.segments)
935 : 0 : segments.push_back (e->clone_type_path_segment ());
936 : 29 : }
937 : :
938 : : // Overloaded assignment operator with vector clone
939 : : QualifiedPathInType &operator= (QualifiedPathInType const &other)
940 : : {
941 : : auto seg = other.associated_segment->clone_type_path_segment_impl ();
942 : : associated_segment = std::unique_ptr<TypePathSegment> (seg);
943 : :
944 : : path_type = other.path_type;
945 : : locus = other.locus;
946 : : mappings = other.mappings;
947 : :
948 : : segments.reserve (other.segments.size ());
949 : : for (const auto &e : other.segments)
950 : : segments.push_back (e->clone_type_path_segment ());
951 : :
952 : : return *this;
953 : : }
954 : :
955 : : // move constructors
956 : : QualifiedPathInType (QualifiedPathInType &&other) = default;
957 : : QualifiedPathInType &operator= (QualifiedPathInType &&other) = default;
958 : :
959 : : std::string as_string () const override;
960 : :
961 : : void accept_vis (HIRFullVisitor &vis) override;
962 : : void accept_vis (HIRTypeVisitor &vis) override;
963 : :
964 : 159 : QualifiedPathType &get_path_type () { return path_type; }
965 : :
966 : : std::unique_ptr<TypePathSegment> &get_associated_segment ()
967 : : {
968 : 159 : return associated_segment;
969 : : }
970 : :
971 : 0 : std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
972 : : {
973 : 159 : return segments;
974 : : }
975 : : };
976 : :
977 : : class SimplePathSegment
978 : : {
979 : : Analysis::NodeMapping mappings;
980 : :
981 : : public:
982 : 12 : SimplePathSegment (Analysis::NodeMapping mappings) : mappings (mappings) {}
983 : :
984 : : const Analysis::NodeMapping &get_mappings () const { return mappings; }
985 : : };
986 : :
987 : 127570 : class SimplePath
988 : : {
989 : : std::vector<SimplePathSegment> segments;
990 : : Analysis::NodeMapping mappings;
991 : : location_t locus;
992 : :
993 : : public:
994 : 26672 : SimplePath (std::vector<SimplePathSegment> segments,
995 : : Analysis::NodeMapping mappings, location_t locus)
996 : 26672 : : segments (std::move (segments)), mappings (mappings), locus (locus)
997 : : {}
998 : :
999 : 26664 : static HIR::SimplePath create_empty ()
1000 : : {
1001 : 26664 : return HIR::SimplePath ({}, Analysis::NodeMapping::get_error (),
1002 : 26664 : UNDEF_LOCATION);
1003 : : }
1004 : :
1005 : 12476 : bool is_error () const { return segments.empty (); }
1006 : :
1007 : 8 : const Analysis::NodeMapping &get_mappings () const { return mappings; }
1008 : 8 : location_t get_locus () const { return locus; }
1009 : : };
1010 : :
1011 : : } // namespace HIR
1012 : : } // namespace Rust
1013 : :
1014 : : #endif
|