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