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 9513 : SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics,
26 : const std::vector<TyTy::Region> ®ions,
27 9513 : location_t locus)
28 9513 : : resolved (new TyTy::ErrorType (ref)), generics (generics),
29 9513 : regions (regions), locus (locus)
30 9513 : {}
31 :
32 : TyTy::BaseType *
33 9516 : SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
34 : HIR::GenericArgs *generics,
35 : const std::vector<TyTy::Region> ®ions)
36 : {
37 9516 : 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 9513 : SubstMapper mapper (base->get_ref (), generics, regions, locus);
47 9513 : base->accept_vis (mapper);
48 9513 : 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 9516 : SubstMapper::valid_type (TyTy::BaseType *base)
60 : {
61 9516 : bool is_fn = base->is<TyTy::FnType> ();
62 9516 : bool is_adt = base->is<TyTy::ADTType> ();
63 9516 : bool is_placeholder = base->is<TyTy::PlaceholderType> ();
64 9516 : bool is_projection = base->is<TyTy::ProjectionType> ();
65 :
66 9516 : return is_fn || is_adt || is_placeholder || is_projection;
67 : }
68 :
69 : bool
70 9513 : SubstMapper::have_generic_args () const
71 : {
72 9513 : 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 7 : SubstMapper::visit (TyTy::ProjectionType &type)
137 : {
138 7 : TyTy::ProjectionType *concrete = nullptr;
139 7 : 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 7 : TyTy::SubstitutionArgumentMappings mappings
148 7 : = type.get_mappings_from_generic_args (*generics, regions);
149 7 : if (mappings.is_error ())
150 0 : return;
151 :
152 7 : concrete = type.handle_substitions (mappings);
153 7 : }
154 :
155 7 : if (concrete != nullptr)
156 7 : resolved = concrete;
157 : }
158 :
159 84843 : SubstMapperInternal::SubstMapperInternal (
160 84843 : HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
161 84843 : : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
162 84843 : {}
163 :
164 : TyTy::BaseType *
165 84843 : SubstMapperInternal::Resolve (TyTy::BaseType *base,
166 : TyTy::SubstitutionArgumentMappings &mappings)
167 : {
168 84843 : auto context = TypeCheckContext::get ();
169 :
170 84843 : SubstMapperInternal mapper (base->get_ref (), mappings);
171 84843 : base->accept_vis (mapper);
172 84843 : rust_assert (mapper.resolved != nullptr);
173 :
174 : // insert these new implict types into the context
175 84843 : TyTy::BaseType *unused = nullptr;
176 84843 : bool is_ty_available
177 84843 : = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
178 84843 : if (!is_ty_available)
179 : {
180 24291 : context->insert_type (
181 24291 : Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
182 : mapper.resolved);
183 : }
184 84843 : bool is_ref_available
185 84843 : = context->lookup_type (mapper.resolved->get_ref (), &unused);
186 84843 : if (!is_ref_available)
187 : {
188 45257 : context->insert_type (Analysis::NodeMapping (0, 0,
189 : mapper.resolved->get_ref (),
190 45257 : 0),
191 : mapper.resolved);
192 : }
193 :
194 84843 : 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 6591 : SubstMapperInternal::visit (TyTy::FnType &type)
217 : {
218 6591 : TyTy::SubstitutionArgumentMappings adjusted
219 6591 : = type.adjust_mappings_for_this (mappings);
220 6591 : if (adjusted.is_error () && !mappings.trait_item_mode ())
221 0 : return;
222 6591 : if (adjusted.is_error () && mappings.trait_item_mode ())
223 0 : adjusted = mappings;
224 :
225 6591 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
226 6591 : if (concrete != nullptr)
227 6591 : resolved = concrete;
228 6591 : }
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 59064 : SubstMapperInternal::visit (TyTy::ParamType &type)
266 : {
267 59064 : resolved = type.handle_substitions (mappings);
268 59064 : }
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 745 : SubstMapperInternal::visit (TyTy::ProjectionType &type)
310 : {
311 745 : resolved = type.handle_substitions (mappings);
312 745 : }
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 42965 : GetUsedSubstArgs::GetUsedSubstArgs ()
452 42965 : : args (TyTy::SubstitutionArgumentMappings::error ())
453 42965 : {}
454 :
455 : TyTy::SubstitutionArgumentMappings
456 42965 : GetUsedSubstArgs::From (const TyTy::BaseType *from)
457 : {
458 42965 : GetUsedSubstArgs mapper;
459 42965 : from->accept_vis (mapper);
460 42965 : return mapper.args;
461 42965 : }
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 11026 : GetUsedSubstArgs::visit (const TyTy::ADTType &type)
471 : {
472 11026 : args = type.get_substitution_arguments ();
473 11026 : }
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
|