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