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 : 9282 : SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics,
26 : : const std::vector<TyTy::Region> ®ions,
27 : 9282 : location_t locus)
28 : 9282 : : resolved (new TyTy::ErrorType (ref)), generics (generics),
29 : 9282 : regions (regions), locus (locus)
30 : 9282 : {}
31 : :
32 : : TyTy::BaseType *
33 : 9285 : SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
34 : : HIR::GenericArgs *generics,
35 : : const std::vector<TyTy::Region> ®ions)
36 : : {
37 : 9285 : 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 : 9282 : SubstMapper mapper (base->get_ref (), generics, regions, locus);
47 : 9282 : base->accept_vis (mapper);
48 : 9282 : rust_assert (mapper.resolved != nullptr);
49 : : return mapper.resolved;
50 : : }
51 : :
52 : : TyTy::BaseType *
53 : 6400 : SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
54 : : {
55 : 6400 : return SubstMapper::Resolve (base, locus, nullptr, {});
56 : : }
57 : :
58 : : bool
59 : 9285 : SubstMapper::valid_type (TyTy::BaseType *base)
60 : : {
61 : 9285 : bool is_fn = base->is<TyTy::FnType> ();
62 : 9285 : bool is_adt = base->is<TyTy::ADTType> ();
63 : 9285 : bool is_placeholder = base->is<TyTy::PlaceholderType> ();
64 : 9285 : bool is_projection = base->is<TyTy::ProjectionType> ();
65 : :
66 : 9285 : return is_fn || is_adt || is_placeholder || is_projection;
67 : : }
68 : :
69 : : bool
70 : 9282 : SubstMapper::have_generic_args () const
71 : : {
72 : 9282 : return generics != nullptr;
73 : : }
74 : :
75 : : void
76 : 4560 : SubstMapper::visit (TyTy::FnType &type)
77 : : {
78 : 4560 : TyTy::FnType *concrete = nullptr;
79 : 4560 : if (!have_generic_args ())
80 : : {
81 : 3936 : TyTy::BaseType *substs = type.infer_substitions (locus);
82 : 3936 : rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
83 : : concrete = static_cast<TyTy::FnType *> (substs);
84 : : }
85 : : else
86 : : {
87 : 624 : TyTy::SubstitutionArgumentMappings mappings
88 : 624 : = type.get_mappings_from_generic_args (*generics, regions);
89 : 624 : if (mappings.is_error ())
90 : 1 : return;
91 : :
92 : 623 : concrete = type.handle_substitions (mappings);
93 : 624 : }
94 : :
95 : 623 : if (concrete != nullptr)
96 : 4559 : resolved = concrete;
97 : : }
98 : :
99 : : void
100 : 4722 : SubstMapper::visit (TyTy::ADTType &type)
101 : : {
102 : 4722 : TyTy::ADTType *concrete = nullptr;
103 : 4722 : if (!have_generic_args ())
104 : : {
105 : 2464 : TyTy::BaseType *substs = type.infer_substitions (locus);
106 : 2464 : rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
107 : : concrete = static_cast<TyTy::ADTType *> (substs);
108 : : }
109 : : else
110 : : {
111 : 2258 : TyTy::SubstitutionArgumentMappings mappings
112 : 2258 : = type.get_mappings_from_generic_args (*generics, regions);
113 : 2258 : if (mappings.is_error ())
114 : 8 : return;
115 : :
116 : 2250 : concrete = type.handle_substitions (mappings);
117 : 2258 : }
118 : :
119 : 2250 : if (concrete != nullptr)
120 : 4714 : 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 : 81940 : SubstMapperInternal::SubstMapperInternal (
160 : 81940 : HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
161 : 81940 : : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
162 : 81940 : {}
163 : :
164 : : TyTy::BaseType *
165 : 81940 : SubstMapperInternal::Resolve (TyTy::BaseType *base,
166 : : TyTy::SubstitutionArgumentMappings &mappings)
167 : : {
168 : 81940 : auto context = TypeCheckContext::get ();
169 : :
170 : 81940 : SubstMapperInternal mapper (base->get_ref (), mappings);
171 : 81940 : base->accept_vis (mapper);
172 : 81940 : rust_assert (mapper.resolved != nullptr);
173 : :
174 : : // insert these new implict types into the context
175 : 81940 : TyTy::BaseType *unused = nullptr;
176 : 81940 : bool is_ty_available
177 : 81940 : = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
178 : 81940 : if (!is_ty_available)
179 : : {
180 : 22936 : context->insert_type (
181 : 22936 : Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
182 : : mapper.resolved);
183 : : }
184 : 81940 : bool is_ref_available
185 : 81940 : = context->lookup_type (mapper.resolved->get_ref (), &unused);
186 : 81940 : if (!is_ref_available)
187 : : {
188 : 45147 : context->insert_type (Analysis::NodeMapping (0, 0,
189 : : mapper.resolved->get_ref (),
190 : 45147 : 0),
191 : : mapper.resolved);
192 : : }
193 : :
194 : 81940 : 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 : 6658 : SubstMapperInternal::visit (TyTy::FnType &type)
217 : : {
218 : 6658 : TyTy::SubstitutionArgumentMappings adjusted
219 : 6658 : = type.adjust_mappings_for_this (mappings);
220 : 6658 : if (adjusted.is_error () && !mappings.trait_item_mode ())
221 : 0 : return;
222 : 6658 : if (adjusted.is_error () && mappings.trait_item_mode ())
223 : 0 : adjusted = mappings;
224 : :
225 : 6658 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
226 : 6658 : if (concrete != nullptr)
227 : 6658 : resolved = concrete;
228 : 6658 : }
229 : :
230 : : void
231 : 1927 : SubstMapperInternal::visit (TyTy::ADTType &type)
232 : : {
233 : 1927 : TyTy::SubstitutionArgumentMappings adjusted
234 : 1927 : = type.adjust_mappings_for_this (mappings);
235 : 1927 : if (adjusted.is_error () && !mappings.trait_item_mode ())
236 : 0 : return;
237 : 1927 : if (adjusted.is_error () && mappings.trait_item_mode ())
238 : 8 : adjusted = mappings;
239 : :
240 : 1927 : TyTy::BaseType *concrete = type.handle_substitions (adjusted);
241 : 1927 : if (concrete != nullptr)
242 : 1927 : resolved = concrete;
243 : 1927 : }
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 : 9937 : SubstMapperInternal::visit (TyTy::ReferenceType &type)
254 : : {
255 : 9937 : resolved = type.handle_substitions (mappings);
256 : 9937 : }
257 : :
258 : : void
259 : 2930 : SubstMapperInternal::visit (TyTy::PointerType &type)
260 : : {
261 : 2930 : resolved = type.handle_substitions (mappings);
262 : 2930 : }
263 : :
264 : : void
265 : 57555 : SubstMapperInternal::visit (TyTy::ParamType &type)
266 : : {
267 : 57555 : resolved = type.handle_substitions (mappings);
268 : 57555 : }
269 : :
270 : : void
271 : 43 : SubstMapperInternal::visit (TyTy::ConstType &type)
272 : : {
273 : 43 : resolved = type.handle_substitions (mappings);
274 : 43 : }
275 : :
276 : : void
277 : 481 : SubstMapperInternal::visit (TyTy::PlaceholderType &type)
278 : : {
279 : 481 : rust_assert (type.can_resolve ());
280 : 481 : if (mappings.trait_item_mode ())
281 : : {
282 : 479 : resolved = type.resolve ();
283 : : }
284 : : else
285 : : {
286 : 2 : resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
287 : : }
288 : 481 : }
289 : :
290 : : void
291 : 731 : SubstMapperInternal::visit (TyTy::ProjectionType &type)
292 : : {
293 : 731 : resolved = type.handle_substitions (mappings);
294 : 731 : }
295 : :
296 : : void
297 : 0 : SubstMapperInternal::visit (TyTy::ClosureType &type)
298 : : {
299 : 0 : resolved = type.handle_substitions (mappings);
300 : 0 : }
301 : :
302 : : void
303 : 43 : SubstMapperInternal::visit (TyTy::ArrayType &type)
304 : : {
305 : 43 : resolved = type.handle_substitions (mappings);
306 : 43 : }
307 : :
308 : : void
309 : 1177 : SubstMapperInternal::visit (TyTy::SliceType &type)
310 : : {
311 : 1177 : resolved = type.handle_substitions (mappings);
312 : 1177 : }
313 : :
314 : : // nothing to do for these
315 : : void
316 : 0 : SubstMapperInternal::visit (TyTy::InferType &type)
317 : : {
318 : 0 : resolved = type.clone ();
319 : 0 : }
320 : : void
321 : 3 : SubstMapperInternal::visit (TyTy::FnPtr &type)
322 : : {
323 : 3 : resolved = type.clone ();
324 : 3 : }
325 : : void
326 : 0 : SubstMapperInternal::visit (TyTy::BoolType &type)
327 : : {
328 : 0 : resolved = type.clone ();
329 : 0 : }
330 : : void
331 : 1 : SubstMapperInternal::visit (TyTy::IntType &type)
332 : : {
333 : 1 : resolved = type.clone ();
334 : 1 : }
335 : : void
336 : 59 : SubstMapperInternal::visit (TyTy::UintType &type)
337 : : {
338 : 59 : resolved = type.clone ();
339 : 59 : }
340 : : void
341 : 0 : SubstMapperInternal::visit (TyTy::FloatType &type)
342 : : {
343 : 0 : resolved = type.clone ();
344 : 0 : }
345 : : void
346 : 75 : SubstMapperInternal::visit (TyTy::USizeType &type)
347 : : {
348 : 75 : resolved = type.clone ();
349 : 75 : }
350 : : void
351 : 56 : SubstMapperInternal::visit (TyTy::ISizeType &type)
352 : : {
353 : 56 : resolved = type.clone ();
354 : 56 : }
355 : : void
356 : 0 : SubstMapperInternal::visit (TyTy::ErrorType &type)
357 : : {
358 : 0 : resolved = type.clone ();
359 : 0 : }
360 : : void
361 : 0 : SubstMapperInternal::visit (TyTy::CharType &type)
362 : : {
363 : 0 : resolved = type.clone ();
364 : 0 : }
365 : : void
366 : 0 : SubstMapperInternal::visit (TyTy::StrType &type)
367 : : {
368 : 0 : resolved = type.clone ();
369 : 0 : }
370 : : void
371 : 0 : SubstMapperInternal::visit (TyTy::NeverType &type)
372 : : {
373 : 0 : resolved = type.clone ();
374 : 0 : }
375 : : void
376 : 0 : SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
377 : : {
378 : 0 : resolved = type.clone ();
379 : 0 : }
380 : : void
381 : 0 : SubstMapperInternal::visit (TyTy::OpaqueType &type)
382 : : {
383 : 0 : resolved = type.clone ();
384 : 0 : }
385 : :
386 : : // SubstMapperFromExisting
387 : :
388 : 0 : SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
389 : 0 : TyTy::BaseType *receiver)
390 : 0 : : concrete (concrete), receiver (receiver), resolved (nullptr)
391 : 0 : {}
392 : :
393 : : TyTy::BaseType *
394 : 0 : SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
395 : : TyTy::BaseType *receiver)
396 : : {
397 : 0 : rust_assert (concrete->get_kind () == receiver->get_kind ());
398 : :
399 : 0 : SubstMapperFromExisting mapper (concrete, receiver);
400 : 0 : concrete->accept_vis (mapper);
401 : 0 : return mapper.resolved;
402 : : }
403 : :
404 : : void
405 : 0 : SubstMapperFromExisting::visit (TyTy::FnType &type)
406 : : {
407 : 0 : rust_assert (type.was_substituted ());
408 : :
409 : 0 : TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
410 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
411 : 0 : }
412 : :
413 : : void
414 : 0 : SubstMapperFromExisting::visit (TyTy::ADTType &type)
415 : : {
416 : 0 : rust_assert (type.was_substituted ());
417 : :
418 : 0 : TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
419 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
420 : 0 : }
421 : :
422 : : void
423 : 0 : SubstMapperFromExisting::visit (TyTy::ClosureType &type)
424 : : {
425 : 0 : rust_assert (type.was_substituted ());
426 : :
427 : 0 : TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
428 : 0 : resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
429 : 0 : }
430 : :
431 : : // GetUsedSubstArgs
432 : :
433 : 42097 : GetUsedSubstArgs::GetUsedSubstArgs ()
434 : 42097 : : args (TyTy::SubstitutionArgumentMappings::error ())
435 : 42097 : {}
436 : :
437 : : TyTy::SubstitutionArgumentMappings
438 : 42097 : GetUsedSubstArgs::From (const TyTy::BaseType *from)
439 : : {
440 : 42097 : GetUsedSubstArgs mapper;
441 : 42097 : from->accept_vis (mapper);
442 : 42097 : return mapper.args;
443 : 42097 : }
444 : :
445 : : void
446 : 0 : GetUsedSubstArgs::visit (const TyTy::FnType &type)
447 : : {
448 : 0 : args = type.get_substitution_arguments ();
449 : 0 : }
450 : :
451 : : void
452 : 9670 : GetUsedSubstArgs::visit (const TyTy::ADTType &type)
453 : : {
454 : 9670 : args = type.get_substitution_arguments ();
455 : 9670 : }
456 : :
457 : : void
458 : 0 : GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
459 : : {
460 : 0 : args = type.get_substitution_arguments ();
461 : 0 : }
462 : :
463 : : } // namespace Resolver
464 : : } // namespace Rust
|