1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #include "rust-substitution-mapper.h"
20 #include "rust-hir-type-check.h"
25 SubstMapper::SubstMapper (HirId ref
, HIR::GenericArgs
*generics
,
26 const std::vector
<TyTy::Region
> ®ions
,
28 : resolved (new TyTy::ErrorType (ref
)), generics (generics
),
29 regions (regions
), locus (locus
)
33 SubstMapper::Resolve (TyTy::BaseType
*base
, location_t locus
,
34 HIR::GenericArgs
*generics
,
35 const std::vector
<TyTy::Region
> ®ions
)
37 SubstMapper
mapper (base
->get_ref (), generics
, regions
, locus
);
38 base
->accept_vis (mapper
);
39 rust_assert (mapper
.resolved
!= nullptr);
40 return mapper
.resolved
;
44 SubstMapper::InferSubst (TyTy::BaseType
*base
, location_t locus
)
46 return SubstMapper::Resolve (base
, locus
, nullptr, {});
50 SubstMapper::have_generic_args () const
52 return generics
!= nullptr;
56 SubstMapper::visit (TyTy::FnType
&type
)
58 TyTy::FnType
*concrete
= nullptr;
59 if (!have_generic_args ())
61 TyTy::BaseType
*substs
= type
.infer_substitions (locus
);
62 rust_assert (substs
->get_kind () == TyTy::TypeKind::FNDEF
);
63 concrete
= static_cast<TyTy::FnType
*> (substs
);
67 TyTy::SubstitutionArgumentMappings mappings
68 = type
.get_mappings_from_generic_args (*generics
, regions
);
69 if (mappings
.is_error ())
72 concrete
= type
.handle_substitions (mappings
);
75 if (concrete
!= nullptr)
80 SubstMapper::visit (TyTy::ADTType
&type
)
82 TyTy::ADTType
*concrete
= nullptr;
83 if (!have_generic_args ())
85 TyTy::BaseType
*substs
= type
.infer_substitions (locus
);
86 rust_assert (substs
->get_kind () == TyTy::TypeKind::ADT
);
87 concrete
= static_cast<TyTy::ADTType
*> (substs
);
91 TyTy::SubstitutionArgumentMappings mappings
92 = type
.get_mappings_from_generic_args (*generics
, regions
);
93 if (mappings
.is_error ())
96 concrete
= type
.handle_substitions (mappings
);
99 if (concrete
!= nullptr)
104 SubstMapper::visit (TyTy::PlaceholderType
&type
)
106 rust_assert (type
.can_resolve ());
107 resolved
= SubstMapper::Resolve (type
.resolve (), locus
, generics
, regions
);
111 SubstMapper::visit (TyTy::ProjectionType
&type
)
113 TyTy::ProjectionType
*concrete
= nullptr;
114 if (!have_generic_args ())
116 TyTy::BaseType
*substs
= type
.infer_substitions (locus
);
117 rust_assert (substs
->get_kind () == TyTy::TypeKind::PROJECTION
);
118 concrete
= static_cast<TyTy::ProjectionType
*> (substs
);
122 TyTy::SubstitutionArgumentMappings mappings
123 = type
.get_mappings_from_generic_args (*generics
, regions
);
124 if (mappings
.is_error ())
127 concrete
= type
.handle_substitions (mappings
);
130 if (concrete
!= nullptr)
134 SubstMapperInternal::SubstMapperInternal (
135 HirId ref
, TyTy::SubstitutionArgumentMappings
&mappings
)
136 : resolved (new TyTy::ErrorType (ref
)), mappings (mappings
)
140 SubstMapperInternal::Resolve (TyTy::BaseType
*base
,
141 TyTy::SubstitutionArgumentMappings
&mappings
)
143 auto context
= TypeCheckContext::get ();
145 SubstMapperInternal
mapper (base
->get_ref (), mappings
);
146 base
->accept_vis (mapper
);
147 rust_assert (mapper
.resolved
!= nullptr);
149 // insert these new implict types into the context
150 TyTy::BaseType
*unused
= nullptr;
152 = context
->lookup_type (mapper
.resolved
->get_ty_ref (), &unused
);
153 if (!is_ty_available
)
155 context
->insert_type (
156 Analysis::NodeMapping (0, 0, mapper
.resolved
->get_ty_ref (), 0),
159 bool is_ref_available
160 = context
->lookup_type (mapper
.resolved
->get_ref (), &unused
);
161 if (!is_ref_available
)
163 context
->insert_type (Analysis::NodeMapping (0, 0,
164 mapper
.resolved
->get_ref (),
169 return mapper
.resolved
;
173 SubstMapperInternal::mappings_are_bound (
174 TyTy::BaseType
*tyseg
, TyTy::SubstitutionArgumentMappings
&mappings
)
176 if (tyseg
->get_kind () == TyTy::TypeKind::ADT
)
178 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (tyseg
);
179 return adt
->are_mappings_bound (mappings
);
181 else if (tyseg
->get_kind () == TyTy::TypeKind::FNDEF
)
183 TyTy::FnType
*fn
= static_cast<TyTy::FnType
*> (tyseg
);
184 return fn
->are_mappings_bound (mappings
);
191 SubstMapperInternal::visit (TyTy::FnType
&type
)
193 TyTy::SubstitutionArgumentMappings adjusted
194 = type
.adjust_mappings_for_this (mappings
);
195 if (adjusted
.is_error ())
198 TyTy::BaseType
*concrete
= type
.handle_substitions (adjusted
);
199 if (concrete
!= nullptr)
204 SubstMapperInternal::visit (TyTy::ADTType
&type
)
206 TyTy::SubstitutionArgumentMappings adjusted
207 = type
.adjust_mappings_for_this (mappings
);
208 if (adjusted
.is_error ())
211 TyTy::BaseType
*concrete
= type
.handle_substitions (adjusted
);
212 if (concrete
!= nullptr)
216 // these don't support generic arguments but might contain a type param
218 SubstMapperInternal::visit (TyTy::TupleType
&type
)
220 resolved
= type
.handle_substitions (mappings
);
224 SubstMapperInternal::visit (TyTy::ReferenceType
&type
)
226 resolved
= type
.handle_substitions (mappings
);
230 SubstMapperInternal::visit (TyTy::PointerType
&type
)
232 resolved
= type
.handle_substitions (mappings
);
236 SubstMapperInternal::visit (TyTy::ParamType
&type
)
238 resolved
= type
.handle_substitions (mappings
);
242 SubstMapperInternal::visit (TyTy::PlaceholderType
&type
)
244 rust_assert (type
.can_resolve ());
245 if (mappings
.trait_item_mode ())
247 resolved
= type
.resolve ();
251 resolved
= SubstMapperInternal::Resolve (type
.resolve (), mappings
);
256 SubstMapperInternal::visit (TyTy::ProjectionType
&type
)
258 resolved
= type
.handle_substitions (mappings
);
262 SubstMapperInternal::visit (TyTy::ClosureType
&type
)
264 resolved
= type
.handle_substitions (mappings
);
268 SubstMapperInternal::visit (TyTy::ArrayType
&type
)
270 resolved
= type
.handle_substitions (mappings
);
274 SubstMapperInternal::visit (TyTy::SliceType
&type
)
276 resolved
= type
.handle_substitions (mappings
);
279 // nothing to do for these
281 SubstMapperInternal::visit (TyTy::InferType
&type
)
283 resolved
= type
.clone ();
286 SubstMapperInternal::visit (TyTy::FnPtr
&type
)
288 resolved
= type
.clone ();
291 SubstMapperInternal::visit (TyTy::BoolType
&type
)
293 resolved
= type
.clone ();
296 SubstMapperInternal::visit (TyTy::IntType
&type
)
298 resolved
= type
.clone ();
301 SubstMapperInternal::visit (TyTy::UintType
&type
)
303 resolved
= type
.clone ();
306 SubstMapperInternal::visit (TyTy::FloatType
&type
)
308 resolved
= type
.clone ();
311 SubstMapperInternal::visit (TyTy::USizeType
&type
)
313 resolved
= type
.clone ();
316 SubstMapperInternal::visit (TyTy::ISizeType
&type
)
318 resolved
= type
.clone ();
321 SubstMapperInternal::visit (TyTy::ErrorType
&type
)
323 resolved
= type
.clone ();
326 SubstMapperInternal::visit (TyTy::CharType
&type
)
328 resolved
= type
.clone ();
331 SubstMapperInternal::visit (TyTy::StrType
&type
)
333 resolved
= type
.clone ();
336 SubstMapperInternal::visit (TyTy::NeverType
&type
)
338 resolved
= type
.clone ();
341 SubstMapperInternal::visit (TyTy::DynamicObjectType
&type
)
343 resolved
= type
.clone ();
346 // SubstMapperFromExisting
348 SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType
*concrete
,
349 TyTy::BaseType
*receiver
)
350 : concrete (concrete
), receiver (receiver
), resolved (nullptr)
354 SubstMapperFromExisting::Resolve (TyTy::BaseType
*concrete
,
355 TyTy::BaseType
*receiver
)
357 rust_assert (concrete
->get_kind () == receiver
->get_kind ());
359 SubstMapperFromExisting
mapper (concrete
, receiver
);
360 concrete
->accept_vis (mapper
);
361 return mapper
.resolved
;
365 SubstMapperFromExisting::visit (TyTy::FnType
&type
)
367 rust_assert (type
.was_substituted ());
369 TyTy::FnType
*to_sub
= static_cast<TyTy::FnType
*> (receiver
);
370 resolved
= to_sub
->handle_substitions (type
.get_substitution_arguments ());
374 SubstMapperFromExisting::visit (TyTy::ADTType
&type
)
376 rust_assert (type
.was_substituted ());
378 TyTy::ADTType
*to_sub
= static_cast<TyTy::ADTType
*> (receiver
);
379 resolved
= to_sub
->handle_substitions (type
.get_substitution_arguments ());
383 SubstMapperFromExisting::visit (TyTy::ClosureType
&type
)
385 rust_assert (type
.was_substituted ());
387 TyTy::ClosureType
*to_sub
= static_cast<TyTy::ClosureType
*> (receiver
);
388 resolved
= to_sub
->handle_substitions (type
.get_substitution_arguments ());
393 GetUsedSubstArgs::GetUsedSubstArgs ()
394 : args (TyTy::SubstitutionArgumentMappings::error ())
397 TyTy::SubstitutionArgumentMappings
398 GetUsedSubstArgs::From (const TyTy::BaseType
*from
)
400 GetUsedSubstArgs mapper
;
401 from
->accept_vis (mapper
);
406 GetUsedSubstArgs::visit (const TyTy::FnType
&type
)
408 args
= type
.get_substitution_arguments ();
412 GetUsedSubstArgs::visit (const TyTy::ADTType
&type
)
414 args
= type
.get_substitution_arguments ();
418 GetUsedSubstArgs::visit (const TyTy::ClosureType
&type
)
420 args
= type
.get_substitution_arguments ();
423 } // namespace Resolver