Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : : #include "rust-substitution-mapper.h"
20 : : #include "rust-hir-type-check.h"
21 : :
22 : : namespace Rust {
23 : : namespace Resolver {
24 : :
25 : 9506 : SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics,
26 : : const std::vector<TyTy::Region> ®ions,
27 : 9506 : location_t locus)
28 : 9506 : : resolved (new TyTy::ErrorType (ref)), generics (generics),
29 : 9506 : regions (regions), locus (locus)
30 : 9506 : {}
31 : :
32 : : TyTy::BaseType *
33 : 9509 : SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
34 : : HIR::GenericArgs *generics,
35 : : const std::vector<TyTy::Region> ®ions)
36 : : {
37 : 9509 : if (!valid_type (base))
38 : : {
39 : 3 : rich_location r (line_table, locus);
40 : 3 : r.add_fixit_remove (generics->get_locus ());
41 : 3 : rust_error_at (r, ErrorCode::E0109,
42 : : "generic arguments are not allowed for this type");
43 : 3 : return base;
44 : 3 : }
45 : :
46 : 9506 : SubstMapper mapper (base->get_ref (), generics, regions, locus);
47 : 9506 : base->accept_vis (mapper);
48 : 9506 : rust_assert (mapper.resolved != nullptr);
49 : : return mapper.resolved;
50 : : }
51 : :
52 : : TyTy::BaseType *
53 : 6541 : SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
54 : : {
55 : 6541 : return SubstMapper::Resolve (base, locus, nullptr, {});
56 : : }
57 : :
58 : : bool
59 : 9509 : SubstMapper::valid_type (TyTy::BaseType *base)
60 : : {
61 : 9509 : bool is_fn = base->is<TyTy::FnType> ();
62 : 9509 : bool is_adt = base->is<TyTy::ADTType> ();
63 : 9509 : bool is_placeholder = base->is<TyTy::PlaceholderType> ();
64 : 9509 : bool is_projection = base->is<TyTy::ProjectionType> ();
65 : :
66 : 9509 : return is_fn || is_adt || is_placeholder || is_projection;
67 : : }
68 : :
69 : : bool
70 : 9506 : SubstMapper::have_generic_args () const
71 : : {
72 : 9506 : return generics != nullptr;
73 : : }
74 : :
75 : : void
76 : 4707 : SubstMapper::visit (TyTy::FnType &type)
77 : : {
78 : 4707 : TyTy::FnType *concrete = nullptr;
79 : 4707 : if (!have_generic_args ())
80 : : {
81 : 4076 : TyTy::BaseType *substs = type.infer_substitions (locus);
82 : 4076 : rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
83 : : concrete = static_cast<TyTy::FnType *> (substs);
84 : : }
85 : : else
86 : : {
87 : 631 : TyTy::SubstitutionArgumentMappings mappings
88 : 631 : = type.get_mappings_from_generic_args (*generics, regions);
89 : 631 : if (mappings.is_error ())
90 : 1 : return;
91 : :
92 : 630 : concrete = type.handle_substitions (mappings);
93 : 631 : }
94 : :
95 : 630 : if (concrete != nullptr)
96 : 4706 : resolved = concrete;
97 : : }
98 : :
99 : : void
100 : 4799 : SubstMapper::visit (TyTy::ADTType &type)
101 : : {
102 : 4799 : TyTy::ADTType *concrete = nullptr;
103 : 4799 : if (!have_generic_args ())
104 : : {
105 : 2465 : TyTy::BaseType *substs = type.infer_substitions (locus);
106 : 2465 : rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
107 : : concrete = static_cast<TyTy::ADTType *> (substs);
108 : : }
109 : : else
110 : : {
111 : 2334 : TyTy::SubstitutionArgumentMappings mappings
112 : 2334 : = type.get_mappings_from_generic_args (*generics, regions);
113 : 2334 : if (mappings.is_error ())
114 : 8 : return;
115 : :
116 : 2326 : concrete = type.handle_substitions (mappings);
117 : 2334 : }
118 : :
119 : 2326 : if (concrete != nullptr)
120 : 4791 : resolved = concrete;
121 : : }
122 : :
123 : : void
124 : 0 : SubstMapper::visit (TyTy::PlaceholderType &type)
125 : : {
126 : 0 : if (!type.can_resolve ())
127 : : {
128 : 0 : resolved = &type;
129 : 0 : return;
130 : : }
131 : :
132 : 0 : resolved = SubstMapper::Resolve (type.resolve (), locus, generics, regions);
133 : : }
134 : :
135 : : void
136 : 0 : SubstMapper::visit (TyTy::ProjectionType &type)
137 : : {
138 : 0 : TyTy::ProjectionType *concrete = nullptr;
139 : 0 : if (!have_generic_args ())
140 : : {
141 : 0 : TyTy::BaseType *substs = type.infer_substitions (locus);
142 : 0 : rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
143 : : concrete = static_cast<TyTy::ProjectionType *> (substs);
144 : : }
145 : : else
146 : : {
147 : 0 : TyTy::SubstitutionArgumentMappings mappings
148 : 0 : = type.get_mappings_from_generic_args (*generics, regions);
149 : 0 : if (mappings.is_error ())
150 : 0 : return;
151 : :
152 : 0 : concrete = type.handle_substitions (mappings);
153 : 0 : }
154 : :
155 : 0 : if (concrete != nullptr)
156 : 0 : resolved = concrete;
157 : : }
158 : :
159 : 84803 : SubstMapperInternal::SubstMapperInternal (
160 : 84803 : HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
161 : 84803 : : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
162 : 84803 : {}
163 : :
164 : : TyTy::BaseType *
165 : 84803 : SubstMapperInternal::Resolve (TyTy::BaseType *base,
166 : : TyTy::SubstitutionArgumentMappings &mappings)
167 : : {
168 : 84803 : auto context = TypeCheckContext::get ();
169 : :
170 : 84803 : SubstMapperInternal mapper (base->get_ref (), mappings);
171 : 84803 : base->accept_vis (mapper);
172 : 84803 : rust_assert (mapper.resolved != nullptr);
173 : :
174 : : // insert these new implict types into the context
175 : 84803 : TyTy::BaseType *unused = nullptr;
176 : 84803 : bool is_ty_available
177 : 84803 : = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
178 : 84803 : if (!is_ty_available)
179 : : {
180 : 24289 : context->insert_type (
181 : 24289 : Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
182 : : mapper.resolved);
183 : : }
184 : 84803 : bool is_ref_available
185 : 84803 : = context->lookup_type (mapper.resolved->get_ref (), &unused);
186 : 84803 : if (!is_ref_available)
187 : : {
188 : 45240 : context->insert_type (Analysis::NodeMapping (0, 0,
189 : : mapper.resolved->get_ref (),
190 : 45240 : 0),
191 : : mapper.resolved);
192 : : }
193 : :
194 : 84803 : return mapper.resolved;
195 : : }
196 : :
197 : : bool
198 : 0 : SubstMapperInternal::mappings_are_bound (
199 : : TyTy::BaseType *tyseg, TyTy::SubstitutionArgumentMappings &mappings)
200 : : {
201 : 0 : if (tyseg->get_kind () == TyTy::TypeKind::ADT)
202 : : {
203 : 0 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
204 : 0 : return adt->are_mappings_bound (mappings);
205 : : }
206 : 0 : else if (tyseg->get_kind () == TyTy::TypeKind::FNDEF)
207 : : {
208 : 0 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (tyseg);
209 : 0 : return fn->are_mappings_bound (mappings);
210 : : }
211 : :
212 : : return false;
213 : : }
214 : :
215 : : void
216 : 6589 : SubstMapperInternal::visit (TyTy::FnType &type)
217 : : {
218 : 6589 : TyTy::SubstitutionArgumentMappings adjusted
219 : 6589 : = type.adjust_mappings_for_this (mappings);
220 : 6589 : if (adjusted.is_error () && !mappings.trait_item_mode ())
221 : 0 : return;
222 : 6589 : if (adjusted.is_error () && mappings.trait_item_mode ())
223 : 0 : adjusted = mappings;
224 : :
225 : 6589 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
226 : 6589 : if (concrete != nullptr)
227 : 6589 : resolved = concrete;
228 : 6589 : }
229 : :
230 : : void
231 : 3356 : SubstMapperInternal::visit (TyTy::ADTType &type)
232 : : {
233 : 3356 : TyTy::SubstitutionArgumentMappings adjusted
234 : 3356 : = type.adjust_mappings_for_this (mappings);
235 : 3356 : if (adjusted.is_error () && !mappings.trait_item_mode ())
236 : 0 : return;
237 : 3356 : if (adjusted.is_error () && mappings.trait_item_mode ())
238 : 8 : adjusted = mappings;
239 : :
240 : 3356 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
241 : 3356 : if (concrete != nullptr)
242 : 3356 : resolved = concrete;
243 : 3356 : }
244 : :
245 : : // these don't support generic arguments but might contain a type param
246 : : void
247 : 264 : SubstMapperInternal::visit (TyTy::TupleType &type)
248 : : {
249 : 264 : resolved = type.handle_substitions (mappings);
250 : 264 : }
251 : :
252 : : void
253 : 9957 : SubstMapperInternal::visit (TyTy::ReferenceType &type)
254 : : {
255 : 9957 : resolved = type.handle_substitions (mappings);
256 : 9957 : }
257 : :
258 : : void
259 : 2930 : SubstMapperInternal::visit (TyTy::PointerType &type)
260 : : {
261 : 2930 : resolved = type.handle_substitions (mappings);
262 : 2930 : }
263 : :
264 : : void
265 : 59040 : SubstMapperInternal::visit (TyTy::ParamType &type)
266 : : {
267 : 59040 : resolved = type.handle_substitions (mappings);
268 : 59040 : }
269 : :
270 : : void
271 : 57 : SubstMapperInternal::visit (TyTy::ConstParamType &type)
272 : : {
273 : 57 : resolved = type.handle_substitions (mappings);
274 : 57 : }
275 : :
276 : : void
277 : 0 : SubstMapperInternal::visit (TyTy::ConstValueType &type)
278 : : {
279 : 0 : resolved = type.clone ();
280 : 0 : }
281 : :
282 : : void
283 : 0 : SubstMapperInternal::visit (TyTy::ConstInferType &type)
284 : : {
285 : 0 : resolved = type.clone ();
286 : 0 : }
287 : :
288 : : void
289 : 0 : SubstMapperInternal::visit (TyTy::ConstErrorType &type)
290 : : {
291 : 0 : resolved = type.clone ();
292 : 0 : }
293 : :
294 : : void
295 : 481 : SubstMapperInternal::visit (TyTy::PlaceholderType &type)
296 : : {
297 : 481 : rust_assert (type.can_resolve ());
298 : 481 : if (mappings.trait_item_mode ())
299 : : {
300 : 479 : resolved = type.resolve ();
301 : : }
302 : : else
303 : : {
304 : 2 : resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
305 : : }
306 : 481 : }
307 : :
308 : : void
309 : 731 : SubstMapperInternal::visit (TyTy::ProjectionType &type)
310 : : {
311 : 731 : resolved = type.handle_substitions (mappings);
312 : 731 : }
313 : :
314 : : void
315 : 0 : SubstMapperInternal::visit (TyTy::ClosureType &type)
316 : : {
317 : 0 : resolved = type.handle_substitions (mappings);
318 : 0 : }
319 : :
320 : : void
321 : 57 : SubstMapperInternal::visit (TyTy::ArrayType &type)
322 : : {
323 : 57 : resolved = type.handle_substitions (mappings);
324 : 57 : }
325 : :
326 : : void
327 : 1128 : SubstMapperInternal::visit (TyTy::SliceType &type)
328 : : {
329 : 1128 : resolved = type.handle_substitions (mappings);
330 : 1128 : }
331 : : void
332 : 8 : SubstMapperInternal::visit (TyTy::FnPtr &type)
333 : : {
334 : 8 : resolved = type.handle_substitions (mappings);
335 : 8 : }
336 : :
337 : : // nothing to do for these
338 : : void
339 : 0 : SubstMapperInternal::visit (TyTy::InferType &type)
340 : : {
341 : 0 : resolved = type.clone ();
342 : 0 : }
343 : : void
344 : 0 : SubstMapperInternal::visit (TyTy::BoolType &type)
345 : : {
346 : 0 : resolved = type.clone ();
347 : 0 : }
348 : : void
349 : 1 : SubstMapperInternal::visit (TyTy::IntType &type)
350 : : {
351 : 1 : resolved = type.clone ();
352 : 1 : }
353 : : void
354 : 73 : SubstMapperInternal::visit (TyTy::UintType &type)
355 : : {
356 : 73 : resolved = type.clone ();
357 : 73 : }
358 : : void
359 : 0 : SubstMapperInternal::visit (TyTy::FloatType &type)
360 : : {
361 : 0 : resolved = type.clone ();
362 : 0 : }
363 : : void
364 : 75 : SubstMapperInternal::visit (TyTy::USizeType &type)
365 : : {
366 : 75 : resolved = type.clone ();
367 : 75 : }
368 : : void
369 : 56 : SubstMapperInternal::visit (TyTy::ISizeType &type)
370 : : {
371 : 56 : resolved = type.clone ();
372 : 56 : }
373 : : void
374 : 0 : SubstMapperInternal::visit (TyTy::ErrorType &type)
375 : : {
376 : 0 : resolved = type.clone ();
377 : 0 : }
378 : : void
379 : 0 : SubstMapperInternal::visit (TyTy::CharType &type)
380 : : {
381 : 0 : resolved = type.clone ();
382 : 0 : }
383 : : void
384 : 0 : SubstMapperInternal::visit (TyTy::StrType &type)
385 : : {
386 : 0 : resolved = type.clone ();
387 : 0 : }
388 : : void
389 : 0 : SubstMapperInternal::visit (TyTy::NeverType &type)
390 : : {
391 : 0 : resolved = type.clone ();
392 : 0 : }
393 : : void
394 : 0 : SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
395 : : {
396 : 0 : resolved = type.clone ();
397 : 0 : }
398 : : void
399 : 0 : SubstMapperInternal::visit (TyTy::OpaqueType &type)
400 : : {
401 : 0 : resolved = type.clone ();
402 : 0 : }
403 : :
404 : : // SubstMapperFromExisting
405 : :
406 : 0 : SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
407 : 0 : TyTy::BaseType *receiver)
408 : 0 : : concrete (concrete), receiver (receiver), resolved (nullptr)
409 : 0 : {}
410 : :
411 : : TyTy::BaseType *
412 : 0 : SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
413 : : TyTy::BaseType *receiver)
414 : : {
415 : 0 : rust_assert (concrete->get_kind () == receiver->get_kind ());
416 : :
417 : 0 : SubstMapperFromExisting mapper (concrete, receiver);
418 : 0 : concrete->accept_vis (mapper);
419 : 0 : return mapper.resolved;
420 : : }
421 : :
422 : : void
423 : 0 : SubstMapperFromExisting::visit (TyTy::FnType &type)
424 : : {
425 : 0 : rust_assert (type.was_substituted ());
426 : :
427 : 0 : TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
428 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
429 : 0 : }
430 : :
431 : : void
432 : 0 : SubstMapperFromExisting::visit (TyTy::ADTType &type)
433 : : {
434 : 0 : rust_assert (type.was_substituted ());
435 : :
436 : 0 : TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
437 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
438 : 0 : }
439 : :
440 : : void
441 : 0 : SubstMapperFromExisting::visit (TyTy::ClosureType &type)
442 : : {
443 : 0 : rust_assert (type.was_substituted ());
444 : :
445 : 0 : TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
446 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
447 : 0 : }
448 : :
449 : : // GetUsedSubstArgs
450 : :
451 : 42956 : GetUsedSubstArgs::GetUsedSubstArgs ()
452 : 42956 : : args (TyTy::SubstitutionArgumentMappings::error ())
453 : 42956 : {}
454 : :
455 : : TyTy::SubstitutionArgumentMappings
456 : 42956 : GetUsedSubstArgs::From (const TyTy::BaseType *from)
457 : : {
458 : 42956 : GetUsedSubstArgs mapper;
459 : 42956 : from->accept_vis (mapper);
460 : 42956 : return mapper.args;
461 : 42956 : }
462 : :
463 : : void
464 : 0 : GetUsedSubstArgs::visit (const TyTy::FnType &type)
465 : : {
466 : 0 : args = type.get_substitution_arguments ();
467 : 0 : }
468 : :
469 : : void
470 : 11017 : GetUsedSubstArgs::visit (const TyTy::ADTType &type)
471 : : {
472 : 11017 : args = type.get_substitution_arguments ();
473 : 11017 : }
474 : :
475 : : void
476 : 0 : GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
477 : : {
478 : 0 : args = type.get_substitution_arguments ();
479 : 0 : }
480 : :
481 : : } // namespace Resolver
482 : : } // namespace Rust
|