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 10314 : SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics,
26 : const std::vector<TyTy::Region> ®ions,
27 10314 : location_t locus)
28 10314 : : resolved (new TyTy::ErrorType (ref)), generics (generics),
29 10314 : regions (regions), locus (locus)
30 10314 : {}
31 :
32 : TyTy::BaseType *
33 10317 : SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
34 : HIR::GenericArgs *generics,
35 : const std::vector<TyTy::Region> ®ions)
36 : {
37 10317 : 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 10314 : SubstMapper mapper (base->get_ref (), generics, regions, locus);
47 10314 : base->accept_vis (mapper);
48 10314 : rust_assert (mapper.resolved != nullptr);
49 : return mapper.resolved;
50 : }
51 :
52 : TyTy::BaseType *
53 7289 : SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
54 : {
55 7289 : return SubstMapper::Resolve (base, locus, nullptr, {});
56 : }
57 :
58 : bool
59 10317 : SubstMapper::valid_type (TyTy::BaseType *base)
60 : {
61 10317 : bool is_fn = base->is<TyTy::FnType> ();
62 10317 : bool is_adt = base->is<TyTy::ADTType> ();
63 10317 : bool is_placeholder = base->is<TyTy::PlaceholderType> ();
64 10317 : bool is_projection = base->is<TyTy::ProjectionType> ();
65 :
66 10317 : return is_fn || is_adt || is_placeholder || is_projection;
67 : }
68 :
69 : bool
70 10314 : SubstMapper::have_generic_args () const
71 : {
72 10314 : return generics != nullptr;
73 : }
74 :
75 : void
76 5435 : SubstMapper::visit (TyTy::FnType &type)
77 : {
78 5435 : TyTy::FnType *concrete = nullptr;
79 5435 : if (!have_generic_args ())
80 : {
81 4793 : TyTy::BaseType *substs = type.infer_substitions (locus);
82 4793 : rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
83 : concrete = static_cast<TyTy::FnType *> (substs);
84 : }
85 : else
86 : {
87 642 : TyTy::SubstitutionArgumentMappings mappings
88 642 : = type.get_mappings_from_generic_args (*generics, regions);
89 642 : if (mappings.is_error ())
90 2 : return;
91 :
92 640 : concrete = type.handle_substitions (mappings);
93 642 : }
94 :
95 640 : if (concrete != nullptr)
96 5433 : resolved = concrete;
97 : }
98 :
99 : void
100 4852 : SubstMapper::visit (TyTy::ADTType &type)
101 : {
102 4852 : TyTy::ADTType *concrete = nullptr;
103 4852 : if (!have_generic_args ())
104 : {
105 2496 : TyTy::BaseType *substs = type.infer_substitions (locus);
106 2496 : rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
107 : concrete = static_cast<TyTy::ADTType *> (substs);
108 : }
109 : else
110 : {
111 2356 : TyTy::SubstitutionArgumentMappings mappings
112 2356 : = type.get_mappings_from_generic_args (*generics, regions);
113 2356 : if (mappings.is_error ())
114 9 : return;
115 :
116 2347 : concrete = type.handle_substitions (mappings);
117 2356 : }
118 :
119 2347 : if (concrete != nullptr)
120 4843 : 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 27 : SubstMapper::visit (TyTy::ProjectionType &type)
137 : {
138 27 : TyTy::ProjectionType *concrete = nullptr;
139 27 : 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 27 : TyTy::SubstitutionArgumentMappings mappings
148 27 : = type.get_mappings_from_generic_args (*generics, regions);
149 27 : if (mappings.is_error ())
150 0 : return;
151 :
152 27 : concrete = type.handle_substitions (mappings);
153 27 : }
154 :
155 27 : if (concrete != nullptr)
156 27 : resolved = concrete;
157 : }
158 :
159 115696 : SubstMapperInternal::SubstMapperInternal (
160 115696 : HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
161 115696 : : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
162 115696 : {}
163 :
164 : TyTy::BaseType *
165 115696 : SubstMapperInternal::Resolve (TyTy::BaseType *base,
166 : TyTy::SubstitutionArgumentMappings &mappings)
167 : {
168 115696 : auto context = TypeCheckContext::get ();
169 :
170 115696 : SubstMapperInternal mapper (base->get_ref (), mappings);
171 115696 : base->accept_vis (mapper);
172 115696 : rust_assert (mapper.resolved != nullptr);
173 :
174 : // insert these new implict types into the context
175 115696 : TyTy::BaseType *unused = nullptr;
176 115696 : bool is_ty_available
177 115696 : = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
178 115696 : if (!is_ty_available)
179 : {
180 28844 : context->insert_type (
181 28844 : Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
182 : mapper.resolved);
183 : }
184 115696 : bool is_ref_available
185 115696 : = context->lookup_type (mapper.resolved->get_ref (), &unused);
186 115696 : if (!is_ref_available)
187 : {
188 58793 : context->insert_type (Analysis::NodeMapping (0, 0,
189 : mapper.resolved->get_ref (),
190 58793 : 0),
191 : mapper.resolved);
192 : }
193 :
194 115696 : 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 6742 : SubstMapperInternal::visit (TyTy::FnType &type)
217 : {
218 6742 : TyTy::SubstitutionArgumentMappings adjusted
219 6742 : = type.adjust_mappings_for_this (mappings);
220 6742 : if (adjusted.is_error () && !mappings.trait_item_mode ())
221 0 : return;
222 6742 : if (adjusted.is_error () && mappings.trait_item_mode ())
223 0 : adjusted = mappings;
224 :
225 6742 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
226 6742 : if (concrete != nullptr)
227 6742 : resolved = concrete;
228 6742 : }
229 :
230 : void
231 6631 : SubstMapperInternal::visit (TyTy::ADTType &type)
232 : {
233 6631 : TyTy::SubstitutionArgumentMappings adjusted
234 6631 : = type.adjust_mappings_for_this (mappings);
235 6631 : if (adjusted.is_error () && !mappings.trait_item_mode ())
236 0 : return;
237 6631 : if (adjusted.is_error () && mappings.trait_item_mode ())
238 12 : adjusted = mappings;
239 :
240 6631 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
241 6631 : if (concrete != nullptr)
242 6631 : resolved = concrete;
243 6631 : }
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 10501 : SubstMapperInternal::visit (TyTy::ReferenceType &type)
254 : {
255 10501 : resolved = type.handle_substitions (mappings);
256 10501 : }
257 :
258 : void
259 3023 : SubstMapperInternal::visit (TyTy::PointerType &type)
260 : {
261 3023 : resolved = type.handle_substitions (mappings);
262 3023 : }
263 :
264 : void
265 79148 : SubstMapperInternal::visit (TyTy::ParamType &type)
266 : {
267 79148 : resolved = type.handle_substitions (mappings);
268 79148 : }
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 0 : SubstMapperInternal::visit (TyTy::PlaceholderType &type)
296 : {
297 0 : rust_assert (type.can_resolve ());
298 0 : if (mappings.trait_item_mode ())
299 : {
300 0 : resolved = type.resolve ();
301 : }
302 : else
303 : {
304 0 : resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
305 : }
306 0 : }
307 :
308 : void
309 7487 : SubstMapperInternal::visit (TyTy::ProjectionType &type)
310 : {
311 7487 : resolved = type.handle_substitions (mappings);
312 7487 : }
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 1618 : SubstMapperInternal::visit (TyTy::SliceType &type)
328 : {
329 1618 : resolved = type.handle_substitions (mappings);
330 1618 : }
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 22 : SubstMapperInternal::visit (TyTy::IntType &type)
350 : {
351 22 : resolved = type.clone ();
352 22 : }
353 : void
354 75 : SubstMapperInternal::visit (TyTy::UintType &type)
355 : {
356 75 : resolved = type.clone ();
357 75 : }
358 : void
359 0 : SubstMapperInternal::visit (TyTy::FloatType &type)
360 : {
361 0 : resolved = type.clone ();
362 0 : }
363 : void
364 7 : SubstMapperInternal::visit (TyTy::USizeType &type)
365 : {
366 7 : resolved = type.clone ();
367 7 : }
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 45427 : GetUsedSubstArgs::GetUsedSubstArgs ()
452 45427 : : args (TyTy::SubstitutionArgumentMappings::error ())
453 45427 : {}
454 :
455 : TyTy::SubstitutionArgumentMappings
456 45427 : GetUsedSubstArgs::From (const TyTy::BaseType *from)
457 : {
458 45427 : GetUsedSubstArgs mapper;
459 45427 : from->accept_vis (mapper);
460 45427 : return mapper.args;
461 45427 : }
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 11543 : GetUsedSubstArgs::visit (const TyTy::ADTType &type)
471 : {
472 11543 : args = type.get_substitution_arguments ();
473 11543 : }
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
|